# HG changeset patch
# User Frank Benoit
+ * By defining constants like UP and DOWN in a single class, SWT
+ * can share common names and concepts at the same time minimizing
+ * the number of classes, names and constants for the application
+ * programmer.
+ *
+ * Note that some of the constants provided by this class represent
+ * optional, appearance related aspects of widgets which are available
+ * either only on some window systems, or for a differing set of
+ * widgets on each window system. These constants are marked
+ * as HINTs. The set of widgets which support a particular
+ * HINT may change from release to release, although we typically
+ * will not withdraw support for a HINT once it is made available.
+ *
+ * The settings changed event is sent when an operating system
+ * property, such as a system font or color, has been changed.
+ * The event occurs after the property has been changed, but
+ * before any widget is redrawn. Applications that cache operating
+ * system properties can use this event to update their caches.
+ * A specific property change can be detected by querying the
+ * new value of a property and comparing it with the equivalent
+ * cached value. The operating system automatically redraws and
+ * lays out all widgets after this event is sent.
+ *
+ * The IME composition event is sent to allow
+ * custom text editors to implement in-line
+ * editing of international text.
+ *
+ *
Used By:
Menu
Used By:
Menu
ToolItem
CoolItem
Combo
Used By:
Menu
Used By:
Label
MenuItem
ToolItem
Used By:
Button
Used By:
Button
Used By:
Button
MenuItem
ToolItem
Used By:
Button
MenuItem
ToolItem
Used By:
Button
MenuItem
ToolItem
Table
Tree
Used By:
MenuItem
Used By:
Text
List
FileDialog
Used By:
Text
List
Table
Tree
Used By:
Combo
Text
Used By:
Label
Text
ToolBar
Spinner
Used By:
Text
Used By:
Combo
Used By:
Text
Used By:
Label
Group
Used By:
Label
Group
ToolBar
Used By:
Group
Used By:
Group
Used By:
Label
Group
Used By:
ProgressBar
+ * A tool window is a window intended to be used as a floating toolbar.
+ * It typically has a title bar that is shorter than a normal title bar,
+ * and the window title is typically drawn using a smaller font.
+ *
Note that this is a HINT.
+ *
Used By:
Decorations
and subclassesUsed By:
Decorations
and subclassesUsed By:
Decorations
and subclassesTracker
Used By:
Decorations
and subclassesUsed By:
Decorations
and subclassesUsed By:
Decorations
and subclassesUsed By:
Decorations
and subclassesUsed By:
Decorations
and subclassesUsed By:
Scrollable
and subclassesUsed By:
Scrollable
and subclasses+ * When neither H_SCROLL or V_SCROLL are specified, controls + * are free to create the default scroll bars for the control. + * Using NO_SCROLL overrides the default and forces the control + * to have no scroll bars. + * + * Used By:
Tree
Table
Used By:
Control
and subclassesUsed By:
Control
and subclassesUsed By:
Control
and subclassesUsed By:
Shell
and subclassesUsed By:
Shell
Used By:
Shell
Used By:
Dialog
Shell
Used By:
Dialog
Shell
Used By:
Dialog
Shell
Used By:
Dialog
Shell
Used By:
Table
Used By:
Table
Tree
StyledText
TextLayout
Used By:
Button
ToolBar
Used By:
ProgressBar
Sash
+ * By default, before a widget paints, the client area is filled with the current background. + * When this style is specified, the background is not filled, and the application is responsible + * for filling every pixel of the client area. + * This style might be used as an alternative to "double-buffering" in order to reduce flicker. + * This style does not mean "transparent" - widgets that are obscured will not draw through. + *
Used By:
Composite
+ * Normally, when the user clicks on a control, focus is assigned to that
+ * control, providing the control has no children. Some controls, such as
+ * tool bars and sashes, don't normally take focus when the mouse is clicked
+ * or accept focus when assigned from within the program. This style allows
+ * Composites to implement "no focus" mouse behavior.
+ *
+ *
Note that this is a HINT.
+ *
Used By:
Composite
+ * This style stops the entire client area from being invalidated when the size
+ * of the Canvas changes. Specifically, when the size of the Canvas gets smaller,
+ * the SWT.Paint event is not sent. When it gets bigger, an SWT.Paint event is
+ * sent with a GC clipped to only the new areas to be painted. Without this
+ * style, the entire client area will be repainted.
+ *
+ *
Note that this is a HINT.
+ *
Used By:
Composite
Used By:
Composite
Used By:
Composite
+ * When orientation is not explicitly specified, orientation is
+ * inherited. This means that children will be assigned the
+ * orientation of their parent. To override this behavior and
+ * force an orientation for a child, explicitly set the orientation
+ * of the child when that child is created.
+ *
Note that this is a HINT.
+ *
Used By:
Control
Menu
GC
+ * When orientation is not explicitly specified, orientation is
+ * inherited. This means that children will be assigned the
+ * orientation of their parent. To override this behavior and
+ * force an orientation for a child, explicitly set the orientation
+ * of the child when that child is created.
+ *
Note that this is a HINT.
+ *
Used By:
Control
Menu
GC
Used By:
Control
Menu
Used By:
Composite
Used By:
Table
Tree
Used By:
Control
+ * By default, before a widget paints, the client area is filled with the current background. + * When this style is specified, the background is not filled and widgets that are obscured + * will draw through. + *
Used By:
Composite
Used By:
Button
with ARROW
styleTracker
Table
Tree
Used By:
TextStyle
Used By:
TextStyle
Used By:
TextStyle
Used By:
TextStyle
Used By:
TextStyle
Used By:
TextStyle
Used By:
TextStyle
Used By:
FormAttachment
in a FormLayout
Used By:
Button
with ARROW
styleTracker
Table
Tree
Used By:
FormAttachment
in a FormLayout
Used By:
Button
Label
TableColumn
Tracker
FormAttachment
in a FormLayout
Used By:
Button
Label
TableColumn
Tracker
FormAttachment
in a FormLayout
Used By:
Button
Label
TableColumn
FormAttachment
in a FormLayout
Used By:
Label
ProgressBar
Sash
Scale
ScrollBar
Slider
ToolBar
FillLayout
typeRowLayout
typeUsed By:
Label
ProgressBar
Sash
Scale
ScrollBar
Slider
ToolBar
CoolBar
FillLayout
typeRowLayout
typeUsed By:
DateTime
Used By:
DateTime
Used By:
DateTime
+ * A short date displays the month and year.
+ * A short time displays hours and minutes.
+ *
Note that this is a HINT.
+ *
Used By:
DateTime
+ * A medium date displays the day, month and year.
+ * A medium time displays hours, minutes, and seconds.
+ *
Note that this is a HINT.
+ *
Used By:
DateTime
+ * A long date displays the day, month and year.
+ * A long time displays hours, minutes, and seconds.
+ * The day and month names may be displayed.
+ *
Note that this is a HINT.
+ *
Used By:
DateTime
+ *
Used By:
Browser
Used By:
ToolTip
Used By:
GridLayout
typeUsed By:
GridLayout
typechar
'\b').
+ */
+ public static const char BS = '\b';
+
+ /**
+ * ASCII character convenience constant for the carriage return character
+ * (value is the char
'\r').
+ */
+ public static const char CR = '\r';
+
+ /**
+ * ASCII character convenience constant for the delete character
+ * (value is the char
with value 127).
+ */
+ public static const char DEL = 0x7F;
+
+ /**
+ * ASCII character convenience constant for the escape character
+ * (value is the char
with value 27).
+ */
+ public static const char ESC = 0x1B;
+
+ /**
+ * ASCII character convenience constant for the line feed character
+ * (value is the char
'\n').
+ */
+ public static const char LF = '\n';
+
+ /**
+ * ASCII character convenience constant for the tab character
+ * (value is the char
'\t').
+ *
+ * @since 2.1
+ */
+ public static const char TAB = '\t';
+
+ /**
+ * keyboard and/or mouse event mask indicating that the ALT key
+ * was pushed on the keyboard when the event was generated
+ * (value is 1<<16).
+ */
+ public static const int ALT = 1 << 16;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that the SHIFT key
+ * was pushed on the keyboard when the event was generated
+ * (value is 1<<17).
+ */
+ public static const int SHIFT = 1 << 17;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that the CTRL key
+ * was pushed on the keyboard when the event was generated
+ * (value is 1<<18).
+ */
+ public static const int CTRL = 1 << 18;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that the CTRL key
+ * was pushed on the keyboard when the event was generated. This
+ * is a synonym for CTRL (value is 1<<18).
+ */
+ public static const int CONTROL = CTRL;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that the COMMAND key
+ * was pushed on the keyboard when the event was generated
+ * (value is 1<<22).
+ *
+ * @since 2.1
+ */
+ public static const int COMMAND = 1 << 22;
+
+ /**
+ * Keyboard and/or mouse event mask indicating all possible
+ * keyboard modifiers.
+ *
+ * To allow for the future, this mask is intended to be used in
+ * place of code that references each individual keyboard mask.
+ * For example, the following expression will determine whether
+ * any modifier is pressed and will continue to work as new modifier
+ * masks are added.
+ *
+ * (stateMask & SWT.MODIFIER_MASK) !is 0
.
+ *
+ * @since 2.1
+ */
+ public static const int MODIFIER_MASK = ALT | SHIFT | CTRL | COMMAND;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that mouse button one
+ * was pushed when the event was generated. (value is 1<<19).
+ */
+ public static const int BUTTON1 = 1 << 19;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that mouse button two
+ * was pushed when the event was generated. (value is 1<<20).
+ */
+ public static const int BUTTON2 = 1 << 20;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that mouse button three
+ * was pushed when the event was generated. (value is 1<<21).
+ */
+ public static const int BUTTON3 = 1 << 21;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that mouse button four
+ * was pushed when the event was generated. (value is 1<<23).
+ *
+ * @since 3.1
+ */
+ public static const int BUTTON4 = 1 << 23;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that mouse button five
+ * was pushed when the event was generated. (value is 1<<25).
+ *
+ * @since 3.1
+ */
+ public static const int BUTTON5 = 1 << 25;
+
+ /**
+ * Keyboard and/or mouse event mask indicating all possible
+ * mouse buttons.
+ *
+ * To allow for the future, this mask is intended to be used
+ * in place of code that references each individual button mask.
+ * For example, the following expression will determine whether
+ * any button is pressed and will continue to work as new button
+ * masks are added.
+ *
+ * (stateMask & SWT.BUTTON_MASK) !is 0
.
+ *
+ * @since 2.1
+ */
+ public static const int BUTTON_MASK = BUTTON1 | BUTTON2 | BUTTON3 | BUTTON4 | BUTTON5;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that the MOD1 key
+ * was pushed on the keyboard when the event was generated.
+ *
+ * This is the primary keyboard modifier for the platform.
+ *
+ * @since 2.1
+ */
+ public static const int MOD1 = CONTROL;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that the MOD2 key
+ * was pushed on the keyboard when the event was generated.
+ *
+ * This is the secondary keyboard modifier for the platform.
+ *
+ * @since 2.1
+ */
+ public static const int MOD2 = SHIFT;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that the MOD3 key
+ * was pushed on the keyboard when the event was generated.
+ *
+ * @since 2.1
+ */
+ public static const int MOD3 = ALT;
+
+ /**
+ * Keyboard and/or mouse event mask indicating that the MOD4 key
+ * was pushed on the keyboard when the event was generated.
+ *
+ * @since 2.1
+ */
+ public static const int MOD4 = 0;
+
+ /**
+ * Constants to indicate line scrolling (value is 1).
+ * Used By:
Control
Used By:
Control
((SWT.MOD1 | SWT.MOD2 | 'T') & SWT.KEYCODE_BIT) !is 0
.
+ *
+ * The following expression is true:
+ *
+ * ((SWT.MOD3 | SWT.F2) & SWT.KEYCODE_BIT) !is 0
.
+ *
+ * (value is (1<<24))
+ *
+ * @since 2.1
+ */
+ public static const int KEYCODE_BIT = (1 << 24);
+
+ /**
+ * Accelerator constant used to extract the key stroke portion of
+ * an accelerator.
+ *
+ * The key stroke may be a key code or a unicode
+ * value. If the key stroke is a key code KEYCODE_BIT
+ * will be set.
+ *
+ * @since 2.1
+ */
+ public static const int KEY_MASK = KEYCODE_BIT + 0xFFFF;
+
+ /**
+ * Keyboard event constant representing the UP ARROW key
+ * (value is (1<<24)+1).
+ */
+ public static const int ARROW_UP = KEYCODE_BIT + 1;
+
+ /**
+ * Keyboard event constant representing the DOWN ARROW key
+ * (value is (1<<24)+2).
+ */
+ public static const int ARROW_DOWN = KEYCODE_BIT + 2;
+
+ /**
+ * Keyboard event constant representing the LEFT ARROW key
+ * (value is (1<<24)+3).
+ */
+ public static const int ARROW_LEFT = KEYCODE_BIT + 3;
+
+ /**
+ * Keyboard event constant representing the RIGHT ARROW key
+ * (value is (1<<24)+4).
+ */
+ public static const int ARROW_RIGHT = KEYCODE_BIT + 4;
+
+ /**
+ * Keyboard event constant representing the PAGE UP key
+ * (value is (1<<24)+5).
+ */
+ public static const int PAGE_UP = KEYCODE_BIT + 5;
+
+ /**
+ * Keyboard event constant representing the PAGE DOWN key
+ * (value is (1<<24)+6).
+ */
+ public static const int PAGE_DOWN = KEYCODE_BIT + 6;
+
+ /**
+ * Keyboard event constant representing the HOME key
+ * (value is (1<<24)+7).
+ */
+ public static const int HOME = KEYCODE_BIT + 7;
+
+ /**
+ * Keyboard event constant representing the END key
+ * (value is (1<<24)+8).
+ */
+ public static const int END = KEYCODE_BIT + 8;
+
+ /**
+ * Keyboard event constant representing the INSERT key
+ * (value is (1<<24)+9).
+ */
+ public static const int INSERT = KEYCODE_BIT + 9;
+
+ /**
+ * Keyboard event constant representing the F1 key
+ * (value is (1<<24)+10).
+ */
+ public static const int F1 = KEYCODE_BIT + 10;
+
+ /**
+ * Keyboard event constant representing the F2 key
+ * (value is (1<<24)+11).
+ */
+ public static const int F2 = KEYCODE_BIT + 11;
+
+ /**
+ * Keyboard event constant representing the F3 key
+ * (value is (1<<24)+12).
+ */
+ public static const int F3 = KEYCODE_BIT + 12;
+
+ /**
+ * Keyboard event constant representing the F4 key
+ * (value is (1<<24)+13).
+ */
+ public static const int F4 = KEYCODE_BIT + 13;
+
+ /**
+ * Keyboard event constant representing the F5 key
+ * (value is (1<<24)+14).
+ */
+ public static const int F5 = KEYCODE_BIT + 14;
+
+ /**
+ * Keyboard event constant representing the F6 key
+ * (value is (1<<24)+15).
+ */
+ public static const int F6 = KEYCODE_BIT + 15;
+
+ /**
+ * Keyboard event constant representing the F7 key
+ * (value is (1<<24)+16).
+ */
+ public static const int F7 = KEYCODE_BIT + 16;
+
+ /**
+ * Keyboard event constant representing the F8 key
+ * (value is (1<<24)+17).
+ */
+ public static const int F8 = KEYCODE_BIT + 17;
+
+ /**
+ * Keyboard event constant representing the F9 key
+ * (value is (1<<24)+18).
+ */
+ public static const int F9 = KEYCODE_BIT + 18;
+
+ /**
+ * Keyboard event constant representing the F10 key
+ * (value is (1<<24)+19).
+ */
+ public static const int F10 = KEYCODE_BIT + 19;
+
+ /**
+ * Keyboard event constant representing the F11 key
+ * (value is (1<<24)+20).
+ */
+ public static const int F11 = KEYCODE_BIT + 20;
+
+ /**
+ * Keyboard event constant representing the F12 key
+ * (value is (1<<24)+21).
+ */
+ public static const int F12 = KEYCODE_BIT + 21;
+
+ /**
+ * Keyboard event constant representing the F13 key
+ * (value is (1<<24)+22).
+ *
+ * @since 3.0
+ */
+ public static const int F13 = KEYCODE_BIT + 22;
+
+ /**
+ * Keyboard event constant representing the F14 key
+ * (value is (1<<24)+23).
+ *
+ * @since 3.0
+ */
+ public static const int F14 = KEYCODE_BIT + 23;
+
+ /**
+ * Keyboard event constant representing the F15 key
+ * (value is (1<<24)+24).
+ *
+ * @since 3.0
+ */
+ public static const int F15 = KEYCODE_BIT + 24;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad multiply key (value is (1<<24)+42).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_MULTIPLY = KEYCODE_BIT + 42;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad add key (value is (1<<24)+43).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_ADD = KEYCODE_BIT + 43;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad subtract key (value is (1<<24)+45).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_SUBTRACT = KEYCODE_BIT + 45;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad decimal key (value is (1<<24)+46).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_DECIMAL = KEYCODE_BIT + 46;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad divide key (value is (1<<24)+47).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_DIVIDE = KEYCODE_BIT + 47;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad zero key (value is (1<<24)+48).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_0 = KEYCODE_BIT + 48;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad one key (value is (1<<24)+49).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_1 = KEYCODE_BIT + 49;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad two key (value is (1<<24)+50).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_2 = KEYCODE_BIT + 50;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad three key (value is (1<<24)+51).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_3 = KEYCODE_BIT + 51;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad four key (value is (1<<24)+52).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_4 = KEYCODE_BIT + 52;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad five key (value is (1<<24)+53).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_5 = KEYCODE_BIT + 53;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad six key (value is (1<<24)+54).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_6 = KEYCODE_BIT + 54;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad seven key (value is (1<<24)+55).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_7 = KEYCODE_BIT + 55;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad eight key (value is (1<<24)+56).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_8 = KEYCODE_BIT + 56;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad nine key (value is (1<<24)+57).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_9 = KEYCODE_BIT + 57;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad equal key (value is (1<<24)+61).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_EQUAL = KEYCODE_BIT + 61;
+
+ /**
+ * Keyboard event constant representing the numeric key
+ * pad enter key (value is (1<<24)+80).
+ *
+ * @since 3.0
+ */
+ public static const int KEYPAD_CR = KEYCODE_BIT + 80;
+
+ /**
+ * Keyboard event constant representing the help
+ * key (value is (1<<24)+81).
+ *
+ * NOTE: The HELP key maps to the key labeled "help",
+ * not "F1". If your keyboard does not have a HELP key,
+ * you will never see this key press. To listen for
+ * help on a control, use SWT.Help.
+ *
+ * @since 3.0
+ *
+ * @see SWT#Help
+ */
+ public static const int HELP = KEYCODE_BIT + 81;
+
+ /**
+ * Keyboard event constant representing the caps
+ * lock key (value is (1<<24)+82).
+ *
+ * @since 3.0
+ */
+ public static const int CAPS_LOCK = KEYCODE_BIT + 82;
+
+ /**
+ * Keyboard event constant representing the num
+ * lock key (value is (1<<24)+83).
+ *
+ * @since 3.0
+ */
+ public static const int NUM_LOCK = KEYCODE_BIT + 83;
+
+ /**
+ * Keyboard event constant representing the scroll
+ * lock key (value is (1<<24)+84).
+ *
+ * @since 3.0
+ */
+ public static const int SCROLL_LOCK = KEYCODE_BIT + 84;
+
+ /**
+ * Keyboard event constant representing the pause
+ * key (value is (1<<24)+85).
+ *
+ * @since 3.0
+ */
+ public static const int PAUSE = KEYCODE_BIT + 85;
+
+ /**
+ * Keyboard event constant representing the break
+ * key (value is (1<<24)+86).
+ *
+ * @since 3.0
+ */
+ public static const int BREAK = KEYCODE_BIT + 86;
+
+ /**
+ * Keyboard event constant representing the print screen
+ * key (value is (1<<24)+87).
+ *
+ * @since 3.0
+ */
+ public static const int PRINT_SCREEN = KEYCODE_BIT + 87;
+
+ /**
+ * The MessageBox
style constant for error icon
+ * behavior (value is 1).
+ */
+ public static const int ICON_ERROR = 1;
+
+ /**
+ * The MessageBox
style constant for information icon
+ * behavior (value is 1<<1).
+ */
+ public static const int ICON_INFORMATION = 1 << 1;
+
+ /**
+ * The MessageBox
style constant for question icon
+ * behavior (value is 1<<2).
+ */
+ public static const int ICON_QUESTION = 1 << 2;
+
+ /**
+ * The MessageBox
style constant for warning icon
+ * behavior (value is 1<<3).
+ */
+ public static const int ICON_WARNING = 1 << 3;
+
+ /**
+ * The MessageBox
style constant for "working" icon
+ * behavior (value is 1<<4).
+ */
+ public static const int ICON_WORKING = 1 << 4;
+
+ /**
+ * The MessageBox
style constant for an OK button;
+ * valid combinations are OK, OK|CANCEL
+ * (value is 1<<5).
+ */
+ public static const int OK = 1 << 5;
+
+ /**
+ * The MessageBox
style constant for YES button;
+ * valid combinations are YES|NO, YES|NO|CANCEL
+ * (value is 1<<6).
+ */
+ public static const int YES = 1 << 6;
+
+ /**
+ * The MessageBox
style constant for NO button;
+ * valid combinations are YES|NO, YES|NO|CANCEL
+ * (value is 1<<7).
+ */
+ public static const int NO = 1 << 7;
+
+ /**
+ * The MessageBox
style constant for a CANCEL button;
+ * valid combinations are OK|CANCEL, YES|NO|CANCEL, RETRY|CANCEL
+ * (value is 1<<8). This style constant is also used with
+ * Text
in combination with SEARCH.
+ *
+ * Used By:
MessageBox
Text
MessageBox
style constant for an ABORT button;
+ * the only valid combination is ABORT|RETRY|IGNORE
+ * (value is 1<<9).
+ */
+ public static const int ABORT = 1 << 9;
+
+ /**
+ * The MessageBox
style constant for a RETRY button;
+ * valid combinations are ABORT|RETRY|IGNORE, RETRY|CANCEL
+ * (value is 1<<10).
+ */
+ public static const int RETRY = 1 << 10;
+
+ /**
+ * The MessageBox
style constant for an IGNORE button;
+ * the only valid combination is ABORT|RETRY|IGNORE
+ * (value is 1<<11).
+ */
+ public static const int IGNORE = 1 << 11;
+
+ /**
+ * The FileDialog
style constant for open file dialog behavior
+ * (value is 1<<12).
+ */
+ public static const int OPEN = 1 << 12;
+
+ /**
+ * The FileDialog
style constant for save file dialog behavior
+ * (value is 1<<13).
+ */
+ public static const int SAVE = 1 << 13;
+
+ /**
+ * The Composite
constant to indicate that
+ * an attribute (such as background) is not inherited
+ * by the children (value is 0).
+ *
+ * @since 3.2
+ */
+ public static const int INHERIT_NONE = 0;
+
+ /**
+ * The Composite
constant to indicate that
+ * an attribute (such as background) is inherited by
+ * children who choose this value as their "default"
+ * (value is 1). For example, a label child will
+ * typically choose to inherit the background color
+ * of a composite while a list or table will not.
+ *
+ * @since 3.2
+ */
+ public static const int INHERIT_DEFAULT = 1;
+
+ /**
+ * The Composite
constant to indicate that
+ * an attribute (such as background) is inherited by
+ * all children.
+ *
+ * @since 3.2
+ */
+ public static const int INHERIT_FORCE = 2;
+
+ /**
+ * Default color white (value is 1).
+ */
+ public static const int COLOR_WHITE = 1;
+
+ /**
+ * Default color black (value is 2).
+ */
+ public static const int COLOR_BLACK = 2;
+
+ /**
+ * Default color red (value is 3).
+ */
+ public static const int COLOR_RED = 3;
+
+ /**
+ * Default color dark red (value is 4).
+ */
+ public static const int COLOR_DARK_RED = 4;
+
+ /**
+ * Default color green (value is 5).
+ */
+ public static const int COLOR_GREEN = 5;
+
+ /**
+ * Default color dark green (value is 6).
+ */
+ public static const int COLOR_DARK_GREEN = 6;
+
+ /**
+ * Default color yellow (value is 7).
+ */
+ public static const int COLOR_YELLOW = 7;
+
+ /**
+ * Default color dark yellow (value is 8).
+ */
+ public static const int COLOR_DARK_YELLOW = 8;
+
+ /**
+ * Default color blue (value is 9).
+ */
+ public static const int COLOR_BLUE = 9;
+
+ /**
+ * Default color dark blue (value is 10).
+ */
+ public static const int COLOR_DARK_BLUE = 10;
+
+ /**
+ * Default color magenta (value is 11).
+ */
+ public static const int COLOR_MAGENTA = 11;
+
+ /**
+ * Default color dark magenta (value is 12).
+ */
+ public static const int COLOR_DARK_MAGENTA = 12;
+
+ /**
+ * Default color cyan (value is 13).
+ */
+ public static const int COLOR_CYAN = 13;
+
+ /**
+ * Default color dark cyan (value is 14).
+ */
+ public static const int COLOR_DARK_CYAN = 14;
+
+ /**
+ * Default color gray (value is 15).
+ */
+ public static const int COLOR_GRAY = 15;
+
+ /**
+ * Default color dark gray (value is 16).
+ */
+ public static const int COLOR_DARK_GRAY = 16;
+
+ /*
+ * System Colors
+ *
+ * Dealing with system colors is an area where there are
+ * many platform differences. On some platforms, system
+ * colors can change dynamically while the program is
+ * running. On other platforms, system colors can be
+ * changed for all instances of a particular widget.
+ * Therefore, the only truly portable method to obtain
+ * a widget color query is to query the color from an
+ * instance of the widget.
+ *
+ * It is expected that the list of supported colors
+ * will grow over time.
+ */
+
+ /**
+ * System color used to paint dark shadow areas (value is 17).
+ */
+ public static const int COLOR_WIDGET_DARK_SHADOW = 17;
+
+ /**
+ * System color used to paint normal shadow areas (value is 18).
+ */
+ public static const int COLOR_WIDGET_NORMAL_SHADOW = 18;
+
+ /**
+ * System color used to paint light shadow areas (value is 19).
+ */
+ public static const int COLOR_WIDGET_LIGHT_SHADOW = 19;
+
+ /**
+ * System color used to paint highlight shadow areas (value is 20).
+ */
+ public static const int COLOR_WIDGET_HIGHLIGHT_SHADOW = 20;
+
+ /**
+ * System color used to paint foreground areas (value is 21).
+ */
+ public static const int COLOR_WIDGET_FOREGROUND = 21;
+
+ /**
+ * System color used to paint background areas (value is 22).
+ */
+ public static const int COLOR_WIDGET_BACKGROUND = 22;
+
+ /**
+ * System color used to paint border areas (value is 23).
+ */
+ public static const int COLOR_WIDGET_BORDER = 23;
+
+ /**
+ * System color used to paint list foreground areas (value is 24).
+ */
+ public static const int COLOR_LIST_FOREGROUND = 24;
+
+ /**
+ * System color used to paint list background areas (value is 25).
+ */
+ public static const int COLOR_LIST_BACKGROUND = 25;
+
+ /**
+ * System color used to paint list selection background areas (value is 26).
+ */
+ public static const int COLOR_LIST_SELECTION = 26;
+
+ /**
+ * System color used to paint list selected text (value is 27).
+ */
+ public static const int COLOR_LIST_SELECTION_TEXT = 27;
+
+ /**
+ * System color used to paint tooltip text (value is 28).
+ */
+ public static const int COLOR_INFO_FOREGROUND = 28;
+
+ /**
+ * System color used to paint tooltip background areas (value is 29).
+ */
+ public static const int COLOR_INFO_BACKGROUND = 29;
+
+ /**
+ * System color used to paint title text (value is 30).
+ */
+ public static const int COLOR_TITLE_FOREGROUND = 30;
+
+ /**
+ * System color used to paint title background areas (value is 31).
+ */
+ public static const int COLOR_TITLE_BACKGROUND = 31;
+
+ /**
+ * System color used to paint title background gradient (value is 32).
+ */
+ public static const int COLOR_TITLE_BACKGROUND_GRADIENT = 32;
+
+ /**
+ * System color used to paint inactive title text (value is 33).
+ */
+ public static const int COLOR_TITLE_INACTIVE_FOREGROUND = 33;
+
+ /**
+ * System color used to paint inactive title background areas (value is 34).
+ */
+ public static const int COLOR_TITLE_INACTIVE_BACKGROUND = 34;
+
+ /**
+ * System color used to paint inactive title background gradient (value is 35).
+ */
+ public static const int COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT = 35;
+
+ /**
+ * Draw constant indicating whether the drawing operation
+ * should fill the background (value is 1<<0).
+ */
+ public static const int DRAW_TRANSPARENT = 1 << 0;
+
+ /**
+ * Draw constant indicating whether the string drawing operation
+ * should handle line-delimiters (value is 1<<1).
+ */
+ public static const int DRAW_DELIMITER = 1 << 1;
+
+ /**
+ * Draw constant indicating whether the string drawing operation
+ * should expand TAB characters (value is 1<<2).
+ */
+ public static const int DRAW_TAB = 1 << 2;
+
+ /**
+ * Draw constant indicating whether the string drawing operation
+ * should handle mnemonics (value is 1<<3).
+ */
+ public static const int DRAW_MNEMONIC = 1 << 3;
+
+
+ /**
+ * Selection constant indicating that a line delimiter should be
+ * drawn (value is 1<<17).
+ *
+ * Used By:
TextLayout
Used By:
TextLayout
checkSubclass()
method
+ * (value is 43).
+ *
+ * For additional information see the comment in
+ * Widget.checkSubclass()
.
+ *
+ * @see org.eclipse.swt.widgets.Widget#checkSubclass
+ */
+ public static const int ERROR_INVALID_SUBCLASS = 43;
+
+ /**
+ * SWT error constant indicating that an attempt was made to
+ * invoke an SWT operation using a graphics object which had
+ * already been disposed
+ * (value is 44).
+ */
+ public static const int ERROR_GRAPHIC_DISPOSED = 44;
+
+ /**
+ * SWT error constant indicating that an attempt was made to
+ * invoke an SWT operation using a device which had already
+ * been disposed
+ * (value is 45).
+ */
+ public static const int ERROR_DEVICE_DISPOSED = 45;
+
+ /**
+ * SWT error constant indicating that an exception happened
+ * when executing a runnable
+ * (value is 46).
+ */
+ public static const int ERROR_FAILED_EXEC = 46;
+
+ /**
+ * SWT error constant indicating that an unsatisfied link
+ * error occurred while attempting to load a library
+ * (value is 47).
+ *
+ * @since 3.1
+ */
+ public static const int ERROR_FAILED_LOAD_LIBRARY = 47;
+
+ /**
+ * SWT error constant indicating that a font is not valid
+ * (value is 48).
+ *
+ * @since 3.1
+ */
+ public static const int ERROR_INVALID_FONT = 48;
+
+ /**
+ * Constant indicating that an image or operation is of type bitmap (value is 0).
+ */
+ public static const int BITMAP = 0;
+
+ /**
+ * Constant indicating that an image or operation is of type icon (value is 1).
+ */
+ public static const int ICON = 1;
+
+ /**
+ * The Image
constructor argument indicating that
+ * the new image should be a copy of the image provided as
+ * an argument (value is 0).
+ */
+ public static const int IMAGE_COPY = 0;
+
+ /**
+ * The Image
constructor argument indicating that
+ * the new image should have the appearance of a "disabled"
+ * (using the platform's rules for how this should look)
+ * copy of the image provided as an argument (value is 1).
+ */
+ public static const int IMAGE_DISABLE = 1;
+
+ /**
+ * The Image
constructor argument indicating that
+ * the new image should have the appearance of a "gray scaled"
+ * copy of the image provided as an argument (value is 2).
+ */
+ public static const int IMAGE_GRAY = 2;
+
+ /**
+ * Constant to indicate an error state (value is 1).
+ * Used By:
ProgressBar
Used By:
ProgressBar
ProgressBar
+ * to indicate a normal state.
+ * Used By:
ProgressBar
throwable
argument should be either null, or the
+ * throwable which caused SWT to throw an exception.
+ * + * In SWT, errors are reported by throwing one of three exceptions: + *
throwable
argument should be either null, or the
+ * throwable which caused SWT to throw an exception.
+ * + * In SWT, errors are reported by throwing one of three exceptions: + *
throwable
field which holds the underlying
+ * throwable that caused the problem (if this information is
+ * available (i.e. it may be null)).
+ * + * SWTErrors are thrown when something fails internally which + * either leaves SWT in an unknown state (eg. the o/s call to + * remove an item from a list returns an error code) or when SWT + * is left in a known-to-be-unrecoverable state (eg. it runs out + * of callback resources). SWTErrors should not occur in typical + * programs, although "high reliability" applications should + * still catch them. + *
+ * This class also provides support methods used by SWT to match + * error codes to the appropriate exception class (SWTError, + * SWTException, or IllegalArgumentException) and to provide + * human readable strings for SWT error codes. + *
+ * + * @see SWTException + * @see SWT#error(int) + * @see Sample code and further information + */ + +public class SWTError : PlatformException { + /** + * The SWT error code, one of SWT.ERROR_*. + */ + public int code; + + /** + * The underlying throwable that caused the problem, + * or null if this information is not available. + */ + public Exception throwable( Exception e ){ + this.next = e; + return this.next; + } + public Exception throwable(){ + return this.next; + } + + //static final long serialVersionUID = 3833467327105808433L; + +/** + * Constructs a new instance of this class with its + * stack trace filled in. The error code is set to an + * unspecified value. + */ +public this () { + this (SWT.ERROR_UNSPECIFIED); +} + +/** + * Constructs a new instance of this class with its + * stack trace and message filled in. The error code is + * set to an unspecified value. Specifyingnull
+ * as the message is equivalent to specifying an empty string.
+ *
+ * @param message the detail message for the exception
+ */
+public this (String message) {
+ this (SWT.ERROR_UNSPECIFIED, message);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace and error code filled in.
+ *
+ * @param code the SWT error code
+ */
+public this (int code) {
+ this (code, SWT.findErrorText (code));
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace, error code and message filled in.
+ * Specifying null
as the message is
+ * equivalent to specifying an empty string.
+ *
+ * @param code the SWT error code
+ * @param message the detail message for the exception
+ */
+public this (int code, String message) {
+ super (message);
+ this.code = code;
+}
+
+/**
+ * Returns the underlying throwable that caused the problem,
+ * or null if this information is not available.
+ * + * NOTE: This method overrides Throwable.getCause() that was + * added to JDK1.4. It is necessary to override this method + * in order for inherited printStackTrace() methods to work. + *
+ * @return the underlying throwable + * + * @since 3.1 + */ +public Exception getCause() { + return throwable; +} + +/** + * Returns the string describing this SWTError object. + *+ * It is combined with the message string of the Throwable + * which caused this SWTError (if this information is available). + *
+ * @return the error message string of this SWTError object + */ +public String getMessage () { + if (throwable is null) + return super.toString(); + return super.toString () ~ " (" ~ throwable.toString () ~ ")"; //$NON-NLS-1$ //$NON-NLS-2$ +} + +/** + * Outputs a printable representation of this error's + * stack trace on the standard error stream. + *+ * Note: printStackTrace(PrintStream) and printStackTrace(PrintWriter) + * are not provided in order to maintain compatibility with CLDC. + *
+ */ +public void printStackTrace () { + Stderr.formatln( "stacktrace follows (if feature compiled in)" ); + foreach( msg; info ){ + Stderr.formatln( "{}", msg ); + } + if ( throwable !is null) { + Stderr.formatln ("*** Stack trace of contained error ***"); //$NON-NLS-1$ + foreach( msg; throwable.info ){ + Stderr.formatln( "{}", msg ); + } + } +} + +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/SWTException.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/SWTException.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank Benoitthrowable
field which holds the underlying
+ * exception that caused the problem (if this information is
+ * available (i.e. it may be null)).
+ * + * SWTExceptions are thrown when something fails internally, + * but SWT is left in a known stable state (eg. a widget call + * was made from a non-u/i thread, or there is failure while + * reading an Image because the source file was corrupt). + *
+ * + * @see SWTError + * @see Sample code and further information + */ + +public class SWTException : Exception { + /** + * The SWT error code, one of SWT.ERROR_*. + */ + public int code; + + /** + * The underlying throwable that caused the problem, + * or null if this information is not available. + */ + public Exception throwable( Exception e ){ + this.next = e; + return this.next; + } + public Exception throwable(){ + return this.next; + } + + + //static final long serialVersionUID = 3257282552304842547L; + +/** + * Constructs a new instance of this class with its + * stack trace filled in. The error code is set to an + * unspecified value. + */ +public this () { + this (SWT.ERROR_UNSPECIFIED); +} + +/** + * Constructs a new instance of this class with its + * stack trace and message filled in. The error code is + * set to an unspecified value. Specifyingnull
+ * as the message is equivalent to specifying an empty string.
+ *
+ * @param message the detail message for the exception
+ */
+public this (String message) {
+ this (SWT.ERROR_UNSPECIFIED, message);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace and error code filled in.
+ *
+ * @param code the SWT error code
+ */
+public this (int code) {
+ this (code, SWT.findErrorText (code));
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace, error code and message filled in.
+ * Specifying null
as the message is
+ * equivalent to specifying an empty string.
+ *
+ * @param code the SWT error code
+ * @param message the detail message for the exception
+ */
+public this (int code, String message) {
+ super (message);
+ this.code = code;
+}
+
+/**
+ * Returns the underlying throwable that caused the problem,
+ * or null if this information is not available.
+ * + * NOTE: This method overrides Throwable.getCause() that was + * added to JDK1.4. It is necessary to override this method + * in order for inherited printStackTrace() methods to work. + *
+ * @return the underlying throwable + * + * @since 3.1 + */ +public Exception getCause() { + return throwable; +} + +/** + * Returns the string describing this SWTException object. + *+ * It is combined with the message string of the Throwable + * which caused this SWTException (if this information is available). + *
+ * @return the error message string of this SWTException object + */ +public String getMessage () { + if (throwable is null) return super.toString (); + return super.toString () ~ " (" ~ throwable.toString () ~ ")"; //$NON-NLS-1$ //$NON-NLS-2$ +} + +/** + * Outputs a printable representation of this exception's + * stack trace on the standard error stream. + *+ * Note: printStackTrace(PrintStream) and printStackTrace(PrintWriter) + * are not provided in order to maintain compatibility with CLDC. + *
+ */ +public void printStackTrace () { + Stderr.formatln( "stacktrace follows (if feature compiled in)" ); + foreach( msg; info ){ + Stderr.formatln( "{}", msg ); + } + if ( throwable !is null) { + Stderr.formatln ("*** Stack trace of contained exception ***"); //$NON-NLS-1$ + foreach( msg; throwable.info ){ + Stderr.formatln( "{}", msg ); + } + } +} + +} + + diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/ACC.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/ACC.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank BenoitgetAccessible
, 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
+ * @see Accessibility snippets
+ * @see Sample code and further information
+ *
+ * @since 2.0
+ */
+public class Accessible {
+ int refCount = 0, enumIndex = 0;
+ _IAccessibleImpl objIAccessible;
+ _IEnumVARIANTImpl objIEnumVARIANT;
+ IAccessible iaccessible;
+ SWTEventListener[] accessibleListeners;
+ SWTEventListener[] accessibleControlListeners;
+ SWTEventListener[] textListeners;
+ Object[] variants;
+ Control control;
+
+ this(Control control) {
+ this.control = control;
+ int /*long*/[] ppvObject = new int /*long*/[1];
+ /* CreateStdAccessibleObject([in] hwnd, [in] idObject, [in] riidInterface, [out] ppvObject).
+ * AddRef has already been called on ppvObject by the callee and must be released by the caller.
+ */
+ HRESULT result = COM.CreateStdAccessibleObject(control.handle, COM.OBJID_CLIENT, &COM.IIDIAccessible, cast(void**)&iaccessible);
+ /* The object needs to be checked, because if the CreateStdAccessibleObject()
+ * symbol is not found, the return value is S_OK.
+ */
+ if (iaccessible is null) return;
+ if (result !is COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+ objIAccessible = new _IAccessibleImpl(this);
+
+//PORTING_FIXME: i don't understand this...
+/+
+ int /*long*/ ppVtable = objIAccessible.ppVtable;
+ int /*long*/[] pVtable = new int /*long*/[1];
+ COM.MoveMemory(pVtable, ppVtable, OS.PTR_SIZEOF);
+ int /*long*/[] funcs = new int /*long*/[28];
+ COM.MoveMemory(funcs, pVtable[0], OS.PTR_SIZEOF * funcs.length);
+ funcs[9] = COM.get_accChild_CALLBACK(funcs[9]);
+ funcs[10] = COM.get_accName_CALLBACK(funcs[10]);
+ funcs[11] = COM.get_accValue_CALLBACK(funcs[11]);
+ funcs[12] = COM.get_accDescription_CALLBACK(funcs[12]);
+ funcs[13] = COM.get_accRole_CALLBACK(funcs[13]);
+ funcs[14] = COM.get_accState_CALLBACK(funcs[14]);
+ funcs[15] = COM.get_accHelp_CALLBACK(funcs[15]);
+ funcs[16] = COM.get_accHelpTopic_CALLBACK(funcs[16]);
+ funcs[17] = COM.get_accKeyboardShortcut_CALLBACK(funcs[17]);
+ funcs[20] = COM.get_accDefaultAction_CALLBACK(funcs[20]);
+ funcs[21] = COM.accSelect_CALLBACK(funcs[21]);
+ funcs[22] = COM.accLocation_CALLBACK(funcs[22]);
+ funcs[23] = COM.accNavigate_CALLBACK(funcs[23]);
+ funcs[25] = COM.accDoDefaultAction_CALLBACK(funcs[25]);
+ funcs[26] = COM.put_accName_CALLBACK(funcs[26]);
+ funcs[27] = COM.put_accValue_CALLBACK(funcs[27]);
+ COM.MoveMemory(pVtable[0], funcs, OS.PTR_SIZEOF * funcs.length);
++/
+
+ objIEnumVARIANT = new _IEnumVARIANTImpl(this) ;
+ AddRef();
+ }
+
+ /**
+ * 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.
+ *
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 AccessibleControlListener
+ * interface.
+ *
+ * @param listener the listener that should be notified when the receiver
+ * is asked for custom control specific information
+ *
+ * @exception IllegalArgumentException AccessibleTextListener
+ * interface.
+ *
+ * @param listener the listener that should be notified when the receiver
+ * is asked for custom text control specific information
+ *
+ * @exception IllegalArgumentException
+ * 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.
+ *
+ * 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.
+ *
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 AccessibleListener
interface.
+ *
+ * Classes that wish to deal with AccessibleEvent
s can
+ * extend this class and override only the methods that they are
+ * interested in.
+ *
+ * Note: Accessibility clients use child identifiers to specify + * whether they want information about a control or one of its children. + * Child identifiers are increasing integers beginning with 0. + * The identifier CHILDID_SELF represents the control itself. + *
+ * + * @see AccessibleListener + * @see AccessibleEvent + * @see Sample code and further information + * + * @since 2.0 + */ +public abstract class AccessibleAdapter : AccessibleListener { + + /** + * Sent when an accessibility client requests the name + * of the control, or the name of a child of the control. + * The default behavior is to do nothing. + *
+ * Return the name of the control or specified child in the
+ * result
field of the event object. Returning
+ * an empty string tells the client that the control or child
+ * does not have a name, and returning null tells the client
+ * to use the platform name.
+ *
+ * The information in this property should be similar to the help + * provided by toolTipText. It describes what the control or child + * does or how to use it, as opposed to getDescription, which + * describes appearance. + *
+ * Return the help string of the control or specified child in
+ * the result
field of the event object. Returning
+ * an empty string tells the client that the control or child
+ * does not have a help string, and returning null tells the
+ * client to use the platform help string.
+ *
+ * A keyboard shortcut can either be a mnemonic, or an accelerator. + * As a general rule, if the control or child can receive keyboard focus, + * then you should expose its mnemonic, and if it cannot receive keyboard + * focus, then you should expose its accelerator. + *
+ * Return the keyboard shortcut string of the control or specified child
+ * in the result
field of the event object. Returning an
+ * empty string tells the client that the control or child does not
+ * have a keyboard shortcut string, and returning null tells the client
+ * to use the platform keyboard shortcut string.
+ *
+ * This is a textual description of the control or child's visual + * appearance, which is typically only necessary if it cannot be + * determined from other properties such as role. + *
+ * Return the description of the control or specified child in
+ * the result
field of the event object. Returning
+ * an empty string tells the client that the control or child
+ * does not have a description, and returning null tells the
+ * client to use the platform description.
+ *
AccessibleControlListener
interface.
+ *
+ * Classes that wish to deal with AccessibleControlEvent
s can
+ * extend this class and override only the methods that they are
+ * interested in.
+ *
+ * Note: Accessibility clients use child identifiers to specify + * whether they want information about a control or one of its children. + * Child identifiers are increasing integers beginning with 0. + * The identifier CHILDID_SELF represents the control itself. + * When returning a child identifier to a client, you may use CHILDID_NONE + * to indicate that no child or control has the required information. + *
+ * Note: This adapter is typically used by implementors of + * a custom control to provide very detailed information about + * the control instance to accessibility clients. + *
+ * + * @see AccessibleControlListener + * @see AccessibleControlEvent + * @see Sample code and further information + * + * @since 2.0 + */ +public abstract class AccessibleControlAdapter : AccessibleControlListener { + + /** + * Sent when an accessibility client requests the identifier + * of the control child at the specified display coordinates. + * The default behavior is to do nothing. + *
+ * Return the identifier of the child at display point (x, y)
+ * in the childID
field of the event object.
+ * Return CHILDID_SELF if point (x, y) is in the control itself
+ * and not in any child. Return CHILDID_NONE if point (x, y)
+ * is not contained in either the control or any of its children.
+ *
+ * Return a rectangle describing the location of the specified
+ * control or child in the x, y, width, and height
+ * fields of the event object.
+ *
+ * Return an Accessible
for the specified control or
+ * child in the accessible
field of the event object.
+ * Return null if the specified child does not have its own
+ * Accessible
.
+ *
+ * Return the number of child items in the detail
+ * field of the event object.
+ *
+ * This string is typically a verb describing what the user does to it. + * For example, a Push Button's default action is "Press", a Check Button's + * is "Check" or "UnCheck", and List items have the default action "Double Click". + *
+ * Return a string describing the default action of the specified
+ * control or child in the result
field of the event object.
+ * Returning null tells the client to use the platform default action string.
+ *
+ * Return the identifier of the child that has focus in the
+ * childID
field of the event object.
+ * Return CHILDID_SELF if the control itself has keyboard focus.
+ * Return CHILDID_NONE if neither the control nor any of its children has focus.
+ *
+ * Return a role constant (constant defined in ACC beginning with ROLE_)
+ * that describes the role of the specified control or child in the
+ * detail
field of the event object.
+ *
+ * Return the identifier of the selected child in the
+ * childID
field of the event object.
+ * Return CHILDID_SELF if the control itself is selected.
+ * Return CHILDID_MULTIPLE if multiple children are selected, and return an array of childIDs in the children
field.
+ * Return CHILDID_NONE if neither the control nor any of its children are selected.
+ *
+ * Return a state mask (mask bit constants defined in ACC beginning with STATE_)
+ * that describes the current state of the specified control or child in the
+ * detail
field of the event object.
+ *
+ * Many controls do not return a value. Examples of controls + * that do are: Combo returns the text string, Text returns + * its contents, ProgressBar returns a string representing a + * percentage, and Tree items return a string representing + * their level in the tree. + *
+ * Return a string describing the value of the specified control
+ * or child in the result
field of the event object.
+ * Returning null tells the client to use the platform value string.
+ *
+ * Return the children as an array of childIDs in the children
+ * field of the event object.
+ *
+ * Note: The meaning of each field depends on the + * message that was sent. + *
+ * + * @see AccessibleControlListener + * @see AccessibleControlAdapter + * @see Sample code and further information + * + * @since 2.0 + */ +public class AccessibleControlEvent : SWTEventObject { + public int childID; // IN/OUT + public Accessible accessible; // OUT + public int x, y; // IN/OUT + public int width, height; // OUT + public int detail; // IN/OUT + public String result; // OUT + public Object children[]; // [OUT] + + //static final long serialVersionUID = 3257281444169529141L; + +/** + * Constructs a new instance of this class. + * + * @param source the object that fired the event + */ +public this(Object source) { + super(source); +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the event + */ +public String toString () { + return Format( "AccessibleControlEvent {childID={} accessible={} x={} y={} width={} heigth={} detail={} result={}", + childID, accessible, x, y, width, height, detail, result); +} +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleControlListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleControlListener.d Mon Mar 02 14:44:16 2009 +0100 @@ -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 + * Port to the D programming language: + * Frank Benoit
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * addAccessibleControlListener
method and removed
+ * using the removeAccessibleControlListener
method.
+ * When a client requests information the appropriate method
+ * will be invoked.
+ *
+ * Note: Accessibility clients use child identifiers to specify + * whether they want information about a control or one of its children. + * Child identifiers are increasing integers beginning with 0. + * The identifier CHILDID_SELF represents the control itself. + *
+ * Note: This interface is typically used by implementors of + * a custom control to provide very detailed information about + * the control instance to accessibility clients. + *
+ * + * @see AccessibleControlAdapter + * @see AccessibleControlEvent + * + * @since 2.0 + */ +public interface AccessibleControlListener : SWTEventListener { + + /** + * Sent when an accessibility client requests the identifier + * of the control child at the specified display coordinates. + *
+ * Return the identifier of the child at display point (x, y)
+ * in the childID
field of the event object.
+ * Return CHILDID_SELF if point (x, y) is in the control itself
+ * and not in any child. Return CHILDID_NONE if point (x, y)
+ * is not contained in either the control or any of its children.
+ *
+ * Return a rectangle describing the location of the specified
+ * control or child in the x, y, width, and height
+ * fields of the event object.
+ *
+ * Return an Accessible
for the specified control or
+ * child in the accessible
field of the event object.
+ * Return null if the specified child does not have its own
+ * Accessible
.
+ *
+ * Return the number of child items in the detail
+ * field of the event object.
+ *
+ * This string is typically a verb describing what the user does to it. + * For example, a Push Button's default action is "Press", a Check Button's + * is "Check" or "UnCheck", and List items have the default action "Double Click". + *
+ * Return a string describing the default action of the specified
+ * control or child in the result
field of the event object.
+ * Returning null tells the client to use the platform default action string.
+ *
+ * Return the identifier of the child that has focus in the
+ * childID
field of the event object.
+ * Return CHILDID_SELF if the control itself has keyboard focus.
+ * Return CHILDID_NONE if neither the control nor any of its children has focus.
+ *
+ * Return a role constant (constant defined in ACC beginning with ROLE_)
+ * that describes the role of the specified control or child in the
+ * detail
field of the event object.
+ *
+ * Return the identifier of the selected child in the
+ * childID
field of the event object.
+ * Return CHILDID_SELF if the control itself is selected.
+ * Return CHILDID_MULTIPLE if multiple children are selected, and return an array of childIDs in the children
field.
+ * Return CHILDID_NONE if neither the control nor any of its children are selected.
+ *
+ * Return a state mask (mask bit constants defined in ACC beginning with STATE_)
+ * that describes the current state of the specified control or child in the
+ * detail
field of the event object.
+ *
+ * Many controls do not return a value. Examples of controls + * that do are: Combo returns the text string, Text returns + * its contents, ProgressBar returns a string representing a + * percentage, and Tree items return a string representing + * their level in the tree. + *
+ * Return a string describing the value of the specified control
+ * or child in the result
field of the event object.
+ * Returning null tells the client to use the platform value string.
+ *
+ * Return the children as an array of childIDs in the children
+ * field of the event object.
+ *
+ * Note: The meaning of the result field depends + * on the message that was sent. + *
+ * + * @see AccessibleListener + * @see AccessibleAdapter + * @see Sample code and further information + * + * @since 2.0 + */ +public class AccessibleEvent : SWTEventObject { + /** + * The value of this field is set by an accessibility client + * before the accessible listener method is called. + * ChildID can be CHILDID_SELF, representing the control itself, + * or a 0-based integer representing a specific child of the control. + */ + public int childID; + + /** + * The value of this field must be set in the accessible listener + * method before returning. + * What to set it to depends on the listener method called, and + * the childID specified by the client. + */ + public String result; + + //static final long serialVersionUID = 3257567304224026934L; + +/** + * Constructs a new instance of this class. + * + * @param source the object that fired the event + */ +public this(Object source) { + super(source); +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the event + */ +override public String toString () { + return Format( "AccessibleEvent {childID={} result={}}", childID, result ); +} +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleListener.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,129 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * addAccessibleListener
method and removed
+ * using the removeAccessibleListener
method.
+ * When a client requests information, the appropriate method
+ * will be invoked.
+ *
+ * Note: Accessibility clients use child identifiers to specify + * whether they want information about a control or one of its children. + * Child identifiers are increasing integers beginning with 0. + * The identifier CHILDID_SELF represents the control itself. + *
+ * + * @see AccessibleAdapter + * @see AccessibleEvent + * + * @since 2.0 + */ +public interface AccessibleListener : SWTEventListener { + + /** + * Sent when an accessibility client requests the name + * of the control, or the name of a child of the control. + *
+ * Return the name of the control or specified child in the
+ * result
field of the event object. Returning
+ * an empty string tells the client that the control or child
+ * does not have a name, and returning null tells the client
+ * to use the platform name.
+ *
+ * The information in this property should be similar to the help + * provided by toolTipText. It describes what the control or child + * does or how to use it, as opposed to getDescription, which + * describes appearance. + *
+ * Return the help string of the control or specified child in
+ * the result
field of the event object. Returning
+ * an empty string tells the client that the control or child
+ * does not have a help string, and returning null tells the
+ * client to use the platform help string.
+ *
+ * A keyboard shortcut can either be a mnemonic, or an accelerator. + * As a general rule, if the control or child can receive keyboard focus, + * then you should expose its mnemonic, and if it cannot receive keyboard + * focus, then you should expose its accelerator. + *
+ * Return the keyboard shortcut string of the control or specified child
+ * in the result
field of the event object. Returning an
+ * empty string tells the client that the control or child does not
+ * have a keyboard shortcut string, and returning null tells the client
+ * to use the platform keyboard shortcut string.
+ *
+ * This is a textual description of the control or child's visual + * appearance, which is typically only necessary if it cannot be + * determined from other properties such as role. + *
+ * Return the description of the control or specified child in
+ * the result
field of the event object. Returning
+ * an empty string tells the client that the control or child
+ * does not have a description, and returning null tells the
+ * client to use the platform description.
+ *
AccessibleTextListener
interface.
+ *
+ * Classes that wish to deal with AccessibleTextEvent
s can
+ * extend this class and override only the methods that they are
+ * interested in.
+ *
+ * Note: Accessibility clients use child identifiers to specify + * whether they want information about a control or one of its children. + * Child identifiers are increasing integers beginning with 0. + * The identifier CHILDID_SELF represents the control itself. + * When returning a child identifier to a client, you may use CHILDID_NONE + * to indicate that no child or control has the required information. + *
+ * Note: This adapter is typically used by implementors of + * a custom control to provide very detailed information about + * the control instance to accessibility clients. + *
+ * + * @see AccessibleTextListener + * @see AccessibleTextEvent + * @see Sample code and further information + * + * @since 3.0 + */ +public abstract class AccessibleTextAdapter : AccessibleTextListener { + + /** + * Sent when an accessibility client requests the current character offset + * of the text caret. + * The default behavior is to do nothing. + *
+ * Return the caret offset in the offset
+ * field of the event object.
+ *
+ * Return the selection start offset and non-negative length in the
+ * offset
and length
fields of the event object.
+ *
+ * Note: The meaning of each field depends on the + * message that was sent. + *
+ * + * @see AccessibleTextListener + * @see AccessibleTextAdapter + * @see Sample code and further information + * + * @since 3.0 + */ +public class AccessibleTextEvent : SWTEventObject { + public int childID; // IN + public int offset, length; // OUT + + //static final long serialVersionUID = 3977019530868308275L; + +/** + * Constructs a new instance of this class. + * + * @param source the object that fired the event + */ +public this (Object source) { + super (source); +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the event + */ +override public String toString () { + return Format( "AccessibleTextEvent {{childID={} offset={} length={}}", + childID, + offset, + length); +} +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleTextListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleTextListener.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,78 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * addAccessibleTextListener
method and removed
+ * using the removeAccessibleTextListener
method.
+ * When a client requests information the appropriate method
+ * will be invoked.
+ *
+ * Note: Accessibility clients use child identifiers to specify + * whether they want information about a control or one of its children. + * Child identifiers are increasing integers beginning with 0. + * The identifier CHILDID_SELF represents the control itself. + *
+ * Note: This interface is typically used by implementors of + * a custom control to provide very detailed information about + * the control instance to accessibility clients. + *
+ * + * @see AccessibleTextAdapter + * @see AccessibleTextEvent + * + * @since 3.0 + */ +public interface AccessibleTextListener : SWTEventListener { + + /** + * Sent when an accessibility client requests the current character offset + * of the text caret. + *
+ * Return the caret offset in the offset
+ * field of the event object.
+ *
+ * Return the selection start offset and non-negative length in the
+ * offset
and length
fields of the event object.
+ *
+ * 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.
+ *
+ * The elements in the segments field specify the start offset of + * a segment relative to the start of the line. They must follow + * the following rules: + *
+ * stored line = "R1R2R3" + "R4R5R6" + * R1 to R6 are right-to-left characters. The quotation marks + * are part of the line text. The line is 13 characters long. + * + * segments = null: + * entire line will be reordered and thus the two R2L segments + * swapped (as per the bidi algorithm). + * visual line (rendered on screen) = "R6R5R4" + "R3R2R1" + * + * segments = [0, 5, 8] + * "R1R2R3" will be reordered, followed by [blank]+[blank] and + * "R4R5R6". + * visual line = "R3R2R1" + "R6R5R4" + *+ * + * @see Sample code and further information + */ +public class BidiSegmentEvent : TypedEvent { + + /** + * line start offset + */ + public int lineOffset; + + /** + * line text + */ + public String lineText; + + /** + * bidi segments, see above + */ + public int[] segments; + +this(StyledTextEvent e) { + super(cast(Object)e); + lineOffset = e.detail; + lineText = e.text; +} +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/BidiSegmentListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/BidiSegmentListener.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,43 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit
+ * The following event fields are used:
StyledText
.
+ * + * The hashCode() method in this class uses the values of the public + * fields to compute the hash value. When storing instances of the + * class in hashed collections, do not modify these fields after the + * object has been inserted. + *
+ *
+ * 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.
+ *
ST.BULLET_DOT
ST.BULLET_NUMBER
ST.BULLET_LETTER_LOWER
ST.BULLET_LETTER_UPPER
ST.BULLET_TEXT
ST.BULLET_CUSTOM
ST.BULLET_DOT
.
+ * The style must have a glyph metrics set.
+ *
+ * @param style the style
+ *
+ * @exception IllegalArgumentException Runnable
while providing
+ * busy feedback using this busy indicator.
+ *
+ * @param display the display on which the busy feedback should be
+ * displayed. If the display is null, the Display for the current
+ * thread will be used. If there is no Display for the current thread,
+ * the runnable code will be executed and no busy feedback will be displayed.
+ * @param runnable the runnable for which busy feedback is to be shown.
+ * Must not be null.
+ *
+* @exception IllegalArgumentException
+ * 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. + *
+ * + * @see Sample code and further information + * + * @since 3.0 + */ + +public class CBanner : Composite { + + Control left; + Control right; + Control bottom; + + bool simple = true; + + int[] curve; + int curveStart = 0; + Rectangle curveRect; + int curve_width = 5; + int curve_indent = -2; + + int rightWidth = SWT.DEFAULT; + int rightMinWidth = 0; + int rightMinHeight = 0; + Cursor resizeCursor; + bool dragging = false; + int rightDragDisplacement = 0; + + static const int OFFSCREEN = -200; + static const int BORDER_BOTTOM = 2; + static const int BORDER_TOP = 3; + static const int BORDER_STRIPE = 1; + static const int CURVE_TAIL = 200; + static const int BEZIER_RIGHT = 30; + static const int BEZIER_LEFT = 30; + static const int MIN_LEFT = 10; + static int BORDER1 = SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW; + + +/** + * 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.
+ *
true
if the CBanner is rendered
+ * with a simple, traditional shape.
+ *
+ * @return true
if the CBanner is rendered with a simple shape
+ *
+ * @since 3.0
+ */
+public bool getSimple() {
+ checkWidget();
+ return simple;
+}
+void onDispose() {
+ if (resizeCursor !is null) resizeCursor.dispose();
+ resizeCursor = null;
+ left = null;
+ right = null;
+ bottom = null;
+}
+void onMouseDown (int x, int y) {
+ if (curveRect.contains(x, y)) {
+ dragging = true;
+ rightDragDisplacement = curveStart - x + curve_width - curve_indent;
+ }
+}
+void onMouseExit() {
+ if (!dragging) setCursor(null);
+}
+void onMouseMove(int x, int y) {
+ if (dragging) {
+ Point size = getSize();
+ if (!(0 < x && x < size.x)) return;
+ rightWidth = Math.max(0, size.x - x - rightDragDisplacement);
+ if (rightMinWidth is SWT.DEFAULT) {
+ Point minSize = right.computeSize(rightMinWidth, rightMinHeight);
+ rightWidth = Math.max(minSize.x, rightWidth);
+ } else {
+ rightWidth = Math.max(rightMinWidth, rightWidth);
+ }
+ layout(false);
+ return;
+ }
+ if (curveRect.contains(x, y)) {
+ setCursor(resizeCursor);
+ } else {
+ setCursor(null);
+ }
+}
+void onMouseUp () {
+ dragging = false;
+}
+void onPaint(GC gc) {
+// Useful for debugging paint problems
+// {
+// Point size = getSize();
+// gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GREEN));
+// gc.fillRectangle(-10, -10, size.x+20, size.y+20);
+// }
+ if (left is null && right is null) return;
+ Point size = getSize();
+ Color border1 = getDisplay().getSystemColor(BORDER1);
+ if (bottom !is null) {
+ int y = bottom.getBounds().y - BORDER_STRIPE - 1;
+ gc.setForeground(border1);
+ gc.drawLine(0, y, size.x, y);
+ }
+ if (left is null || right is null) return;
+ int[] line1 = new int[curve.length+6];
+ int index = 0;
+ int x = curveStart;
+ line1[index++] = x + 1;
+ line1[index++] = size.y - BORDER_STRIPE;
+ for (int i = 0; i < curve.length/2; i++) {
+ line1[index++]=x+curve[2*i];
+ line1[index++]=curve[2*i+1];
+ }
+ line1[index++] = x + curve_width;
+ line1[index++] = 0;
+ line1[index++] = size.x;
+ line1[index++] = 0;
+
+ Color background = getBackground();
+
+ if (getDisplay().getDepth() >= 15) {
+ // Anti- aliasing
+ int[] line2 = new int[line1.length];
+ index = 0;
+ for (int i = 0; i < line1.length/2; i++) {
+ line2[index] = line1[index++] - 1;
+ line2[index] = line1[index++];
+ }
+ int[] line3 = new int[line1.length];
+ index = 0;
+ for (int i = 0; i < line1.length/2; i++) {
+ line3[index] = line1[index++] + 1;
+ line3[index] = line1[index++];
+ }
+ RGB from = border1.getRGB();
+ RGB to = background.getRGB();
+ int red = from.red + 3*(to.red - from.red)/4;
+ int green = from.green + 3*(to.green - from.green)/4;
+ int blue = from.blue + 3*(to.blue - from.blue)/4;
+ Color color = new Color(getDisplay(), red, green, blue);
+ gc.setForeground(color);
+ gc.drawPolyline(line2);
+ gc.drawPolyline(line3);
+ color.dispose();
+
+ // draw tail fading to background
+ int x1 = Math.max(0, curveStart - CURVE_TAIL);
+ gc.setForeground(background);
+ gc.setBackground(border1);
+ gc.fillGradientRectangle(x1, size.y - BORDER_STRIPE, curveStart-x1+1, 1, false);
+ } else {
+ // draw solid tail
+ int x1 = Math.max(0, curveStart - CURVE_TAIL);
+ gc.setForeground(border1);
+ gc.drawLine(x1, size.y - BORDER_STRIPE, curveStart+1, size.y - BORDER_STRIPE);
+ }
+
+ // draw border
+ gc.setForeground(border1);
+ gc.drawPolyline(line1);
+}
+
+void onResize() {
+ updateCurve(getSize().y);
+}
+/**
+* Set the control that appears on the bottom side of the banner.
+* The bottom control is optional. Setting the bottom control to null will remove it from
+* the banner - however, the creator of the control must dispose of the control.
+*
+* @param control the control to be displayed on the bottom or null
+*
+* @exception SWTException + * Note: No Layout can be set on this Control because it already + * manages the size and position of its children. + *
+ * + * @param layout the receiver's new layout or null + * + * @exception SWTExceptiontrue
if the CBanner should render itself in a simple, traditional style
+ *
+ * @exception SWTException + * CCombo was written to work around certain limitations in the native + * combo box. Specifically, on win32, the height of a CCombo can be set; + * attempts to set the height of a Combo are ignored. CCombo can be used + * anywhere that having the increased flexibility is more important than + * getting native L&F, but the decision should not be taken lightly. + * There is no is no strict requirement that CCombo look or behave + * the same as the native combo box. + *
+ *
+ * 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.
+ *
+ * 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: To add an item at the end of the list, use the
+ * result of calling getItemCount()
as the
+ * index or use add(String)
.
+ *
ModifyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException 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.
+ *
VerifyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ * Note: To clear the selected items in the receiver's list,
+ * use deselectAll()
.
+ *
+ * The current selection is copied to the clipboard. + *
+ * + * @exception SWTException
+ * Note: To clear the selection in the receiver's text field,
+ * use clearSelection()
.
+ *
String
s 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 SWTExceptiontrue
if the receiver's list 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 list's visibility state + * + * @exception SWTExceptionPoint
whose x coordinate is the start
+ * of the selection in the receiver's text field, and whose y
+ * coordinate is the end of the selection. The returned values
+ * are zero-relative. An "empty" selection as indicated by
+ * the the x and y coordinates having the same value.
+ *
+ * @return a point representing the selection start and end
+ *
+ * @exception SWTException setTextLimit()
, it will be the constant
+ * Combo.LIMIT
.
+ *
+ * @return the text limit
+ *
+ * @exception SWTException + * The selected text is deleted from the widget + * and new text inserted from the clipboard. + *
+ * + * @exception SWTException+ * @exception SWTException
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 + * Note: No Layout can be set on this Control because it already + * manages the size and position of its children. + *
+ * + * @param layout the receiver's new layout or null + * + * @exception SWTExceptiontrue
,
+ * 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
+ * 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.
+ *
+ * If there is not enough space a CLabel uses the following strategy to fit the + * information into the available space: + *
+ * ignores the indent in left align mode + * ignores the image and the gap + * shortens the text by replacing the center portion of the label with an ellipsis + * shortens the text by removing the center portion of the label + *+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see SWT Example: CustomControlExample + * @see Sample code and further information + */ +public class CLabel : Canvas { + + alias Canvas.computeSize computeSize; + + /** Gap between icon and text */ + private static const int GAP = 5; + /** Left and right margins */ + private static const int INDENT = 3; + /** a string inserted in the middle of text that has been shortened */ + private static const String ELLIPSIS = "..."; //$NON-NLS-1$ // could use the ellipsis glyph on some platforms "\u2026" + /** the alignment. Either CENTER, RIGHT, LEFT. Default is LEFT*/ + private int align_ = SWT.LEFT; + private int hIndent = INDENT; + private int vIndent = INDENT; + /** the current text */ + private String text; + /** the current icon */ + private Image image; + // The tooltip is used for two purposes - the application can set + // a tooltip or the tooltip can be used to display the full text when the + // the text has been truncated due to the label being too short. + // The appToolTip stores the tooltip set by the application. Control.tooltiptext + // contains whatever tooltip is currently being displayed. + private String appToolTipText; + + private Image backgroundImage; + private Color[] gradientColors; + private int[] gradientPercents; + private bool gradientVertical; + private Color background; + + private static int DRAW_FLAGS = SWT.DRAW_MNEMONIC | SWT.DRAW_TAB | SWT.DRAW_TRANSPARENT | SWT.DRAW_DELIMITER; + +/** + * 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.
+ *
null
.
+ *
+ * @return the image of the label or null
+ */
+public Image getImage() {
+ //checkWidget();
+ return image;
+}
+/**
+ * Compute the minimum size.
+ */
+private Point getTotalSize(Image image, String text) {
+ Point size = new Point(0, 0);
+
+ if (image !is null) {
+ Rectangle r = image.getBounds();
+ size.x += r.width;
+ size.y += r.height;
+ }
+
+ GC gc = new GC(this);
+ if (text !is null && text.length > 0) {
+ Point e = gc.textExtent(text, DRAW_FLAGS);
+ size.x += e.x;
+ size.y = Math.max(size.y, e.y);
+ if (image !is null) size.x += GAP;
+ } else {
+ size.y = Math.max(size.y, gc.getFontMetrics().getHeight());
+ }
+ gc.dispose();
+
+ return size;
+}
+public override int getStyle () {
+ int style = super.getStyle();
+ switch (align_) {
+ case SWT.RIGHT: style |= SWT.RIGHT; break;
+ case SWT.CENTER: style |= SWT.CENTER; break;
+ case SWT.LEFT: style |= SWT.LEFT; break;
+ default:
+ }
+ return style;
+}
+
+/**
+ * Return the Label's text.
+ *
+ * @return the text of the label or null
+ */
+public String getText() {
+ //checkWidget();
+ return text;
+}
+public override String getToolTipText () {
+ checkWidget();
+ return appToolTipText;
+}
+private void initAccessible() {
+ Accessible accessible = getAccessible();
+ accessible.addAccessibleListener(new class() AccessibleAdapter {
+ public void getName(AccessibleEvent e) {
+ e.result = getText();
+ }
+
+ public void getHelp(AccessibleEvent e) {
+ e.result = getToolTipText();
+ }
+
+ public void getKeyboardShortcut(AccessibleEvent e) {
+ dchar mnemonic = _findMnemonic(this.outer.text);
+ if (mnemonic !is '\0') {
+ dchar[1] d;
+ d[0] = mnemonic;
+ e.result = "Alt+" ~ tango.text.convert.Utf.toString(d); //$NON-NLS-1$
+ }
+ }
+ });
+
+ accessible.addAccessibleControlListener(new class() AccessibleControlAdapter {
+ public void getChildAtPoint(AccessibleControlEvent e) {
+ e.childID = ACC.CHILDID_SELF;
+ }
+
+ public void getLocation(AccessibleControlEvent e) {
+ Rectangle rect = getDisplay().map(getParent(), null, getBounds());
+ e.x = rect.x;
+ e.y = rect.y;
+ e.width = rect.width;
+ e.height = rect.height;
+ }
+
+ public void getChildCount(AccessibleControlEvent e) {
+ e.detail = 0;
+ }
+
+ public void getRole(AccessibleControlEvent e) {
+ e.detail = ACC.ROLE_LABEL;
+ }
+
+ public void getState(AccessibleControlEvent e) {
+ e.detail = ACC.STATE_READONLY;
+ }
+ });
+}
+void onDispose(DisposeEvent event) {
+ gradientColors = null;
+ gradientPercents = null;
+ backgroundImage = null;
+ text = null;
+ image = null;
+ appToolTipText = null;
+}
+void onMnemonic(TraverseEvent event) {
+ dchar mnemonic = _findMnemonic(text);
+ if (mnemonic is '\0') return;
+ dchar[1] d; uint ate;
+ auto r = tango.text.convert.Utf.toString32( [event.character][], d, &ate );
+ if (tango.text.Unicode.toLower(r)[0] !is mnemonic) return;
+ Composite control = this.getParent();
+ while (control !is null) {
+ Control [] children = control.getChildren();
+ int index = 0;
+ while (index < children.length) {
+ if (children [index] is this) break;
+ index++;
+ }
+ index++;
+ if (index < children.length) {
+ if (children [index].setFocus ()) {
+ event.doit = true;
+ event.detail = SWT.TRAVERSE_NONE;
+ }
+ }
+ control = control.getParent();
+ }
+}
+
+void onPaint(PaintEvent event) {
+ Rectangle rect = getClientArea();
+ if (rect.width is 0 || rect.height is 0) return;
+
+ bool shortenText_ = false;
+ String t = text;
+ Image img = image;
+ int availableWidth = Math.max(0, rect.width - 2*hIndent);
+ Point extent = getTotalSize(img, t);
+ if (extent.x > availableWidth) {
+ img = null;
+ extent = getTotalSize(img, t);
+ if (extent.x > availableWidth) {
+ shortenText_ = true;
+ }
+ }
+
+ GC gc = event.gc;
+ String[] lines = text is null ? null : splitString(text);
+
+ // shorten the text
+ if (shortenText_) {
+ extent.x = 0;
+ for(int i = 0; i < lines.length; i++) {
+ Point e = gc.textExtent(lines[i], DRAW_FLAGS);
+ if (e.x > availableWidth) {
+ lines[i] = shortenText(gc, lines[i], availableWidth);
+ extent.x = Math.max(extent.x, getTotalSize(null, lines[i]).x);
+ } else {
+ extent.x = Math.max(extent.x, e.x);
+ }
+ }
+ if (appToolTipText is null) {
+ super.setToolTipText(text);
+ }
+ } else {
+ super.setToolTipText(appToolTipText);
+ }
+
+ // determine horizontal position
+ int x = rect.x + hIndent;
+ if (align_ is SWT.CENTER) {
+ x = (rect.width - extent.x)/2;
+ }
+ if (align_ is SWT.RIGHT) {
+ x = rect.width - hIndent - extent.x;
+ }
+
+ // draw a background image behind the text
+ try {
+ if (backgroundImage !is null) {
+ // draw a background image behind the text
+ Rectangle imageRect = backgroundImage.getBounds();
+ // tile image to fill space
+ gc.setBackground(getBackground());
+ gc.fillRectangle(rect);
+ int xPos = 0;
+ while (xPos < rect.width) {
+ int yPos = 0;
+ while (yPos < rect.height) {
+ gc.drawImage(backgroundImage, xPos, yPos);
+ yPos += imageRect.height;
+ }
+ xPos += imageRect.width;
+ }
+ } else if (gradientColors !is null) {
+ // draw a gradient behind the text
+ final Color oldBackground = gc.getBackground();
+ if (gradientColors.length is 1) {
+ if (gradientColors[0] !is null) gc.setBackground(gradientColors[0]);
+ gc.fillRectangle(0, 0, rect.width, rect.height);
+ } else {
+ final Color oldForeground = gc.getForeground();
+ Color lastColor = gradientColors[0];
+ if (lastColor is null) lastColor = oldBackground;
+ int pos = 0;
+ for (int i = 0; i < gradientPercents.length; ++i) {
+ gc.setForeground(lastColor);
+ lastColor = gradientColors[i + 1];
+ if (lastColor is null) lastColor = oldBackground;
+ gc.setBackground(lastColor);
+ if (gradientVertical) {
+ final int gradientHeight = (gradientPercents[i] * rect.height / 100) - pos;
+ gc.fillGradientRectangle(0, pos, rect.width, gradientHeight, true);
+ pos += gradientHeight;
+ } else {
+ final int gradientWidth = (gradientPercents[i] * rect.width / 100) - pos;
+ gc.fillGradientRectangle(pos, 0, gradientWidth, rect.height, false);
+ pos += gradientWidth;
+ }
+ }
+ if (gradientVertical && pos < rect.height) {
+ gc.setBackground(getBackground());
+ gc.fillRectangle(0, pos, rect.width, rect.height - pos);
+ }
+ if (!gradientVertical && pos < rect.width) {
+ gc.setBackground(getBackground());
+ gc.fillRectangle(pos, 0, rect.width - pos, rect.height);
+ }
+ gc.setForeground(oldForeground);
+ }
+ gc.setBackground(oldBackground);
+ } else {
+ if (background !is null || (getStyle() & SWT.DOUBLE_BUFFERED) is 0) {
+ gc.setBackground(getBackground());
+ gc.fillRectangle(rect);
+ }
+ }
+ } catch (SWTException e) {
+ if ((getStyle() & SWT.DOUBLE_BUFFERED) is 0) {
+ gc.setBackground(getBackground());
+ gc.fillRectangle(rect);
+ }
+ }
+
+ // draw border
+ int style = getStyle();
+ if ((style & SWT.SHADOW_IN) !is 0 || (style & SWT.SHADOW_OUT) !is 0) {
+ paintBorder(gc, rect);
+ }
+
+ // draw the image
+ if (img !is null) {
+ Rectangle imageRect = img.getBounds();
+ gc.drawImage(img, 0, 0, imageRect.width, imageRect.height,
+ x, (rect.height-imageRect.height)/2, imageRect.width, imageRect.height);
+ x += imageRect.width + GAP;
+ extent.x -= imageRect.width + GAP;
+ }
+ // draw the text
+ if (lines !is null) {
+ int lineHeight = gc.getFontMetrics().getHeight();
+ int textHeight = lines.length * lineHeight;
+ int lineY = Math.max(vIndent, rect.y + (rect.height - textHeight) / 2);
+ gc.setForeground(getForeground());
+ for (int i = 0; i < lines.length; i++) {
+ int lineX = x;
+ if (lines.length > 1) {
+ if (align_ is SWT.CENTER) {
+ int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
+ lineX = x + Math.max(0, (extent.x - lineWidth) / 2);
+ }
+ if (align_ is SWT.RIGHT) {
+ int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
+ lineX = Math.max(x, rect.x + rect.width - hIndent - lineWidth);
+ }
+ }
+ gc.drawText(lines[i], lineX, lineY, DRAW_FLAGS);
+ lineY += lineHeight;
+ }
+ }
+}
+/**
+ * Paint the Label's border.
+ */
+private void paintBorder(GC gc, Rectangle r) {
+ Display disp= getDisplay();
+
+ Color c1 = null;
+ Color c2 = null;
+
+ int style = getStyle();
+ if ((style & SWT.SHADOW_IN) !is 0) {
+ c1 = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+ c2 = disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
+ }
+ if ((style & SWT.SHADOW_OUT) !is 0) {
+ c1 = disp.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
+ c2 = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+ }
+
+ if (c1 !is null && c2 !is null) {
+ gc.setLineWidth(1);
+ drawBevelRect(gc, r.x, r.y, r.width-1, r.height-1, c1, c2);
+ }
+}
+/**
+ * Set the alignment of the CLabel.
+ * Use the values LEFT, CENTER and RIGHT to align image and text within the available space.
+ *
+ * @param align the alignment style of LEFT, RIGHT or CENTER
+ *
+ * @exception SWTException For example, to draw a gradient that varies from dark blue to blue and then to + * white and stays white for the right half of the label, use the following call + * to setBackground:
+ *+ * clabel.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE), + * display.getSystemColor(SWT.COLOR_BLUE), + * display.getSystemColor(SWT.COLOR_WHITE), + * display.getSystemColor(SWT.COLOR_WHITE)}, + * new int[] {25, 50, 100}); + *+ * + * @param colors an array of Color that specifies the colors to appear in the gradient + * in order of appearance from left to right; The value
null
+ * clears the background gradient; the value null
can be used
+ * inside the array of Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ * of the widget at which the color should change; the size of the percents
+ * array must be one less than the size of the colors array.
+ *
+ * @exception SWTException For example, to draw a gradient that varies from dark blue to white in the vertical, + * direction use the following call + * to setBackground:
+ *+ * clabel.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE), + * display.getSystemColor(SWT.COLOR_WHITE)}, + * new int[] {100}, true); + *+ * + * @param colors an array of Color that specifies the colors to appear in the gradient + * in order of appearance from left/top to right/bottom; The value
null
+ * clears the background gradient; the value null
can be used
+ * inside the array of Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width/height
+ * of the widget at which the color should change; the size of the percents
+ * array must be one less than the size of the colors array.
+ * @param vertical indicate the direction of the gradient. True is vertical and false is horizontal.
+ *
+ * @exception SWTException null
clears it.
+ *
+ * @param image the image to be displayed in the label or null
+ *
+ * @exception SWTException null
clears it.
+ *
+ * @param text the text to be displayed in the label or null
+ *
+ * @exception SWTException t
so that its length doesn't exceed
+ * the given width. The default implementation replaces characters in the
+ * center of the original string with an ellipsis ("...").
+ * Override if you need a different strategy.
+ *
+ * @param gc the gc to use for text measurement
+ * @param t the text to shorten
+ * @param width the width to shorten the text to, in pixels
+ * @return the shortened text
+ */
+protected String shortenText(GC gc, String t, int width) {
+ if (t is null) return null;
+ int w = gc.textExtent(ELLIPSIS, DRAW_FLAGS).x;
+ if (width<=w) return t;
+ int l = t.length;
+ int max = l/2;
+ int min = 0;
+ int mid = (max+min)/2 - 1;
+ if (mid <= 0) return t;
+ TextLayout layout = new TextLayout (getDisplay());
+ layout.setText(t);
+ mid = validateOffset(layout, mid);
+ while (min < mid && mid < max) {
+ String s1 = t[0 .. mid].dup;
+ String s2 = t.substring(validateOffset(layout, l-mid), l);
+ int l1 = gc.textExtent(s1, DRAW_FLAGS).x;
+ int l2 = gc.textExtent(s2, DRAW_FLAGS).x;
+ if (l1+w+l2 > width) {
+ max = mid;
+ mid = validateOffset(layout, (max+min)/2);
+ } else if (l1+w+l2 < width) {
+ min = mid;
+ mid = validateOffset(layout, (max+min)/2);
+ } else {
+ min = max;
+ }
+ }
+ String result = mid is 0 ? t : t.substring(0, mid) ~ ELLIPSIS ~ t.substring(validateOffset(layout, l-mid), l);
+ layout.dispose();
+ return result;
+}
+int validateOffset(TextLayout layout, int offset) {
+ int nextOffset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER);
+ if (nextOffset !is offset) return layout.getPreviousOffset(nextOffset, SWT.MOVEMENT_CLUSTER);
+ return offset;
+}
+private String[] splitString(String text) {
+ String[] lines = new String[1];
+ int start = 0, pos;
+ do {
+ pos = tango.text.Util.locate( text, '\n', start);
+ if (pos is text.length ) {
+ lines[lines.length - 1] = text[start .. $ ];
+ } else {
+ bool crlf = (pos > 0) && (text[ pos - 1 ] is '\r');
+ lines[lines.length - 1] = text[ start .. pos - (crlf ? 1 : 0)];
+ start = pos + 1;
+ String[] newLines = new String[lines.length+1];
+ System.arraycopy(lines, 0, newLines, 0, lines.length);
+ lines = newLines;
+ }
+ } while (pos !is text.length);
+ return lines;
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CLayoutData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CLayoutData.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * The item children that may be added to instances of this class
+ * must be of type CTabItem
.
+ * Control
children are created and then set into a
+ * tab item using CTabItem#setControl
.
+ *
+ * Note that although this class is a subclass of Composite
,
+ * it does not make sense to set a layout on it.
+ *
+ *
+ * Note: Only one of the styles TOP and BOTTOM + * may be specified. + *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see CTabFolder, CTabItem snippets + * @see SWT Example: CustomControlExample + * @see Sample code and further information + */ + +public class CTabFolder : Composite { + + /** + * marginWidth specifies the number of pixels of horizontal margin + * that will be placed along the left and right edges of the form. + * + * The default value is 0. + */ + public int marginWidth = 0; + /** + * marginHeight specifies the number of pixels of vertical margin + * that will be placed along the top and bottom edges of the form. + * + * The default value is 0. + */ + public int marginHeight = 0; + + /** + * A multiple of the tab height that specifies the minimum width to which a tab + * will be compressed before scrolling arrows are used to navigate the tabs. + * + * NOTE This field is badly named and can not be fixed for backwards compatibility. + * It should not be capitalized. + * + * @deprecated This field is no longer used. See setMinimumCharacters(int) + */ + public int MIN_TAB_WIDTH = 4; + + /** + * Color of innermost line of drop shadow border. + * + * NOTE This field is badly named and can not be fixed for backwards compatibility. + * It should be capitalized. + * + * @deprecated drop shadow border is no longer drawn in 3.0 + */ + public static RGB borderInsideRGB; + /** + * Color of middle line of drop shadow border. + * + * NOTE This field is badly named and can not be fixed for backwards compatibility. + * It should be capitalized. + * + * @deprecated drop shadow border is no longer drawn in 3.0 + */ + public static RGB borderMiddleRGB; + /** + * Color of outermost line of drop shadow border. + * + * NOTE This field is badly named and can not be fixed for backwards compatibility. + * It should be capitalized. + * + * @deprecated drop shadow border is no longer drawn in 3.0 + */ + public static RGB borderOutsideRGB; + + /* sizing, positioning */ + int xClient, yClient; + bool onBottom = false; + bool single = false; + bool simple = true; + int fixedTabHeight = SWT.DEFAULT; + int tabHeight; + int minChars = 20; + + /* item management */ + CTabItem items[]; + int firstIndex = -1; // index of the left most visible tab. + int selectedIndex = -1; + int[] priority; + bool mru = false; + Listener listener; + + /* External Listener management */ + CTabFolder2Listener[] folderListeners; + // support for deprecated listener mechanism + CTabFolderListener[] tabListeners; + + /* Selected item appearance */ + Image selectionBgImage; + Color[] selectionGradientColors; + int[] selectionGradientPercents; + bool selectionGradientVertical; + Color selectionForeground; + Color selectionBackground; //selection fade end + Color selectionFadeStart; + + Color selectionHighlightGradientBegin = null; //null is no highlight + //Although we are given new colours all the time to show different states (active, etc), + //some of which may have a highlight and some not, we'd like to retain the highlight colours + //as a cache so that we can reuse them if we're again told to show the highlight. + //We are relying on the fact that only one tab state usually gets a highlight, so only + //a single cache is required. If that happens to not be true, cache simply becomes less effective, + //but we don't leak colours. + Color[] selectionHighlightGradientColorsCache = null; //null is a legal value, check on access + + /* Unselected item appearance */ + Image bgImage; + Color[] gradientColors; + int[] gradientPercents; + bool gradientVertical; + bool showUnselectedImage = true; + + static Color borderColor; + + // close, min/max and chevron buttons + bool showClose = false; + bool showUnselectedClose = true; + + Rectangle chevronRect; + int chevronImageState = NORMAL; + bool showChevron = false; + Menu showMenu; + + bool showMin = false; + Rectangle minRect; + bool minimized = false; + int minImageState = NORMAL; + + bool showMax = false; + Rectangle maxRect; + bool maximized = false; + int maxImageState = NORMAL; + + Control topRight; + Rectangle topRightRect; + int topRightAlignment = SWT.RIGHT; + + // borders and shapes + int borderLeft = 0; + int borderRight = 0; + int borderTop = 0; + int borderBottom = 0; + + int highlight_margin = 0; + int highlight_header = 0; + + int[] curve; + int[] topCurveHighlightStart; + int[] topCurveHighlightEnd; + int curveWidth = 0; + int curveIndent = 0; + + // when disposing CTabFolder, don't try to layout the items or + // change the selection as each child is destroyed. + bool inDispose = false; + + // keep track of size changes in order to redraw only affected area + // on Resize + Point oldSize; + Font oldFont; + + // internal constants + static const int DEFAULT_WIDTH = 64; + static const int DEFAULT_HEIGHT = 64; + static const int BUTTON_SIZE = 18; + + static const int[] TOP_LEFT_CORNER = [0,6, 1,5, 1,4, 4,1, 5,1, 6,0]; + + //TOP_LEFT_CORNER_HILITE is laid out in reverse (ie. top to bottom) + //so can fade in same direction as right swoop curve + static const int[] TOP_LEFT_CORNER_HILITE = [5,2, 4,2, 3,3, 2,4, 2,5, 1,6]; + + static const int[] TOP_RIGHT_CORNER = [-6,0, -5,1, -4,1, -1,4, -1,5, 0,6]; + static const int[] BOTTOM_LEFT_CORNER = [0,-6, 1,-5, 1,-4, 4,-1, 5,-1, 6,0]; + static const int[] BOTTOM_RIGHT_CORNER = [-6,0, -5,-1, -4,-1, -1,-4, -1,-5, 0,-6]; + + static const int[] SIMPLE_TOP_LEFT_CORNER = [0,2, 1,1, 2,0]; + static const int[] SIMPLE_TOP_RIGHT_CORNER = [-2,0, -1,1, 0,2]; + static const int[] SIMPLE_BOTTOM_LEFT_CORNER = [0,-2, 1,-1, 2,0]; + static const int[] SIMPLE_BOTTOM_RIGHT_CORNER = [-2,0, -1,-1, 0,-2]; + static const int[] SIMPLE_UNSELECTED_INNER_CORNER = [0,0]; + + static const int[] TOP_LEFT_CORNER_BORDERLESS = [0,6, 1,5, 1,4, 4,1, 5,1, 6,0]; + static const int[] TOP_RIGHT_CORNER_BORDERLESS = [-7,0, -6,1, -5,1, -2,4, -2,5, -1,6]; + static const int[] BOTTOM_LEFT_CORNER_BORDERLESS = [0,-6, 1,-6, 1,-5, 2,-4, 4,-2, 5,-1, 6,-1, 6,0]; + static const int[] BOTTOM_RIGHT_CORNER_BORDERLESS = [-7,0, -7,-1, -6,-1, -5,-2, -3,-4, -2,-5, -2,-6, -1,-6]; + + static const int[] SIMPLE_TOP_LEFT_CORNER_BORDERLESS = [0,2, 1,1, 2,0]; + static const int[] SIMPLE_TOP_RIGHT_CORNER_BORDERLESS= [-3,0, -2,1, -1,2]; + static const int[] SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS = [0,-3, 1,-2, 2,-1, 3,0]; + static const int[] SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS = [-4,0, -3,-1, -2,-2, -1,-3]; + + static const int SELECTION_FOREGROUND = SWT.COLOR_LIST_FOREGROUND; + static const int SELECTION_BACKGROUND = SWT.COLOR_LIST_BACKGROUND; + static const int BORDER1_COLOR = SWT.COLOR_WIDGET_NORMAL_SHADOW; + static const int FOREGROUND = SWT.COLOR_WIDGET_FOREGROUND; + static const int BACKGROUND = SWT.COLOR_WIDGET_BACKGROUND; + static const int BUTTON_BORDER = SWT.COLOR_WIDGET_DARK_SHADOW; + static const int BUTTON_FILL = SWT.COLOR_LIST_BACKGROUND; + + static const int NONE = 0; + static const int NORMAL = 1; + static const int HOT = 2; + static const int SELECTED = 3; + static const RGB CLOSE_FILL; + + static const int CHEVRON_CHILD_ID = 0; + static const int MINIMIZE_CHILD_ID = 1; + static const int MAXIMIZE_CHILD_ID = 2; + static const int EXTRA_CHILD_ID_COUNT = 3; + +static this(){ + borderInsideRGB = new RGB (132, 130, 132); + borderMiddleRGB = new RGB (143, 141, 138); + borderOutsideRGB = new RGB (171, 168, 165); + CLOSE_FILL = new RGB(252, 160, 160); +} + +/** + * 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.
+ *
SelectionListener
+ * interface.
+ *
+ * widgetSelected
is called when the user changes the selected tab.
+ * widgetDefaultSelected
is not called.
+ *
true
if the receiver's border is visible.
+ *
+ * @return the receiver's border visibility state
+ *
+ * @exception SWTException true
if the receiver is minimized.
+ *
+ * @return the receiver's minimized state
+ *
+ * @exception SWTException true
if the minimize button
+ * is visible.
+ *
+ * @return the visibility of the minimized button
+ *
+ * @exception SWTException true
if the receiver is maximized.
+ * + * + * @return the receiver's maximized state + * + * @exception SWTException
true
if the maximize button
+ * is visible.
+ *
+ * @return the visibility of the maximized button
+ *
+ * @exception SWTException true
if the receiver displays most
+ * recently used tabs and false
otherwise.
+ * + * When there is not enough horizontal space to show all the tabs, + * by default, tabs are shown sequentially from left to right in + * order of their index. When the MRU visibility is turned on, + * the tabs that are visible will be the tabs most recently selected. + * Tabs will still maintain their left to right order based on index + * but only the most recently selected tabs are visible. + *
+ * For example, consider a CTabFolder that contains "Tab 1", "Tab 2", + * "Tab 3" and "Tab 4" (in order by index). The user selects + * "Tab 1" and then "Tab 3". If the CTabFolder is now + * compressed so that only two tabs are visible, by default, + * "Tab 2" and "Tab 3" will be shown ("Tab 3" since it is currently + * selected and "Tab 2" because it is the previous item in index order). + * If MRU visibility is enabled, the two visible tabs will be "Tab 1" + * and "Tab 3" (in that order from left to right).
+ * + * @return the receiver's header's visibility state + * + * @exception SWTExceptiontrue
if the CTabFolder is rendered
+ * with a simple, traditional shape.
+ *
+ * @return true
if the CTabFolder is rendered with a simple shape
+ *
+ * @since 3.0
+ */
+public bool getSimple() {
+ checkWidget();
+ return simple;
+}
+/**
+ * Returns true
if the CTabFolder only displays the selected tab
+ * and false
if the CTabFolder displays multiple tabs.
+ *
+ * @return true
if the CTabFolder only displays the selected tab and false
if the CTabFolder displays multiple tabs
+ *
+ * @since 3.0
+ */
+public bool getSingle() {
+ checkWidget();
+ return single;
+}
+
+public override int getStyle() {
+ int style = super.getStyle();
+ style &= ~(SWT.TOP | SWT.BOTTOM);
+ style |= onBottom ? SWT.BOTTOM : SWT.TOP;
+ style &= ~(SWT.SINGLE | SWT.MULTI);
+ style |= single ? SWT.SINGLE : SWT.MULTI;
+ if (borderLeft !is 0) style |= SWT.BORDER;
+ style &= ~SWT.CLOSE;
+ if (showClose) style |= SWT.CLOSE;
+ return style;
+}
+/**
+ * Returns the height of the tab
+ *
+ * @return the height of the tab
+ *
+ * @exception SWTException true
if the close button appears
+ * when the user hovers over an unselected tabs.
+ *
+ * @return true
if the close button appears on unselected tabs
+ *
+ * @since 3.0
+ */
+public bool getUnselectedCloseVisible() {
+ checkWidget();
+ return showUnselectedClose;
+}
+/**
+ * Returns true
if an image appears
+ * in unselected tabs.
+ *
+ * @return true
if an image appears in unselected tabs
+ *
+ * @since 3.0
+ */
+public bool getUnselectedImageVisible() {
+ checkWidget();
+ return showUnselectedImage;
+}
+/**
+ * Return the index of the specified tab or -1 if the tab is not
+ * in the receiver.
+ *
+ * @param item the tab item for which the index is required
+ *
+ * @return the index of the specified tab item or -1
+ *
+ * @exception IllegalArgumentException + * cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE), + * display.getSystemColor(SWT.COLOR_BLUE), + * display.getSystemColor(SWT.COLOR_WHITE), + * display.getSystemColor(SWT.COLOR_WHITE)}, + * new int[] {25, 50, 100}); + *+ * + * @param colors an array of Color that specifies the colors to appear in the gradient + * in order of appearance left to right. The value
null
clears the
+ * background gradient. The value null
can be used inside the array of
+ * Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ * of the widget at which the color should change. The size of the percents array must be one
+ * less than the size of the colors array.
+ *
+ * @exception SWTException + * cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE), + * display.getSystemColor(SWT.COLOR_BLUE), + * display.getSystemColor(SWT.COLOR_WHITE), + * display.getSystemColor(SWT.COLOR_WHITE)}, + * new int[] {25, 50, 100}, true); + *+ * + * @param colors an array of Color that specifies the colors to appear in the gradient + * in order of appearance left to right. The value
null
clears the
+ * background gradient. The value null
can be used inside the array of
+ * Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ * of the widget at which the color should change. The size of the percents array must be one
+ * less than the size of the colors array.
+ *
+ * @param vertical indicate the direction of the gradient. True is vertical and false is horizontal.
+ *
+ * @exception SWTException true
,
+ * and marks it invisible otherwise.
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException + * Note: No Layout can be set on this Control because it already + * manages the size and position of its children. + *
+ * + * @param layout the receiver's new layout or null + * + * @exception SWTExceptiontrue
,
+ * and marks it invisible otherwise.
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException + * For example, consider a CTabFolder that contains "Tab 1", "Tab 2", + * "Tab 3" and "Tab 4" (in order by index). The user selects + * "Tab 1" and then "Tab 3". If the CTabFolder is now + * compressed so that only two tabs are visible, by default, + * "Tab 2" and "Tab 3" will be shown ("Tab 3" since it is currently + * selected and "Tab 2" because it is the previous item in index order). + * If MRU visibility is enabled, the two visible tabs will be "Tab 1" + * and "Tab 3" (in that order from left to right).
+ * + * @param show the new visibility state + * + * @exception SWTException+ * cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE), + * display.getSystemColor(SWT.COLOR_BLUE), + * display.getSystemColor(SWT.COLOR_WHITE), + * display.getSystemColor(SWT.COLOR_WHITE)}, + * new int[] {25, 50, 100}); + *+ * + * @param colors an array of Color that specifies the colors to appear in the gradient + * in order of appearance left to right. The value
null
clears the
+ * background gradient. The value null
can be used inside the array of
+ * Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ * of the widget at which the color should change. The size of the percents array must be one
+ * less than the size of the colors array.
+ *
+ * @exception SWTException + * cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE), + * display.getSystemColor(SWT.COLOR_BLUE), + * display.getSystemColor(SWT.COLOR_WHITE), + * display.getSystemColor(SWT.COLOR_WHITE)}, + * new int[] {25, 50, 100}, true); + *+ * + * @param colors an array of Color that specifies the colors to appear in the gradient + * in order of appearance left to right. The value
null
clears the
+ * background gradient. The value null
can be used inside the array of
+ * Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ * of the widget at which the color should change. The size of the percents array must be one
+ * less than the size of the colors array.
+ *
+ * @param vertical indicate the direction of the gradient. True is vertical and false is horizontal.
+ *
+ * @exception SWTException true
if the CTabFolder should render itself in a simple, traditional style
+ *
+ * @exception SWTException true
if only the selected tab should be displayed otherwise, multiple tabs will be shown.
+ *
+ * @exception SWTException SWT.TOP
for tabs along the top or SWT.BOTTOM
for tabs along the bottom
+ *
+ * @exception SWTException
+ * The alignment parameter sets the layout of the control in the tab area.
+ * SWT.RIGHT
will cause the control to be positioned on the far
+ * right of the folder and it will have its default size. SWT.FILL
+ * will size the control to fill all the available space to the right of the
+ * last tab. If there is no available space, the control will not be visible.
+ *
SWT.RIGHT
or SWT.FILL
+ *
+ * @exception SWTException true
makes the close button appear
+ *
+ * @exception SWTException true
makes the image appear
+ *
+ * @exception SWTException CTabFolder2Listener
interface.
+ *
+ * Classes that wish to deal with CTabFolderEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ * The default behaviour is to close the CTabItem. + *
+ * + * @param event an event indicating the item being closed + */ +public void close(CTabFolderEvent event){} + +/** + * Sent when the user clicks on the minimize button of a CTabFolder. + *+ * The default behaviour is to do nothing. + *
+ * + * @param event an event containing information about the minimize + */ +public void minimize(CTabFolderEvent event){} + +/** + * Sent when the user clicks on the maximize button of a CTabFolder. + *+ * The default behaviour is to do nothing. + *
+ * + * @param event an event containing information about the maximize + */ +public void maximize(CTabFolderEvent event){} + +/** + * Sent when the user clicks on the restore button of a CTabFolder. + *+ * The default behaviour is to do nothing. + *
+ * + * @param event an event containing information about the restore + */ +public void restore(CTabFolderEvent event){} + +/** + * Sent when the user clicks on the chevron button of a CTabFolder. + *+ * The default behaviour is to show a list of items that are not currently + * visible and to change the selection based on the item selected from the list. + *
+ * + * @param event an event containing information about the show list + */ +public void showList(CTabFolderEvent event){} +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolder2Listener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolder2Listener.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,195 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a CTabFolder using the
+ * addCTabFolder2Listener
method and removed using
+ * the removeCTabFolder2Listener
method. When
+ * events occurs in a CTabFolder the appropriate method
+ * will be invoked.
+ *
false
and displaying a selection list.
+ *
+ * @param event an event containing information about the show list
+ *
+ * @see CTabFolder#setSelection(CTabItem)
+ */
+public void showList(CTabFolderEvent event);
+}
+
+
+
+/// Helper class for the dgListener template function
+private class _DgCTabFolder2ListenerT(Dg,T...) : CTabFolder2Listener {
+
+ alias ParameterTupleOf!(Dg) DgArgs;
+ static assert( is(DgArgs == Tuple!(CTabFolderEvent,T)),
+ "Delegate args not correct: "~DgArgs.stringof~" vs. (Event,"~T.stringof~")" );
+
+ Dg dg;
+ T t;
+ int type;
+
+ private this( int type, Dg dg, T t ){
+ this.type = type;
+ this.dg = dg;
+ static if( T.length > 0 ){
+ this.t = t;
+ }
+ }
+
+ void itemClosed( CTabFolderEvent e ){
+ dg(e,t);
+ }
+ public void close(CTabFolderEvent e){
+ if( type is CTabFolder2Listener.CLOSE ){
+ dg(e,t);
+ }
+ }
+ public void minimize(CTabFolderEvent e){
+ if( type is CTabFolder2Listener.MINIMIZE ){
+ dg(e,t);
+ }
+ }
+ public void maximize(CTabFolderEvent e){
+ if( type is CTabFolder2Listener.MAXIMIZE ){
+ dg(e,t);
+ }
+ }
+ public void restore(CTabFolderEvent e){
+ if( type is CTabFolder2Listener.RESTORE ){
+ dg(e,t);
+ }
+ }
+ public void showList(CTabFolderEvent e){
+ if( type is CTabFolder2Listener.SHOWLIST ){
+ dg(e,t);
+ }
+ }
+}
+
+/++
+ + dgListener creates a class implementing the Listener interface and delegating the call to
+ + handleEvent to the users delegate. This template function will store also additional parameters.
+ +
+ + Examle of usage:
+ + ---
+ + void handleTextEvent ( Event e, int inset ) {
+ + // ...
+ + }
+ + text.addListener (SWT.FocusOut, dgListener( &handleTextEvent, inset ));
+ + ---
+ +/
+CTabFolder2Listener dgCTabFolder2Listener( Dg, T... )( int type, Dg dg, T args ){
+ return new _DgCTabFolder2ListenerT!( Dg, T )( type, dg, args );
+}
+
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderAdapter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderAdapter.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit CTabFolderListener
interface.
+ *
+ * @see CTabFolderListener
+ * @see CTabFolderEvent
+ * @see Sample code and further information
+ */
+public class CTabFolderAdapter : CTabFolderListener {
+ public void itemClosed(CTabFolderEvent event){}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit false
will cancel the operation.
+ * Applies to the close and showList events.
+ */
+ public bool doit;
+
+ /**
+ * The widget-relative, x coordinate of the chevron button
+ * at the time of the event. Applies to the showList event.
+ *
+ * @since 3.0
+ */
+ public int x;
+ /**
+ * The widget-relative, y coordinate of the chevron button
+ * at the time of the event. Applies to the showList event.
+ *
+ * @since 3.0
+ */
+ public int y;
+ /**
+ * The width of the chevron button at the time of the event.
+ * Applies to the showList event.
+ *
+ * @since 3.0
+ */
+ public int width;
+ /**
+ * The height of the chevron button at the time of the event.
+ * Applies to the showList event.
+ *
+ * @since 3.0
+ */
+ public int height;
+
+ static final long serialVersionUID = 3760566386225066807L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param w the widget that fired the event
+ */
+this(Widget w) {
+ super(w);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+ String string = super.toString ();
+ return string[0.. $ - 1] // remove trailing '}'
+ ~ " item=" ~ to!(String)(item)
+ ~ " doit=" ~ to!(String)(doit)
+ ~ " x=" ~ to!(String)(x)
+ ~ " y=" ~ to!(String)(y)
+ ~ " width=" ~ to!(String)(width)
+ ~ " height=" ~ to!(String)(height)
+ ~ "}";
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderLayout.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a CTabFolder using the
+ * addCTabFolderListener
method and removed using
+ * the removeCTabFolderListener
method. When a
+ * tab item is closed, the itemClosed method will be invoked.
+ *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see CTabFolder, CTabItem snippets + * @see Sample code and further information + */ +public class CTabItem : Item { + CTabFolder parent; + int x,y,width,height = 0; + Control control; // the tab page + + String toolTipText; + String shortenedText; + int shortenedTextWidth; + + // Appearance + Font font; + Image disabledImage; + + Rectangle closeRect; + int closeImageState = CTabFolder.NONE; + bool showClose = false; + bool showing = false; + + // internal constants + static final int TOP_MARGIN = 2; + static final int BOTTOM_MARGIN = 2; + static final int LEFT_MARGIN = 4; + static final int RIGHT_MARGIN = 4; + static final int INTERNAL_SPACING = 4; + static final int FLAGS = SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC; + static final String ELLIPSIS = "..."; //$NON-NLS-1$ // could use the ellipsis glyph on some platforms "\u2026" + +/** + * Constructs a new instance of this class given its parent + * (which must be aCTabFolder
) 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.
+ *
CTabFolder
), 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.
+ *
CTabFolder
.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException true
to indicate that the receiver's close button should be shown.
+ * Otherwise return false
. The initial value is defined by the style (SWT.CLOSE)
+ * that was used to create the receiver.
+ *
+ * @return true
if the close button should be shown
+ *
+ * @exception SWTException true
if the item will be rendered in the visible area of the CTabFolder. Returns false otherwise.
+*
+* @return true
if the item will be rendered in the visible area of the CTabFolder. Returns false otherwise.
+*
+* @exception SWTException true
to indicate that the receiver's close button should be shown.
+ * If the parent (CTabFolder) was created with SWT.CLOSE style, changing this value has
+ * no effect.
+ *
+ * @param close the new state of the close button
+ *
+ * @exception SWTException Here is an example of using a ControlEditor:
+*
+*
+ *
+ * @param start the start of the line
+ * @param length the length of the line
+ */
+void addLineIndex(int start, int length) {
+ int size = lines.length;
+ if (lineCount_ is size) {
+ // expand the lines by powers of 2
+ int[][] newLines = new int[][]( size+Compatibility.pow2(expandExp), 2 );
+ System.arraycopy(lines, 0, newLines, 0, size);
+ lines = newLines;
+ expandExp++;
+ }
+ int[] range = [start, length];
+ lines[lineCount_] = range;
+ lineCount_++;
+}
+/**
+ * Adds a line index to the end of
+ *
+ * @param start the start of the line
+ * @param length the length of the line
+ * @param linesArray the array to which to add the line index
+ * @param count the position at which to add the line
+ * @return a new array of line indexes
+ */
+int[][] addLineIndex(int start, int length, int[][] linesArray, int count) {
+ int size = linesArray.length;
+ int[][] newLines = linesArray;
+ if (count is size) {
+ newLines = new int[][]( size+Compatibility.pow2(replaceExpandExp), 2 );
+ replaceExpandExp++;
+ System.arraycopy(linesArray, 0, newLines, 0, size);
+ }
+ int[] range = [start, length];
+ newLines[count] = range;
+ return newLines;
+}
+/**
+ * Adds a
+ *
+ * @param listener the listener
+ * @exception IllegalArgumentException
+ *
+ * @param position the position at which a change is occurring
+ * @param sizeHint the size of the change
+ * @param line the line where the gap will go
+ */
+void adjustGap(int position, int sizeHint, int line) {
+ if (position is gapStart) {
+ // text is being inserted at the gap position
+ int size = (gapEnd - gapStart) - sizeHint;
+ if (lowWatermark <= size && size <= highWatermark)
+ return;
+ } else if ((position + sizeHint is gapStart) && (sizeHint < 0)) {
+ // text is being deleted at the gap position
+ int size = (gapEnd - gapStart) - sizeHint;
+ if (lowWatermark <= size && size <= highWatermark)
+ return;
+ }
+ moveAndResizeGap(position, sizeHint, line);
+}
+/**
+ * Calculates the indexes of each line in the text store. Assumes no gap exists.
+ * Optimized to do less checking.
+ */
+void indexLines(){
+ int start = 0;
+ lineCount_ = 0;
+ int textLength = textStore.length;
+ int i;
+ for (i = start; i < textLength; i++) {
+ char ch = textStore[i];
+ if (ch is SWT.CR) {
+ // see if the next character is a LF
+ if (i + 1 < textLength) {
+ ch = textStore[i+1];
+ if (ch is SWT.LF) {
+ i++;
+ }
+ }
+ addLineIndex(start, i - start + 1);
+ start = i + 1;
+ } else if (ch is SWT.LF) {
+ addLineIndex(start, i - start + 1);
+ start = i + 1;
+ }
+ }
+ addLineIndex(start, i - start);
+}
+/**
+ * Returns whether or not the given character is a line delimiter. Both CR and LF
+ * are valid line delimiters.
+ *
+ *
+ * @param ch the character to test
+ * @return true if ch is a delimiter, false otherwise
+ */
+bool isDelimiter(char ch) {
+ if (ch is SWT.CR) return true;
+ if (ch is SWT.LF) return true;
+ return false;
+}
+/**
+ * Determine whether or not the replace operation is valid. DefaultContent will not allow
+ * the /r/n line delimiter to be split or partially deleted.
+ *
+ *
+ * @param start start offset of text to replace
+ * @param replaceLength start offset of text to replace
+ * @param newText start offset of text to replace
+ * @return a bool specifying whether or not the replace operation is valid
+ */
+protected bool isValidReplace(int start, int replaceLength, String newText){
+ if (replaceLength is 0) {
+ // inserting text, see if the \r\n line delimiter is being split
+ if (start is 0) return true;
+ if (start is getCharCount()) return true;
+ char before = getTextRange(start - 1, 1)[0];
+ if (before is '\r') {
+ char after = getTextRange(start, 1)[0];
+ if (after is '\n') return false;
+ }
+ } else {
+ // deleting text, see if part of a \r\n line delimiter is being deleted
+ char startChar = getTextRange(start, 1)[0];
+ if (startChar is '\n') {
+ // see if char before delete position is \r
+ if (start !is 0) {
+ char before = getTextRange(start - 1, 1)[0];
+ if (before is '\r') return false;
+ }
+ }
+ char endChar = getTextRange(start + replaceLength - 1, 1)[0];
+ if (endChar is '\r') {
+ // see if char after delete position is \n
+ if (start + replaceLength !is getCharCount()) {
+ char after = getTextRange(start + replaceLength, 1)[0];
+ if (after is '\n') return false;
+ }
+ }
+ }
+ return true;
+}
+/**
+ * Calculates the indexes of each line of text in the given range.
+ *
+ *
+ * @param offset the logical start offset of the text lineate
+ * @param length the length of the text to lineate, includes gap
+ * @param numLines the number of lines to initially allocate for the line index array,
+ * passed in for efficiency (the exact number of lines may be known)
+ * @return a line indexes array where each line is identified by a start offset and
+ * a length
+ */
+int[][] indexLines(int offset, int length, int numLines){
+ int[][] indexedLines = new int[][]( numLines, 2 );
+ int start = 0;
+ int lineCount_ = 0;
+ int i;
+ replaceExpandExp = 1;
+ for (i = start; i < length; i++) {
+ int location = i + offset;
+ if ((location >= gapStart) && (location < gapEnd)) {
+ // ignore the gap
+ } else {
+ char ch = textStore[location];
+ if (ch is SWT.CR) {
+ // see if the next character is a LF
+ if (location+1 < textStore.length) {
+ ch = textStore[location+1];
+ if (ch is SWT.LF) {
+ i++;
+ }
+ }
+ indexedLines = addLineIndex(start, i - start + 1, indexedLines, lineCount_);
+ lineCount_++;
+ start = i + 1;
+ } else if (ch is SWT.LF) {
+ indexedLines = addLineIndex(start, i - start + 1, indexedLines, lineCount_);
+ lineCount_++;
+ start = i + 1;
+ }
+ }
+ }
+ int[][] newLines = new int[][]( lineCount_+1, 2 );
+ System.arraycopy(indexedLines, 0, newLines, 0, lineCount_);
+ int[] range = [start, i - start];
+ newLines[lineCount_] = range;
+ return newLines;
+}
+/**
+ * Inserts text.
+ *
+ *
+ * @param position the position at which to insert the text
+ * @param text the text to insert
+ */
+void insert(int position, String text) {
+ if (text.length is 0) return;
+
+ int startLine = getLineAtOffset(position);
+ int change = text.length;
+ bool endInsert = position is getCharCount();
+ adjustGap(position, change, startLine);
+
+ // during an insert the gap will be adjusted to start at
+ // position and it will be associated with startline, the
+ // inserted text will be placed in the gap
+ int startLineOffset = getOffsetAtLine(startLine);
+ // at this point, startLineLength will include the start line
+ // and all of the newly inserted text
+ int startLineLength = getPhysicalLine(startLine).length;
+
+ if (change > 0) {
+ // shrink gap
+ gapStart += (change);
+ for (int i = 0; i < text.length; i++) {
+ textStore[position + i]= text[i];
+ }
+ }
+
+ // figure out the number of new lines that have been inserted
+ int [][] newLines = indexLines(startLineOffset, startLineLength, 10);
+ // only insert an empty line if it is the last line in the text
+ int numNewLines = newLines.length - 1;
+ if (newLines[numNewLines][1] is 0) {
+ // last inserted line is a new line
+ if (endInsert) {
+ // insert happening at end of the text, leave numNewLines as
+ // is since the last new line will not be concatenated with another
+ // line
+ numNewLines += 1;
+ } else {
+ numNewLines -= 1;
+ }
+ }
+
+ // make room for the new lines
+ expandLinesBy(numNewLines);
+ // shift down the lines after the replace line
+ for (int i = lineCount_ - 1; i > startLine; i--) {
+ lines[i + numNewLines]=lines[i];
+ }
+ // insert the new lines
+ for (int i = 0; i < numNewLines; i++) {
+ newLines[i][0] += startLineOffset;
+ lines[startLine + i]=newLines[i];
+ }
+ // update the last inserted line
+ if (numNewLines < newLines.length) {
+ newLines[numNewLines][0] += startLineOffset;
+ lines[startLine + numNewLines] = newLines[numNewLines];
+ }
+
+ lineCount_ += numNewLines;
+ gapLine = getLineAtPhysicalOffset(gapStart);
+}
+/**
+ * Moves the gap and adjusts its size in anticipation of a text change.
+ * The gap is resized to actual size + the specified size and moved to the given
+ * position.
+ *
+ *
+ * @param position the position at which a change is occurring
+ * @param size the size of the change
+ * @param newGapLine the line where the gap should be put
+ */
+void moveAndResizeGap(int position, int size, int newGapLine) {
+ char[] content = null;
+ int oldSize = gapEnd - gapStart;
+ int newSize;
+ if (size > 0) {
+ newSize = highWatermark + size;
+ } else {
+ newSize = lowWatermark - size;
+ }
+ // remove the old gap from the lines information
+ if (gapExists()) {
+ // adjust the line length
+ lines[gapLine][1] = lines[gapLine][1] - oldSize;
+ // adjust the offsets of the lines after the gapLine
+ for (int i = gapLine + 1; i < lineCount_; i++) {
+ lines[i][0] = lines[i][0] - oldSize;
+ }
+ }
+
+ if (newSize < 0) {
+ if (oldSize > 0) {
+ // removing the gap
+ content = new char[textStore.length - oldSize];
+ System.arraycopy(textStore, 0, content, 0, gapStart);
+ System.arraycopy(textStore, gapEnd, content, gapStart, content.length - gapStart);
+ textStore = content;
+ }
+ gapStart = gapEnd = position;
+ return;
+ }
+ content = new char[textStore.length + (newSize - oldSize)];
+ int newGapStart = position;
+ int newGapEnd = newGapStart + newSize;
+ if (oldSize is 0) {
+ System.arraycopy(textStore, 0, content, 0, newGapStart);
+ System.arraycopy(textStore, newGapStart, content, newGapEnd, content.length - newGapEnd);
+ } else if (newGapStart < gapStart) {
+ int delta = gapStart - newGapStart;
+ System.arraycopy(textStore, 0, content, 0, newGapStart);
+ System.arraycopy(textStore, newGapStart, content, newGapEnd, delta);
+ System.arraycopy(textStore, gapEnd, content, newGapEnd + delta, textStore.length - gapEnd);
+ } else {
+ int delta = newGapStart - gapStart;
+ System.arraycopy(textStore, 0, content, 0, gapStart);
+ System.arraycopy(textStore, gapEnd, content, gapStart, delta);
+ System.arraycopy(textStore, gapEnd + delta, content, newGapEnd, content.length - newGapEnd);
+ }
+ textStore = content;
+ gapStart = newGapStart;
+ gapEnd = newGapEnd;
+
+ // add the new gap to the lines information
+ if (gapExists()) {
+ gapLine = newGapLine;
+ // adjust the line length
+ int gapLength = gapEnd - gapStart;
+ lines[gapLine][1] = lines[gapLine][1] + (gapLength);
+ // adjust the offsets of the lines after the gapLine
+ for (int i = gapLine + 1; i < lineCount_; i++) {
+ lines[i][0] = lines[i][0] + gapLength;
+ }
+ }
+}
+/**
+ * Returns the number of lines that are in the specified text.
+ *
+ *
+ * @param startOffset the start of the text to lineate
+ * @param length the length of the text to lineate
+ * @return number of lines
+ */
+int lineCount(int startOffset, int length){
+ if (length is 0) {
+ return 0;
+ }
+ int lineCount_ = 0;
+ int count = 0;
+ int i = startOffset;
+ if (i >= gapStart) {
+ i += gapEnd - gapStart;
+ }
+ while (count < length) {
+ if ((i >= gapStart) && (i < gapEnd)) {
+ // ignore the gap
+ } else {
+ char ch = textStore[i];
+ if (ch is SWT.CR) {
+ // see if the next character is a LF
+ if (i + 1 < textStore.length) {
+ ch = textStore[i+1];
+ if (ch is SWT.LF) {
+ i++;
+ count++;
+ }
+ }
+ lineCount_++;
+ } else if (ch is SWT.LF) {
+ lineCount_++;
+ }
+ count++;
+ }
+ i++;
+ }
+ return lineCount_;
+}
+/**
+ * Returns the number of lines that are in the specified text.
+ *
+ *
+ * @param text the text to lineate
+ * @return number of lines in the text
+ */
+int lineCount(String text){
+ int lineCount_ = 0;
+ int length = text.length;
+ for (int i = 0; i < length; i++) {
+ char ch = text[i];
+ if (ch is SWT.CR) {
+ if (i + 1 < length && text[i + 1] is SWT.LF) {
+ i++;
+ }
+ lineCount_++;
+ } else if (ch is SWT.LF) {
+ lineCount_++;
+ }
+ }
+ return lineCount_;
+}
+/**
+ * @return the logical length of the text store
+ */
+public int getCharCount() {
+ int length = gapEnd - gapStart;
+ return (textStore.length - length);
+}
+/**
+ * Returns the line at
+ *
+ * @param index the index of the line to return
+ * @return the logical line text (i.e., without the gap)
+ * @exception IllegalArgumentException
+ *
+ * @return the platform line delimiter as specified in the line.separator
+ * system property.
+ */
+public String getLineDelimiter() {
+ return LineDelimiter;
+}
+/**
+ * Returns the line at the given index with delimiters.
+ *
+ * @param index the index of the line to return
+ * @return the logical line text (i.e., without the gap) with delimiters
+ */
+String getFullLine(int index) {
+ int start = lines[index][0];
+ int length_ = lines[index][1];
+ int end = start + length_ - 1;
+ if (!gapExists() || (end < gapStart) || (start >= gapEnd)) {
+ // line is before or after the gap
+ return textStore[ start .. start + length_ ].dup;
+ } else {
+ // gap is in the specified range, strip out the gap
+ StringBuffer buffer = new StringBuffer();
+ int gapLength = gapEnd - gapStart;
+ buffer.append(textStore[ start .. gapStart ]);
+ buffer.append(textStore[ gapEnd .. gapEnd + length_ - gapLength - (gapStart - start) ]);
+ return buffer.toString().dup;
+ }
+}
+/**
+ * Returns the physical line at the given index (i.e., with delimiters and the gap).
+ *
+ *
+ * @param index the line index
+ * @return the physical line
+ */
+String getPhysicalLine(int index) {
+ int start = lines[index][0];
+ int length_ = lines[index][1];
+ return getPhysicalText(start, length_);
+}
+/**
+ * @return the number of lines in the text store
+ */
+public int getLineCount(){
+ return lineCount_;
+}
+/**
+ * Returns the line at the given offset.
+ *
+ *
+ * @param charPosition logical character offset (i.e., does not include gap)
+ * @return the line index
+ * @exception IllegalArgumentException
+ *
+ * @param position physical character offset (i.e., includes gap)
+ * @return the line index
+ */
+int getLineAtPhysicalOffset(int position){
+ int high = lineCount_;
+ int low = -1;
+ int index = lineCount_;
+ while (high - low > 1) {
+ index = (high + low) / 2;
+ int lineStart = lines[index][0];
+ int lineEnd = lineStart + lines[index][1] - 1;
+ if (position <= lineStart) {
+ high = index;
+ } else if (position <= lineEnd) {
+ high = index;
+ break;
+ } else {
+ low = index;
+ }
+ }
+ return high;
+}
+/**
+ * Returns the logical offset of the given line.
+ *
+ *
+ * @param lineIndex index of line
+ * @return the logical starting offset of the line. When there are not any lines,
+ * getOffsetAtLine(0) is a valid call that should answer 0.
+ * @exception IllegalArgumentException
+ *
+ * @param numLines the number to increase the array by
+ */
+void expandLinesBy(int numLines) {
+ int size = lines.length;
+ if (size - lineCount_ >= numLines) {
+ return;
+ }
+ int[][] newLines = new int[][]( size+Math.max(10, numLines), 2 );
+ System.arraycopy(lines, 0, newLines, 0, size);
+ lines = newLines;
+}
+/**
+ * Reports an SWT error.
+ *
+ *
+ * @param code the error code
+ */
+void error (int code) {
+ SWT.error(code);
+}
+/**
+ * Returns whether or not a gap exists in the text store.
+ *
+ *
+ * @return true if gap exists, false otherwise
+ */
+bool gapExists() {
+ return gapStart !is gapEnd;
+}
+/**
+ * Returns a string representing the continuous content of
+ * the text store.
+ *
+ *
+ * @param start the physical start offset of the text to return
+ * @param length the physical length of the text to return
+ * @return the text
+ */
+String getPhysicalText(int start, int length_) {
+ return textStore[ start .. start + length_ ].dup;
+}
+/**
+ * Returns a string representing the logical content of
+ * the text store (i.e., gap stripped out).
+ *
+ *
+ * @param start the logical start offset of the text to return
+ * @param length the logical length of the text to return
+ * @return the text
+ */
+public String getTextRange(int start, int length_) {
+ if (textStore is null)
+ return "";
+ if (length_ is 0)
+ return "";
+ int end= start + length_;
+ if (!gapExists() || (end < gapStart))
+ return textStore[ start .. start + length_].dup;
+ if (gapStart < start) {
+ int gapLength= gapEnd - gapStart;
+ return textStore[ start + gapLength .. start + gapLength + length_ ].dup;
+ }
+ StringBuffer buf = new StringBuffer();
+ buf.append(textStore[ start .. start + gapStart - start ] );
+ buf.append(textStore[ gapEnd .. gapEnd + end - gapStart ] );
+ return buf.toString().dup;
+}
+/**
+ * Removes the specified
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
+ * When sending the TextChangingEvent,
+*
+* @see Sample code and further information
+*/
+public class ControlEditor {
+
+ /**
+ * Specifies how the editor should be aligned relative to the control. Allowed values
+ * are SWT.LEFT, SWT.RIGHT and SWT.CENTER. The default value is SWT.CENTER.
+ */
+ public int horizontalAlignment = SWT.CENTER;
+
+ /**
+ * Specifies whether the editor should be sized to use the entire width of the control.
+ * True means resize the editor to the same width as the cell. False means do not adjust
+ * the width of the editor. The default value is false.
+ */
+ public bool grabHorizontal = false;
+
+ /**
+ * Specifies the minimum width the editor can have. This is used in association with
+ * a true value of grabHorizontal. If the cell becomes smaller than the minimumWidth, the
+ * editor will not made smaller than the minimum width value. The default value is 0.
+ */
+ public int minimumWidth = 0;
+
+ /**
+ * Specifies how the editor should be aligned relative to the control. Allowed values
+ * are SWT.TOP, SWT.BOTTOM and SWT.CENTER. The default value is SWT.CENTER.
+ */
+ public int verticalAlignment = SWT.CENTER;
+
+ /**
+ * Specifies whether the editor should be sized to use the entire height of the control.
+ * True means resize the editor to the same height as the underlying control. False means do not adjust
+ * the height of the editor. The default value is false.
+ */
+ public bool grabVertical = false;
+
+ /**
+ * Specifies the minimum height the editor can have. This is used in association with
+ * a true value of grabVertical. If the control becomes smaller than the minimumHeight, the
+ * editor will not made smaller than the minimum height value. The default value is 0.
+ */
+ public int minimumHeight = 0;
+
+ Composite parent;
+ Control editor;
+ private bool hadFocus;
+ private Listener controlListener;
+ private Listener scrollbarListener;
+
+ private final static int [] EVENTS = [SWT.KeyDown, SWT.KeyUp, SWT.MouseDown, SWT.MouseUp, SWT.Resize];
+/**
+* Creates a ControlEditor for the specified Composite.
+*
+* @param parent the Composite above which this editor will be displayed
+*
+*/
+public this (Composite parent) {
+ this.parent = parent;
+
+ controlListener = new class() Listener {
+ public void handleEvent(Event e) {
+ layout ();
+ }
+ };
+ for (int i=0; i
+* Canvas canvas = new Canvas(shell, SWT.BORDER);
+* canvas.setBounds(10, 10, 300, 300);
+* Color color = new Color(null, 255, 0, 0);
+* canvas.setBackground(color);
+* ControlEditor editor = new ControlEditor (canvas);
+* // The editor will be a button in the bottom right corner of the canvas.
+* // When selected, it will launch a Color dialog that will change the background
+* // of the canvas.
+* Button button = new Button(canvas, SWT.PUSH);
+* button.setText("Select Color...");
+* button.addSelectionListener (new SelectionAdapter() {
+* public void widgetSelected(SelectionEvent e) {
+* ColorDialog dialog = new ColorDialog(shell);
+* dialog.open();
+* RGB rgb = dialog.getRGB();
+* if (rgb !is null) {
+* if (color !is null) color.dispose();
+* color = new Color(null, rgb);
+* canvas.setBackground(color);
+* }
+*
+* }
+* });
+*
+* editor.horizontalAlignment = SWT.RIGHT;
+* editor.verticalAlignment = SWT.BOTTOM;
+* editor.grabHorizontal = false;
+* editor.grabVertical = false;
+* Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+* editor.minimumWidth = size.x;
+* editor.minimumHeight = size.y;
+* editor.setEditor (button);
+*
StyledTextContent> will always have
+ * at least one empty line.
+ */
+this() {
+ lines = new int[][]( 50, 2 );
+ setText("");
+}
+/**
+ * Adds a line to the end of the line indexes array. Increases the size of the array if necessary.
+ *
lineCount
is updated to reflect the new entry.
+ * linesArray
. Increases the
+ * size of the array if necessary and returns a new array.
+ * TextChangeListener
listening for
+ * TextChangingEvent
and TextChangedEvent
. A
+ * TextChangingEvent
is sent before changes to the text occur.
+ * A TextChangedEvent
is sent after changes to the text
+ * occurred.
+ *
+ *
+ */
+public void addTextChangeListener(TextChangeListener listener) {
+ if (listener is null) error(SWT.ERROR_NULL_ARGUMENT);
+ StyledTextListener typedListener = new StyledTextListener(listener);
+ textListeners ~= typedListener;
+}
+/**
+ * Adjusts the gap to accommodate a text change that is occurring.
+ * index
without delimiters.
+ *
+ *
+ */
+public String getLine(int index) {
+ if ((index >= lineCount_) || (index < 0)) error(SWT.ERROR_INVALID_ARGUMENT);
+ int start = lines[index][0];
+ int length_ = lines[index][1];
+ int end = start + length_ - 1;
+ if (!gapExists() || (end < gapStart) || (start >= gapEnd)) {
+ // line is before or after the gap
+ while ((length_ - 1 >= 0) && isDelimiter(textStore[start+length_-1])) {
+ length_--;
+ }
+ return textStore[ start .. start + length_].dup;
+ } else {
+ // gap is in the specified range, strip out the gap
+ StringBuffer buf = new StringBuffer();
+ int gapLength = gapEnd - gapStart;
+ buf.append(textStore[ start .. gapStart ] );
+ buf.append(textStore[ gapEnd .. gapEnd + length_ - gapLength - (gapStart - start) ]);
+ length_ = buf.length;
+ while ((length_ - 1 >=0) && isDelimiter(buf.slice[length_ - 1])) {
+ length_--;
+ }
+ return buf.toString()[ 0 .. length_ ].dup;
+ }
+}
+/**
+ * Returns the line delimiter that should be used by the StyledText
+ * widget when inserting new lines. This delimiter may be different than the
+ * delimiter that is used by the StyledTextContent
interface.
+ *
+ *
+ */
+public int getLineAtOffset(int charPosition){
+ if ((charPosition > getCharCount()) || (charPosition < 0)) error(SWT.ERROR_INVALID_ARGUMENT);
+ int position;
+ if (charPosition < gapStart) {
+ // position is before the gap
+ position = charPosition;
+ } else {
+ // position includes the gap
+ position = charPosition + (gapEnd - gapStart);
+ }
+
+ // if last line and the line is not empty you can ask for
+ // a position that doesn't exist (the one to the right of the
+ // last character) - for inserting
+ if (lineCount_ > 0) {
+ int lastLine = lineCount_ - 1;
+ if (position is lines[lastLine][0] + lines[lastLine][1])
+ return lastLine;
+ }
+
+ int high = lineCount_;
+ int low = -1;
+ int index = lineCount_;
+ while (high - low > 1) {
+ index = (high + low) / 2;
+ int lineStart = lines[index][0];
+ int lineEnd = lineStart + lines[index][1] - 1;
+ if (position <= lineStart) {
+ high = index;
+ } else if (position <= lineEnd) {
+ high = index;
+ break;
+ } else {
+ low = index;
+ }
+ }
+ return high;
+}
+/**
+ * Returns the line index at the given physical offset.
+ *
+ *
+ */
+public int getOffsetAtLine(int lineIndex) {
+ if (lineIndex is 0) return 0;
+ if ((lineIndex >= lineCount_) || (lineIndex < 0)) error(SWT.ERROR_INVALID_ARGUMENT);
+ int start = lines[lineIndex][0];
+ if (start > gapEnd) {
+ return start - (gapEnd - gapStart);
+ } else {
+ return start;
+ }
+}
+/**
+ * Increases the line indexes array to accommodate more lines.
+ * TextChangeListener
.
+ *
+ *
+ */
+public void removeTextChangeListener(TextChangeListener listener){
+ if (listener is null) error(SWT.ERROR_NULL_ARGUMENT);
+ for (int i = 0; i < textListeners.length; i++) {
+ TypedListener typedListener = cast(TypedListener) textListeners[i];
+ if (typedListener.getEventListener () is listener) {
+ textListeners = textListeners[ 0 .. i ] ~ textListeners[ i+1 .. $ ];
+ break;
+ }
+ }
+}
+/**
+ * Replaces the text with newText
starting at position start
+ * for a length of replaceLength
. Notifies the appropriate listeners.
+ * newLineCount
is the number of
+ * lines that are going to be inserted and replaceLineCount
is
+ * the number of lines that are going to be deleted, based on the change
+ * that occurs visually. For example:
+ *
+ *
+ *
+ * + * @param text the text + */ +public void setText (String text){ + textStore = text.dup; + gapStart = -1; + gapEnd = -1; + expandExp = 1; + indexLines(); + StyledTextEvent event = new StyledTextEvent(this); + event.type = StyledText.TextSet; + event.text = ""; + sendTextEvent(event); +} +/** + * Deletes text. + *
+ * @param position the position at which the text to delete starts
+ * @param length the length of the text to delete
+ * @param numLines the number of lines that are being deleted
+ */
+void delete_(int position, int length_, int numLines) {
+ if (length_ is 0) return;
+
+ int startLine = getLineAtOffset(position);
+ int startLineOffset = getOffsetAtLine(startLine);
+ int endLine = getLineAtOffset(position + length_);
+
+ String endText = "";
+ bool splittingDelimiter = false;
+ if (position + length_ < getCharCount()) {
+ endText = getTextRange(position + length_ - 1, 2);
+ if ((endText[0] is SWT.CR) && (endText[1] is SWT.LF)) {
+ splittingDelimiter = true;
+ }
+ }
+
+ adjustGap(position + length_, -length_, startLine);
+ int [][] oldLines = indexLines(position, length_ + (gapEnd - gapStart), numLines);
+
+ // enlarge the gap - the gap can be enlarged either to the
+ // right or left
+ if (position + length_ is gapStart) {
+ gapStart -= length_;
+ } else {
+ gapEnd += length_;
+ }
+
+ // figure out the length of the new concatenated line, do so by
+ // finding the first line delimiter after position
+ int j = position;
+ bool eol = false;
+ while (j < textStore.length && !eol) {
+ if (j < gapStart || j >= gapEnd) {
+ char ch = textStore[j];
+ if (isDelimiter(ch)) {
+ if (j + 1 < textStore.length) {
+ if (ch is SWT.CR && (textStore[j+1] is SWT.LF)) {
+ j++;
+ }
+ }
+ eol = true;
+ }
+ }
+ j++;
+ }
+ // update the line where the deletion started
+ lines[startLine][1] = (position - startLineOffset) + (j - position);
+ // figure out the number of lines that have been deleted
+ int numOldLines = oldLines.length - 1;
+ if (splittingDelimiter) numOldLines -= 1;
+ // shift up the lines after the last deleted line, no need to update
+ // the offset or length of the lines
+ for (int i = endLine + 1; i < lineCount_; i++) {
+ lines[i - numOldLines] = lines[i];
+ }
+ lineCount_ -= numOldLines;
+ gapLine = getLineAtPhysicalOffset(gapStart);
+}
+
+/++
+ + SWT extension
+ +/
+int utf8AdjustOffset( int offset ){
+ if (textStore is null)
+ return offset;
+ if (offset is 0)
+ return offset;
+ if( offset >= textStore.length ){
+ return offset;
+ }
+ if (!gapExists() || (offset < gapStart)){
+ while( textStore[offset] & 0xC0 is 0x80 ){
+ offset--;
+ }
+ return offset;
+ }
+ int gapLength= gapEnd - gapStart;
+ if( offset+gapLength >= textStore.length ){
+ return offset;
+ }
+ while( textStore[offset+gapLength] & 0xC0 is 0x80 ){
+ offset--;
+ }
+ return offset;
+}
+
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ExtendedModifyEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ExtendedModifyEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * The following event fields are used:
+ * The following event fields are used:
+ * The following event fields are used:
+ * The following event fields are used:
+ * The following event fields are used:
+ * The following event fields are used:
+* @return the widget font
+*
+* @exception SWTException
+* This operation will fail if the items cannot
+* be queried from the OS.
+*
+* @return the items in the widget
+*
+* @exception SWTException
+* If the item is not currently selected, it is selected.
+* If the item at an index is selected, it remains selected.
+* If the string is not matched, it is ignored.
+*
+* @param string the text of the item
+*
+* @exception SWTException
+* When new font is null, the font reverts
+* to the default system font for the widget.
+*
+* @param font the new font (or null)
+*
+* @exception SWTException
+* The previous selection is cleared.
+* The previous items are deleted.
+* The new items are added.
+* The top index is set to 0.
+*
+* @param strings the array of items
+*
+* This operation will fail when an item is null
+* or could not be added in the OS.
+*
+* @exception IllegalArgumentException
+ *
+ *
+ *
+ * @param event the given event
+ * @see ExtendedModifyEvent
+ */
+public void modifyText(ExtendedModifyEvent event);
+}
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineBackgroundEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineBackgroundEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ *
+ * @param event the given event
+ * @see LineBackgroundEvent
+ */
+public void lineGetBackground(LineBackgroundEvent event);
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineStyleEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineStyleEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit ranges
can be used to share
+ * styles and reduce memory usage.
+ */
+ public StyleRange[] styles;
+
+ /**
+ * line alignment (input, output)
+ *
+ * @since 3.2
+ */
+ public int alignment;
+
+ /**
+ * line indent (input, output)
+ *
+ * @since 3.2
+ */
+ public int indent;
+
+ /**
+ * line justification (input, output)
+ *
+ * @since 3.2
+ */
+ public bool justify;
+
+ /**
+ * line bullet (output)
+ * @since 3.2
+ */
+ public Bullet bullet;
+
+ /**
+ * line bullet index (output)
+ * @since 3.2
+ */
+ public int bulletIndex;
+
+ static final long serialVersionUID = 3906081274027192884L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given event.
+ *
+ * @param e the event containing the information
+ */
+public this(StyledTextEvent e) {
+ super(cast(Object)e);
+ styles = e.styles;
+ ranges = e.ranges;
+ lineOffset = e.detail;
+ lineText = e.text;
+ alignment = e.alignment;
+ justify = e.justify;
+ indent = e.indent;
+ bullet = e.bullet;
+ bulletIndex = e.bulletIndex;
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineStyleListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineStyleListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ *
+ * @param event the given event
+ * @see LineStyleEvent
+ */
+public void lineGetStyle(LineStyleEvent event);
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/MovementEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/MovementEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ *
+ * @param event the event
+ *
+ * @see MovementEvent
+ * @see StyledText#addWordMovementListener(MovementListener)
+ */
+public void getNextOffset (MovementEvent event);
+/**
+ * This method is called when a new offset is required based on the current
+ * offset and a movement type.
+ *
+ *
+ *
+ *
+ * @param event the event
+ *
+ * @see MovementEvent
+ * @see StyledText#addWordMovementListener(MovementListener)
+ */
+public void getPreviousOffset (MovementEvent event);
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PaintObjectEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PaintObjectEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ *
+ * @param event the event
+ *
+ * @see PaintObjectEvent
+ * @see StyledText#addPaintObjectListener(PaintObjectListener)
+ */
+public void paintObject(PaintObjectEvent event);
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PopupList.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PopupList.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+*
+*/
+public Font getFont () {
+ return list.getFont();
+}
+/**
+* Gets the items.
+*
+*
+*/
+public String[] getItems () {
+ return list.getItems();
+}
+/**
+* Gets the minimum width of the list.
+*
+* @return the minimum width of the list
+*/
+public int getMinimumWidth () {
+ return minimumWidth;
+}
+/**
+* Launches the Popup List, waits for an item to be selected and then closes the PopupList.
+*
+* @param rect the initial size and location of the PopupList; the dialog will be
+* positioned so that it does not run off the screen and the largest number of items are visible
+*
+* @return the text of the selected item or null if no item is selected
+*/
+public String open (Rectangle rect) {
+
+ Point listSize = list.computeSize (rect.width, SWT.DEFAULT, false);
+ Rectangle screenSize = shell.getDisplay().getBounds();
+
+ // Position the dialog so that it does not run off the screen and the largest number of items are visible
+ int spaceBelow = screenSize.height - (rect.y + rect.height) - 30;
+ int spaceAbove = rect.y - 30;
+
+ int y = 0;
+ if (spaceAbove > spaceBelow && listSize.y > spaceBelow) {
+ // place popup list above table cell
+ if (listSize.y > spaceAbove){
+ listSize.y = spaceAbove;
+ } else {
+ listSize.y += 2;
+ }
+ y = rect.y - listSize.y;
+
+ } else {
+ // place popup list below table cell
+ if (listSize.y > spaceBelow){
+ listSize.y = spaceBelow;
+ } else {
+ listSize.y += 2;
+ }
+ y = rect.y + rect.height;
+ }
+
+ // Make dialog as wide as the cell
+ listSize.x = rect.width;
+ // dialog width should not be less than minimumWidth
+ if (listSize.x < minimumWidth)
+ listSize.x = minimumWidth;
+
+ // Align right side of dialog with right side of cell
+ int x = rect.x + rect.width - listSize.x;
+
+ shell.setBounds(x, y, listSize.x, listSize.y);
+
+ shell.open();
+ list.setFocus();
+
+ Display display = shell.getDisplay();
+ while (!shell.isDisposed () && shell.isVisible ()) {
+ if (!display.readAndDispatch()) display.sleep();
+ }
+
+ String result = null;
+ if (!shell.isDisposed ()) {
+ String [] strings = list.getSelection ();
+ shell.dispose();
+ if (strings.length !is 0) result = strings [0];
+ }
+ return result;
+}
+/**
+* Selects an item with text that starts with specified String.
+*
+*
+*/
+public void select(String string) {
+ String[] items = list.getItems();
+
+ // find the first entry in the list that starts with the
+ // specified string
+ if (string !is null){
+ for (int i = 0; i < items.length; i++) {
+ if ( tango.text.Util.locatePattern( items[i], string) is 0 ){
+ int index = list.indexOf(items[i]);
+ list.select(index);
+ break;
+ }
+ }
+ }
+}
+/**
+* Sets the widget font.
+*
+*
+*/
+public void setFont (Font font) {
+ list.setFont(font);
+}
+/**
+* Sets all items.
+*
+*
+* @exception SWTException
+*
+*/
+public void setItems (String[] strings) {
+ list.setItems(strings);
+}
+/**
+* Sets the minimum width of the list.
+*
+* @param width the minimum width of the list
+*/
+public void setMinimumWidth (int width) {
+ if (width < 0)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ minimumWidth = width;
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ST.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ST.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit StyledText
.
+ *
+ * @see Sample code and further information
+ */
+public class ST {
+
+ /*
+ * Navigation Key Actions. Key bindings for the actions are set
+ * by the StyledText widget.
+ */
+ public static const int LINE_UP = 16777217; // binding = SWT.ARROW_UP
+ public static const int LINE_DOWN = 16777218; // binding = SWT.ARROW_DOWN
+ public static const int LINE_START = 16777223; // binding = SWT.HOME
+ public static const int LINE_END = 16777224; // binding = SWT.END
+ public static const int COLUMN_PREVIOUS = 16777219; // binding = SWT.ARROW_LEFT
+ public static const int COLUMN_NEXT = 16777220; // binding = SWT.ARROW_RIGHT
+ public static const int PAGE_UP = 16777221; // binding = SWT.PAGE_UP
+ public static const int PAGE_DOWN = 16777222; // binding = SWT.PAGE_DOWN
+ public static const int WORD_PREVIOUS = 17039363; // binding = SWT.MOD1 + SWT.ARROW_LEFT
+ public static const int WORD_NEXT = 17039364; // binding = SWT.MOD1 + SWT.ARROW_RIGHT
+ public static const int TEXT_START = 17039367; // binding = SWT.MOD1 + SWT.HOME
+ public static const int TEXT_END = 17039368; // binding = SWT.MOD1 + SWT.END
+ public static const int WINDOW_START = 17039365; // binding = SWT.MOD1 + SWT.PAGE_UP
+ public static const int WINDOW_END = 17039366; // binding = SWT.MOD1 + SWT.PAGE_DOWN
+
+ /*
+ * Selection Key Actions
+ */
+ public static const int SELECT_ALL = 262209; // binding = SWT.MOD1 + 'A'
+ public static const int SELECT_LINE_UP = 16908289; // binding = SWT.MOD2 + SWT.ARROW_UP
+ public static const int SELECT_LINE_DOWN = 16908290; // binding = SWT.MOD2 + SWT.ARROW_DOWN
+ public static const int SELECT_LINE_START = 16908295; // binding = SWT.MOD2 + SWT.HOME
+ public static const int SELECT_LINE_END = 16908296; // binding = SWT.MOD2 + SWT.END
+ public static const int SELECT_COLUMN_PREVIOUS = 16908291; // binding = SWT.MOD2 + SWT.ARROW_LEFT
+ public static const int SELECT_COLUMN_NEXT = 16908292; // binding = SWT.MOD2 + SWT.ARROW_RIGHT
+ public static const int SELECT_PAGE_UP = 16908293; // binding = SWT.MOD2 + SWT.PAGE_UP
+ public static const int SELECT_PAGE_DOWN = 16908294; // binding = SWT.MOD2 + SWT.PAGE_DOWN
+ public static const int SELECT_WORD_PREVIOUS = 17170435; // binding = SWT.MOD1 + SWT.MOD2 + SWT.ARROW_LEFT
+ public static const int SELECT_WORD_NEXT = 17170436; // binding = SWT.MOD1 + SWT.MOD2 + SWT.ARROW_RIGHT
+ public static const int SELECT_TEXT_START = 17170439; // binding = SWT.MOD1 + SWT.MOD2 + SWT.HOME
+ public static const int SELECT_TEXT_END = 17170440; // binding = SWT.MOD1 + SWT.MOD2 + SWT.END
+ public static const int SELECT_WINDOW_START = 17170437; // binding = SWT.MOD1 + SWT.MOD2 + SWT.PAGE_UP
+ public static const int SELECT_WINDOW_END = 17170438; // binding = SWT.MOD1 + SWT.MOD2 + SWT.PAGE_DOWN
+
+ /*
+ * Modification Key Actions
+ */
+ public static const int CUT = 131199; // binding = SWT.MOD2 + SWT.DEL
+ public static const int COPY = 17039369; // binding = SWT.MOD1 + SWT.INSERT;
+ public static const int PASTE = 16908297; // binding = SWT.MOD2 + SWT.INSERT ;
+ public static const int DELETE_PREVIOUS = '\b'; // binding = SWT.BS;
+ public static const int DELETE_NEXT = 0x7F; // binding = SWT.DEL;
+ public static const int DELETE_WORD_PREVIOUS = 262152; // binding = SWT.BS | SWT.MOD1;
+ public static const int DELETE_WORD_NEXT = 262271; // binding = SWT.DEL | SWT.MOD1;
+
+ /*
+ * Miscellaneous Key Actions
+ */
+ public static const int TOGGLE_OVERWRITE = 16777225; // binding = SWT.INSERT;
+
+ /**
+ * Bullet style dot.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static const int BULLET_DOT = 1 << 0;
+
+ /**
+ * Bullet style number.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static const int BULLET_NUMBER = 1 << 1;
+
+ /**
+ * Bullet style lower case letter.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static const int BULLET_LETTER_LOWER = 1 << 2;
+
+ /**
+ * Bullet style upper case letter.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static const int BULLET_LETTER_UPPER = 1 << 3;
+
+ /**
+ * Bullet style text.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static const int BULLET_TEXT = 1 << 4;
+
+ /**
+ * Bullet style custom draw.
+ *
+ * @see StyledText#addPaintObjectListener(PaintObjectListener)
+ * @see StyledText#removePaintObjectListener(PaintObjectListener)
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static const int BULLET_CUSTOM = 1 << 5;
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/SashForm.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/SashForm.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ *
+ * 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: No Layout can be set on this Control because it already + * manages the size and position of its children. + *
+ * + * @param layout the receiver's new layout or null + * + * @exception SWTExceptionThere are two ways to use the ScrolledComposite: + * + *
+ * 1) Set the size of the control that is being scrolled and the ScrolledComposite
+ * will show scrollbars when the contained control can not be fully seen.
+ *
+ * 2) The second way imitates the way a browser would work. Set the minimum size of
+ * the control and the ScrolledComposite will show scroll bars if the visible area is
+ * less than the minimum size of the control and it will expand the size of the control
+ * if the visible area is greater than the minimum size. This requires invoking
+ * both setMinWidth(), setMinHeight() and setExpandHorizontal(), setExpandVertical().
+ *
+ *
+ *
+ *
+ * public static void main (String [] args) {
+ * Display display = new Display ();
+ * Color red = display.getSystemColor(SWT.COLOR_RED);
+ * Color blue = display.getSystemColor(SWT.COLOR_BLUE);
+ * Shell shell = new Shell (display);
+ * shell.setLayout(new FillLayout());
+ *
+ * // set the size of the scrolled content - method 1
+ * final ScrolledComposite sc1 = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ * final Composite c1 = new Composite(sc1, SWT.NONE);
+ * sc1.setContent(c1);
+ * c1.setBackground(red);
+ * GridLayout layout = new GridLayout();
+ * layout.numColumns = 4;
+ * c1.setLayout(layout);
+ * Button b1 = new Button (c1, SWT.PUSH);
+ * b1.setText("first button");
+ * c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ *
+ * // set the minimum width and height of the scrolled content - method 2
+ * final ScrolledComposite sc2 = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ * sc2.setExpandHorizontal(true);
+ * sc2.setExpandVertical(true);
+ * final Composite c2 = new Composite(sc2, SWT.NONE);
+ * sc2.setContent(c2);
+ * c2.setBackground(blue);
+ * layout = new GridLayout();
+ * layout.numColumns = 4;
+ * c2.setLayout(layout);
+ * Button b2 = new Button (c2, SWT.PUSH);
+ * b2.setText("first button");
+ * sc2.setMinSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ *
+ * Button add = new Button (shell, SWT.PUSH);
+ * add.setText("add children");
+ * final int[] index = new int[]{0};
+ * add.addListener(SWT.Selection, new Listener() {
+ * public void handleEvent(Event e) {
+ * index[0]++;
+ * Button button = new Button(c1, SWT.PUSH);
+ * button.setText("button "+index[0]);
+ * // reset size of content so children can be seen - method 1
+ * c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ * c1.layout();
+ *
+ * button = new Button(c2, SWT.PUSH);
+ * button.setText("button "+index[0]);
+ * // reset the minimum width and height so children can be seen - method 2
+ * sc2.setMinSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ * c2.layout();
+ * }
+ * });
+ *
+ * shell.open ();
+ * while (!shell.isDisposed ()) {
+ * if (!display.readAndDispatch ()) display.sleep ();
+ * }
+ * display.dispose ();
+ * }
+ *
+ * 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.
+ *
true
if the content control
+ * will be expanded to fill available horizontal space.
+ *
+ * @return the receiver's horizontal expansion state
+ *
+ * @exception SWTException true
if the content control
+ * will be expanded to fill available vertical space.
+ *
+ * @return the receiver's vertical expansion state
+ *
+ * @exception SWTException true
if the receiver automatically scrolls to a focused child control
+ * to make it visible. Otherwise, returns false
.
+ *
+ * @return a bool indicating whether focused child controls are automatically scrolled into the viewport
+ *
+ * @exception SWTException + * Note: No Layout can be set on this Control because it already + * manages the size and position of its children. + *
+ * + * @param layout the receiver's new layout or null + * + * @exception SWTExceptionfalse
, show a focused control is off.
+ * By default, show a focused control is off.
+ *
+ * @param show true
to show a focused control.
+ *
+ * @exception SWTException Here is an example which places ten buttons in a stack layout and + * flips between them: + * + *
+ * public static void main(String[] args) {
+ * Display display = new Display();
+ * Shell shell = new Shell(display);
+ * shell.setLayout(new GridLayout());
+ *
+ * final Composite parent = new Composite(shell, SWT.NONE);
+ * parent.setLayoutData(new GridData(GridData.FILL_BOTH));
+ * final StackLayout layout = new StackLayout();
+ * parent.setLayout(layout);
+ * final Button[] bArray = new Button[10];
+ * for (int i = 0; i < 10; i++) {
+ * bArray[i] = new Button(parent, SWT.PUSH);
+ * bArray[i].setText("Button "+i);
+ * }
+ * layout.topControl = bArray[0];
+ *
+ * Button b = new Button(shell, SWT.PUSH);
+ * b.setText("Show Next Button");
+ * final int[] index = new int[1];
+ * b.addListener(SWT.Selection, new Listener(){
+ * public void handleEvent(Event e) {
+ * index[0] = (index[0] + 1) % 10;
+ * layout.topControl = bArray[index[0]];
+ * parent.layout();
+ * }
+ * });
+ *
+ * shell.open();
+ * while (shell !is null && !shell.isDisposed()) {
+ * if (!display.readAndDispatch())
+ * display.sleep();
+ * }
+ * }
+ *
+ *
+ * @see StackLayout snippets
+ * @see SWT Example: LayoutExample
+ * @see Sample code and further information
+ */
+
+public class StackLayout : Layout {
+
+ /**
+ * marginWidth specifies the number of pixels of horizontal margin
+ * that will be placed along the left and right edges of the layout.
+ *
+ * The default value is 0.
+ */
+ public int marginWidth = 0;
+ /**
+ * marginHeight specifies the number of pixels of vertical margin
+ * that will be placed along the top and bottom edges of the layout.
+ *
+ * The default value is 0.
+ */
+ public int marginHeight = 0;
+
+ /**
+ * topControl the Control that is displayed at the top of the stack.
+ * All other controls that are children of the parent composite will not be visible.
+ */
+ public Control topControl;
+
+protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+ Control children[] = composite.getChildren();
+ int maxWidth = 0;
+ int maxHeight = 0;
+ for (int i = 0; i < children.length; i++) {
+ Point size = children[i].computeSize(wHint, hHint, flushCache);
+ maxWidth = Math.max(size.x, maxWidth);
+ maxHeight = Math.max(size.y, maxHeight);
+ }
+ int width = maxWidth + 2 * marginWidth;
+ int height = maxHeight + 2 * marginHeight;
+ if (wHint !is SWT.DEFAULT) width = wHint;
+ if (hHint !is SWT.DEFAULT) height = hHint;
+ return new Point(width, height);
+}
+
+protected override bool flushCache(Control control) {
+ return true;
+}
+
+protected override void layout(Composite composite, bool flushCache) {
+ Control children[] = composite.getChildren();
+ Rectangle rect = composite.getClientArea();
+ rect.x += marginWidth;
+ rect.y += marginHeight;
+ rect.width -= 2 * marginWidth;
+ rect.height -= 2 * marginHeight;
+ for (int i = 0; i < children.length; i++) {
+ children[i].setBounds(rect);
+ children[i].setVisible(children[i] is topControl);
+
+ }
+}
+
+String getName () {
+ String string = this.classinfo.name;
+ int index = tango.text.Util.locatePrior( string ,'.');
+ if (index is string.length ) return string;
+ return string[ index + 1 .. $ ];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the layout
+ */
+public override String toString () {
+ String string = getName ()~" {";
+ if (marginWidth !is 0) string ~= "marginWidth="~to!(String)(marginWidth)~" ";
+ if (marginHeight !is 0) string ~= "marginHeight="~to!(String)(marginHeight)~" ";
+ if (topControl !is null) string ~= "topControl="~to!(String)(topControl)~" ";
+ string = tango.text.Util.trim(string);
+ string ~= "}";
+ return string;
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyleRange.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyleRange.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit StyleRange
defines a set of styles for a specified
+ * range of text.
+ * + * The hashCode() method in this class uses the values of the public + * fields to compute the hash value. When storing instances of the + * class in hashed collections, do not modify these fields after the + * object has been inserted. + *
+ * + * @see Sample code and further information + */ +public class StyleRange : TextStyle, CloneableCompatibility { + + /** + * the start offset of the range, zero-based from the document start + */ + public int start; + + /** + * the length of the range + */ + public int length; + + /** + * the font style of the range. It may be a combination of + * SWT.NORMAL, SWT.ITALIC or SWT.BOLD + * + * Note: the font style is not used if thefont
attribute
+ * is set
+ */
+ public int fontStyle = SWT.NORMAL;
+
+/**
+ * Create a new style range with no styles
+ *
+ * @since 3.2
+ */
+public this() {
+}
+/++
+ + SWT extension for clone implementation
+ +/
+protected this( StyleRange other ){
+ super( other );
+ start = other.start;
+ length = other.length;
+ fontStyle = other.fontStyle;
+}
+
+/**
+ * Create a new style range from an existing text style.
+ *
+ * @param style the text style to copy
+ *
+ * @since 3.4
+ */
+public this(TextStyle style) {
+ super(style);
+}
+
+/**
+ * Create a new style range.
+ *
+ * @param start start offset of the style
+ * @param length length of the style
+ * @param foreground foreground color of the style, null if none
+ * @param background background color of the style, null if none
+ */
+public this(int start, int length, Color foreground, Color background) {
+ super(null, foreground, background);
+ this.start = start;
+ this.length = length;
+}
+
+/**
+ * Create a new style range.
+ *
+ * @param start start offset of the style
+ * @param length length of the style
+ * @param foreground foreground color of the style, null if none
+ * @param background background color of the style, null if none
+ * @param fontStyle font style of the style, may be SWT.NORMAL, SWT.ITALIC or SWT.BOLD
+ */
+public this(int start, int length, Color foreground, Color background, int fontStyle) {
+ this(start, length, foreground, background);
+ this.fontStyle = fontStyle;
+}
+
+/**
+ * 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 override int opEquals(Object object) {
+ if (object is this) return true;
+ if (auto style = cast(StyleRange) object ) {
+ if (start !is style.start) return false;
+ if (length !is style.length) return false;
+ return similarTo(style);
+ }
+ 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 override hash_t toHash() {
+ return super.toHash() ^ fontStyle;
+}
+bool isVariableHeight() {
+ return font !is null || metrics !is null || rise !is 0;
+}
+/**
+ * Returns whether or not the receiver is unstyled (i.e., does not have any
+ * style attributes specified).
+ *
+ * @return true if the receiver is unstyled, false otherwise.
+ */
+public bool isUnstyled() {
+ if (font !is null) return false;
+ if (rise !is 0) return false;
+ if (metrics !is null) return false;
+ if (foreground !is null) return false;
+ if (background !is null) return false;
+ if (fontStyle !is SWT.NORMAL) return false;
+ if (underline) return false;
+ if (strikeout) return false;
+ if (borderStyle !is SWT.NONE) return false;
+ return true;
+}
+
+/**
+ * Compares the specified object to this StyleRange and answer if the two
+ * are similar. The object must be an instance of StyleRange and have the
+ * same field values for except for start and length.
+ *
+ * @param style the object to compare with this object
+ * @return true if the objects are similar, false otherwise
+ */
+public bool similarTo(StyleRange style) {
+ if (!super.opEquals(style)) return false;
+ if (fontStyle !is style.fontStyle) return false;
+ return true;
+}
+
+/**
+ * Returns a new StyleRange with the same values as this StyleRange.
+ *
+ * @return a shallow copy of this StyleRange
+ */
+public /+override+/ Object clone() {
+ return new StyleRange( this );
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the StyleRange
+ */
+public override String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("StyleRange {");
+ buffer.append(start);
+ buffer.append(", ");
+ buffer.append(length);
+ buffer.append(", fontStyle=");
+ switch (fontStyle) {
+ case SWT.BOLD:
+ buffer.append("bold");
+ break;
+ case SWT.ITALIC:
+ buffer.append("italic");
+ break;
+ case SWT.BOLD | SWT.ITALIC:
+ buffer.append("bold-italic");
+ break;
+ default:
+ buffer.append("normal");
+ }
+ String str = super.toString();
+ int index = tango.text.Util.locate( str, '{');
+ if( index is str.length ) index = -1;
+ str = str[ index + 1 .. $ ];
+ if (str.length > 1) buffer.append(", ");
+ buffer.append(str);
+ return buffer.toString();
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledText.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledText.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,8457 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit + * 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: + *
+ * 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: + *
+ * 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. + *
+ *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see StyledText snippets + * @see SWT Examples: CustomControlExample, TextEditor + * @see Sample code and further information + */ +public class StyledText : Canvas { + alias Canvas.computeSize computeSize; + + static const char TAB = '\t'; + static const String PlatformLineDelimiter = tango.io.model.IFile.FileConst.NewlineString; + static const int BIDI_CARET_WIDTH = 3; + static const int DEFAULT_WIDTH = 64; + static const int DEFAULT_HEIGHT = 64; + static const int V_SCROLL_RATE = 50; + static const int H_SCROLL_RATE = 10; + + static const int ExtendedModify = 3000; + static const int LineGetBackground = 3001; + static const int LineGetStyle = 3002; + static const int TextChanging = 3003; + static const int TextSet = 3004; + static const int VerifyKey = 3005; + static const int TextChanged = 3006; + static const int LineGetSegments = 3007; + static const int PaintObject = 3008; + static const int WordNext = 3009; + static const int WordPrevious = 3010; + + static const int PREVIOUS_OFFSET_TRAILING = 0; + static const 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; // 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 + bool editable = true; + bool wordWrap = false; + bool doubleClickEnabled = true; // see getDoubleClickEnabled + bool overwrite = false; // insert/overwrite edit mode + int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. + int[int] keyActionMap; + Color background = null; // workaround for bug 4791 + Color foreground = null; // + 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 lastLineBottom; // the bottom pixel of the last line been replaced + bool isMirrored_; + bool 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; + bool updateCaretDirection = true; + bool fixedLineHeight; + bool dragDetect_ = true; + IME ime; + + int alignment; + bool justify; + int indent; + int lineSpacing; + + const static bool IS_CARBON, IS_GTK, IS_MOTIF; + static this(){ + String platform = SWT.getPlatform(); + IS_CARBON = ("carbon" == platform); + IS_GTK = ("gtk" == platform); + IS_MOTIF = ("motif" == platform); + } + + /** + * The Printing class : printing of a range of text. + * An instance ofPrinting
is returned in the
+ * StyledText#print(Printer) API. The run() method may be
+ * invoked from any thread.
+ */
+ static class Printing : Runnable {
+ const static int LEFT = 0; // left aligned header/footer segment
+ const static int CENTER = 1; // centered header/footer segment
+ const static int RIGHT = 2; // right aligned header/footer segment
+
+ Printer printer;
+ StyledTextRenderer printerRenderer;
+ StyledTextPrintOptions printOptions;
+ Rectangle clientArea;
+ FontData fontData;
+ Font printerFont;
+ Resource[Resource] 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
+ bool singleLine; // widget single line mode
+ Point selection = null; // selected text
+ bool 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
+ */
+ this(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) {
+ this.printer = printer;
+ this.printOptions = printOptions;
+ this.mirrored = (styledText.getStyle() & SWT.MIRRORED) !is 0;
+ singleLine = styledText.isSingleLine();
+ startPage = 1;
+ endPage = int.max;
+ PrinterData data = printer.getPrinterData();
+ if (data.scope_ is PrinterData.PAGE_RANGE) {
+ startPage = data.startPage;
+ endPage = data.endPage;
+ if (endPage < startPage) {
+ int temp = endPage;
+ endPage = startPage;
+ startPage = temp;
+ }
+ } else if (data.scope_ is 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 !is null && event.lineBackground !is 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 !is 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 !is null && styles.length > 0) {
+ printerRenderer.setStyleRanges(event.ranges, styles);
+ }
+ }
+ }
+ }
+ Point screenDPI = styledText.getDisplay().getDPI();
+ Point printerDPI = printer.getDPI();
+ resources = null;
+ for (int i = 0; i < lineCount; i++) {
+ Color color = printerRenderer.getLineBackground(i, null);
+ if (color !is null) {
+ if (printOptions.printLineBackground) {
+ Color printerColor;
+ if ( auto p = color in resources ) {
+ printerColor = cast(Color)*p;
+ }
+ else {
+ printerColor = new Color (printer, color.getRGB());
+ resources[color]=printerColor;
+ }
+ printerRenderer.setLineBackground(i, 1, printerColor);
+ } else {
+ printerRenderer.setLineBackground(i, 1, null);
+ }
+ }
+ int indent = printerRenderer.getLineIndent(i, 0);
+ if (indent !is 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 !is null) {
+ Font printerFont;
+ if ( auto p = font in resources ) {
+ printerFont = cast(Font)*p;
+ }
+ else {
+ printerFont = new Font (printer, font.getFontData());
+ resources[font]= printerFont;
+ }
+ style.font = printerFont;
+ }
+ Color color = style.foreground;
+ if (color !is null) {
+ if (printOptions.printTextForeground) {
+ Color printerColor;
+ if ( auto p = color in resources ) {
+ printerColor = cast(Color)*p;
+ }
+ else {
+ printerColor = new Color (printer, color.getRGB());
+ resources[color]=printerColor;
+ }
+ style.foreground = printerColor;
+ } else {
+ style.foreground = null;
+ }
+ }
+ color = style.background;
+ if (color !is null) {
+ if (printOptions.printTextBackground) {
+ Color printerColor;
+ if ( auto p = color in resources ) {
+ printerColor = cast(Color)*p;
+ }
+ else {
+ printerColor = new Color (printer, color.getRGB());
+ resources[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 !is 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 !is null) {
+ gc.dispose();
+ gc = null;
+ }
+ foreach( resource; resources.values ){
+ resource.dispose();
+ }
+ resources = null;
+ if (printerFont !is null) {
+ printerFont.dispose();
+ printerFont = null;
+ }
+ if (printerRenderer !is null) {
+ printerRenderer.dispose();
+ printerRenderer = null;
+ }
+ }
+ void init_() {
+ Rectangle trim = printer.computeTrim(0, 0, 0, 0);
+ Point dpi = printer.getDPI();
+
+ printerFont = new Font( cast(Device)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 !is null) {
+ clientArea.y += lineHeight * 2;
+ clientArea.height -= lineHeight * 2;
+ }
+ if (printOptions.footer !is 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_ is PrinterData.PAGE_RANGE) {
+ int pageSize = clientArea.height / lineHeight;//WRONG
+ startLine = (startPage - 1) * pageSize;
+ } else if (data.scope_ is 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 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 !is null || printOptions.footer !is 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 !is null) {
+ for (int i = startLine; i < Math.min(count, lineLabels.length); i++) {
+ if (lineLabels[i] !is null) {
+ printLayout.setText(lineLabels[i]);
+ int lineWidth = printLayout.getBounds().width;
+ numberingWidth = Math.max(numberingWidth, lineWidth);
+ }
+ }
+ } else {
+ StringBuffer buffer = new StringBuffer("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 is 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 is 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(cast(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(cast(Rectangle)null);
+ paintY += layoutHeight;
+ }
+ }
+ }
+ printerRenderer.disposeTextLayout(layout);
+ }
+ if (page <= endPage && paintY > clientArea.y) {
+ // close partial page
+ printDecoration(page, false, printLayout);
+ printer.endPage();
+ }
+ if (printLayout !is 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, bool header, TextLayout layout) {
+ String text = header ? printOptions.header : printOptions.footer;
+ if (text is null) return;
+ int lastSegmentIndex = 0;
+ for (int i = 0; i < 3; i++) {
+ int segmentIndex = text.indexOf( StyledTextPrintOptions.SEPARATOR, lastSegmentIndex);
+ String segment;
+ if (segmentIndex is -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, bool header, TextLayout layout) {
+ int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG);
+ if (pageIndex !is -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().dup;
+ }
+ if (segment.length > 0) {
+ layout.setText(segment);
+ int segmentWidth = layout.getBounds().width;
+ int segmentHeight = printerRenderer.getLineHeight();
+ int drawX = 0, drawY;
+ if (alignment is LEFT) {
+ drawX = clientArea.x;
+ } else if (alignment is CENTER) {
+ drawX = (pageWidth - segmentWidth) / 2;
+ } else if (alignment is 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 !is 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 !is null) {
+ if (0 <= index && index < lineLabels.length && lineLabels[index] !is null) {
+ printLayout.setText(lineLabels[index]);
+ } else {
+ printLayout.setText("");
+ }
+ } else {
+ printLayout.setText(to!(String)(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.
+ */
+ public void run() {
+ String jobName = printOptions.jobName;
+ if (jobName is 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 : TextWriter { + + alias TextWriter.write write; + + static const int DEFAULT_FOREGROUND = 0; + static const int DEFAULT_BACKGROUND = 1; + Color[] colorTable; + Font[] fontTable; + bool WriteUnicode; + + /** + * Creates a RTF 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 this(int start, int length) {
+ super(start, length);
+ colorTable ~= getForeground();
+ colorTable ~= getBackground();
+ fontTable ~= 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 override 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 is null) return defaultIndex;
+ int index = -1;
+ foreach( i, col; colorTable ){
+ if( col == color ){
+ index = i;
+ break;
+ }
+ }
+ if (index is -1) {
+ index = colorTable.length;
+ colorTable ~= 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 = -1;
+ foreach( i, f; colorTable ){
+ if( f == font ){
+ index = i;
+ break;
+ }
+ }
+ if (index is -1) {
+ index = fontTable.length;
+ fontTable ~= font;
+ }
+ return index;
+ }
+ /**
+ * Determines if Unicode RTF should be written.
+ * Don't write Unicode RTF on Windows 95/98/ME or NT.
+ */
+ void setUnicode() {
+// const String Win95 = "windows 95";
+// const String Win98 = "windows 98";
+// const String WinME = "windows me";
+// const 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 !is null) {
+// int majorIndex = osVersion.indexOf('.');
+// if (majorIndex !is -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);
+ WriteUnicode = true; // we are on linux-gtk
+ }
+ /**
+ * 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) {
+ start = 0;
+ end = string.length;
+ int incr = 1;
+ for (int index = start; index < end; index+=incr) {
+ dchar ch = firstCodePoint( string[index .. $], incr );
+ 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[start .. index ] );
+ }
+ write("\\u");
+ write( to!(String)( cast(short)ch ));
+ write(' '); // control word delimiter
+ start = index + incr;
+ } else if (ch is '}' || ch is '{' || ch is '\\') {
+ // write the sub string from the last escaped character
+ // to the current one. Fixes bug 21698.
+ if (index > start) {
+ write(string[start .. index]);
+ }
+ write('\\');
+ write(cast(char)ch); // ok because one of {}\
+ start = index + 1;
+ }
+ }
+ // write from the last escaped character to the end.
+ // Fixes bug 21698.
+ if (start < end) {
+ write(string[ 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.
+ // PORTING_TODO: String cpg = System.getProperty("file.encoding").toLowerCase();
+ String cpg = "UTF16";
+ /+
+ 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.length; i++) {
+ header.append("\\f");
+ header.append(i);
+ header.append(" ");
+ FontData fd = (cast(Font)fontTable[i]).getFontData()[0];
+ header.append(fd.getName());
+ header.append(";");
+ }
+ header.append("}}\n{\\colortbl");
+ for (int i = 0; i < colorTable.length; i++) {
+ Color color = cast(Color) colorTable[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 + * 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, bool 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; + default: + } + if (justify) write("\\qj"); + write(" "); + + if (lineBackground !is 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 !is 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 beyond 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 !is DEFAULT_BACKGROUND) { + write("\\highlight"); + write(colorIndex); + } + Font font = style.font; + if (font !is 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) !is 0) { + write("\\b"); + } + if ((style.fontStyle & SWT.ITALIC) !is 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 is null) { + if ((style.fontStyle & SWT.BOLD) !is 0) { + write("\\b0"); + } + if ((style.fontStyle & SWT.ITALIC) !is 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 !is null) write("}"); + } + } + /** + * TheTextWriter
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.
+ *
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 this(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 bool specifying whether or not the writer is closed
+ */
+ public bool isClosed() {
+ return isClosed_;
+ }
+ /**
+ * Returns the string. close()
must be called before toString()
+ * is guaranteed to return a valid string.
+ *
+ * @return the string
+ */
+ public override 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.select( offset ); + buffer.prepend( 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
+ * 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.
+ *
+ * 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
+ * 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.
+ *
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.
+ *
+ * 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.
+ *
+ * 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 is 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 !is -1) { + crIndex = text.indexOf (SWT.CR, i); + } + if (lfIndex !is -1) { + lfIndex = text.indexOf (SWT.LF, i); + } + if (lfIndex is -1 && crIndex is -1) { // no more line breaks? + break; + } else if ((crIndex < lfIndex && crIndex !is -1) || lfIndex is -1) { + convertedText.append(text.substring(i, crIndex)); + if (lfIndex is 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() is 0)) { + convertedText.append(text.substring(i)); + } + return convertedText.toString(); +} +bool checkDragDetect(Event event) { + if (!isListening(SWT.DragDetect)) return false; + if (IS_MOTIF) { + if (event.button !is 2) return false; + } else { + if (event.button !is 1) return false; + } + if (selection.x is selection.y) return false; + int offset = getOffsetAtPoint(event.x, event.y, null, true); + if (selection.x <= offset && offset < selection.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_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 !is null) { + if (defaultCaret !is null && leftCaretBitmap==/*eq*/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 !is null) { + if (defaultCaret !is null && rightCaretBitmap==/*eq*/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+ * 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(dchar key) { + 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 is SWT.CR || key is SWT.LF) { + if (!isSingleLine()) { + event.text = getLineDelimiter(); + } + } else if (selection.x is selection.y && overwrite && key !is 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+=dcharToString( key ).length; + } + event.text = dcharToString( key ); + } else { + event.text = dcharToString( key ); + } + if (event.text !is 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(); + 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 !is 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 is 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 !is 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 = getWordNext(caretOffset, SWT.MOVEMENT_WORD); + sendKeyEvent(event); + } +} +/** + * Deletes the previous word. + */ +void doDeleteWordPrevious() { + if (selection.x !is 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 = 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. + */ +void doLineDown(bool select) { + int caretLine = getCaretLine(); + int lineCount = content.getLineCount(); + int y = 0; + bool 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 is layoutLineCount - 1) { + lastLine = caretLine is lineCount - 1; + caretLine++; + } else { + y = layout.getLineBounds(lineIndex + 1).y; + } + renderer.disposeTextLayout(layout); + } else { + lastLine = caretLine is 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. + */ +void doLineUp(bool select) { + int caretLine = getCaretLine(), y = 0; + bool 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 is 0) { + firstLine = caretLine is 0; + if (!firstLine) { + caretLine--; + y = renderer.getLineHeight(caretLine) - 1; + } + } else { + y = layout.getLineBounds(lineIndex - 1).y; + } + renderer.disposeTextLayout(layout); + } else { + firstLine = caretLine is 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, bool 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 (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 + if (0 <= y && y < clientAreaHeight && + (0 <= x && x < clientAreaWidth || wordWrap || + newCaretLine !is content.getLineAtOffset(caretOffset))) { + if (newCaretOffset !is caretOffset || caretAlignment !is 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 is 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 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 < selectionAnchor && selectionAnchor is selection.x) { + selectionAnchor = doubleClickSelection.y; + } else if (newCaretOffset > selectionAnchor && selectionAnchor is selection.y) { + selectionAnchor = doubleClickSelection.x; + } + if (0 <= x && x < clientAreaWidth) { + bool wordSelect = (clickCount & 1) is 0; + if (caretOffset is selection.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(bool 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 is -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 is -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 is 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 is -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 is 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(bool 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 is -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 is -1) { + if (topIndexY is 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 is 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 is -1) { + selectionAnchor = selection.x; + } + if (direction is 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 !is selectionAnchor) { + redrawEnd = selection.y; + selection.y = selectionAnchor; + } + // test whether selection actually changed. Fixes 1G71EO1 + } else if (selectionAnchor is 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 !is selectionAnchor) { + redrawStart = selection.x; + selection.x = selectionAnchor; + } + // test whether selection actually changed. Fixes 1G71EO1 + } else if (selectionAnchor is 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 !is -1 && redrawEnd !is -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 is 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 = getWordNext(caretOffset, SWT.MOVEMENT_WORD); + // 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) is content.getLineAtOffset(newCaretOffset)) { + caretOffset = newCaretOffset; + showCaret(); + } +} +/** + * Moves the caret to the start of the previous word. + */ +void doSelectionWordPrevious() { + caretAlignment = OFFSET_LEADING; + caretOffset = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD); + 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 is 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 override Color getBackground() { + checkWidget(); + if (background is 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+ * + * @param lineIndex index of the line to return. + * @return the line text without delimiters + * + * @exception SWTException
+ * 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+ * 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 is 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. + * + * @return the top pixel 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 is 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 pixel + * + * @return the line index for a given y-coordinate pixel + * + * @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 is 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+ * 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
+ * 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, bool)
.
+ *
+ * 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, bool)
.
+ *
+ * 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 is start of selection implies that the selection is RtoL). + * @see #getSelectionRange + * @exception SWTException+ * 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 is offset and length is 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+ * 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(bool)
+ * 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 + * 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.
+ *
+ * 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, bool)
+ * can be used to get the styles without the ranges.
+ *
StyleRange
will have a starting offset >= start
+ * and the last returned StyleRange
will have an ending
+ * offset <= start + length - 1
+ *
+ * @exception SWTException + * 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.
+ *
StyleRange
will have a starting offset >= start
+ * and the last returned StyleRange
will have an ending
+ * offset <= start + length - 1
+ *
+ * @exception SWTException + * 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+ * 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+ * 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 !is 0 && offsetInLine <= lineLength) { + if (offsetInLine is lineLength) { + // SWT: Instead of go back one byte, go back one codepoint + int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); + point = layout.getLocation(offsetInLine_m1, true); + } else { + switch (caretAlignment) { + case OFFSET_LEADING: + point = layout.getLocation(offsetInLine, false); + break; + case PREVIOUS_OFFSET_TRAILING: + default: + if (offsetInLine is 0) { + point = layout.getLocation(offsetInLine, false); + } else { + // SWT: Instead of go back one byte, go back one codepoint + int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); + point = layout.getLocation(offsetInLine_m1, 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 SWTExceptionDND.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 + * The runnable may be run in a non-UI thread. + *
+ * + * @param printer the printer to print to + * + * @return aRunnable
for printing the receiver's text
+ *
+ * @exception SWTException + * 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 aRunnable
for printing the receiver's text
+ *
+ * @exception SWTException
+ * 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.
+ *
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.
+ *
true
if children should redraw, and false
otherwise
+ *
+ * @exception SWTException
+ * 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+ * NOTE: During the replace operation the current selection is + * changed as follows: + *
+ * 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.justify = justify; + notifyListeners(eventType, event); + } + return event; +} +void sendModifyEvent(Event event) { + Accessible accessible = getAccessible(); + if (event.text.length is 0) { + accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start); + } else { + if (event.start is 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); +} +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 !is 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; +} +/** + * Sets the alignment of the widget. The argument should be one ofSWT.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.
+ *
+ * NOTE: Italic fonts are not supported unless they have no overhang + * and the same baseline as regular fonts. + *
+ * + * @param font new font + * @exception SWTException+ * 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+ * 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+ * 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+ * 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 SWTExceptionSWT.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.
+ *
+ * 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
+ * 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+ * 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+ * 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+ * 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 SWTExceptionSWT.LEFT_TO_RIGHT
or SWT.RIGHT_TO_LEFT
.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException + * 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+ * 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+ * 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+ * 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, bool sendEvent) { + int end = start + length; + start = content.utf8AdjustOffset(start); + end = content.utf8AdjustOffset(end); + if (start > end) { + int temp = end; + end = start; + start = temp; + } + // is the selection range different or is the selection direction + // different? + if (selection.x !is start || selection.y !is end || + (length > 0 && selectionAnchor !is selection.x) || + (length < 0 && selectionAnchor !is selection.y)) { + clearSelection(sendEvent); + if (length < 0) { + selectionAnchor = selection.y = end; + caretOffset = selection.x = start; + } else { + selectionAnchor = selection.x = start; + caretOffset = selection.y = end; + } + caretAlignment = PREVIOUS_OFFSET_TRAILING; + 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+ * 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 SWTExceptionstart
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+ * 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
+ * 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+ * 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+ * The text limit specifies the amount of text that + * the user can type into the widget. + *
+ * + * @param limit the new text limit. + * @exception SWTException+ * 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+ * 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+ * 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(bool wrap) { + checkWidget(); + if ((getStyle() & SWT.SINGLE) !is 0) return; + if (wordWrap is wrap) return; + wordWrap = wrap; + setVariableLineHeight(); + resetCache(0, content.getLineCount()); + horizontalScrollOffset = 0; + ScrollBar horizontalBar = getHorizontalBar(); + if (horizontalBar !is null) { + horizontalBar.setVisible(!wordWrap); + } + setScrollBars(true); + setCaretLocation(); + super.redraw(); +} +// SWT: If necessary, scroll to show the location +bool showLocation(Rectangle rect, bool scrollPage) { + int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin; + int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; + bool scrolled = false; + if (rect.y <= topMargin) { + scrolled = scrollVertical(rect.y - topMargin, true); + } else if (rect.y + rect.height > clientAreaHeight) { + if (clientAreaHeight is 0) { + scrolled = scrollVertical(rect.y, true); + } else { + scrolled = scrollVertical(rect.y + rect.height - clientAreaHeight, true); + } + } + if (clientAreaWidth > 0) { + int minScroll = scrollPage ? clientAreaWidth / 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) { + int scrollWidth = Math.max(rect.x + rect.width - clientAreaWidth, minScroll); + 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, true)) { + 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+ * 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 + if (wordWrap) setCaretLocation(); + 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 -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextContent.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextContent.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,217 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank Benoit+ * + * @param listener the listener + * @exception IllegalArgumentException
+ * + * @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: + *
+ * + * @return the number of lines. For example: + *
+ * + * @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: + *+ * + * @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 which should no longer be notified + * + * @exception IllegalArgumentException
+ * 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:
+ *
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);
+
+/++
+ + SWT Extension
+ +/
+int utf8AdjustOffset( int offset );
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextDropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextDropTargetEffect.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Classes that wish to provide their own drag under effect for a The feedback value is either one of the FEEDBACK constants defined in
+ * class
+ * StyledText
.
+ *
+ * StyledText
+ * can extend this class, override the StyledTextDropTargetEffect.dragOver
+ * method and override any other applicable methods in StyledTextDropTargetEffect
to
+ * display their own drag under effect.super
method to get the default drag under effect implementation.
+ *
+ * DND
which is applicable to instances of this class,
+ * or it must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
effect constants.
+ *
+ *
+ *
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 this(StyledText styledText) {
+ super(styledText);
+ paintListener = new class() Listener {
+ public void handleEvent (Event event) {
+ if (currentOffset !is -1) {
+ StyledText text = cast(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
+ */
+ public override 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
+ */
+ public override void dragLeave(DropTargetEvent event) {
+ StyledText text = cast(StyledText) getControl();
+ if (currentOffset !is -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
+ */
+ public override void dragOver(DropTargetEvent event) {
+ int effect = event.feedback;
+ StyledText text = cast(StyledText) getControl();
+
+ Point pt = text.getDisplay().map(null, text, event.x, event.y);
+ if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+ scrollBeginTime = 0;
+ scrollX = scrollY = -1;
+ } else {
+ if (text.getCharCount() is 0) {
+ scrollBeginTime = 0;
+ scrollX = scrollY = -1;
+ } else {
+ if (scrollX !is -1 && scrollY !is -1 && scrollBeginTime !is 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();
+ int charWidth = fm.getAverageCharWidth();
+ int scrollAmount = 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) !is 0) {
+ int[] trailing = new int [1];
+ int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false);
+ newOffset += trailing [0];
+ if (newOffset !is currentOffset) {
+ refreshCaret(text, currentOffset, newOffset);
+ currentOffset = newOffset;
+ }
+ }
+ }
+
+ void refreshCaret(StyledText text, int oldOffset, int newOffset) {
+ if (oldOffset !is newOffset) {
+ if (oldOffset !is -1) {
+ Point oldPos = text.getLocationAtOffset(oldOffset);
+ int oldHeight = text.getLineHeight(oldOffset);
+ text.redraw (oldPos.x, oldPos.y, CARET_WIDTH, oldHeight, false);
+ }
+ if (newOffset !is -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
+ */
+ public override void dropAccept(DropTargetEvent event) {
+ if (currentOffset !is -1) {
+ StyledText text = cast(StyledText) getControl();
+ text.setSelection(currentOffset);
+ currentOffset = -1;
+ }
+ }
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit + * 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(); + *+ * + * @see Sample code and further information + * + * @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 = "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>
+ * ( Here is an example of using a TableCursor to navigate to a cell and then edit it.
+ *
+ *
+ * The style value is either one of the style constants defined in
+ * class
+ * When
+ * Note: This operation is a hint and may be overridden by the platform.
+ * For example, on Windows the background of a Button cannot be changed.
+ *
+ * Note: This operation is a hint and may be overridden by the platform.
+ * Here is an example of using a TableEditor:
+* Note: The Control provided as the editor must be created with its parent being the Table control
+* specified in the TableEditor constructor.
+*
+* @param editor the Control that is displayed above the cell being edited
+* @param item the TableItem for the row of the cell being tracked by this editor
+* @param column the zero based index of the column of the cell being tracked by this editor
+*/
+public void setEditor (Control editor, TableItem item, int column) {
+ setItem(item);
+ setColumn(column);
+ setEditor(editor);
+}
+public override void layout () {
+ if (table is null || table.isDisposed()) return;
+ if (item is null || item.isDisposed()) return;
+ int columnCount = table.getColumnCount();
+ if (columnCount is 0 && column !is 0) return;
+ if (columnCount > 0 && (column < 0 || column >= columnCount)) return;
+ super.layout();
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTree.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTree.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,842 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * The item children that may be added to instances of this class
+ * must be of type
+ * Note that although this class is a subclass of
+ *
+ * Note: Only one of the styles SINGLE, and MULTI may be specified.
+ *
+ * The style value is either one of the style constants defined in
+ * class
+ * When
+ * If an item is selected, it is deselected.
+ * If an item is not selected, it remains unselected.
+ *
+ * @exception SWTException
+ * @return the number of items in the widget
+ */
+public int getItemCount () {
+ //checkWidget();
+ return items.length;
+}
+
+/**
+ * Gets the height of one item.
+ *
+ * This operation will fail if the height of
+ * one item could not be queried from the OS.
+ *
+ * @return the height of one item in the widget
+ *
+ * @exception SWTException
+ * @return the items in the widget
+ */
+public TableTreeItem [] getItems () {
+ //checkWidget();
+ TableTreeItem[] newItems = new TableTreeItem[items.length];
+ System.arraycopy(items, 0, newItems, 0, items.length);
+ return newItems;
+}
+
+/**
+ * Gets the selected items.
+ *
+ * This operation will fail if the selected
+ * items cannot be queried from the OS.
+ *
+ * @return the selected items in the widget
+ *
+ * @exception SWTException
+ * This operation will fail if the number of selected
+ * items cannot be queried from the OS.
+ *
+ * @return the number of selected items in the widget
+ *
+ * @exception SWTException The widget 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. This index is relative to the parent only.
+ *
+ * @param item the search item
+ * @return the index of the item or -1
+ */
+public int indexOf (TableTreeItem item) {
+ //checkWidget();
+ for (int i = 0; i < items.length; i++) {
+ if (item is items[i]) return i;
+ }
+ return -1;
+}
+
+void onDispose(Event e) {
+ /*
+ * Usually when an item is disposed, destroyItem will change the size of the items array
+ * and dispose of the underlying table items.
+ * Since the whole table tree is being disposed, this is not necessary. For speed
+ * the inDispose flag is used to skip over this part of the item dispose.
+ */
+ inDispose = true;
+ for (int i = 0; i < items.length; i++) {
+ items[i].dispose();
+ }
+ inDispose = false;
+ if (plusImage !is null) plusImage.dispose();
+ if (minusImage !is null) minusImage.dispose();
+ if (sizeImage !is null) sizeImage.dispose();
+ plusImage = minusImage = sizeImage = null;
+}
+
+void onResize(Event e) {
+ Point size = getSize();
+ table.setBounds(0, 0, size.x, size.y);
+}
+
+void onSelection(Event e) {
+ Event event = new Event();
+ TableItem tableItem = cast(TableItem)e.item;
+ TableTreeItem item = getItem(tableItem);
+ event.item = item;
+
+ if (e.type is SWT.Selection && e.detail is SWT.CHECK && item !is null) {
+ event.detail = SWT.CHECK;
+ item.checked = tableItem.getChecked();
+ }
+ notifyListeners(e.type, event);
+}
+/**
+ * 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
+ * This operation will fail when an item
+ * could not be removed in the OS.
+ *
+ * @exception SWTException
+ * If the receiver is single-select, do nothing.
+ *
+ * @exception SWTException
+ * 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
+ * If there is no selection or the selection
+ * is already visible, this method does nothing.
+ * If the selection is scrolled out of view,
+ * the top index of the widget is changed such
+ * that selection becomes visible.
+ *
+ * @exception SWTException Here is an example of using a TableTreeEditor:
+* Note: The Control provided as the editor must be created with its parent being the Table control
+* specified in the TableEditor constructor.
+*
+* @param editor the Control that is displayed above the cell being edited
+* @param item the TableItem for the row of the cell being tracked by this editor
+* @param column the zero based index of the column of the cell being tracked by this editor
+*/
+alias ControlEditor.setEditor setEditor;
+public void setEditor (Control editor, TableTreeItem item, int column) {
+ setItem(item);
+ setColumn(column);
+ setEditor(editor);
+}
+public override void layout () {
+ if (tableTree is null || tableTree.isDisposed()) return;
+ if (item is null || item.isDisposed()) return;
+ Table table = tableTree.getTable();
+ int columnCount = table.getColumnCount();
+ if (columnCount is 0 && column !is 0) return;
+ if (columnCount > 0 && (column < 0 || column >= columnCount)) return;
+ super.layout();
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTreeItem.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTreeItem.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,894 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * The style value is either one of the style constants defined in
+ * class
+ * The style value is either one of the style constants defined in
+ * class
+ * The style value is either one of the style constants defined in
+ * class
+ * The style value is either one of the style constants defined in
+ * class
+ *
+ * @return the expanded state
+ */
+public bool getExpanded () {
+ //checkWidget();
+ return expanded;
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information for this item.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ * The image in column 0 is reserved for the [+] and [-]
+ * images of the tree, therefore getImage(0) will return null.
+ *
+ * @return the image at index 0
+ *
+ * @exception SWTException
+ * Indexing is zero based. The image can be null.
+ * The image in column 0 is reserved for the [+] and [-]
+ * images of the tree, therefore getImage(0) will return null.
+ * Return null if the index is out of range.
+ *
+ * @param index the index of the image
+ * @return the image at the specified index or null
+ */
+public Image getImage (int index) {
+ //checkWidget();
+ if (0 < index && index < images.length) return images[index];
+ return null;
+}
+
+int getIndent() {
+ if (parentItem is null) return 0;
+ return parentItem.getIndent() + 1;
+}
+
+/**
+ * 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
+ * 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.
+ *
+ * Indexing is zero based.
+ *
+ * This operation will fail when the index is out
+ * of range or an item could not be queried from
+ * the OS.
+ *
+ * @param index the index of the item
+ * @return the item text at the specified index, which can be null
+ */
+public String getText(int index) {
+ //checkWidget();
+ if (0 <= index && index < texts.length) return texts[index];
+ return null;
+}
+
+bool getVisible () {
+ return tableItem !is null;
+}
+
+/**
+ * Gets the index of the specified item.
+ *
+ * The widget 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. This index is relative to the parent only.
+ *
+ * @param item the search item
+ * @return the index of the item or -1 if the item is not found
+ *
+ */
+public int indexOf (TableTreeItem item) {
+ //checkWidget();
+ for (int i = 0; i < items.length; i++) {
+ if (items[i] is item) return i;
+ }
+ return -1;
+}
+
+void expandAll(bool notify) {
+ if (items.length is 0) return;
+ if (!expanded) {
+ setExpanded(true);
+ if (notify) {
+ Event event = new Event();
+ event.item = this;
+ parent.notifyListeners(SWT.Expand, event);
+ }
+ }
+ for (int i = 0; i < items.length; i++) {
+ items[i].expandAll(notify);
+ }
+}
+int expandedIndexOf (TableTreeItem item) {
+ int index = 0;
+ for (int i = 0; i < items.length; i++) {
+ if (items[i] is item) return index;
+ if (items[i].expanded) index += items[i].visibleChildrenCount ();
+ index++;
+ }
+ return -1;
+}
+
+int visibleChildrenCount () {
+ int count = 0;
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].getVisible ()) {
+ count += 1 + items[i].visibleChildrenCount ();
+ }
+ }
+ return count;
+}
+
+public override void dispose () {
+ if (isDisposed()) return;
+ for (int i = items.length - 1; i >= 0; i--) {
+ items[i].dispose();
+ }
+ super.dispose();
+ if (!parent.inDispose) {
+ if (parentItem !is null) {
+ parentItem.removeItem(this);
+ } else {
+ parent.removeItem(this);
+ }
+ if (tableItem !is null) tableItem.dispose();
+ }
+ items = null;
+ parentItem = null;
+ parent = null;
+ images = null;
+ texts = null;
+ tableItem = null;
+ foreground = null;
+ background = null;
+ font = null;
+}
+
+void removeItem(TableTreeItem item) {
+ int index = 0;
+ while (index < items.length && items[index] !is item) index++;
+ if (index is items.length) return;
+ TableTreeItem[] newItems = new TableTreeItem[items.length - 1];
+ System.arraycopy(items, 0, newItems, 0, index);
+ System.arraycopy(items, index + 1, newItems, index, items.length - index - 1);
+ items = newItems;
+ if (items.length is 0) {
+ if (tableItem !is null) tableItem.setImage(0, 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
+ * @param expanded the new expanded state.
+ *
+ * @exception SWTException
+ * The image can be null.
+ * The image in column 0 is reserved for the [+] and [-]
+ * images of the tree, therefore do nothing if index is 0.
+ *
+ * @param image the new image or null
+ *
+ * @exception SWTException
+ * The image can be null.
+ * The image in column 0 is reserved for the [+] and [-]
+ * images of the tree, therefore do nothing.
+ *
+ * @param image the new image or null
+ *
+ * @exception SWTException
+ *
+ * The widget text for an item is the label of the
+ * item or the label of the text specified by a column
+ * number.
+ *
+ * @param index the column number
+ * @param text the new text
+ *
+ * @exception SWTException
+ *
+ * @param source the object that will be sending the TextChangedEvent,
+ * cannot be null
+ */
+public this(StyledTextContent source) {
+ super(cast(Object)source);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangingEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangingEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ * @param source the object that will be sending the new TextChangingEvent,
+ * cannot be null
+ */
+public this(StyledTextContent source) {
+ super( cast(Object)source);
+}
+this(StyledTextContent source, StyledTextEvent e) {
+ super( cast(Object)source);
+ start = e.start;
+ replaceCharCount = e.replaceCharCount;
+ newCharCount = e.newCharCount;
+ replaceLineCount = e.replaceLineCount;
+ newLineCount = e.newLineCount;
+ newText = e.text;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TreeEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TreeEditor.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Here is an example of using a TreeEditor:
+* Note: The Control provided as the editor must be created with its parent being the Tree control
+* specified in the TreeEditor constructor.
+*
+* @param editor the Control that is displayed above the cell being edited
+* @param item the TreeItem for the row of the cell being tracked by this editor
+* @param column the zero based index of the column of the cell being tracked by this editor
+*
+* @since 3.1
+*/
+public void setEditor (Control editor, TreeItem item, int column) {
+ setItem(item);
+ setColumn(column);
+ setEditor(editor);
+}
+public override void setEditor (Control editor) {
+ super.setEditor(editor);
+ resize();
+}
+
+/**
+* Specify the Control that is to be displayed and the cell in the tree that it is to be positioned above.
+*
+* Note: The Control provided as the editor must be created with its parent being the Tree control
+* specified in the TreeEditor constructor.
+*
+* @param editor the Control that is displayed above the cell being edited
+* @param item the TreeItem for the row of the cell being tracked by this editor
+*/
+public void setEditor (Control editor, TreeItem item) {
+ setItem(item);
+ setEditor(editor);
+}
+
+public override void layout () {
+ if (tree is null || tree.isDisposed()) return;
+ if (item is null || item.isDisposed()) return;
+ int columnCount = tree.getColumnCount();
+ if (columnCount is 0 && column !is 0) return;
+ if (columnCount > 0 && (column < 0 || column >= columnCount)) return;
+ super.layout();
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/VerifyKeyListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/VerifyKeyListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * Note that although this class is a subclass of
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ * The style value is either one of the style constants defined in
+ * class
+ * Note: No Layout can be set on this Control because it already
+ * manages the size and position of its children.
+ * If the data you are converting does not map to a
+ * The following snippet shows a subclass of ByteArrayTransfer that transfers
+ * data defined by the class IMPORTANT: This class is not intended to 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.
+ *
+ * Currently, it is an error to invoke any method (other than
+ *
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ * 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 NOTE: On some platforms the data will not be available once the application
+ * has exited or the display has been disposed. The following snippet shows text and RTF text being retrieved from the
+ * clipboard: The following snippet shows text and RTF text being retrieved from the
+ * clipboard: The clipboards value is either one of the clipboard constants defined in
+ * class
+ * 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.
+ * 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 modifies 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:
+ * NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility. 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 modifies 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 The following snippet shows text and RTF text being set on the copy/paste
+ * clipboard:
+ * NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility. The clipboards value is either one of the clipboard constants defined in
+ * class Note:
+ * In DND, errors are reported by throwing one of three exceptions:
+ * 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 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
+ * 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. NOTE: ERROR_CANNOT_INIT_DRAG should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility. Classes that wish to deal with The drag source effect has the same API as the
+ * Classes that wish to provide their own drag source effect such as
+ * displaying a default source image during a drag can extend the Flag to determine if the drag and drop operation should proceed.
+ * The application can set this value to false to prevent the drag from starting.
+ * Set to true by default. In dragFinished: Flag to indicate if the operation was performed successfully.
+ * True if the operation was performed successfully. A value of null indicates that no drag image will be displayed. The default value is null. When the user drops data on a After the drop has completed successfully or has been aborted, the application which defines the
+ * The following fields in the DragSourceEvent apply:
+ * The following fields in the DragSourceEvent apply:
+ * The following fields in the DragSourceEvent apply:
+ * This class identifies the The application is notified of data being dragged over this control and of when a drop occurs by
+ * implementing the interface NOTE: ERROR_CANNOT_INIT_DROP should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.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 bool printTextForeground = false;
+ /**
+ * Print the text background color. Default value is false
.
+ */
+ public bool printTextBackground = false;
+ /**
+ * Print the font styles. Default value is false
.
+ */
+ public bool printTextFontStyle = false;
+ /**
+ * Print the line background color. Default value is false
.
+ */
+ public bool printLineBackground = false;
+
+ /**
+ * Print line numbers. Default value is false
.
+ *
+ * @since 3.3
+ */
+ public bool printLineNumbers = false;
+
+ /**
+ * Labels used for printing line numbers.
+ *
+ * @since 3.4
+ */
+ public String[] lineLabels = null;
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextRenderer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextRenderer.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1552 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ *
+ * public static void main(String[] args) {
+ * Display display = new Display();
+ * Shell shell = new Shell(display);
+ * shell.setLayout(new GridLayout());
+ *
+ * // create a a table with 3 columns and fill with data
+ * final Table table = new Table(shell, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
+ * table.setLayoutData(new GridData(GridData.FILL_BOTH));
+ * TableColumn column1 = new TableColumn(table, SWT.NONE);
+ * TableColumn column2 = new TableColumn(table, SWT.NONE);
+ * TableColumn column3 = new TableColumn(table, SWT.NONE);
+ * for (int i = 0; i < 100; i++) {
+ * TableItem item = new TableItem(table, SWT.NONE);
+ * item.setText(new String[] { "cell "+i+" 0", "cell "+i+" 1", "cell "+i+" 2"});
+ * }
+ * column1.pack();
+ * column2.pack();
+ * column3.pack();
+ *
+ * // create a TableCursor to navigate around the table
+ * final TableCursor cursor = new TableCursor(table, SWT.NONE);
+ * // create an editor to edit the cell when the user hits "ENTER"
+ * // while over a cell in the table
+ * final ControlEditor editor = new ControlEditor(cursor);
+ * editor.grabHorizontal = true;
+ * editor.grabVertical = true;
+ *
+ * cursor.addSelectionListener(new SelectionAdapter() {
+ * // when the TableEditor is over a cell, select the corresponding row in
+ * // the table
+ * public void widgetSelected(SelectionEvent e) {
+ * table.setSelection(new TableItem[] {cursor.getRow()});
+ * }
+ * // when the user hits "ENTER" in the TableCursor, pop up a text editor so that
+ * // they can change the text of the cell
+ * public void widgetDefaultSelected(SelectionEvent e){
+ * final Text text = new Text(cursor, SWT.NONE);
+ * TableItem row = cursor.getRow();
+ * int column = cursor.getColumn();
+ * text.setText(row.getText(column));
+ * text.addKeyListener(new KeyAdapter() {
+ * public void keyPressed(KeyEvent e) {
+ * // close the text editor and copy the data over
+ * // when the user hits "ENTER"
+ * if (e.character is SWT.CR) {
+ * TableItem row = cursor.getRow();
+ * int column = cursor.getColumn();
+ * row.setText(column, text.getText());
+ * text.dispose();
+ * }
+ * // close the text editor when the user hits "ESC"
+ * if (e.character is SWT.ESC) {
+ * text.dispose();
+ * }
+ * }
+ * });
+ * editor.setEditor(text);
+ * text.setFocus();
+ * }
+ * });
+ * // Hide the TableCursor when the user hits the "MOD1" or "MOD2" key.
+ * // This allows the user to select multiple items in the table.
+ * cursor.addKeyListener(new KeyAdapter() {
+ * public void keyPressed(KeyEvent e) {
+ * if (e.keyCode is SWT.MOD1 ||
+ * e.keyCode is SWT.MOD2 ||
+ * (e.stateMask & SWT.MOD1) !is 0 ||
+ * (e.stateMask & SWT.MOD2) !is 0) {
+ * cursor.setVisible(false);
+ * }
+ * }
+ * });
+ * // Show the TableCursor when the user releases the "MOD2" or "MOD1" key.
+ * // This signals the end of the multiple selection task.
+ * table.addKeyListener(new KeyAdapter() {
+ * public void keyReleased(KeyEvent e) {
+ * if (e.keyCode is SWT.MOD1 && (e.stateMask & SWT.MOD2) !is 0) return;
+ * if (e.keyCode is SWT.MOD2 && (e.stateMask & SWT.MOD1) !is 0) return;
+ * if (e.keyCode !is SWT.MOD1 && (e.stateMask & SWT.MOD1) !is 0) return;
+ * if (e.keyCode !is SWT.MOD2 && (e.stateMask & SWT.MOD2) !is 0) return;
+ *
+ * TableItem[] selection = table.getSelection();
+ * TableItem row = (selection.length is 0) ? table.getItem(table.getTopIndex()) : selection[0];
+ * table.showItem(row);
+ * cursor.setSelection(row, 0);
+ * cursor.setVisible(true);
+ * cursor.setFocus();
+ * }
+ * });
+ *
+ * shell.open();
+ * while (!shell.isDisposed()) {
+ * if (!display.readAndDispatch())
+ * display.sleep();
+ * }
+ * display.dispose();
+ * }
+ *
+ *
+ *
+ * @since 2.0
+ *
+ * @see TableCursor snippets
+ * @see Sample code and further information
+ */
+public class TableCursor : Canvas {
+
+ alias Canvas.dispose dispose;
+
+ Table table;
+ TableItem row = null;
+ TableColumn column = null;
+ Listener tableListener, resizeListener, disposeItemListener, disposeColumnListener;
+
+ Color background = null;
+ Color foreground = null;
+
+ // By default, invert the list selection colors
+ static final int BACKGROUND = SWT.COLOR_LIST_SELECTION_TEXT;
+ static final int FOREGROUND = SWT.COLOR_LIST_SELECTION;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * table and a style value describing its behavior and appearance.
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SWT#BORDER
+ * @see Widget#checkSubclass()
+ * @see Widget#getStyle()
+ */
+public this(Table parent, int style) {
+ super(parent, style);
+ table = parent;
+ setBackground(null);
+ setForeground(null);
+
+ Listener listener = new class() Listener {
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case SWT.Dispose :
+ dispose(event);
+ break;
+ case SWT.FocusIn :
+ case SWT.FocusOut :
+ redraw();
+ break;
+ case SWT.KeyDown :
+ keyDown(event);
+ break;
+ case SWT.Paint :
+ paint(event);
+ break;
+ case SWT.Traverse : {
+ event.doit = true;
+ switch (event.detail) {
+ case SWT.TRAVERSE_ARROW_NEXT :
+ case SWT.TRAVERSE_ARROW_PREVIOUS :
+ case SWT.TRAVERSE_RETURN :
+ event.doit = false;
+ break;
+ default:
+ }
+ break;
+ }
+ default:
+ }
+ }
+ };
+ int[] events = [SWT.Dispose, SWT.FocusIn, SWT.FocusOut, SWT.KeyDown, SWT.Paint, SWT.Traverse];
+ for (int i = 0; i < events.length; i++) {
+ addListener(events[i], listener);
+ }
+
+ tableListener = new class() Listener {
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case SWT.MouseDown :
+ tableMouseDown(event);
+ break;
+ case SWT.FocusIn :
+ tableFocusIn(event);
+ break;
+ default:
+ }
+ }
+ };
+ table.addListener(SWT.FocusIn, tableListener);
+ table.addListener(SWT.MouseDown, tableListener);
+
+ disposeItemListener = new class() Listener {
+ public void handleEvent(Event event) {
+ unhookRowColumnListeners();
+ row = null;
+ column = null;
+ _resize();
+ }
+ };
+ disposeColumnListener = new class() Listener {
+ public void handleEvent(Event event) {
+ unhookRowColumnListeners();
+ row = null;
+ column = null;
+ _resize();
+ }
+ };
+ resizeListener = new class() Listener {
+ public void handleEvent(Event event) {
+ _resize();
+ }
+ };
+ ScrollBar hBar = table.getHorizontalBar();
+ if (hBar !is null) {
+ hBar.addListener(SWT.Selection, resizeListener);
+ }
+ ScrollBar vBar = table.getVerticalBar();
+ if (vBar !is null) {
+ vBar.addListener(SWT.Selection, resizeListener);
+ }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SelectionListener
+ * @see SelectionEvent
+ * @see #removeSelectionListener(SelectionListener)
+ *
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener is null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener(SWT.Selection, typedListener);
+ addListener(SWT.DefaultSelection, typedListener);
+}
+
+void dispose(Event event) {
+ table.removeListener(SWT.FocusIn, tableListener);
+ table.removeListener(SWT.MouseDown, tableListener);
+ unhookRowColumnListeners();
+ ScrollBar hBar = table.getHorizontalBar();
+ if (hBar !is null) {
+ hBar.removeListener(SWT.Selection, resizeListener);
+ }
+ ScrollBar vBar = table.getVerticalBar();
+ if (vBar !is null) {
+ vBar.removeListener(SWT.Selection, resizeListener);
+ }
+}
+
+void keyDown(Event event) {
+ if (row is null) return;
+ switch (event.character) {
+ case SWT.CR :
+ notifyListeners(SWT.DefaultSelection, new Event());
+ return;
+ default:
+ }
+ int rowIndex = table.indexOf(row);
+ int columnIndex = column is null ? 0 : table.indexOf(column);
+ switch (event.keyCode) {
+ case SWT.ARROW_UP :
+ setRowColumn(Math.max(0, rowIndex - 1), columnIndex, true);
+ break;
+ case SWT.ARROW_DOWN :
+ setRowColumn(Math.min(rowIndex + 1, table.getItemCount() - 1), columnIndex, true);
+ break;
+ case SWT.ARROW_LEFT :
+ case SWT.ARROW_RIGHT :
+ {
+ int columnCount = table.getColumnCount();
+ if (columnCount is 0) break;
+ int[] order = table.getColumnOrder();
+ int index = 0;
+ while (index < order.length) {
+ if (order[index] is columnIndex) break;
+ index++;
+ }
+ if (index is order.length) index = 0;
+ int leadKey = (getStyle() & SWT.RIGHT_TO_LEFT) !is 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+ if (event.keyCode is leadKey) {
+ setRowColumn(rowIndex, order[Math.max(0, index - 1)], true);
+ } else {
+ setRowColumn(rowIndex, order[Math.min(columnCount - 1, index + 1)], true);
+ }
+ break;
+ }
+ case SWT.HOME :
+ setRowColumn(0, columnIndex, true);
+ break;
+ case SWT.END :
+ {
+ int i = table.getItemCount() - 1;
+ setRowColumn(i, columnIndex, true);
+ break;
+ }
+ case SWT.PAGE_UP :
+ {
+ int index = table.getTopIndex();
+ if (index is rowIndex) {
+ Rectangle rect = table.getClientArea();
+ TableItem item = table.getItem(index);
+ Rectangle itemRect = item.getBounds(0);
+ rect.height -= itemRect.y;
+ int height = table.getItemHeight();
+ int page = Math.max(1, rect.height / height);
+ index = Math.max(0, index - page + 1);
+ }
+ setRowColumn(index, columnIndex, true);
+ break;
+ }
+ case SWT.PAGE_DOWN :
+ {
+ int index = table.getTopIndex();
+ Rectangle rect = table.getClientArea();
+ TableItem item = table.getItem(index);
+ Rectangle itemRect = item.getBounds(0);
+ rect.height -= itemRect.y;
+ int height = table.getItemHeight();
+ int page = Math.max(1, rect.height / height);
+ int end = table.getItemCount() - 1;
+ index = Math.min(end, index + page - 1);
+ if (index is rowIndex) {
+ index = Math.min(end, index + page - 1);
+ }
+ setRowColumn(index, columnIndex, true);
+ break;
+ }
+ default:
+ }
+}
+
+void paint(Event event) {
+ if (row is null) return;
+ int columnIndex = column is null ? 0 : table.indexOf(column);
+ GC gc = event.gc;
+ Display display = getDisplay();
+ gc.setBackground(getBackground());
+ gc.setForeground(getForeground());
+ gc.fillRectangle(event.x, event.y, event.width, event.height);
+ int x = 0;
+ Point size = getSize();
+ Image image = row.getImage(columnIndex);
+ if (image !is null) {
+ Rectangle imageSize = image.getBounds();
+ int imageY = (size.y - imageSize.height) / 2;
+ gc.drawImage(image, x, imageY);
+ x += imageSize.width;
+ }
+ String text = row.getText(columnIndex);
+ if (text.length > 0) {
+ Rectangle bounds = row.getBounds(columnIndex);
+ Point extent = gc.stringExtent(text);
+ // Temporary code - need a better way to determine table trim
+ String platform = SWT.getPlatform();
+ if ("win32"==platform) { //$NON-NLS-1$
+ if (table.getColumnCount() is 0 || columnIndex is 0) {
+ x += 2;
+ } else {
+ int alignmnent = column.getAlignment();
+ switch (alignmnent) {
+ case SWT.LEFT:
+ x += 6;
+ break;
+ case SWT.RIGHT:
+ x = bounds.width - extent.x - 6;
+ break;
+ case SWT.CENTER:
+ x += (bounds.width - x - extent.x) / 2;
+ break;
+ default:
+ }
+ }
+ } else {
+ if (table.getColumnCount() is 0) {
+ x += 5;
+ } else {
+ int alignmnent = column.getAlignment();
+ switch (alignmnent) {
+ case SWT.LEFT:
+ x += 5;
+ break;
+ case SWT.RIGHT:
+ x = bounds.width- extent.x - 2;
+ break;
+ case SWT.CENTER:
+ x += (bounds.width - x - extent.x) / 2 + 2;
+ break;
+ default:
+ }
+ }
+ }
+ int textY = (size.y - extent.y) / 2;
+ gc.drawString(text, x, textY);
+ }
+ if (isFocusControl()) {
+ gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+ gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+ gc.drawFocus(0, 0, size.x, size.y);
+ }
+}
+
+void tableFocusIn(Event event) {
+ if (isDisposed()) return;
+ if (isVisible()) {
+ if (row is null && column is null) return;
+ setFocus();
+ }
+}
+
+void tableMouseDown(Event event) {
+ if (isDisposed() || !isVisible()) return;
+ Point pt = new Point(event.x, event.y);
+ int lineWidth = table.getLinesVisible() ? table.getGridLineWidth() : 0;
+ TableItem item = table.getItem(pt);
+ if ((table.getStyle() & SWT.FULL_SELECTION) !is 0) {
+ if (item is null) return;
+ } else {
+ int start = item !is null ? table.indexOf(item) : table.getTopIndex();
+ int end = table.getItemCount();
+ Rectangle clientRect = table.getClientArea();
+ for (int i = start; i < end; i++) {
+ TableItem nextItem = table.getItem(i);
+ Rectangle rect = nextItem.getBounds(0);
+ if (pt.y >= rect.y && pt.y < rect.y + rect.height + lineWidth) {
+ item = nextItem;
+ break;
+ }
+ if (rect.y > clientRect.y + clientRect.height) return;
+ }
+ if (item is null) return;
+ }
+ TableColumn newColumn = null;
+ int columnCount = table.getColumnCount();
+ if (columnCount is 0) {
+ if ((table.getStyle() & SWT.FULL_SELECTION) is 0) {
+ Rectangle rect = item.getBounds(0);
+ rect.width += lineWidth;
+ rect.height += lineWidth;
+ if (!rect.contains(pt)) return;
+ }
+ } else {
+ for (int i = 0; i < columnCount; i++) {
+ Rectangle rect = item.getBounds(i);
+ rect.width += lineWidth;
+ rect.height += lineWidth;
+ if (rect.contains(pt)) {
+ newColumn = table.getColumn(i);
+ break;
+ }
+ }
+ if (newColumn is null) {
+ if ((table.getStyle() & SWT.FULL_SELECTION) is 0) return;
+ newColumn = table.getColumn(0);
+ }
+ }
+ setRowColumn(item, newColumn, true);
+ setFocus();
+ return;
+}
+void setRowColumn(int row, int column, bool notify) {
+ TableItem item = row is -1 ? null : table.getItem(row);
+ TableColumn col = column is -1 || table.getColumnCount() is 0 ? null : table.getColumn(column);
+ setRowColumn(item, col, notify);
+}
+void setRowColumn(TableItem row, TableColumn column, bool notify) {
+ if (this.row is row && this.column is column) {
+ return;
+ }
+ if (this.row !is null && this.row !is row) {
+ this.row.removeListener(SWT.Dispose, disposeItemListener);
+ this.row = null;
+ }
+ if (this.column !is null && this.column !is column) {
+ this.column.removeListener(SWT.Dispose, disposeColumnListener);
+ this.column.removeListener(SWT.Move, resizeListener);
+ this.column.removeListener(SWT.Resize, resizeListener);
+ this.column = null;
+ }
+ if (row !is null) {
+ if (this.row !is row) {
+ this.row = row;
+ row.addListener(SWT.Dispose, disposeItemListener);
+ table.showItem(row);
+ }
+ if (this.column !is column && column !is null) {
+ this.column = column;
+ column.addListener(SWT.Dispose, disposeColumnListener);
+ column.addListener(SWT.Move, resizeListener);
+ column.addListener(SWT.Resize, resizeListener);
+ table.showColumn(column);
+ }
+ int columnIndex = column is null ? 0 : table.indexOf(column);
+ setBounds(row.getBounds(columnIndex));
+ redraw();
+ if (notify) {
+ notifyListeners(SWT.Selection, new Event());
+ }
+ }
+}
+
+public override void setVisible(bool visible) {
+ checkWidget();
+ if (visible) _resize();
+ super.setVisible(visible);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener(SelectionListener)
+ *
+ * @since 3.0
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener is null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ removeListener(SWT.Selection, listener);
+ removeListener(SWT.DefaultSelection, listener);
+}
+
+void _resize() {
+ if (row is null) {
+ setBounds(-200, -200, 0, 0);
+ } else {
+ int columnIndex = column is null ? 0 : table.indexOf(column);
+ setBounds(row.getBounds(columnIndex));
+ }
+}
+/**
+ * Returns the column over which the TableCursor is positioned.
+ *
+ * @return the column for the current position
+ *
+ * @exception SWTException
+ *
+ */
+public int getColumn() {
+ checkWidget();
+ return column is null ? 0 : table.indexOf(column);
+}
+/**
+ * Returns the background color that the receiver will use to draw.
+ *
+ * @return the receiver's background color
+ */
+public Color getBackground() {
+ checkWidget();
+ if (background is null) {
+ return getDisplay().getSystemColor(BACKGROUND);
+ }
+ return background;
+}
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ */
+public Color getForeground() {
+ checkWidget();
+ if (foreground is null) {
+ return getDisplay().getSystemColor(FOREGROUND);
+ }
+ return foreground;
+}
+/**
+ * Returns the row over which the TableCursor is positioned.
+ *
+ * @return the item for the current position
+ *
+ * @exception SWTException
+ *
+ */
+public TableItem getRow() {
+ checkWidget();
+ return row;
+}
+/**
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ */
+public override void setBackground (Color color) {
+ background = color;
+ super.setBackground(getBackground());
+ redraw();
+}
+/**
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ */
+public override void setForeground (Color color) {
+ foreground = color;
+ super.setForeground(getForeground());
+ redraw();
+}
+/**
+ * Positions the TableCursor over the cell at the given row and column in the parent table.
+ *
+ * @param row the index of the row for the cell to select
+ * @param column the index of column for the cell to select
+ *
+ * @exception SWTException
+ *
+ *
+ */
+public void setSelection(int row, int column) {
+ checkWidget();
+ int columnCount = table.getColumnCount();
+ int maxColumnIndex = columnCount is 0 ? 0 : columnCount - 1;
+ if (row < 0
+ || row >= table.getItemCount()
+ || column < 0
+ || column > maxColumnIndex)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ setRowColumn(row, column, false);
+}
+/**
+ * Positions the TableCursor over the cell at the given row and column in the parent table.
+ *
+ * @param row the TableItem of the row for the cell to select
+ * @param column the index of column for the cell to select
+ *
+ * @exception SWTException
+ *
+ *
+ */
+public void setSelection(TableItem row, int column) {
+ checkWidget();
+ int columnCount = table.getColumnCount();
+ int maxColumnIndex = columnCount is 0 ? 0 : columnCount - 1;
+ if (row is null
+ || row.isDisposed()
+ || column < 0
+ || column > maxColumnIndex)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ setRowColumn(table.indexOf(row), column, false);
+}
+void unhookRowColumnListeners() {
+ if (column !is null) {
+ column.removeListener(SWT.Dispose, disposeColumnListener);
+ column.removeListener(SWT.Move, resizeListener);
+ column.removeListener(SWT.Resize, resizeListener);
+ column = null;
+ }
+ if (row !is null) {
+ row.removeListener(SWT.Dispose, disposeItemListener);
+ row = null;
+ }
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableEditor.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+*
+* @see TableEditor snippets
+* @see Sample code and further information
+*/
+public class TableEditor : ControlEditor {
+ Table table;
+ TableItem item;
+ int column = -1;
+ ControlListener columnListener;
+ Runnable timer;
+ static final int TIMEOUT = 1500;
+/**
+* Creates a TableEditor for the specified Table.
+*
+* @param table the Table Control above which this editor will be displayed
+*
+*/
+public this (Table table) {
+ super(table);
+ this.table = table;
+
+ columnListener = new class() ControlListener {
+ public void controlMoved(ControlEvent e){
+ layout ();
+ }
+ public void controlResized(ControlEvent e){
+ layout ();
+ }
+ };
+ timer = new class() Runnable {
+ public void run() {
+ layout ();
+ }
+ };
+
+ // To be consistent with older versions of SWT, grabVertical defaults to true
+ grabVertical = true;
+}
+override Rectangle computeBounds () {
+ if (item is null || column is -1 || item.isDisposed()) return new Rectangle(0, 0, 0, 0);
+ Rectangle cell = item.getBounds(column);
+ Rectangle rect = item.getImageBounds(column);
+ cell.x = rect.x + rect.width;
+ cell.width -= rect.width;
+ Rectangle area = table.getClientArea();
+ if (cell.x < area.x + area.width) {
+ if (cell.x + cell.width > area.x + area.width) {
+ cell.width = area.x + area.width - cell.x;
+ }
+ }
+ Rectangle editorRect = new Rectangle(cell.x, cell.y, minimumWidth, minimumHeight);
+
+ if (grabHorizontal) {
+ editorRect.width = Math.max(cell.width, minimumWidth);
+ }
+
+ if (grabVertical) {
+ editorRect.height = Math.max(cell.height, minimumHeight);
+ }
+
+ if (horizontalAlignment is SWT.RIGHT) {
+ editorRect.x += cell.width - editorRect.width;
+ } else if (horizontalAlignment is SWT.LEFT) {
+ // do nothing - cell.x is the right answer
+ } else { // default is CENTER
+ editorRect.x += (cell.width - editorRect.width)/2;
+ }
+
+ if (verticalAlignment is SWT.BOTTOM) {
+ editorRect.y += cell.height - editorRect.height;
+ } else if (verticalAlignment is SWT.TOP) {
+ // do nothing - cell.y is the right answer
+ } else { // default is CENTER
+ editorRect.y += (cell.height - editorRect.height)/2;
+ }
+ return editorRect;
+}
+/**
+ * Removes all associations between the TableEditor and the cell in the table. The
+ * Table and the editor Control are not disposed.
+ */
+public override void dispose () {
+ if (table !is null && !table.isDisposed()) {
+ if (this.column > -1 && this.column < table.getColumnCount()){
+ TableColumn tableColumn = table.getColumn(this.column);
+ tableColumn.removeControlListener(columnListener);
+ }
+ }
+ columnListener = null;
+ table = null;
+ item = null;
+ column = -1;
+ timer = null;
+ super.dispose();
+}
+/**
+* Returns the zero based index of the column of the cell being tracked by this editor.
+*
+* @return the zero based index of the column of the cell being tracked by this editor
+*/
+public int getColumn () {
+ return column;
+}
+/**
+* Returns the TableItem for the row of the cell being tracked by this editor.
+*
+* @return the TableItem for the row of the cell being tracked by this editor
+*/
+public TableItem getItem () {
+ return item;
+}
+void resize () {
+ layout();
+ /*
+ * On some platforms, the table scrolls when an item that
+ * is partially visible at the bottom of the table is
+ * selected. Ensure that the correct row is edited by
+ * laying out one more time in a timerExec().
+ */
+ if (table !is null) {
+ Display display = table.getDisplay();
+ display.timerExec(-1, timer);
+ display.timerExec(TIMEOUT, timer);
+ }
+}
+/**
+* Sets the zero based index of the column of the cell being tracked by this editor.
+*
+* @param column the zero based index of the column of the cell being tracked by this editor
+*/
+public void setColumn(int column) {
+ int columnCount = table.getColumnCount();
+ // Separately handle the case where the table has no TableColumns.
+ // In this situation, there is a single default column.
+ if (columnCount is 0) {
+ this.column = (column is 0) ? 0 : -1;
+ resize();
+ return;
+ }
+ if (this.column > -1 && this.column < columnCount){
+ TableColumn tableColumn = table.getColumn(this.column);
+ tableColumn.removeControlListener(columnListener);
+ this.column = -1;
+ }
+
+ if (column < 0 || column >= table.getColumnCount()) return;
+
+ this.column = column;
+ TableColumn tableColumn = table.getColumn(this.column);
+ tableColumn.addControlListener(columnListener);
+ resize();
+}
+/**
+* Specifies the
+* final Table table = new Table(shell, SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
+* TableColumn column1 = new TableColumn(table, SWT.NONE);
+* TableColumn column2 = new TableColumn(table, SWT.NONE);
+* for (int i = 0; i < 10; i++) {
+* TableItem item = new TableItem(table, SWT.NONE);
+* item.setText(new String[] {"item " + i, "edit this value"});
+* }
+* column1.pack();
+* column2.pack();
+*
+* final TableEditor editor = new TableEditor(table);
+* //The editor must have the same size as the cell and must
+* //not be any smaller than 50 pixels.
+* editor.horizontalAlignment = SWT.LEFT;
+* editor.grabHorizontal = true;
+* editor.minimumWidth = 50;
+* // editing the second column
+* final int EDITABLECOLUMN = 1;
+*
+* table.addSelectionListener(new SelectionAdapter() {
+* public void widgetSelected(SelectionEvent e) {
+* // Clean up any previous editor control
+* Control oldEditor = editor.getEditor();
+* if (oldEditor !is null) oldEditor.dispose();
+*
+* // Identify the selected row
+* TableItem item = (TableItem)e.item;
+* if (item is null) return;
+*
+* // The control that will be the editor must be a child of the Table
+* Text newEditor = new Text(table, SWT.NONE);
+* newEditor.setText(item.getText(EDITABLECOLUMN));
+* newEditor.addModifyListener(new ModifyListener() {
+* public void modifyText(ModifyEvent e) {
+* Text text = (Text)editor.getEditor();
+* editor.getItem().setText(EDITABLECOLUMN, text.getText());
+* }
+* });
+* newEditor.selectAll();
+* newEditor.setFocus();
+* editor.setEditor(newEditor, item, EDITABLECOLUMN);
+* }
+* });
+*
TableItem
that is to be edited.
+*
+* @param item the item to be edited
+*/
+public void setItem (TableItem item) {
+ this.item = item;
+ resize();
+}
+public override void setEditor (Control editor) {
+ super.setEditor(editor);
+ resize();
+}
+/**
+* Specify the Control that is to be displayed and the cell in the table that it is to be positioned above.
+*
+* TableTreeItem
.
+ * Composite
,
+ * it does not make sense to add Control
children to it,
+ * or set a layout on it.
+ *
+ *
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#CHECK
+ * @see SWT#FULL_SELECTION
+ * @see #getStyle
+ */
+public this(Composite parent, int style) {
+ super(parent, checkStyle (style));
+ items = EMPTY_ITEMS;
+ table = new Table(this, style);
+ Listener tableListener = new class() Listener {
+ public void handleEvent(Event e) {
+ switch (e.type) {
+ case SWT.MouseDown: onMouseDown(e); break;
+ case SWT.Selection: onSelection(e); break;
+ case SWT.DefaultSelection: onSelection(e); break;
+ case SWT.KeyDown: onKeyDown(e); break;
+ default:
+ }
+ }
+ };
+ int[] tableEvents = [SWT.MouseDown,
+ SWT.Selection,
+ SWT.DefaultSelection,
+ SWT.KeyDown];
+ for (int i = 0; i < tableEvents.length; i++) {
+ table.addListener(tableEvents[i], tableListener);
+ }
+
+ Listener listener = new class() Listener {
+ public void handleEvent(Event e) {
+ switch (e.type) {
+ case SWT.Dispose: onDispose(e); break;
+ case SWT.Resize: onResize(e); break;
+ case SWT.FocusIn: onFocusIn(e); break;
+ default:
+ }
+ }
+ };
+ int[] events = [SWT.Dispose,
+ SWT.Resize,
+ SWT.FocusIn];
+ for (int i = 0; i < events.length; i++) {
+ addListener(events[i], listener);
+ }
+}
+
+int addItem(TableTreeItem item, int index) {
+ if (index < 0 || index > items.length) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ TableTreeItem[] newItems = new TableTreeItem[items.length + 1];
+ System.arraycopy(items, 0, newItems, 0, index);
+ newItems[index] = item;
+ System.arraycopy(items, index, newItems, index + 1, items.length - index);
+ items = newItems;
+
+ /* Return the index in the table where this table should be inserted */
+ if (index is items.length - 1 )
+ return table.getItemCount();
+ else
+ return table.indexOf(items[index+1].tableItem);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener is null) SWT.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
+ *
+ * @exception SWTException
+ *
+ *
+ * @see TreeListener
+ * @see #removeTreeListener
+ */
+public void addTreeListener(TreeListener listener) {
+ checkWidget();
+ if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Expand, typedListener);
+ addListener (SWT.Collapse, typedListener);
+}
+private static int checkStyle (int style) {
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ style = style & mask;
+ return style;
+}
+public override Point computeSize (int wHint, int hHint, bool changed) {
+ checkWidget();
+ return table.computeSize (wHint, hHint, changed);
+}
+public override Rectangle computeTrim (int x, int y, int width, int height) {
+ checkWidget();
+ return table.computeTrim(x, y, width, height);
+}
+
+/**
+ * Deselects all items.
+ *
+ *
+ */
+public void deselectAll () {
+ checkWidget();
+ table.deselectAll();
+}
+
+/* Expand upward from the specified leaf item. */
+void expandItem (TableTreeItem item) {
+ if (item is null) return;
+ expandItem(item.parentItem);
+ if (!item.getVisible()) item.setVisible(true);
+ if ( !item.expanded && item.items.length > 0) {
+ item.setExpanded(true);
+ Event event = new Event();
+ event.item = item;
+ notifyListeners(SWT.Expand, event);
+ }
+}
+public override Color getBackground () {
+ // This method must be overridden otherwise, in a TableTree in which the first
+ // item has no sub items, a grey (Widget background colour) square will appear in
+ // the first column of the first item.
+ // It is not possible in the constructor to set the background of the TableTree
+ // to be the same as the background of the Table because this interferes with
+ // the TableTree adapting to changes in the System color settings.
+ return table.getBackground();
+}
+public override Rectangle getClientArea () {
+ return table.getClientArea();
+}
+public override Color getForeground () {
+ return table.getForeground();
+}
+public override Font getFont () {
+ return table.getFont();
+}
+/**
+ * Gets the number of items.
+ *
+ *
+ */
+public int getItemHeight () {
+ checkWidget();
+ return table.getItemHeight();
+}
+
+/**
+ * Gets the items.
+ *
+ *
+ */
+public TableTreeItem [] getSelection () {
+ checkWidget();
+ TableItem[] selection = table.getSelection();
+ TableTreeItem [] result = new TableTreeItem[selection.length];
+ for (int i = 0; i < selection.length; i++){
+ result[i] = cast(TableTreeItem) selection[i].getData(ITEMID);
+ }
+ return result;
+}
+
+/**
+ * Gets the number of selected items.
+ *
+ *
+ */
+public int getSelectionCount () {
+ checkWidget();
+ return table.getSelectionCount();
+}
+
+public override int getStyle () {
+ checkWidget();
+ return table.getStyle();
+}
+
+/**
+ * Returns the underlying Table control.
+ *
+ * @return the underlying Table control
+ */
+public Table getTable () {
+ //checkWidget();
+ return table;
+}
+
+void createImages () {
+
+ int itemHeight = sizeImage.getBounds().height;
+ // Calculate border around image.
+ // At least 9 pixels are needed to draw the image
+ // Leave at least a 6 pixel border.
+ int indent = Math.min(6, (itemHeight - 9) / 2);
+ indent = Math.max(0, indent);
+ int size = Math.max (10, itemHeight - 2 * indent);
+ size = ((size + 1) / 2) * 2; // size must be an even number
+ int midpoint = indent + size / 2;
+
+ Color foreground = getForeground();
+ Color plusMinus = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+ Color background = getBackground();
+
+ /* Plus image */
+ PaletteData palette = new PaletteData( [ foreground.getRGB(), background.getRGB(), plusMinus.getRGB()]);
+ ImageData imageData = new ImageData(itemHeight, itemHeight, 4, palette);
+ imageData.transparentPixel = 1;
+ plusImage = new Image(getDisplay(), imageData);
+ GC gc = new GC(plusImage);
+ gc.setBackground(background);
+ gc.fillRectangle(0, 0, itemHeight, itemHeight);
+ gc.setForeground(plusMinus);
+ gc.drawRectangle(indent, indent, size, size);
+ gc.setForeground(foreground);
+ gc.drawLine(midpoint, indent + 2, midpoint, indent + size - 2);
+ gc.drawLine(indent + 2, midpoint, indent + size - 2, midpoint);
+ gc.dispose();
+
+ /* Minus image */
+ palette = new PaletteData([foreground.getRGB(), background.getRGB(), plusMinus.getRGB()]);
+ imageData = new ImageData(itemHeight, itemHeight, 4, palette);
+ imageData.transparentPixel = 1;
+ minusImage = new Image(getDisplay(), imageData);
+ gc = new GC(minusImage);
+ gc.setBackground(background);
+ gc.fillRectangle(0, 0, itemHeight, itemHeight);
+ gc.setForeground(plusMinus);
+ gc.drawRectangle(indent, indent, size, size);
+ gc.setForeground(foreground);
+ gc.drawLine(indent + 2, midpoint, indent + size - 2, midpoint);
+ gc.dispose();
+}
+
+Image getPlusImage() {
+ if (plusImage is null) createImages();
+ return plusImage;
+}
+
+Image getMinusImage() {
+ if (minusImage is null) createImages();
+ return minusImage;
+}
+
+/**
+ * Gets the index of an item.
+ *
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.1
+ */
+public TableTreeItem getItem (int index) {
+ checkWidget();
+ int count = items.length;
+ if (!(0 <= index && index < count)) SWT.error (SWT.ERROR_INVALID_RANGE);
+ return items [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.
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point
+ *
+ * @exception IllegalArgumentException
+ *
+ * @exception SWTException
+ *
+ */
+public TableTreeItem getItem(Point point) {
+ checkWidget();
+ TableItem item = table.getItem(point);
+ if (item is null) return null;
+ return getItem(item);
+
+}
+TableTreeItem getItem(TableItem tableItem) {
+ if (tableItem is null) return null;
+ for (int i = 0; i < items.length; i++) {
+ TableTreeItem item = items[i].getItem(tableItem);
+ if (item !is null) return item;
+ }
+ return null;
+}
+void onFocusIn (Event e) {
+ table.setFocus();
+}
+
+void onKeyDown (Event e) {
+ TableTreeItem[] selection = getSelection();
+ if (selection.length is 0) return;
+ TableTreeItem item = selection[0];
+ int type = 0;
+ if (e.keyCode is SWT.ARROW_RIGHT || e.keyCode is SWT.ARROW_LEFT) {
+ int trailKey = (getStyle() & SWT.MIRRORED) !is 0 ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT;
+ if (e.keyCode is trailKey) {
+ if (item.getItemCount() is 0) return;
+ if (item.getExpanded()) {
+ TableTreeItem newSelection = item.getItems()[0];
+ table.setSelection([newSelection.tableItem]);
+ showItem(newSelection);
+ type = SWT.Selection;
+ } else {
+ item.setExpanded(true);
+ type = SWT.Expand;
+ }
+ } else {
+ if (item.getExpanded()) {
+ item.setExpanded(false);
+ type = SWT.Collapse;
+ } else {
+ TableTreeItem parent = item.getParentItem();
+ if (parent !is null) {
+ int index = parent.indexOf(item);
+ if (index !is 0) return;
+ table.setSelection([parent.tableItem]);
+ type = SWT.Selection;
+ }
+ }
+ }
+ }
+ if (e.character is '*') {
+ item.expandAll(true);
+ }
+ if (e.character is '-') {
+ if (item.getExpanded()) {
+ item.setExpanded(false);
+ type = SWT.Collapse;
+ }
+ }
+ if (e.character is '+') {
+ if (item.getItemCount() > 0 && !item.getExpanded()) {
+ item.setExpanded(true);
+ type = SWT.Expand;
+ }
+ }
+ if (type is 0) return;
+ Event event = new Event();
+ event.item = item;
+ notifyListeners(type, event);
+}
+void onMouseDown(Event event) {
+ /* If user clicked on the [+] or [-], expand or collapse the tree. */
+ TableItem[] items = table.getItems();
+ for (int i = 0; i < items.length; i++) {
+ Rectangle rect = items[i].getImageBounds(0);
+ if (rect.contains(event.x, event.y)) {
+ TableTreeItem item = cast(TableTreeItem) items[i].getData(ITEMID);
+ event = new Event();
+ event.item = item;
+ item.setExpanded(!item.getExpanded());
+ if (item.getExpanded()) {
+ notifyListeners(SWT.Expand, event);
+ } else {
+ notifyListeners(SWT.Collapse, event);
+ }
+ return;
+ }
+ }
+}
+
+/**
+ * Removes all items.
+ *
+ *
+ */
+public void removeAll () {
+ checkWidget();
+ setRedraw(false);
+ for (int i = items.length - 1; i >= 0; i--) {
+ items[i].dispose();
+ }
+ items = EMPTY_ITEMS;
+ setRedraw(true);
+}
+
+void removeItem(TableTreeItem item) {
+ int index = 0;
+ while (index < items.length && items[index] !is item) index++;
+ if (index is items.length) return;
+ TableTreeItem[] newItems = new TableTreeItem[items.length - 1];
+ System.arraycopy(items, 0, newItems, 0, index);
+ System.arraycopy(items, index + 1, newItems, index, items.length - index - 1);
+ items = newItems;
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget();
+ if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ removeListener(SWT.Selection, listener);
+ removeListener(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
+ *
+ * @exception SWTException
+ *
+ *
+ * @see TreeListener
+ * @see #addTreeListener
+ */
+public void removeTreeListener (TreeListener listener) {
+ checkWidget();
+ if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ removeListener(SWT.Expand, listener);
+ removeListener(SWT.Collapse, listener);
+}
+
+/**
+ * Selects all of the items in the receiver.
+ *
+ *
+ */
+public void selectAll () {
+ checkWidget();
+ table.selectAll();
+}
+public override void setBackground (Color color) {
+ super.setBackground(color);
+ table.setBackground(color);
+ if (sizeImage !is null) {
+ GC gc = new GC (sizeImage);
+ gc.setBackground(getBackground());
+ Rectangle size = sizeImage.getBounds();
+ gc.fillRectangle(size);
+ gc.dispose();
+ }
+}
+public override void setEnabled (bool enabled) {
+ super.setEnabled(enabled);
+ table.setEnabled(enabled);
+}
+public override void setFont (Font font) {
+ super.setFont(font);
+ table.setFont(font);
+}
+public override void setForeground (Color color) {
+ super.setForeground(color);
+ table.setForeground(color);
+}
+public override void setMenu (Menu menu) {
+ super.setMenu(menu);
+ table.setMenu(menu);
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see TableTree#deselectAll()
+ */
+public void setSelection (TableTreeItem[] items) {
+ checkWidget ();
+ // SWT extension: allow null for zero length string
+ //if (items is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ int length = items.length;
+ if (length is 0 || ((table.getStyle() & SWT.SINGLE) !is 0 && length > 1)) {
+ deselectAll();
+ return;
+ }
+ TableItem[] tableItems = new TableItem[length];
+ for (int i = 0; i < length; i++) {
+ if (items[i] is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (!items[i].getVisible()) expandItem (items[i]);
+ tableItems[i] = items[i].tableItem;
+ }
+ table.setSelection(tableItems);
+}
+public override void setToolTipText (String string) {
+ super.setToolTipText(string);
+ table.setToolTipText(string);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @see TableTree#showSelection()
+ */
+public void showItem (TableTreeItem item) {
+ checkWidget();
+ if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (!item.getVisible()) expandItem (item);
+ TableItem tableItem = item.tableItem;
+ table.showItem(tableItem);
+}
+
+/**
+ * Shows the selection.
+ *
+ *
+ */
+public void showSelection () {
+ checkWidget();
+ table.showSelection();
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTreeEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTreeEditor.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit
+*
+* @deprecated As of 3.1 use TreeEditor with Tree, TreeItem and TreeColumn
+*/
+public class TableTreeEditor : ControlEditor {
+
+ alias ControlEditor.setEditor setEditor;
+
+ TableTree tableTree;
+ TableTreeItem item;
+ int column = -1;
+ ControlListener columnListener;
+ TreeListener treeListener;
+/**
+* Creates a TableTreeEditor for the specified TableTree.
+*
+* @param tableTree the TableTree Control above which this editor will be displayed
+*
+*/
+public this (TableTree tableTree) {
+ super(tableTree.getTable());
+ this.tableTree = tableTree;
+
+ treeListener = new class() TreeListener {
+ Runnable runnable;
+ this() {
+ runnable = new class() Runnable {
+ public void run() {
+ if (editor is null || editor.isDisposed()) return;
+ if (this.outer.outer.tableTree.isDisposed()) return;
+ layout();
+ editor.setVisible(true);
+ }
+ };
+ }
+ public void treeCollapsed(TreeEvent e) {
+ if (editor is null || editor.isDisposed ()) return;
+ editor.setVisible(false);
+ e.display.asyncExec(runnable);
+ }
+ public void treeExpanded(TreeEvent e) {
+ if (editor is null || editor.isDisposed ()) return;
+ editor.setVisible(false);
+ e.display.asyncExec(runnable);
+ }
+ };
+ tableTree.addTreeListener(treeListener);
+
+ columnListener = new class() ControlListener {
+ public void controlMoved(ControlEvent e){
+ layout ();
+ }
+ public void controlResized(ControlEvent e){
+ layout ();
+ }
+ };
+
+ // To be consistent with older versions of SWT, grabVertical defaults to true
+ grabVertical = true;
+}
+
+override Rectangle computeBounds () {
+ if (item is null || column is -1 || item.isDisposed() || item.tableItem is null) return new Rectangle(0, 0, 0, 0);
+ Rectangle cell = item.getBounds(column);
+ Rectangle area = tableTree.getClientArea();
+ if (cell.x < area.x + area.width) {
+ if (cell.x + cell.width > area.x + area.width) {
+ cell.width = area.x + area.width - cell.x;
+ }
+ }
+ Rectangle editorRect = new Rectangle(cell.x, cell.y, minimumWidth, minimumHeight);
+
+ if (grabHorizontal) {
+ editorRect.width = Math.max(cell.width, minimumWidth);
+ }
+
+ if (grabVertical) {
+ editorRect.height = Math.max(cell.height, minimumHeight);
+ }
+
+ if (horizontalAlignment is SWT.RIGHT) {
+ editorRect.x += cell.width - editorRect.width;
+ } else if (horizontalAlignment is SWT.LEFT) {
+ // do nothing - cell.x is the right answer
+ } else { // default is CENTER
+ editorRect.x += (cell.width - editorRect.width)/2;
+ }
+
+ if (verticalAlignment is SWT.BOTTOM) {
+ editorRect.y += cell.height - editorRect.height;
+ } else if (verticalAlignment is SWT.TOP) {
+ // do nothing - cell.y is the right answer
+ } else { // default is CENTER
+ editorRect.y += (cell.height - editorRect.height)/2;
+ }
+ return editorRect;
+}
+/**
+ * Removes all associations between the TableTreeEditor and the cell in the table tree. The
+ * TableTree and the editor Control are not disposed.
+ */
+public override void dispose () {
+ if (tableTree !is null && !tableTree.isDisposed()) {
+ Table table = tableTree.getTable();
+ if (table !is null && !table.isDisposed()) {
+ if (this.column > -1 && this.column < table.getColumnCount()){
+ TableColumn tableColumn = table.getColumn(this.column);
+ tableColumn.removeControlListener(columnListener);
+ }
+ }
+ if (treeListener !is null) tableTree.removeTreeListener(treeListener);
+ }
+ treeListener = null;
+ columnListener = null;
+ tableTree = null;
+ item = null;
+ column = -1;
+ super.dispose();
+}
+/**
+* Returns the zero based index of the column of the cell being tracked by this editor.
+*
+* @return the zero based index of the column of the cell being tracked by this editor
+*/
+public int getColumn () {
+ return column;
+}
+/**
+* Returns the TableTreeItem for the row of the cell being tracked by this editor.
+*
+* @return the TableTreeItem for the row of the cell being tracked by this editor
+*/
+public TableTreeItem getItem () {
+ return item;
+}
+public void setColumn(int column) {
+ Table table = tableTree.getTable();
+ int columnCount = table.getColumnCount();
+ // Separately handle the case where the table has no TableColumns.
+ // In this situation, there is a single default column.
+ if (columnCount is 0) {
+ this.column = (column is 0) ? 0 : -1;
+ layout();
+ return;
+ }
+ if (this.column > -1 && this.column < columnCount){
+ TableColumn tableColumn = table.getColumn(this.column);
+ tableColumn.removeControlListener(columnListener);
+ this.column = -1;
+ }
+
+ if (column < 0 || column >= table.getColumnCount()) return;
+
+ this.column = column;
+ TableColumn tableColumn = table.getColumn(this.column);
+ tableColumn.addControlListener(columnListener);
+ layout();
+}
+public void setItem (TableTreeItem item) {
+ this.item = item;
+ layout();
+}
+
+/**
+* Specify the Control that is to be displayed and the cell in the table that it is to be positioned above.
+*
+*
+* final TableTree tableTree = new TableTree(shell, SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
+* final Table table = tableTree.getTable();
+* TableColumn column1 = new TableColumn(table, SWT.NONE);
+* TableColumn column2 = new TableColumn(table, SWT.NONE);
+* for (int i = 0; i < 10; i++) {
+* TableTreeItem item = new TableTreeItem(tableTree, SWT.NONE);
+* item.setText(0, "item " + i);
+* item.setText(1, "edit this value");
+* for (int j = 0; j < 3; j++) {
+* TableTreeItem subitem = new TableTreeItem(item, SWT.NONE);
+* subitem.setText(0, "subitem " + i + " " + j);
+* subitem.setText(1, "edit this value");
+* }
+* }
+* column1.setWidth(100);
+* column2.pack();
+*
+* final TableTreeEditor editor = new TableTreeEditor(tableTree);
+* //The editor must have the same size as the cell and must
+* //not be any smaller than 50 pixels.
+* editor.horizontalAlignment = SWT.LEFT;
+* editor.grabHorizontal = true;
+* editor.minimumWidth = 50;
+* // editing the second column
+* final int EDITABLECOLUMN = 1;
+*
+* tableTree.addSelectionListener(new SelectionAdapter() {
+* public void widgetSelected(SelectionEvent e) {
+* // Clean up any previous editor control
+* Control oldEditor = editor.getEditor();
+* if (oldEditor !is null) oldEditor.dispose();
+*
+* // Identify the selected row
+* TableTreeItem item = (TableTreeItem)e.item;
+* if (item is null) return;
+*
+* // The control that will be the editor must be a child of the Table
+* Text newEditor = new Text(table, SWT.NONE);
+* newEditor.setText(item.getText(EDITABLECOLUMN));
+* newEditor.addModifyListener(new ModifyListener() {
+* public void modifyText(ModifyEvent e) {
+* Text text = (Text)editor.getEditor();
+* editor.getItem().setText(EDITABLECOLUMN, text.getText());
+* }
+* });
+* newEditor.selectAll();
+* newEditor.setFocus();
+* editor.setEditor(newEditor, item, EDITABLECOLUMN);
+* }
+* });
+*
TableTree
)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this(TableTree parent, int style) {
+ this (parent, style, parent.getItemCount());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a TableTree
,
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this(TableTree parent, int style, int index) {
+ this (parent, null, style, index);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a TableTreeItem
)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this(TableTreeItem parent, int style) {
+ this (parent, style, parent.getItemCount());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a TableTreeItem
),
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this(TableTreeItem parent, int style, int index) {
+ this (parent.getParent(), parent, style, index);
+}
+
+this(TableTree parent, TableTreeItem parentItem, int style, int index) {
+
+ items = TableTree.EMPTY_ITEMS;
+ texts = TableTree.EMPTY_TEXTS;
+ images = TableTree.EMPTY_IMAGES;
+
+ super(parent, style);
+ this.parent = parent;
+ this.parentItem = parentItem;
+ if (parentItem is null) {
+
+ /* Root items are visible immediately */
+ int tableIndex = parent.addItem(this, index);
+ tableItem = new TableItem(parent.getTable(), style, tableIndex);
+ tableItem.setData(TableTree.ITEMID, this);
+ addCheck();
+ /*
+ * Feature in the Table. The table uses the first image that
+ * is inserted into the table to size the table rows. If the
+ * user is allowed to insert the first image, this will cause
+ * the +/- images to be scaled. The fix is to insert a dummy
+ * image to force the size.
+ */
+ if (parent.sizeImage is null) {
+ int itemHeight = parent.getItemHeight();
+ parent.sizeImage = new Image(parent.getDisplay(), itemHeight, itemHeight);
+ GC gc = new GC (parent.sizeImage);
+ gc.setBackground(parent.getBackground());
+ gc.fillRectangle(0, 0, itemHeight, itemHeight);
+ gc.dispose();
+ tableItem.setImage(0, parent.sizeImage);
+ }
+ } else {
+ parentItem.addItem(this, index);
+ }
+}
+void addCheck() {
+ Table table = parent.getTable();
+ if ((table.getStyle() & SWT.CHECK) is 0) return;
+ tableItem.setChecked(checked);
+ tableItem.setGrayed(grayed);
+}
+void addItem(TableTreeItem item, int index) {
+ if (item is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (index < 0 || index > items.length) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ /* Now that item has a sub-node it must indicate that it can be expanded */
+ if (items.length is 0 && index is 0) {
+ if (tableItem !is null) {
+ Image image = expanded ? parent.getMinusImage() : parent.getPlusImage();
+ tableItem.setImage(0, image);
+ }
+ }
+
+ /* Put the item in the items list */
+ TableTreeItem[] newItems = new TableTreeItem[items.length + 1];
+ System.arraycopy(items, 0, newItems, 0, index);
+ newItems[index] = item;
+ System.arraycopy(items, index, newItems, index + 1, items.length - index);
+ items = newItems;
+ if (expanded) item.setVisible(true);
+}
+
+/**
+ * Returns the receiver's background color.
+ *
+ * @return the background color
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 2.0
+ *
+ */
+public Color getBackground () {
+ checkWidget ();
+ return (background is null) ? parent.getBackground() : background;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException
+ *
+ */
+public Rectangle getBounds (int index) {
+ checkWidget();
+ if (tableItem !is null) {
+ return tableItem.getBounds(index);
+ } else {
+ return new Rectangle(0, 0, 0, 0);
+ }
+}
+/**
+ * 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
+ *
+ */
+public bool getChecked () {
+ checkWidget();
+ if (tableItem is null) return checked;
+ return tableItem.getChecked();
+}
+
+/**
+ * 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
+ *
+ *
+ * @since 2.1
+ */
+public bool getGrayed () {
+ checkWidget();
+ if (tableItem is null) return grayed;
+ return tableItem.getGrayed();
+}
+
+/**
+ * Returns true
if the receiver is expanded,
+ * and false otherwise.
+ *
+ *
+ *
+ * @since 3.0
+ */
+public Font getFont () {
+ checkWidget ();
+ return (font is null) ? parent.getFont() : font;
+}
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 2.0
+ *
+ */
+public Color getForeground () {
+ checkWidget ();
+ return (foreground is null) ? parent.getForeground() : foreground;
+}
+/**
+ * Gets the first image.
+ *
+ *
+ */
+public override Image getImage () {
+ checkWidget();
+ return getImage(0);
+}
+
+/**
+ * Gets the image at the specified index.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.1
+ */
+public TableTreeItem getItem (int index) {
+ checkWidget();
+ int count = items.length;
+ if (!(0 <= index && index < count)) SWT.error (SWT.ERROR_INVALID_RANGE);
+ return items [index];
+}
+
+/**
+ * Returns the number of items contained in the receiver
+ * that are direct item children of the receiver.
+ *
+ * @return the number of items
+ */
+public int getItemCount () {
+ //checkWidget();
+ return items.length;
+}
+
+/**
+ * Returns an array of TableTreeItem
s which are the
+ * direct item children of the receiver.
+ * TableTree
.
+ *
+ * @return the receiver's parent
+ */
+public TableTree getParent () {
+ //checkWidget();
+ return parent;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * TableTreeItem
or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ */
+public TableTreeItem getParentItem () {
+ //checkWidget();
+ return parentItem;
+}
+public override String getText () {
+ checkWidget();
+ return getText(0);
+}
+
+/**
+ * Gets the item text at the specified index.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 2.0
+ *
+ */
+public void setBackground (Color color) {
+ checkWidget ();
+ if (color !is null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (tableItem !is null) {
+ tableItem.setBackground(color);
+ }
+ background = color;
+}
+
+/**
+ * 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
+ *
+ */
+public void setChecked (bool checked) {
+ checkWidget();
+ Table table = parent.getTable();
+ if ((table.getStyle() & SWT.CHECK) is 0) return;
+ if (tableItem !is null) {
+ tableItem.setChecked(checked);
+ }
+ this.checked = checked;
+}
+
+/**
+ * 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
+ *
+ *
+ * @since 2.1
+ */
+public void setGrayed (bool grayed) {
+ checkWidget();
+ Table table = parent.getTable();
+ if ((table.getStyle() & SWT.CHECK) is 0) return;
+ if (tableItem !is null) {
+ tableItem.setGrayed(grayed);
+ }
+ this.grayed = grayed;
+}
+
+/**
+ * Sets the expanded state.
+ *
+ *
+ */
+public void setExpanded (bool expanded) {
+ checkWidget();
+ if (items.length is 0) return;
+ if (this.expanded is expanded) return;
+ this.expanded = expanded;
+ if (tableItem is null) return;
+ parent.setRedraw(false);
+ for (int i = 0; i < items.length; i++) {
+ items[i].setVisible(expanded);
+ }
+ Image image = expanded ? parent.getMinusImage() : parent.getPlusImage();
+ tableItem.setImage(0, image);
+ parent.setRedraw(true);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.0
+ */
+public void setFont (Font font){
+ checkWidget ();
+ if (font !is null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (tableItem !is null) {
+ tableItem.setFont(font);
+ }
+ this.font = font;
+}
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 2.0
+ *
+ */
+public void setForeground (Color color) {
+ checkWidget ();
+ if (color !is null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (tableItem !is null) {
+ tableItem.setForeground(color);
+ }
+ foreground = color;
+}
+
+/**
+ * Sets the image at an index.
+ *
+ *
+ */
+public void setImage (int index, Image image) {
+ checkWidget();
+ int columnCount = Math.max(parent.getTable().getColumnCount(), 1);
+ if (index <= 0 || index >= columnCount) return;
+ if (images.length < columnCount) {
+ Image[] newImages = new Image[columnCount];
+ System.arraycopy(images, 0, newImages, 0, images.length);
+ images = newImages;
+ }
+ images[index] = image;
+ if (tableItem !is null) tableItem.setImage(index, image);
+}
+
+/**
+ * Sets the first image.
+ *
+ *
+ */
+public override void setImage (Image image) {
+ setImage(0, image);
+}
+
+/**
+ * Sets the widget text.
+ *
+ *
+ */
+public void setText(int index, String text) {
+ checkWidget();
+ // SWT extension: allow null for zero length string
+ //if (text is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ int columnCount = Math.max(parent.getTable().getColumnCount(), 1);
+ if (index < 0 || index >= columnCount) return;
+ if (texts.length < columnCount) {
+ String[] newTexts = new String[columnCount];
+ System.arraycopy(texts, 0, newTexts, 0, texts.length);
+ texts = newTexts;
+ }
+ texts[index] = text;
+ if (tableItem !is null) tableItem.setText(index, text);
+}
+public override void setText (String string) {
+ setText(0, string);
+}
+
+void setVisible (bool show) {
+ if (parentItem is null) return; // this is a root and can not be toggled between visible and hidden
+ if (getVisible() is show) return;
+
+ if (show) {
+ if (!parentItem.getVisible()) return; // parentItem must already be visible
+ // create underlying table item and set data in table item to stored data
+ Table table = parent.getTable();
+ int parentIndex = table.indexOf(parentItem.tableItem);
+ int index = parentItem.expandedIndexOf(this) + parentIndex + 1;
+ if (index < 0) return;
+ tableItem = new TableItem(table, getStyle(), index);
+ tableItem.setData(TableTree.ITEMID, this);
+ tableItem.setImageIndent(getIndent());
+ if (background !is null) tableItem.setBackground(background);
+ if (foreground !is null) tableItem.setForeground(foreground);
+ if (font !is null) tableItem.setFont(font);
+ addCheck();
+
+ // restore fields to item
+ // ignore any images in the first column
+ int columnCount = Math.max(table.getColumnCount(), 1);
+ for (int i = 0; i < columnCount; i++) {
+ if (i < texts.length && texts[i] !is null) setText(i, texts[i]);
+ if (i < images.length && images[i] !is null) setImage(i, images[i]);
+ }
+
+ // display the children and the appropriate [+]/[-] symbol as required
+ if (items.length !is 0) {
+ if (expanded) {
+ tableItem.setImage(0, parent.getMinusImage());
+ for (int i = 0, length = items.length; i < length; i++) {
+ items[i].setVisible(true);
+ }
+ } else {
+ tableItem.setImage(0, parent.getPlusImage());
+ }
+ }
+
+ } else {
+
+ for (int i = 0, length = items.length; i < length; i++) {
+ items[i].setVisible(false);
+ }
+ // remove row from table
+ tableItem.dispose();
+ tableItem = null;
+ }
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangeListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangeListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+*
+* @see TreeEditor snippets
+* @see Sample code and further information
+*/
+
+public class TreeEditor : ControlEditor {
+ Tree tree;
+ TreeItem item;
+ int column = 0;
+ ControlListener columnListener;
+ TreeListener treeListener;
+ Runnable timer;
+ static const int TIMEOUT = 1500;
+
+/**
+* Creates a TreeEditor for the specified Tree.
+*
+* @param tree the Tree Control above which this editor will be displayed
+*
+*/
+public this (Tree tree) {
+ super(tree);
+ this.tree = tree;
+
+ columnListener = new class() ControlListener {
+ public void controlMoved(ControlEvent e){
+ layout();
+ }
+ public void controlResized(ControlEvent e){
+ layout();
+ }
+ };
+ timer = new class() Runnable {
+ public void run() {
+ layout ();
+ }
+ };
+ treeListener = new class() TreeListener {
+ Runnable runnable;
+ this(){
+ runnable = new class() Runnable {
+ public void run() {
+ if (this.outer.outer.editor is null || this.outer.outer.editor.isDisposed()) return;
+ if (this.outer.outer.tree.isDisposed()) return;
+ layout();
+ this.outer.outer.editor.setVisible(true);
+ }
+ };
+ }
+ public void treeCollapsed(TreeEvent e) {
+ if (this.outer.editor is null || this.outer.editor.isDisposed ()) return;
+ this.outer.editor.setVisible(false);
+ e.display.asyncExec(runnable);
+ }
+ public void treeExpanded(TreeEvent e) {
+ if (this.outer.editor is null || this.outer.editor.isDisposed ()) return;
+ this.outer.editor.setVisible(false);
+ e.display.asyncExec(runnable);
+ }
+ };
+ tree.addTreeListener(treeListener);
+
+ // To be consistent with older versions of SWT, grabVertical defaults to true
+ grabVertical = true;
+}
+
+override Rectangle computeBounds () {
+ if (item is null || column is -1 || item.isDisposed()) return new Rectangle(0, 0, 0, 0);
+ Rectangle cell = item.getBounds(column);
+ Rectangle rect = item.getImageBounds(column);
+ cell.x = rect.x + rect.width;
+ cell.width -= rect.width;
+ Rectangle area = tree.getClientArea();
+ if (cell.x < area.x + area.width) {
+ if (cell.x + cell.width > area.x + area.width) {
+ cell.width = area.x + area.width - cell.x;
+ }
+ }
+ Rectangle editorRect = new Rectangle(cell.x, cell.y, minimumWidth, minimumHeight);
+
+ if (grabHorizontal) {
+ if (tree.getColumnCount() is 0) {
+ // Bounds of tree item only include the text area - stretch out to include
+ // entire client area
+ cell.width = area.x + area.width - cell.x;
+ }
+ editorRect.width = Math.max(cell.width, minimumWidth);
+ }
+
+ if (grabVertical) {
+ editorRect.height = Math.max(cell.height, minimumHeight);
+ }
+
+ if (horizontalAlignment is SWT.RIGHT) {
+ editorRect.x += cell.width - editorRect.width;
+ } else if (horizontalAlignment is SWT.LEFT) {
+ // do nothing - cell.x is the right answer
+ } else { // default is CENTER
+ editorRect.x += (cell.width - editorRect.width)/2;
+ }
+ // don't let the editor overlap with the + / - of the tree
+ editorRect.x = Math.max(cell.x, editorRect.x);
+
+ if (verticalAlignment is SWT.BOTTOM) {
+ editorRect.y += cell.height - editorRect.height;
+ } else if (verticalAlignment is SWT.TOP) {
+ // do nothing - cell.y is the right answer
+ } else { // default is CENTER
+ editorRect.y += (cell.height - editorRect.height)/2;
+ }
+ return editorRect;
+}
+
+/**
+ * Removes all associations between the TreeEditor and the row in the tree. The
+ * tree and the editor Control are not disposed.
+ */
+public override void dispose () {
+ if (tree !is null && !tree.isDisposed()) {
+ if (this.column > -1 && this.column < tree.getColumnCount()){
+ TreeColumn treeColumn = tree.getColumn(this.column);
+ treeColumn.removeControlListener(columnListener);
+ }
+ if (treeListener !is null) tree.removeTreeListener(treeListener);
+ }
+ columnListener = null;
+ treeListener = null;
+ tree = null;
+ item = null;
+ column = 0;
+ timer = null;
+ super.dispose();
+}
+
+/**
+* Returns the zero based index of the column of the cell being tracked by this editor.
+*
+* @return the zero based index of the column of the cell being tracked by this editor
+*
+* @since 3.1
+*/
+public int getColumn () {
+ return column;
+}
+
+/**
+* Returns the TreeItem for the row of the cell being tracked by this editor.
+*
+* @return the TreeItem for the row of the cell being tracked by this editor
+*/
+public TreeItem getItem () {
+ return item;
+}
+
+void resize () {
+ layout();
+ /*
+ * On some platforms, the table scrolls when an item that
+ * is partially visible at the bottom of the table is
+ * selected. Ensure that the correct row is edited by
+ * laying out one more time in a timerExec().
+ */
+ if (tree !is null) {
+ Display display = tree.getDisplay();
+ display.timerExec(-1, timer);
+ display.timerExec(TIMEOUT, timer);
+ }
+}
+
+/**
+* Sets the zero based index of the column of the cell being tracked by this editor.
+*
+* @param column the zero based index of the column of the cell being tracked by this editor
+*
+* @since 3.1
+*/
+public void setColumn(int column) {
+ int columnCount = tree.getColumnCount();
+ // Separately handle the case where the tree has no TreeColumns.
+ // In this situation, there is a single default column.
+ if (columnCount is 0) {
+ this.column = (column is 0) ? 0 : -1;
+ resize();
+ return;
+ }
+ if (this.column > -1 && this.column < columnCount){
+ TreeColumn treeColumn = tree.getColumn(this.column);
+ treeColumn.removeControlListener(columnListener);
+ this.column = -1;
+ }
+
+ if (column < 0 || column >= tree.getColumnCount()) return;
+
+ this.column = column;
+ TreeColumn treeColumn = tree.getColumn(this.column);
+ treeColumn.addControlListener(columnListener);
+ resize();
+}
+
+/**
+* Specifies the
+* final Tree tree = new Tree(shell, SWT.BORDER);
+* for (int i = 0; i < 3; i++) {
+* TreeItem item = new TreeItem(tree, SWT.NONE);
+* item.setText("item " + i);
+* for (int j = 0; j < 3; j++) {
+* TreeItem subItem = new TreeItem(item, SWT.NONE);
+* subItem.setText("item " + i + " " + j);
+* }
+* }
+*
+* final TreeEditor editor = new TreeEditor(tree);
+* //The editor must have the same size as the cell and must
+* //not be any smaller than 50 pixels.
+* editor.horizontalAlignment = SWT.LEFT;
+* editor.grabHorizontal = true;
+* editor.minimumWidth = 50;
+*
+* tree.addSelectionListener(new SelectionAdapter() {
+* public void widgetSelected(SelectionEvent e) {
+* // Clean up any previous editor control
+* Control oldEditor = editor.getEditor();
+* if (oldEditor !is null) oldEditor.dispose();
+*
+* // Identify the selected row
+* TreeItem item = (TreeItem)e.item;
+* if (item is null) return;
+*
+* // The control that will be the editor must be a child of the Tree
+* Text newEditor = new Text(tree, SWT.NONE);
+* newEditor.setText(item.getText());
+* newEditor.addModifyListener(new ModifyListener() {
+* public void modifyText(ModifyEvent e) {
+* Text text = (Text)editor.getEditor();
+* editor.getItem().setText(text.getText());
+* }
+* });
+* newEditor.selectAll();
+* newEditor.setFocus();
+* editor.setEditor(newEditor, item);
+* }
+* });
+*
TreeItem
that is to be edited.
+*
+* @param item the item to be edited
+*/
+public void setItem (TreeItem item) {
+ this.item = item;
+ resize();
+}
+
+/**
+* Specify the Control that is to be displayed and the cell in the tree that it is to be positioned above.
+*
+*
+ *
+ * @param event the verify event
+ * @see VerifyEvent
+ */
+public void verifyKey (VerifyEvent event);
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ViewForm.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ViewForm.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,493 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Composite
,
+ * it does not make sense to set a layout on it.
+ *
+ *
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see SWT#BORDER
+ * @see SWT#FLAT
+ * @see #getStyle()
+ */
+public this(Composite parent, int style) {
+ super(parent, checkStyle(style));
+ super.setLayout(new ViewFormLayout());
+
+ setBorderVisible((style & SWT.BORDER) !is 0);
+
+ Listener listener = new class() Listener {
+ public void handleEvent(Event e) {
+ switch (e.type) {
+ case SWT.Dispose: onDispose(); break;
+ case SWT.Paint: onPaint(e.gc); break;
+ case SWT.Resize: onResize(); break;
+ default:
+ }
+ }
+ };
+
+ int[] events = [SWT.Dispose, SWT.Paint, SWT.Resize];
+
+ for (int i = 0; i < events.length; i++) {
+ addListener(events[i], listener);
+ }
+}
+
+static int checkStyle (int style) {
+ int mask = SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ return style & mask | SWT.NO_REDRAW_RESIZE;
+}
+
+//protected void checkSubclass () {
+// String name = getClass().getName ();
+// String validName = ViewForm.class.getName();
+// if (!validName.equals(name)) {
+// SWT.error (SWT.ERROR_INVALID_SUBCLASS);
+// }
+//}
+
+public override Rectangle computeTrim (int x, int y, int width, int height) {
+ checkWidget ();
+ int trimX = x - borderLeft - highlight;
+ int trimY = y - borderTop - highlight;
+ int trimWidth = width + borderLeft + borderRight + 2*highlight;
+ int trimHeight = height + borderTop + borderBottom + 2*highlight;
+ return new Rectangle(trimX, trimY, trimWidth, trimHeight);
+}
+public override Rectangle getClientArea() {
+ checkWidget();
+ Rectangle clientArea = super.getClientArea();
+ clientArea.x += borderLeft;
+ clientArea.y += borderTop;
+ clientArea.width -= borderLeft + borderRight;
+ clientArea.height -= borderTop + borderBottom;
+ return clientArea;
+}
+/**
+* Returns the content area.
+*
+* @return the control in the content area of the pane or null
+*/
+public Control getContent() {
+ //checkWidget();
+ return content;
+}
+/**
+* Returns Control that appears in the top center of the pane.
+* Typically this is a toolbar.
+*
+* @return the control in the top center of the pane or null
+*/
+public Control getTopCenter() {
+ //checkWidget();
+ return topCenter;
+}
+/**
+* Returns the Control that appears in the top left corner of the pane.
+* Typically this is a label such as CLabel.
+*
+* @return the control in the top left corner of the pane or null
+*/
+public Control getTopLeft() {
+ //checkWidget();
+ return topLeft;
+}
+/**
+* Returns the control in the top right corner of the pane.
+* Typically this is a Close button or a composite with a Menu and Close button.
+*
+* @return the control in the top right corner of the pane or null
+*/
+public Control getTopRight() {
+ //checkWidget();
+ return topRight;
+}
+void onDispose() {
+ topLeft = null;
+ topCenter = null;
+ topRight = null;
+ content = null;
+ oldSize = null;
+ selectionBackground = null;
+}
+void onPaint(GC gc) {
+ Color gcForeground = gc.getForeground();
+ Point size = getSize();
+ Color border = getDisplay().getSystemColor(BORDER1_COLOR);
+ if (showBorder) {
+ gc.setForeground(border);
+ gc.drawRectangle(0, 0, size.x - 1, size.y - 1);
+ if (highlight > 0) {
+ int x1 = 1;
+ int y1 = 1;
+ int x2 = size.x - 1;
+ int y2 = size.y - 1;
+ int[] shape = [x1,y1, x2,y1, x2,y2, x1,y2, x1,y1+highlight,
+ x1+highlight,y1+highlight, x1+highlight,y2-highlight,
+ x2-highlight,y2-highlight, x2-highlight,y1+highlight, x1,y1+highlight];
+ Color highlightColor = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+ gc.setBackground(highlightColor);
+ gc.fillPolygon(shape);
+ }
+ }
+ if (separator > -1) {
+ gc.setForeground(border);
+ gc.drawLine(borderLeft + highlight, separator, size.x - borderLeft - borderRight - highlight, separator);
+ }
+ gc.setForeground(gcForeground);
+}
+void onResize() {
+ Point size = getSize();
+ if (oldSize is null || oldSize.x is 0 || oldSize.y is 0) {
+ redraw();
+ } else {
+ int width = 0;
+ if (oldSize.x < size.x) {
+ width = size.x - oldSize.x + borderRight + highlight;
+ } else if (oldSize.x > size.x) {
+ width = borderRight + highlight;
+ }
+ redraw(size.x - width, 0, width, size.y, false);
+
+ int height = 0;
+ if (oldSize.y < size.y) {
+ height = size.y - oldSize.y + borderBottom + highlight;
+ }
+ if (oldSize.y > size.y) {
+ height = borderBottom + highlight;
+ }
+ redraw(0, size.y - height, size.x, height, false);
+ }
+ oldSize = size;
+}
+/**
+* Sets the content.
+* Setting the content to null will remove it from
+* the pane - however, the creator of the content must dispose of the content.
+*
+* @param content the control to be displayed in the content area or null
+*
+* @exception SWTException
+*
+*/
+public void setContent(Control content) {
+ checkWidget();
+ if (content !is null && content.getParent() !is this) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (this.content !is null && !this.content.isDisposed()) {
+ this.content.setBounds(OFFSCREEN, OFFSCREEN, 0, 0);
+ }
+ this.content = content;
+ layout(false);
+}
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ *
+ *
+ */
+public override void setLayout (Layout layout) {
+ checkWidget();
+ return;
+}
+void setSelectionBackground (Color color) {
+ checkWidget();
+ if (selectionBackground is color) return;
+ if (color is null) color = getDisplay().getSystemColor(SELECTION_BACKGROUND);
+ selectionBackground = color;
+ redraw();
+}
+/**
+* Set the control that appears in the top center of the pane.
+* Typically this is a toolbar.
+* The topCenter is optional. Setting the topCenter to null will remove it from
+* the pane - however, the creator of the topCenter must dispose of the topCenter.
+*
+* @param topCenter the control to be displayed in the top center or null
+*
+* @exception SWTException
+*
+*/
+public void setTopCenter(Control topCenter) {
+ checkWidget();
+ if (topCenter !is null && topCenter.getParent() !is this) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (this.topCenter !is null && !this.topCenter.isDisposed()) {
+ Point size = this.topCenter.getSize();
+ this.topCenter.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+ }
+ this.topCenter = topCenter;
+ layout(false);
+}
+/**
+* Set the control that appears in the top left corner of the pane.
+* Typically this is a label such as CLabel.
+* The topLeft is optional. Setting the top left control to null will remove it from
+* the pane - however, the creator of the control must dispose of the control.
+*
+* @param c the control to be displayed in the top left corner or null
+*
+* @exception SWTException
+*
+*/
+public void setTopLeft(Control c) {
+ checkWidget();
+ if (c !is null && c.getParent() !is this) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (this.topLeft !is null && !this.topLeft.isDisposed()) {
+ Point size = this.topLeft.getSize();
+ this.topLeft.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+ }
+ this.topLeft = c;
+ layout(false);
+}
+/**
+* Set the control that appears in the top right corner of the pane.
+* Typically this is a Close button or a composite with a Menu and Close button.
+* The topRight is optional. Setting the top right control to null will remove it from
+* the pane - however, the creator of the control must dispose of the control.
+*
+* @param c the control to be displayed in the top right corner or null
+*
+* @exception SWTException
+*
+*/
+public void setTopRight(Control c) {
+ checkWidget();
+ if (c !is null && c.getParent() !is this) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (this.topRight !is null && !this.topRight.isDisposed()) {
+ Point size = this.topRight.getSize();
+ this.topRight.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+ }
+ this.topRight = c;
+ layout(false);
+}
+/**
+* Specify whether the border should be displayed or not.
+*
+* @param show true if the border should be displayed
+*
+* @exception SWTException
+*
+*/
+public void setBorderVisible(bool show) {
+ checkWidget();
+ if (showBorder is show) return;
+
+ showBorder = show;
+ if (showBorder) {
+ borderLeft = borderTop = borderRight = borderBottom = 1;
+ if ((getStyle() & SWT.FLAT)is 0) highlight = 2;
+ } else {
+ borderBottom = borderTop = borderLeft = borderRight = 0;
+ highlight = 0;
+ }
+ layout(false);
+ redraw();
+}
+/**
+* If true, the topCenter will always appear on a separate line by itself, otherwise the
+* topCenter will appear in the top row if there is room and will be moved to the second row if
+* required.
+*
+* @param show true if the topCenter will always appear on a separate line by itself
+*
+* @exception SWTException
+*
+*/
+public void setTopCenterSeparate(bool show) {
+ checkWidget();
+ separateTopCenter = show;
+ layout(false);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ViewFormLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ViewFormLayout.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit ByteArrayTransfer
provides a platform specific
+ * mechanism for converting a java byte[]
to a platform
+ * specific representation of the byte array and vice versa.
+ *
+ * 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.
+ *
+ * byte[]
, you should sub-class Transfer
directly
+ * and do your own mapping to a platform data type.MyType
.
+ *
+ *
+ * public class MyType {
+ * public String fileName;
+ * public long fileLength;
+ * public long lastModified;
+ * }
+ *
+ *
+ * @see Transfer
+ */
+public abstract class ByteArrayTransfer : Transfer {
+
+public TransferData[] getSupportedTypes() {
+ int[] types = getTypeIds();
+ TransferData[] data = new TransferData[types.length];
+ for (int i = 0; i < types.length; i++) {
+ data[i] = new TransferData();
+ data[i].type = types[i];
+ data[i].formatetc = new FORMATETC();
+ data[i].formatetc.cfFormat = types[i];
+ data[i].formatetc.dwAspect = COM.DVASPECT_CONTENT;
+ data[i].formatetc.lindex = -1;
+ data[i].formatetc.tymed = COM.TYMED_HGLOBAL;
+ }
+ return data;
+}
+
+public bool isSupportedType(TransferData transferData){
+ if (transferData is null) return false;
+ int[] types = getTypeIds();
+ for (int i = 0; i < types.length; i++) {
+ FORMATETC* format = transferData.formatetc;
+ if (format.cfFormat is types[i] &&
+ (format.dwAspect & COM.DVASPECT_CONTENT) is COM.DVASPECT_CONTENT &&
+ (format.tymed & COM.TYMED_HGLOBAL) is COM.TYMED_HGLOBAL )
+ return true;
+ }
+ return false;
+}
+
+/**
+ * This implementation of
+ * 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 is 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 is 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};
+ * }
+ * }
+ *
javaToNative
converts a java
+ * byte[]
to a platform specific representation.
+ *
+ * @param object a java byte[]
containing the data to be converted
+ * @param transferData an empty TransferData
object that will
+ * be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#nativeToJava
+ */
+protected void javaToNative (Object object, TransferData transferData) {
+ if (!checkByteArray(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ // Allocate the memory because the caller (DropTarget) has not handed it in
+ // The caller of this method must release the data when it is done with it.
+ byte[] data = (cast(ArrayWrapperByte)object).array;
+ int size = data.length;
+ auto newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, size);
+ OS.MoveMemory(newPtr, data.ptr, size);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = newPtr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of a byte array to a java byte[]
.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java byte[]
containing the converted data if the conversion was
+ * successful; otherwise null
+ *
+ * @see Transfer#javaToNative
+ */
+protected Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+
+ IDataObject data = transferData.pIDataObject;
+ data.AddRef();
+ FORMATETC* formatetc = transferData.formatetc;
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = getData(data, formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ auto hMem = stgmedium.unionField;
+ int size = OS.GlobalSize(hMem);
+ byte[] buffer = new byte[size];
+ auto ptr = OS.GlobalLock(hMem);
+ OS.MoveMemory(buffer.ptr, ptr, size);
+ OS.GlobalUnlock(hMem);
+ OS.GlobalFree(hMem);
+ return new ArrayWrapperByte(buffer);
+}
+
+bool checkByteArray(Object object) {
+ return (object !is null && ( null !is cast(ArrayWrapperByte)object) && (cast(ArrayWrapperByte)object).array.length > 0);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/Clipboard.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/Clipboard.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,819 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Clipboard
provides a mechanism for transferring data from one
+ * application to another or within an application.
+ *
+ *
+ *
+ *
+ * @see Clipboard#dispose
+ * @see Clipboard#checkSubclass
+ */
+public this(Display display) {
+ checkSubclass ();
+ if (display is null) {
+ display = Display.getCurrent();
+ if (display is null) {
+ display = Display.getDefault();
+ }
+ }
+ if (display.getThread() !is Thread.getThis()) {
+ DND.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ this.display = display;
+ TCHAR* chFormatName = StrToTCHARz(0, "Preferred DropEffect"); //$NON-NLS-1$
+ CFSTR_PREFERREDDROPEFFECT = OS.RegisterClipboardFormat(chFormatName);
+ createCOMInterfaces();
+ this.AddRef();
+}
+
+/**
+ * Checks that this class can be subclassed.
+ *
+ *
+ */
+protected void checkSubclass () {
+ String name = this.classinfo.name;
+ String validName = Clipboard.classinfo.name;
+ if (validName!=/*eq*/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.
+ * 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.
+ *
+ *
+ */
+protected void checkWidget () {
+ Display display = this.display;
+ if (display is null) DND.error (SWT.ERROR_WIDGET_DISPOSED);
+ if (display.getThread() !is Thread.getThis ()) 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
+ *
+ *
+ * @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.
+ *
+ * DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ *
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public void clearContents(int clipboards) {
+ checkWidget();
+ if ((clipboards & DND.CLIPBOARD) !is 0) {
+ /* OleIsCurrentClipboard([in] pDataObject)
+ * The argument pDataObject is owned by the caller so reference count does not
+ * need to be incremented.
+ */
+ if (COM.OleIsCurrentClipboard(this.iDataObject) is COM.S_OK) {
+ /* OleSetClipboard([in] pDataObject)
+ * The argument pDataObject is owned by the caller so reference count does not
+ * need to be incremented.
+ */
+ COM.OleSetClipboard(null);
+ }
+ }
+}
+
+/**
+ * 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.
+ *
+ *
+ *
+ */
+public void dispose () {
+ if (isDisposed()) return;
+ if (display.getThread() !is Thread.getThis ()) DND.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+ /* OleIsCurrentClipboard([in] pDataObject)
+ * The argument pDataObject is owned by the caller so reference count does not
+ * need to be incremented.
+ */
+ if (COM.OleIsCurrentClipboard(this.iDataObject) is COM.S_OK) {
+ COM.OleFlushClipboard();
+ }
+ this.Release();
+ 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.
+ *
+ *
+ *
+ * @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
+ * Clipboard clipboard = new Clipboard(display);
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String textData = (String)clipboard.getContents(textTransfer);
+ * if (textData !is null) System.out.println("Text is "+textData);
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * String rtfData = (String)clipboard.getContents(rtfTransfer);
+ * if (rtfData !is null) System.out.println("RTF Text is "+rtfData);
+ * clipboard.dispose();
+ *
+ *
+ * @exception IllegalArgumentException
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ *
+ * Clipboard clipboard = new Clipboard(display);
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String textData = (String)clipboard.getContents(textTransfer);
+ * if (textData !is null) System.out.println("Text is "+textData);
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * String rtfData = (String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD);
+ * if (rtfData !is null) System.out.println("RTF Text is "+rtfData);
+ * clipboard.dispose();
+ *
DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ * @exception IllegalArgumentException
+ *
+ *
+ * @see Transfer
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public Object getContents(Transfer transfer, int clipboards) {
+ checkWidget();
+ if (transfer is null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+ if ((clipboards & DND.CLIPBOARD) is 0) return null;
+ /*
+ * Bug in Windows. When a new application takes control
+ * of the clipboard, other applications may open the
+ * clipboard to determine if they want to record the
+ * clipboard updates. When this happens, the clipboard
+ * can not be accessed until the other application is
+ * finished. To allow the other applications to release
+ * the clipboard, use PeekMessage() to enable cross thread
+ * message sends.
+ */
+ IDataObject dataObject;
+ int retryCount = 0;
+ /* OleGetClipboard([out] ppDataObject).
+ * AddRef has already been called on ppDataObject by the callee and must be released by the caller.
+ */
+ int result = COM.OleGetClipboard(&dataObject);
+ while (result !is COM.S_OK && retryCount++ < 10) {
+ try {Thread.sleep(0.050);} catch (Exception t) {}
+ MSG msg;
+ OS.PeekMessage(&msg, null, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD);
+ result = COM.OleGetClipboard(&dataObject);
+ }
+ if (result !is COM.S_OK) return null;
+ try {
+ TransferData[] allowed = transfer.getSupportedTypes();
+ for (int i = 0; i < allowed.length; i++) {
+ if (dataObject.QueryGetData(allowed[i].formatetc) is COM.S_OK) {
+ TransferData data = allowed[i];
+ data.pIDataObject = dataObject;
+ return transfer.nativeToJava(data);
+ }
+ }
+ } finally {
+ dataObject.Release();
+ }
+ return null; // No data available for this transfer
+}
+/**
+ * Returns true
if the clipboard has been disposed,
+ * and false
otherwise.
+ * true
when the widget is disposed and false
otherwise
+ *
+ * @since 3.0
+ */
+public bool isDisposed () {
+ return (display is 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.
+ *
+ *
+ *
+ * @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
+ * 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();
+ *
+ *
+ * @exception SWTException
+ *
+ * @exception SWTError
+ *
+ *
+ * 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 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
+ * 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();
+ *
+ *
+ * @exception SWTException
+ *
+ * @exception SWTError
+ *
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ * DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ *
+ * @see Transfer#isSupportedType
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public TransferData[] getAvailableTypes(int clipboards) {
+ checkWidget();
+ if ((clipboards & DND.CLIPBOARD) is 0) return null;
+ FORMATETC*[] types = _getAvailableTypes();
+ TransferData[] data = new TransferData[types.length];
+ for (int i = 0; i < types.length; i++) {
+ data[i] = new TransferData();
+ data[i].type = types[i].cfFormat;
+ data[i].formatetc = types[i];
+ }
+ return data;
+}
+
+/**
+ * Returns a platform specific list of the data types currently available on the
+ * system clipboard.
+ *
+ * getAvailableTypeNames
is a utility for writing a Transfer
+ * sub-class. It should NOT be used within an application because it provides
+ * platform specific information.
+ *
+ */
+public String[] getAvailableTypeNames() {
+ checkWidget();
+ FORMATETC*[] types = _getAvailableTypes();
+ String[] names = new String[](types.length);
+ int maxSize = 128;
+ for (int i = 0; i < types.length; i++){
+ TCHAR[] buffer = NewTCHARs(0, maxSize);
+ int size = OS.GetClipboardFormatName(types[i].cfFormat, buffer.ptr, maxSize);
+ if (size !is 0) {
+ names[i] = TCHARzToStr(buffer.ptr)[0..size];
+ } else {
+ switch (types[i].cfFormat) {
+ case COM.CF_HDROP: names[i] = "CF_HDROP"; break; //$NON-NLS-1$
+ case COM.CF_TEXT: names[i] = "CF_TEXT"; break; //$NON-NLS-1$
+ case COM.CF_BITMAP: names[i] = "CF_BITMAP"; break; //$NON-NLS-1$
+ case COM.CF_METAFILEPICT: names[i] = "CF_METAFILEPICT"; break; //$NON-NLS-1$
+ case COM.CF_SYLK: names[i] = "CF_SYLK"; break; //$NON-NLS-1$
+ case COM.CF_DIF: names[i] = "CF_DIF"; break; //$NON-NLS-1$
+ case COM.CF_TIFF: names[i] = "CF_TIFF"; break; //$NON-NLS-1$
+ case COM.CF_OEMTEXT: names[i] = "CF_OEMTEXT"; break; //$NON-NLS-1$
+ case COM.CF_DIB: names[i] = "CF_DIB"; break; //$NON-NLS-1$
+ case COM.CF_PALETTE: names[i] = "CF_PALETTE"; break; //$NON-NLS-1$
+ case COM.CF_PENDATA: names[i] = "CF_PENDATA"; break; //$NON-NLS-1$
+ case COM.CF_RIFF: names[i] = "CF_RIFF"; break; //$NON-NLS-1$
+ case COM.CF_WAVE: names[i] = "CF_WAVE"; break; //$NON-NLS-1$
+ case COM.CF_UNICODETEXT: names[i] = "CF_UNICODETEXT"; break; //$NON-NLS-1$
+ case COM.CF_ENHMETAFILE: names[i] = "CF_ENHMETAFILE"; break; //$NON-NLS-1$
+ case COM.CF_LOCALE: names[i] = "CF_LOCALE"; break; //$NON-NLS-1$
+ case COM.CF_MAX: names[i] = "CF_MAX"; break; //$NON-NLS-1$
+ default: names[i] = "UNKNOWN"; //$NON-NLS-1$
+ }
+ }
+ }
+ return names;
+}
+
+private FORMATETC*[] _getAvailableTypes() {
+ FORMATETC*[] types = null;
+ IDataObject dataObject;
+ /* OleGetClipboard([out] ppDataObject).
+ * AddRef has already been called on ppDataObject by the callee and must be released by the caller.
+ */
+ if (COM.OleGetClipboard(&dataObject) !is COM.S_OK) return types;
+ IEnumFORMATETC enumFormatetc;
+ /* EnumFormatEtc([in] dwDirection, [out] ppenumFormatetc)
+ * AddRef has already been called on ppenumFormatetc by the callee and must be released by the caller.
+ */
+ int rc = dataObject.EnumFormatEtc(COM.DATADIR_GET, &enumFormatetc);
+ dataObject.Release();
+ if (rc !is COM.S_OK)return types;
+ // Loop over enumerator and save any types that match what we are looking for
+ //int /*long*/ rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof);
+ uint[1] pceltFetched;
+ FORMATETC rgelt;
+ enumFormatetc.Reset();
+ while (enumFormatetc.Next(1, &rgelt, pceltFetched.ptr) is COM.S_OK && pceltFetched[0] is 1) {
+ FORMATETC* formatetc = new FORMATETC();
+ COM.MoveMemory(formatetc, &rgelt, FORMATETC.sizeof);
+ FORMATETC*[] newTypes = new FORMATETC*[types.length + 1];
+ SimpleType!(FORMATETC*).arraycopy(types, 0, newTypes, 0, types.length);
+ newTypes[types.length] = formatetc;
+ types = newTypes;
+ }
+ //OS.GlobalFree(rgelt);
+ enumFormatetc.Release();
+ return types;
+}
+}
+
+private class _IDataObjectImpl : IDataObject {
+
+ Clipboard parent;
+ this(Clipboard p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(GUID* riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface IDataObject
+ LRESULT GetData( FORMATETC *pFormatetc, STGMEDIUM *pmedium) { return parent.GetData(pFormatetc, pmedium); }
+ LRESULT GetDataHere(FORMATETC * pFormatetc, STGMEDIUM * pmedium) { return COM.E_NOTIMPL; }
+ LRESULT QueryGetData(FORMATETC* pFormatetc) { return parent.QueryGetData(pFormatetc); }
+ LRESULT GetCanonicalFormatEtc(FORMATETC* pFormatetcIn, FORMATETC* pFormatetcOut) { return COM.E_NOTIMPL; }
+ LRESULT SetData(FORMATETC* pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) { return COM.E_NOTIMPL; }
+ LRESULT EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC * ppenumFormatetc) { return parent.EnumFormatEtc(dwDirection, ppenumFormatetc); }
+ LRESULT DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink pAdvSink, DWORD* pdwConnection) { return COM.E_NOTIMPL; }
+ LRESULT DUnadvise(DWORD dwConnection) { return COM.E_NOTIMPL; }
+ LRESULT EnumDAdvise(IEnumSTATDATA * ppenumAdvise) { return COM.E_NOTIMPL; }
+}
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DND.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DND.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit getData(String)
. When a drop target
+ * is created for a control, it is stored as a property in the control
+ * using setData(String, Object)
.
+ *
+ * @since 3.4
+ */
+ public static final String DROP_TARGET_KEY = "DropTarget"; //$NON-NLS-1$
+
+ /**
+ * DragSource Key: The string constant for looking up the drag source
+ * for a control using getData(String)
. When a drag source
+ * is created for a control, it is stored as a property in the control
+ * using setData(String, Object)
.
+ *
+ * @since 3.4
+ */
+ public static final String DRAG_SOURCE_KEY = "DragSource"; //$NON-NLS-1$
+
+ static const String INIT_DRAG_MESSAGE = "Cannot initialize Drag"; //$NON-NLS-1$
+ static const String INIT_DROP_MESSAGE = "Cannot initialize Drop"; //$NON-NLS-1$
+ static const String CANNOT_SET_CLIPBOARD_MESSAGE = "Cannot set data in clipboard"; //$NON-NLS-1$
+ static const String INVALID_DATA_MESSAGE = "Data does not have correct format for type"; //$NON-NLS-1$
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ *
+ * @param code the DND error code
+ */
+public static void error (int code) {
+ error (code, 0);
+}
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ * The hresult
argument should be either 0, or the
+ * platform specific error code.
+ *
+ *
+ * This method provides the logic which maps between error codes
+ * and one of the above exceptions.
+ * DragSource
defines the source object for a drag and drop transfer.
+ *
+ * ByteArrayTransfer
.DragSourceListener
and associating it with the DragSource via DragSource#addDragListener.
+ *
+ *
+ *
+ * // 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() is 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 is DND.DROP_MOVE)
+ * label.setText("");
+ * }
+ * });
+ *
+ *
+ *
+ * @see Drag and Drop snippets
+ * @see SWT Example: DNDExample
+ * @see Sample code and further information
+ */
+public class DragSource : Widget {
+
+ // info for registering as a drag source
+ Control control;
+ Listener controlListener;
+ Transfer[] transferAgents;
+ DragSourceEffect dragEffect;
+ Composite topControl;
+ HWND hwndDrag;
+
+ // ole interfaces
+ _IDropSourceImpl iDropSource;
+ _IDataObjectImpl iDataObject;
+ int refCount;
+
+ //workaround - track the operation performed by the drop target for DragEnd event
+ int dataEffect = DND.DROP_NONE;
+
+ static const String DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; //$NON-NLS-1$
+ static const int CFSTR_PERFORMEDDROPEFFECT;
+ static final TCHAR[] WindowClass = "#32770\0";
+ static this(){
+ 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
+ *
+ * @exception SWTError
+ *
+ *
+ * DragSourceListener
+ * 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.
+ *
+ *
+ * @exception SWTException
+ *
+ *
+ * @see DragSourceListener
+ * @see #getDragListeners
+ * @see #removeDragListener
+ * @see DragSourceEvent
+ */
+public void addDragListener(DragSourceListener listener) {
+ if (listener is null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+ DNDListener typedListener = new DNDListener(listener);
+ typedListener.dndWidget = this;
+ addListener(DND.DragStart, typedListener);
+ addListener(DND.DragSetData, typedListener);
+ addListener(DND.DragEnd, typedListener);
+}
+
+private int AddRef() {
+ refCount++;
+ return refCount;
+}
+
+private void createCOMInterfaces() {
+ // register each of the interfaces that this object implements
+ iDropSource = new _IDropSourceImpl(this);
+ iDataObject = new _IDataObjectImpl(this);
+}
+
+protected void checkSubclass() {
+ String name = this.classinfo.name;
+ String validName = DragSource.classinfo.name;
+ if (validName!=/*eq*/name) {
+ DND.error(SWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+
+private void disposeCOMInterfaces() {
+ iDropSource = null;
+ iDataObject = null;
+}
+
+private void drag(Event dragEvent) {
+ DNDEvent event = new DNDEvent();
+ event.widget = this;
+ event.x = dragEvent.x;
+ event.y = dragEvent.y;
+ event.time = OS.GetMessageTime();
+ event.doit = true;
+ notifyListeners(DND.DragStart,event);
+ if (!event.doit || transferAgents is null || transferAgents.length is 0 ) return;
+
+ uint[1] pdwEffect;
+ int operations = opToOs(getStyle());
+ Display display = control.getDisplay();
+ String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
+ Object oldValue = display.getData(key);
+ display.setData(key, new Boolean(true));
+ ImageList imagelist = null;
+ Image image = event.image;
+ hwndDrag = null;
+ topControl = null;
+ if (image !is null) {
+ imagelist = new ImageList(SWT.NONE);
+ imagelist.add(image);
+ topControl = control.getShell();
+ /*
+ * Bug in Windows. The image is inverted if the shell is RIGHT_TO_LEFT.
+ * The fix is to create a transparent window that covers the shell client
+ * area and use it during the drag to prevent the image from being inverted.
+ * On XP if the shell is RTL, the image is not displayed.
+ */
+ int offset = event.x - dragEvent.x;
+ hwndDrag = topControl.handle;
+ if ((topControl.getStyle() & SWT.RIGHT_TO_LEFT) !is 0) {
+ offset = image.getBounds().width - offset;
+ RECT rect;
+ OS.GetClientRect (topControl.handle, &rect);
+ hwndDrag = OS.CreateWindowEx (
+ OS.WS_EX_TRANSPARENT | OS.WS_EX_NOINHERITLAYOUT,
+ WindowClass.ptr,
+ null,
+ OS.WS_CHILD | OS.WS_CLIPSIBLINGS,
+ 0, 0,
+ rect.right - rect.left, rect.bottom - rect.top,
+ topControl.handle,
+ null,
+ OS.GetModuleHandle (null),
+ null);
+ OS.ShowWindow (hwndDrag, OS.SW_SHOW);
+ }
+ OS.ImageList_BeginDrag(imagelist.getHandle(), 0, offset, event.y - dragEvent.y);
+ /*
+ * Feature in Windows. When ImageList_DragEnter() is called,
+ * it takes a snapshot of the screen If a drag is started
+ * when another window is in front, then the snapshot will
+ * contain part of the other window, causing pixel corruption.
+ * The fix is to force all paints to be delivered before
+ * calling ImageList_DragEnter().
+ */
+ if (OS.IsWinCE) {
+ OS.UpdateWindow (topControl.handle);
+ } else {
+ int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+ OS.RedrawWindow (topControl.handle, null, null, flags);
+ }
+ POINT pt;
+ pt.x = dragEvent.x;
+ pt.y = dragEvent.y;
+ OS.MapWindowPoints (control.handle, null, &pt, 1);
+ RECT rect;
+ OS.GetWindowRect (hwndDrag, &rect);
+ OS.ImageList_DragEnter(hwndDrag, pt.x - rect.left, pt.y - rect.top);
+ }
+ int result = COM.DRAGDROP_S_CANCEL;
+ try {
+ result = COM.DoDragDrop(iDataObject, iDropSource, operations, pdwEffect.ptr);
+ } finally {
+ // ensure that we don't leave transparent window around
+ if (hwndDrag !is null) {
+ OS.ImageList_DragLeave(hwndDrag);
+ OS.ImageList_EndDrag();
+ imagelist.dispose();
+ if (hwndDrag !is topControl.handle) OS.DestroyWindow(hwndDrag);
+ hwndDrag = null;
+ topControl = null;
+ }
+ display.setData(key, oldValue);
+ }
+ int operation = osToOp(pdwEffect[0]);
+ if (dataEffect is DND.DROP_MOVE) {
+ operation = (operation is DND.DROP_NONE || operation is DND.DROP_COPY) ? DND.DROP_TARGET_MOVE : DND.DROP_MOVE;
+ } else {
+ if (dataEffect !is DND.DROP_NONE) {
+ operation = dataEffect;
+ }
+ }
+ event = new DNDEvent();
+ event.widget = this;
+ event.time = OS.GetMessageTime();
+ event.doit = (result is COM.DRAGDROP_S_DROP);
+ event.detail = operation;
+ notifyListeners(DND.DragEnd,event);
+ dataEffect = DND.DROP_NONE;
+}
+/*
+ * EnumFormatEtc([in] dwDirection, [out] ppenumFormatetc)
+ * Ownership of ppenumFormatetc transfers from callee to caller so reference count on ppenumFormatetc
+ * must be incremented before returning. Caller is responsible for releasing ppenumFormatetc.
+ */
+private int EnumFormatEtc(int dwDirection, IEnumFORMATETC* ppenumFormatetc) {
+ // only allow getting of data - SetData is not currently supported
+ if (dwDirection is COM.DATADIR_SET) return COM.E_NOTIMPL;
+
+ // what types have been registered?
+ TransferData[] allowedDataTypes = new TransferData[0];
+ for (int i = 0; i < transferAgents.length; i++){
+ Transfer transferAgent = transferAgents[i];
+ if (transferAgent !is null) {
+ TransferData[] formats = transferAgent.getSupportedTypes();
+ TransferData[] newAllowedDataTypes = new TransferData[allowedDataTypes.length + formats.length];
+ System.arraycopy(allowedDataTypes, 0, newAllowedDataTypes, 0, allowedDataTypes.length);
+ System.arraycopy(formats, 0, newAllowedDataTypes, allowedDataTypes.length, formats.length);
+ allowedDataTypes = newAllowedDataTypes;
+ }
+ }
+
+ OleEnumFORMATETC enumFORMATETC = new OleEnumFORMATETC();
+ enumFORMATETC.AddRef();
+
+ FORMATETC*[] formats = new FORMATETC*[allowedDataTypes.length];
+ for (int i = 0; i < formats.length; i++){
+ formats[i] = allowedDataTypes[i].formatetc;
+ }
+ enumFORMATETC.setFormats(formats);
+
+ *ppenumFormatetc = enumFORMATETC.getAddress();
+ return COM.S_OK;
+}
+/**
+ * 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;
+}
+
+.LRESULT GetData(FORMATETC *pFormatetc, STGMEDIUM *pmedium) {
+ /* Called by a data consumer to obtain data from a source data object.
+ The GetData method renders the data described in the specified FORMATETC
+ structure and transfers it through the specified STGMEDIUM structure.
+ The caller then assumes responsibility for releasing the STGMEDIUM structure.
+ */
+ if (pFormatetc is null || pmedium is null) return COM.E_INVALIDARG;
+
+ if (QueryGetData(pFormatetc) !is COM.S_OK) return COM.DV_E_FORMATETC;
+
+ TransferData transferData = new TransferData();
+ transferData.formatetc = new FORMATETC();
+ COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof);
+ transferData.type = transferData.formatetc.cfFormat;
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.E_FAIL;
+
+ DNDEvent event = new DNDEvent();
+ event.widget = this;
+ event.time = OS.GetMessageTime();
+ event.dataType = transferData;
+ notifyListeners(DND.DragSetData,event);
+
+ // get matching transfer agent to perform conversion
+ Transfer transfer = null;
+ for (int i = 0; i < transferAgents.length; i++){
+ Transfer transferAgent = transferAgents[i];
+ if (transferAgent !is null && transferAgent.isSupportedType(transferData)){
+ transfer = transferAgent;
+ break;
+ }
+ }
+
+ if (transfer is null) return COM.DV_E_FORMATETC;
+ transfer.javaToNative(event.data, transferData);
+ if (transferData.result !is COM.S_OK) return transferData.result;
+ COM.MoveMemory(pmedium, transferData.stgmedium, STGMEDIUM.sizeof);
+ return transferData.result;
+}
+
+/**
+ * Returns an array of listeners who will be notified when a drag and drop
+ * operation is in progress, by sending it one of the messages defined in
+ * the DragSourceListener
interface.
+ *
+ * @return the listeners who will be notified when a drag and drop
+ * operation is in progress
+ *
+ * @exception SWTException
+ *
+ *
+ * @see DragSourceListener
+ * @see #addDragListener
+ * @see #removeDragListener
+ * @see DragSourceEvent
+ *
+ * @since 3.4
+ */
+public DragSourceListener[] getDragListeners() {
+ Listener[] listeners = getListeners(DND.DragStart);
+ int length = listeners.length;
+ DragSourceListener[] dragListeners = new DragSourceListener[length];
+ int count = 0;
+ for (int i = 0; i < length; i++) {
+ Listener listener = listeners[i];
+ if ( auto l = cast(DNDListener)listener ) {
+ dragListeners[count] = cast(DragSourceListener) (l.getEventListener());
+ count++;
+ }
+ }
+ if (count is length) return dragListeners;
+ DragSourceListener[] result = new DragSourceListener[count];
+ SimpleType!(DragSourceListener).arraycopy(dragListeners, 0, result, 0, count);
+ return result;
+}
+
+/**
+ * Returns the drag effect that is registered for this DragSource. This drag
+ * effect will be used during a drag and drop operation.
+ *
+ * @return the drag effect that is registered for this DragSource
+ *
+ * @since 3.3
+ */
+public DragSourceEffect getDragSourceEffect() {
+ return dragEffect;
+}
+
+/**
+ * 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;
+}
+
+package .LRESULT GiveFeedback(DWORD dwEffect) {
+ return COM.DRAGDROP_S_USEDEFAULTCURSORS;
+}
+
+package .LRESULT QueryContinueDrag(int fEscapePressed, DWORD grfKeyState) {
+ if (topControl !is null && topControl.isDisposed()) return COM.DRAGDROP_S_CANCEL;
+ if (fEscapePressed !is 0){
+ if (hwndDrag !is null) OS.ImageList_DragLeave(hwndDrag);
+ return COM.DRAGDROP_S_CANCEL;
+ }
+ /*
+ * Bug in Windows. On some machines that do not have XBUTTONs,
+ * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
+ * causing mouse capture to become stuck. The fix is to test
+ * for the extra buttons only when they exist.
+ */
+ int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
+// if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+ if ((grfKeyState & mask) is 0) {
+ if (hwndDrag !is null) OS.ImageList_DragLeave(hwndDrag);
+ return COM.DRAGDROP_S_DROP;
+ }
+
+ if (hwndDrag !is null) {
+ POINT pt;
+ OS.GetCursorPos (&pt);
+ RECT rect;
+ OS.GetWindowRect (hwndDrag, &rect);
+ OS.ImageList_DragMove (pt.x - rect.left, pt.y - rect.top);
+ }
+ return COM.S_OK;
+}
+
+private void onDispose() {
+ if (control is null) return;
+ this.Release();
+ if (controlListener !is null){
+ control.removeListener(SWT.Dispose, controlListener);
+ control.removeListener(SWT.DragDetect, controlListener);
+ }
+ controlListener = null;
+ control.setData(DND.DRAG_SOURCE_KEY, null);
+ control = null;
+ transferAgents = null;
+}
+
+private int opToOs(int operation) {
+ int osOperation = 0;
+ if ((operation & DND.DROP_COPY) !is 0){
+ osOperation |= COM.DROPEFFECT_COPY;
+ }
+ if ((operation & DND.DROP_LINK) !is 0) {
+ osOperation |= COM.DROPEFFECT_LINK;
+ }
+ if ((operation & DND.DROP_MOVE) !is 0) {
+ osOperation |= COM.DROPEFFECT_MOVE;
+ }
+ return osOperation;
+}
+
+private int osToOp(int osOperation){
+ int operation = 0;
+ if ((osOperation & COM.DROPEFFECT_COPY) !is 0){
+ operation |= DND.DROP_COPY;
+ }
+ if ((osOperation & COM.DROPEFFECT_LINK) !is 0) {
+ operation |= DND.DROP_LINK;
+ }
+ if ((osOperation & COM.DROPEFFECT_MOVE) !is 0) {
+ operation |= DND.DROP_MOVE;
+ }
+ return operation;
+}
+
+private .LRESULT QueryGetData(FORMATETC* pFormatetc) {
+ if (transferAgents is null) return COM.E_FAIL;
+ TransferData transferData = new TransferData();
+ transferData.formatetc = new FORMATETC();
+ COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof);
+ transferData.type = transferData.formatetc.cfFormat;
+
+ // is this type supported by the transfer agent?
+ for (int i = 0; i < transferAgents.length; i++){
+ Transfer transfer = transferAgents[i];
+ if (transfer !is null && transfer.isSupportedType(transferData))
+ return COM.S_OK;
+ }
+
+ return COM.DV_E_FORMATETC;
+}
+
+/* QueryInterface([in] riid, [out] ppvObject)
+ * Ownership of ppvObject transfers from callee to caller so reference count on ppvObject
+ * must be incremented before returning. Caller is responsible for releasing ppvObject.
+ */
+private HRESULT QueryInterface(REFIID riid, void** ppvObject) {
+ if (riid is null || ppvObject is null)
+ return COM.E_INVALIDARG;
+
+ if (COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIDropSource)) {
+ *ppvObject = cast(void*)cast(IUnknown) iDropSource;
+ AddRef();
+ return COM.S_OK;
+ }
+
+ if (COM.IsEqualGUID(riid, &COM.IIDIDataObject) ) {
+ *ppvObject = cast(void*)cast(IDataObject) iDataObject;
+ AddRef();
+ return COM.S_OK;
+ }
+
+ *ppvObject = null;
+ return COM.E_NOINTERFACE;
+}
+
+private ULONG Release() {
+ refCount--;
+ if (refCount is 0) {
+ disposeCOMInterfaces();
+ COM.CoFreeUnusedLibraries();
+ }
+ return refCount;
+}
+
+/**
+ * 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 no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
+ * @exception SWTException
+ *
+ *
+ * @see DragSourceListener
+ * @see #addDragListener
+ * @see #getDragListeners
+ */
+public void removeDragListener(DragSourceListener listener) {
+ if (listener is null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+ removeListener(DND.DragStart, listener);
+ removeListener(DND.DragSetData, listener);
+ removeListener(DND.DragEnd, listener);
+}
+
+.LRESULT SetData(FORMATETC* pFormatetc, STGMEDIUM* pmedium, int fRelease) {
+ if (pFormatetc is null || pmedium is null) return COM.E_INVALIDARG;
+ FORMATETC* formatetc = new FORMATETC();
+ COM.MoveMemory(formatetc, pFormatetc, FORMATETC.sizeof);
+ if (formatetc.cfFormat is CFSTR_PERFORMEDDROPEFFECT && formatetc.tymed is COM.TYMED_HGLOBAL) {
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ COM.MoveMemory(stgmedium, pmedium,STGMEDIUM.sizeof);
+ //TODO - this should be GlobalLock()
+ int[1] ptrEffect;
+ OS.MoveMemory(ptrEffect.ptr, stgmedium.unionField,4);
+ int[1] effect;
+ OS.MoveMemory(effect.ptr, ptrEffect[0],4);
+ dataEffect = osToOp(effect[0]);
+ }
+ if (fRelease is 1) {
+ COM.ReleaseStgMedium(pmedium);
+ }
+ return COM.S_OK;
+}
+
+/**
+ * Specifies the drag effect for this DragSource. This drag effect will be
+ * used during a drag and drop operation.
+ *
+ * @param effect the drag effect that is registered for this DragSource
+ *
+ * @since 3.3
+ */
+public void setDragSourceEffect(DragSourceEffect effect) {
+ dragEffect = effect;
+}
+
+/**
+ * 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;
+}
+
+}
+
+
+private class _IDropSourceImpl : IDropSource {
+
+ DragSource parent;
+ this(DragSource p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface of IDropSource
+ HRESULT QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) { return parent.QueryContinueDrag(fEscapePressed, grfKeyState); }
+ HRESULT GiveFeedback(DWORD dwEffect) { return parent.GiveFeedback(dwEffect);}
+}
+
+private class _IDataObjectImpl : IDataObject {
+
+ DragSource parent;
+ this(DragSource p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+
+ // interface IDataObject
+ LRESULT GetData( FORMATETC *pFormatetc, STGMEDIUM *pmedium) { return parent.GetData(pFormatetc, pmedium); }
+ LRESULT GetDataHere(FORMATETC * pFormatetc, STGMEDIUM * pmedium) { return COM.E_NOTIMPL; }
+ LRESULT QueryGetData(FORMATETC* pFormatetc) { return parent.QueryGetData(pFormatetc); }
+ LRESULT GetCanonicalFormatEtc(FORMATETC* pFormatetcIn, FORMATETC* pFormatetcOut) { return COM.E_NOTIMPL; }
+ LRESULT SetData(FORMATETC* pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) { return parent.SetData(pFormatetc, pmedium, fRelease); }
+ LRESULT EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC * ppenumFormatetc) { return parent.EnumFormatEtc(dwDirection, ppenumFormatetc); }
+ LRESULT DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink pAdvSink, DWORD* pdwConnection) { return COM.E_NOTIMPL; }
+ LRESULT DUnadvise(DWORD dwConnection) { return COM.E_NOTIMPL; }
+ LRESULT EnumDAdvise(IEnumSTATDATA * ppenumAdvise) { return COM.E_NOTIMPL; }
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceAdapter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceAdapter.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit DragSourceListener
interface.
+ *
+ * DragSourceEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.dragStart
permits the drag operation to start.
+ * For additional information see DragSourceListener.dragStart
.
+ *
+ * @param event the information associated with the drag start event
+ */
+public void dragStart(DragSourceEvent event){}
+
+/**
+ * This implementation of dragFinished
does nothing.
+ * For additional information see DragSourceListener.dragFinished
.
+ *
+ * @param event the information associated with the drag finished event
+ */
+public void dragFinished(DragSourceEvent event){}
+
+/**
+ * This implementation of dragSetData
does nothing.
+ * For additional information see DragSourceListener.dragSetData
.
+ *
+ * @param event the information associated with the drag set data event
+ */
+public void dragSetData(DragSourceEvent event){}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceEffect.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit DragSourceAdapter
so that it can provide custom visual
+ * feedback when a DragSourceEvent
occurs.
+ * DragSourceEffect
+ * class, override the DragSourceAdapter.dragStart
method and set
+ * the field DragSourceEvent.image
with their own image.
+ * The image should be disposed when DragSourceAdapter.dragFinished
is called.
+ * DragSourceEffect
to handle drag effect from the specified Control
.
+ *
+ * @param control the Control
that the user clicks on to initiate the drag
+ *
+ * @exception IllegalArgumentException
+ *
+ */
+ public this(Control control) {
+ if (control is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.control = control;
+ }
+
+ /**
+ * Returns the Control which is registered for this DragSourceEffect. This is the control that the
+ * user clicks in to initiate dragging.
+ *
+ * @return the Control which is registered for this DragSourceEffect
+ */
+ public Control getControl() {
+ return control;
+ }
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit DragSourceListener
class provides event notification to the application for DragSource events.
+ *
+ * DropTarget
, the application which defines the DragSource
+ * must provide the dropped data by implementing dragSetData
. In the dragSetData, the application
+ * must support all the data types that were specified in the DragSource#setTransfer method.DragSource
is required to take the appropriate cleanup action. In the case of a successful
+ * move operation, the application must remove the data that was transferred.
+ *
+ *
+ *
DropTarget
defines the target object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ * 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);
+ *
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 is 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
+ * }
+ * });
+ *
+ *
+ *
+ * @see Drag and Drop snippets
+ * @see SWT Example: DNDExample
+ * @see Sample code and further information
+ */
+public class DropTarget : Widget {
+
+ Control control;
+ Listener controlListener;
+ Transfer[] transferAgents;
+ DropTargetEffect dropEffect;
+
+ // Track application selections
+ TransferData selectedDataType;
+ int selectedOperation;
+
+ // workaround - There is no event for "operation changed" so track operation based on key state
+ int keyOperation = -1;
+
+ // workaround - The dataobject address is only passed as an argument in drag enter and drop.
+ // To allow applications to query the data values during the drag over operations,
+ // maintain a reference to it.
+ IDataObject iDataObject;
+
+ // interfaces
+ _IDropTargetImpl iDropTarget;
+ int refCount;
+
+ static final String DEFAULT_DROP_TARGET_EFFECT = "DEFAULT_DROP_TARGET_EFFECT"; //$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
+ *
+ * @exception SWTError
+ *
+ *
+ * DropTargetListener
+ * 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
+ *
DropTargetListener
interface.
+ *
+ * @return the listeners who will be notified when a drag and drop
+ * operation is in progress
+ *
+ * @exception SWTException DropTargetListener
interface.
+ *
+ * Classes that wish to deal with DropTargetEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
dragEnter
permits the default
+ * operation defined in event.detail
to be performed on the current data type
+ * defined in event.currentDataType
.
+ * For additional information see DropTargetListener.dragEnter
.
+ *
+ * @param event the information associated with the drag enter event
+ */
+public void dragEnter(DropTargetEvent event){}
+
+/**
+ * This implementation of dragLeave
does nothing.
+ * For additional information see DropTargetListener.dragOperationChanged
.
+ *
+ * @param event the information associated with the drag leave event
+ */
+public void dragLeave(DropTargetEvent event){}
+
+/**
+ * This implementation of dragOperationChanged
permits the default
+ * operation defined in event.detail
to be performed on the current data type
+ * defined in event.currentDataType
.
+ * For additional information see DropTargetListener.dragOperationChanged
.
+ *
+ * @param event the information associated with the drag operation changed event
+ */
+public void dragOperationChanged(DropTargetEvent event){}
+
+/**
+ * This implementation of dragOver
permits the default
+ * operation defined in event.detail
to be performed on the current data type
+ * defined in event.currentDataType
.
+ * For additional information see DropTargetListener.dragOver
.
+ *
+ * @param event the information associated with the drag over event
+ */
+public void dragOver(DropTargetEvent event){}
+
+/**
+ * This implementation of drop
does nothing.
+ * For additional information see DropTargetListener.drop
.
+ *
+ * @param event the information associated with the drop event
+ */
+public void drop(DropTargetEvent event){}
+
+/**
+ * This implementation of dropAccept
permits the default
+ * operation defined in event.detail
to be performed on the current data type
+ * defined in event.currentDataType
.
+ * For additional information see DropTargetListener.dropAccept
.
+ *
+ * @param event the information associated with the drop accept event
+ */
+public void dropAccept(DropTargetEvent event){}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetEffect.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit The drop target effect has the same API as the
+ * DropTargetAdapter
so that it can provide custom visual
+ * feedback when a DropTargetEvent
occurs.
+ *
Classes that wish to provide their own drag under effect
+ * can extend the DropTargetEffect
and override any applicable methods
+ * in DropTargetAdapter
to display their own drag under effect.
The feedback value is either one of the FEEDBACK constants defined in
+ * class DND
which is applicable to instances of this class,
+ * or it must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
effect constants.
+ *
+ *
DropTargetEffect
to handle the drag under effect on the specified
+ * Control
.
+ *
+ * @param control the Control
over which the user positions the cursor to drop the data
+ *
+ * @exception IllegalArgumentException Display
+ */
+ public int x;
+
+ /**
+ * The y-cordinate of the cursor relative to the Display
+ */
+ public int y;
+
+ /**
+ * The operation being performed.
+ * @see DND#DROP_NONE
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_LINK
+ */
+ public int detail;
+
+ /**
+ * A bitwise OR'ing of the operations that the DragSource can support
+ * (e.g. DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK).
+ * The detail value must be a member of this list or DND.DROP_NONE.
+ * @see DND#DROP_NONE
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_LINK
+ */
+ public int operations;
+
+ /**
+ * A bitwise OR'ing of the drag under effect feedback to be displayed to the user
+ * (e.g. DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND).
+ * A value of DND.FEEDBACK_NONE indicates that no drag under effect will be displayed.
+ *Feedback effects will only be applied if they are applicable.
+ *The default value is DND.FEEDBACK_SELECT.
+ * @see DND#FEEDBACK_NONE + * @see DND#FEEDBACK_SELECT + * @see DND#FEEDBACK_INSERT_BEFORE + * @see DND#FEEDBACK_INSERT_AFTER + * @see DND#FEEDBACK_SCROLL + * @see DND#FEEDBACK_EXPAND + */ + public int feedback; + + /** + * If the associated control is a table or tree, this field contains the item located + * at the cursor coordinates. + */ + public Widget item; + + /** + * The type of data that will be dropped. + */ + public TransferData currentDataType; + + /** + * A list of the types of data that the DragSource is capable of providing. + * The currentDataType must be a member of this list. + */ + public TransferData[] dataTypes; + + static const long serialVersionUID = 3256727264573338678L; + +/** + * Constructs a new instance of this class based on the + * information in the given untyped event. + * + * @param e the untyped event containing the information + */ +public this(DNDEvent e) { + super(cast(Event)e); + this.data = e.data; + this.x = e.x; + this.y = e.y; + this.detail = e.detail; + this.currentDataType = e.dataType; + this.dataTypes = e.dataTypes; + this.operations = e.operations; + this.feedback = e.feedback; + this.item = e.item; +} +void updateEvent(DNDEvent e) { + e.widget = this.widget; + e.time = this.time; + e.data = this.data; + e.x = this.x; + e.y = this.y; + e.detail = this.detail; + e.dataType = this.currentDataType; + e.dataTypes = this.dataTypes; + e.operations = this.operations; + e.feedback = this.feedback; + e.item = this.item; +} +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetListener.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,254 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank BenoitDropTargetListener
class provides event notification to the application
+ * for DropTarget events.
+ *
+ * As the user moves the cursor into, over and out of a Control that has been designated + * as a DropTarget, events indicate what operation can be performed and what data can be + * transferred if a drop where to occur at that point. + * The application can respond to these events and change the type of data that will + * be dropped by modifying event.currentDataType, or change the operation that will be performed + * by modifying the event.detail field or stop any drop from happening on the current target + * by setting the event.detail field to DND_DROP_NONE.
+ * + *When the user causes a drop to happen by releasing the mouse over a valid drop target, + * the application has one last chance to change the data type of the drop through the + * DropAccept event. If the drop is still allowed, the DropAccept event is immediately + * followed by the Drop event. In the Drop event, the application can still change the + * operation that is performed but the data type is fixed.
+ * + * @see DropTargetEvent + * + */ +public interface DropTargetListener : SWTEventListener { + +/** + * The cursor has entered the drop target boundaries. + * + *The following fields in the DropTargetEvent apply: + *
The operation
value is determined by the modifier keys pressed by the user.
+ * If no keys are pressed the event.detail
field is set to DND.DROP_DEFAULT.
+ * If the application does not set the event.detail
to something other
+ * than DND.DROP_DEFAULT
the operation will be set to the platform defined standard
+ * default.
The currentDataType
is determined by the first transfer agent specified in
+ * setTransfer() that matches a data type provided by the drag source.
It is possible to get a DragEnter event when the drag source does not provide any matching data. + * In this case, the default operation is DND.DROP_NONE and the currentDataType is null.
+ * + *The application can change the operation that will be performed by modifying the
+ * detail
field but the choice must be one of the values in the operations
+ * field or DND.DROP_NONE.
The application can also change the type of data being requested by
+ * modifying the currentDataTypes
field but the value must be one of the values
+ * in the dataTypes
list.
The following fields in the DropTargetEvent apply: + *
The following fields in the DropTargetEvent apply: + *
The operation
value is determined by the modifier keys pressed by the user.
+ * If no keys are pressed the event.detail
field is set to DND.DROP_DEFAULT.
+ * If the application does not set the event.detail
to something other than
+ * DND.DROP_DEFAULT
the operation will be set to the platform defined standard default.
The currentDataType
value is determined by the value assigned to
+ * currentDataType
in previous dragEnter and dragOver calls.
The application can change the operation that will be performed by modifying the
+ * detail
field but the choice must be one of the values in the operations
+ * field.
The application can also change the type of data being requested by modifying
+ * the currentDataTypes
field but the value must be one of the values in the
+ * dataTypes
list.
The following fields in the DropTargetEvent apply: + *
The operation
value is determined by the value assigned to
+ * currentDataType
in previous dragEnter and dragOver calls.
The currentDataType
value is determined by the value assigned to
+ * currentDataType
in previous dragEnter and dragOver calls.
The application can change the operation that will be performed by modifying the
+ * detail
field but the choice must be one of the values in the operations
+ * field.
The application can also change the type of data being requested by modifying the
+ * currentDataTypes
field but the value must be one of the values in the
+ * dataTypes
list.
NOTE: At this point the data
field is null. On some platforms, it is possible
+ * to obtain the data being transferred before the transfer occurs but in most platforms this is
+ * not possible. On those platforms where the data is available, the application can access the
+ * data as follows:
+ * public void dragOver(DropTargetEvent event) {
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String data = (String)textTransfer.nativeToJava(event.currentDataType);
+ * if (data !is null) {
+ * System.out.println("Data to be dropped is (Text)"+data);
+ * }
+ * };
+ *
+ *
+ * @param event the information associated with the drag over event
+ *
+ * @see DropTargetEvent
+ */
+public void dragOver(DropTargetEvent event);
+
+/**
+ * The data is being dropped. The data field contains java format of the data being dropped.
+ * To determine the type of the data object, refer to the documentation for the Transfer subclass
+ * specified in event.currentDataType.
+ *
+ * The following fields in DropTargetEvent apply: + *
The application can refuse to perform the drop operation by setting the detail + * field to DND.DROP_NONE.
+ * + * @param event the information associated with the drop event + * + * @see DropTargetEvent + */ +public void drop(DropTargetEvent event); + +/** + * The drop is about to be performed. + * The drop target is given a last chance to change the nature of the drop. + * + *The following fields in the DropTargetEvent apply: + *
The application can veto the drop by setting the event.detail
field to
+ * DND.DROP_NONE
.
The application can change the operation that will be performed by modifying the
+ * detail
field but the choice must be one of the values in the
+ * operations
field.
The application can also change the type of data being requested by modifying the
+ * currentDataTypes
field but the value must be one of the values in the <
+ * code>dataTypes list.
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.
+ *
+ * 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();
+ *
+ *
+ * @see Transfer
+ */
+public class FileTransfer : ByteArrayTransfer {
+
+ private static FileTransfer _instance;
+ private static final String CF_HDROP = "CF_HDROP "; //$NON-NLS-1$
+ private static final int CF_HDROPID = COM.CF_HDROP;
+ private static final String CF_HDROP_SEPARATOR = "\0"; //$NON-NLS-1$
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the FileTransfer class.
+ *
+ * @return the singleton instance of the FileTransfer class
+ */
+public static FileTransfer getInstance () {
+ if( _instance is null ){
+ synchronized {
+ if( _instance is null ){
+ _instance = new FileTransfer();
+ }
+ }
+ }
+ 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.
+ *
+ * @param object a java String[]
containing the file names to be converted
+ * @param transferData an empty TransferData
object that will
+ * be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative(Object object, TransferData transferData) {
+ if (!checkFile(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String[] fileNames;
+ if( auto strs = cast(ArrayWrapperString2) object ){
+ fileNames = strs.array;
+ }
+ StringBuffer allFiles = new StringBuffer();
+ for (int i = 0; i < fileNames.length; i++) {
+ allFiles.append(fileNames[i]);
+ allFiles.append(CF_HDROP_SEPARATOR); // each name is null terminated
+ }
+ TCHAR[] buffer = StrToTCHARs(0, allFiles.toString(), true); // there is an extra null terminator at the very end
+ DROPFILES dropfiles;
+ dropfiles.pFiles = DROPFILES.sizeof;
+ dropfiles.pt.x = dropfiles.pt.y = 0;
+ dropfiles.fNC = 0;
+ dropfiles.fWide = OS.IsUnicode ? 1 : 0;
+ // Allocate the memory because the caller (DropTarget) has not handed it in
+ // The caller of this method must release the data when it is done with it.
+ int byteCount = buffer.length * TCHAR.sizeof;
+ auto newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, DROPFILES.sizeof + byteCount);
+ OS.MoveMemory(newPtr, &dropfiles, DROPFILES.sizeof);
+ OS.MoveMemory(newPtr + DROPFILES.sizeof, buffer.ptr, byteCount);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = newPtr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+}
+
+/**
+ * This implementation of nativeToJava
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.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java String[]
containing a list of file names if the conversion
+ * was successful; otherwise null
+ *
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+
+ // get file names from IDataObject
+ IDataObject dataObject = transferData.pIDataObject;
+ dataObject.AddRef();
+ FORMATETC* formatetc = new FORMATETC();
+ formatetc.cfFormat = COM.CF_HDROP;
+ formatetc.ptd = null;
+ formatetc.dwAspect = COM.DVASPECT_CONTENT;
+ formatetc.lindex = -1;
+ formatetc.tymed = COM.TYMED_HGLOBAL;
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = getData(dataObject, formatetc, stgmedium);
+ dataObject.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ // How many files are there?
+ int count = OS.DragQueryFile(stgmedium.unionField, 0xFFFFFFFF, null, 0);
+ String[] fileNames = new String[](count);
+ for (int i = 0; i < count; i++) {
+ // How long is the name ?
+ int size = OS.DragQueryFile(stgmedium.unionField, i, null, 0) + 1;
+ TCHAR[] lpszFile = NewTCHARs(0, size);
+ // Get file name and append it to string
+ OS.DragQueryFile(stgmedium.unionField, i, lpszFile.ptr, size);
+ fileNames[i] = TCHARzToStr(lpszFile.ptr);
+ }
+ OS.DragFinish(stgmedium.unionField); // frees data associated with HDROP data
+ return new ArrayWrapperString2(fileNames);
+}
+
+protected int[] getTypeIds(){
+ return [CF_HDROPID];
+}
+
+protected String[] getTypeNames(){
+ return [CF_HDROP];
+}
+bool checkFile(Object object) {
+ String[] strings;
+ if( auto strs = cast(ArrayWrapperString2)object ){
+ strings = strs.array;
+ }
+ if (!strings) return false;
+ for (int i = 0; i < strings.length; i++) {
+ if (strings[i] is null || strings[i].length is 0) return false;
+ }
+ return true;
+}
+
+protected bool validate(Object object) {
+ return checkFile(object);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/HTMLTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/HTMLTransfer.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit HTMLTransfer
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.
+ *
+ * An example of a java String
containing HTML text is shown
+ * below:
+ * String htmlData = "This is a paragraph of text.
";
+ *
+ *
+ * @see Transfer
+ */
+public class HTMLTransfer : ByteArrayTransfer {
+
+ static HTMLTransfer _instance;
+ static const String HTML_FORMAT = "HTML Format"; //$NON-NLS-1$
+ static const int HTML_FORMATID;
+ static const String NUMBER = "00000000"; //$NON-NLS-1$
+ static const String HEADER = "Version:0.9\r\nStartHTML:"~NUMBER~"\r\nEndHTML:"~NUMBER~"\r\nStartFragment:"~NUMBER~"\r\nEndFragment:"~NUMBER~"\r\n";
+ static const String PREFIX = ""; //$NON-NLS-1$
+ static const String SUFFIX = ""; //$NON-NLS-1$
+ static const String StartFragment = "StartFragment:"; //$NON-NLS-1$
+ static const String EndFragment = "EndFragment:"; //$NON-NLS-1$
+
+static this(){
+ HTML_FORMATID = registerType(HTML_FORMAT);
+}
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the HTMLTransfer class.
+ *
+ * @return the singleton instance of the HTMLTransfer class
+ */
+public static HTMLTransfer getInstance () {
+ if( _instance is null ){
+ synchronized {
+ if( _instance is null ){
+ _instance = new HTMLTransfer();
+ }
+ }
+ }
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts HTML-formatted text
+ * represented by a java String
to a platform specific representation.
+ *
+ * @param object a java String
containing HTML text
+ * @param transferData an empty TransferData
object that will
+ * be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkHTML(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String string = ( cast(ArrayWrapperString)object ).array;
+ /* NOTE: CF_HTML uses UTF-8 encoding. */
+ int cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, StrToTCHARz(string), -1, null, 0, null, null);
+ if (cchMultiByte is 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ int startHTML = HEADER.length;
+ int startFragment = startHTML + PREFIX.length;
+ int endFragment = startFragment + cchMultiByte - 1;
+ int endHTML = endFragment + SUFFIX.length;
+
+ StringBuffer buffer = new StringBuffer(HEADER);
+ int maxLength = NUMBER.length;
+ //startHTML
+ int start = buffer.toString().indexOf(NUMBER);
+ String temp = Integer.toString(startHTML);
+ buffer.select(start + maxLength-temp.length, temp.length);
+ buffer.replace(temp);
+ buffer.select();
+
+ //endHTML
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(endHTML);
+ buffer.select(start + maxLength-temp.length, temp.length);
+ buffer.replace( temp);
+ buffer.select();
+
+ //startFragment
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(startFragment);
+ buffer.select(start + maxLength-temp.length, temp.length);
+ buffer.replace(temp);
+ buffer.select();
+ //endFragment
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(endFragment);
+ buffer.select(start + maxLength-temp.length, temp.length);
+ buffer.replace(temp);
+ buffer.select();
+
+ buffer.append(PREFIX);
+ buffer.append(string);
+ buffer.append(SUFFIX);
+
+ auto wstrz = StrToTCHARz(OS.CP_UTF8,buffer.toString);
+ cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, null, 0, null, null);
+ auto lpMultiByteStr = cast(PCHAR) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
+ OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, lpMultiByteStr, cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+ return;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of HTML text to a java String
.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java String
containing HTML text if the conversion was successful;
+ * otherwise null
+ *
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+ IDataObject data = transferData.pIDataObject;
+ data.AddRef();
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ FORMATETC* formatetc = transferData.formatetc;
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = getData(data, formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ auto hMem = stgmedium.unionField;
+
+ try {
+ auto lpMultiByteStr = cast(PCHAR) OS.GlobalLock(hMem);
+ if (lpMultiByteStr is null) return null;
+ try {
+ /* NOTE: CF_HTML uses UTF-8 encoding.
+ * The MSDN documentation for MultiByteToWideChar states that dwFlags must be set to 0 for UTF-8.
+ * Otherwise, the function fails with ERROR_INVALID_FLAGS. */
+ auto cchWideChar = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, null, 0);
+ if (cchWideChar is 0) return null;
+ wchar[] lpWideCharStr = new wchar [cchWideChar - 1];
+ OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length);
+ String string = WCHARzToStr(lpWideCharStr.ptr);
+ int fragmentStart = 0, fragmentEnd = 0;
+ int start = string.indexOf(StartFragment) + StartFragment.length;
+ int end = start + 1;
+ while (end < string.length) {
+ String s = string.substring(start, end);
+ try {
+ fragmentStart = Integer.parseInt(s);
+ end++;
+ } catch (NumberFormatException e) {
+ break;
+ }
+ }
+ start = string.indexOf(EndFragment) + EndFragment.length;
+ end = start + 1;
+ while (end < string.length) {
+ String s = string.substring(start, end);
+ try {
+ fragmentEnd = Integer.parseInt(s);
+ end++;
+ } catch (NumberFormatException e) {
+ break;
+ }
+ }
+ if (fragmentEnd <= fragmentStart || fragmentEnd > OS.strlen(lpMultiByteStr)) return null;
+ cchWideChar = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr+fragmentStart, fragmentEnd - fragmentStart, lpWideCharStr.ptr, lpWideCharStr.length);
+ if (cchWideChar is 0) return null;
+ String s = TCHARsToStr( lpWideCharStr[ 0 .. cchWideChar ] );
+ /*
+ * Firefox includes in the fragment, so remove it.
+ */
+ String foxStart = "\r\n"; //$NON-NLS-1$
+ int prefix = s.indexOf(foxStart);
+ if (prefix !is -1) {
+ prefix += foxStart.length;
+ s = s.substring(prefix);
+ }
+ return new ArrayWrapperString(s);
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+}
+protected int[] getTypeIds(){
+ return [HTML_FORMATID];
+}
+protected String[] getTypeNames(){
+ return [HTML_FORMAT];
+}
+bool checkHTML(Object object) {
+ if( auto ws = cast(ArrayWrapperString)object ){
+ return ws.array.length > 0;
+ }
+ return false;
+}
+protected bool validate(Object object) {
+ return checkHTML(object);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/ImageTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/ImageTransfer.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ *******************************************************************************/
+module org.eclipse.swt.dnd.ImageTransfer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+
+/**
+ * The class ImageTransfer
provides a platform specific mechanism
+ * for converting an Image represented as a java ImageData
to a
+ * platform specific representation of the data and vice versa.
+ *
+ * An example of a java ImageData
is shown below:
+ * Image image = new Image(display, "C:\temp\img1.gif");
+ * ImageData imgData = image.getImageData();
+ *
+ *
+ * @see Transfer
+ *
+ * @since 3.4
+ */
+public class ImageTransfer : ByteArrayTransfer {
+
+ private static ImageTransfer _instance;
+ private static const String CF_DIB = "CF_DIB"; //$NON-NLS-1$
+ private static const int CF_DIBID = COM.CF_DIB;
+
+static this(){
+ _instance = new ImageTransfer();
+}
+
+private this() {
+}
+
+/**
+ * Returns the singleton instance of the ImageTransfer class.
+ *
+ * @return the singleton instance of the ImageTransfer class
+ */
+public static ImageTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts an ImageData object represented
+ * by java ImageData
to a platform specific representation.
+ *
+ * @param object a java ImageData
containing the ImageData to be converted
+ * @param transferData an empty TransferData
object that will
+ * be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative(Object object, TransferData transferData) {
+ if (!checkImage(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ ImageData imgData = cast(ImageData)object;
+ if (imgData is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ int imageSize = imgData.data.length;
+ int imageHeight = imgData.height;
+ int bytesPerLine = imgData.bytesPerLine;
+
+ BITMAPINFOHEADER bmiHeader;
+ bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+ bmiHeader.biSizeImage = imageSize;
+ bmiHeader.biWidth = imgData.width;
+ bmiHeader.biHeight = imageHeight;
+ bmiHeader.biPlanes = 1;
+ bmiHeader.biBitCount = cast(short)imgData.depth;
+ bmiHeader.biCompression = OS.DIB_RGB_COLORS;
+
+ int colorSize = 0;
+ if (bmiHeader.biBitCount <= 8) {
+ colorSize += (1 << bmiHeader.biBitCount) * 4;
+ }
+ byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + colorSize];
+ OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+
+ RGB[] rgbs = imgData.palette.getRGBs();
+ if (rgbs !is null && colorSize > 0) {
+ int offset = BITMAPINFOHEADER.sizeof;
+ for (int j = 0; j < rgbs.length; j++) {
+ bmi[offset] = cast(byte)rgbs[j].blue;
+ bmi[offset + 1] = cast(byte)rgbs[j].green;
+ bmi[offset + 2] = cast(byte)rgbs[j].red;
+ bmi[offset + 3] = 0;
+ offset += 4;
+ }
+ }
+ auto newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, BITMAPINFOHEADER.sizeof + colorSize + imageSize);
+ OS.MoveMemory(newPtr, bmi.ptr, bmi.length);
+ auto pBitDest = newPtr + BITMAPINFOHEADER.sizeof + colorSize;
+
+ if (imageHeight <= 0) {
+ OS.MoveMemory(pBitDest, imgData.data.ptr, imageSize);
+ } else {
+ int offset = 0;
+ pBitDest += bytesPerLine * (imageHeight - 1);
+ byte[] scanline = new byte[bytesPerLine];
+ for (int i = 0; i < imageHeight; i++) {
+ System.arraycopy(imgData.data, offset, scanline, 0, bytesPerLine);
+ OS.MoveMemory(pBitDest, scanline.ptr, bytesPerLine);
+ offset += bytesPerLine;
+ pBitDest -= bytesPerLine;
+ }
+ }
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = newPtr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+}
+
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of an image to java ImageData
.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java ImageData
of the image if the conversion was successful;
+ * otherwise null
+ *
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+ IDataObject dataObject = cast(IDataObject)(transferData.pIDataObject);
+ dataObject.AddRef();
+ FORMATETC* formatetc = new FORMATETC();
+ formatetc.cfFormat = COM.CF_DIB;
+ formatetc.ptd = null;
+ formatetc.dwAspect = COM.DVASPECT_CONTENT;
+ formatetc.lindex = -1;
+ formatetc.tymed = COM.TYMED_HGLOBAL;
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = getData(dataObject, formatetc, stgmedium);
+
+ if (transferData.result !is COM.S_OK) return null;
+ HANDLE hMem = stgmedium.unionField;
+ dataObject.Release();
+ try {
+ auto ptr = OS.GlobalLock(hMem);
+ if (ptr is null) return null;
+ try {
+ BITMAPINFOHEADER bmiHeader;
+ OS.MoveMemory(&bmiHeader, ptr, BITMAPINFOHEADER.sizeof);
+ void* pBits;
+ auto memDib = OS.CreateDIBSection(null, cast(BITMAPINFO*)ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+ if (memDib is null) SWT.error(SWT.ERROR_NO_HANDLES);
+ void* bits = ptr + bmiHeader.biSize;
+ if (bmiHeader.biBitCount <= 8) {
+ bits += (1 << bmiHeader.biBitCount) * 4;
+ } else if (bmiHeader.biCompression is OS.BI_BITFIELDS) {
+ bits += 12;
+ }
+ if (bmiHeader.biHeight < 0) {
+ OS.MoveMemory(pBits, bits, bmiHeader.biSizeImage);
+ } else {
+ DIBSECTION dib;
+ OS.GetObject(memDib, DIBSECTION.sizeof, &dib);
+ int biHeight = dib.dsBmih.biHeight;
+ int scanline = dib.dsBmih.biSizeImage / biHeight;
+ auto pDestBits = pBits;
+ auto pSourceBits = bits + scanline * (biHeight - 1);
+ for (int i = 0; i < biHeight; i++) {
+ OS.MoveMemory(pDestBits, pSourceBits, scanline);
+ pDestBits += scanline;
+ pSourceBits -= scanline;
+ }
+ }
+ Image image = Image.win32_new(null, SWT.BITMAP, memDib);
+ ImageData data = image.getImageData();
+ OS.DeleteObject(memDib);
+ image.dispose();
+ return data;
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+}
+
+protected int[] getTypeIds(){
+ return [CF_DIBID];
+}
+
+protected String[] getTypeNames(){
+ return [CF_DIB];
+}
+bool checkImage(Object object) {
+ if (object is null || !(null !is cast(ImageData)object )) return false;
+ return true;
+}
+
+protected bool validate(Object object) {
+ return checkImage(object);
+}
+}
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/OleEnumFORMATETC.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/OleEnumFORMATETC.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit 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.
+ *
+ * An example of a java String
containing RTF text is shown
+ * below:
+ * String rtfData = "{\\rtf1{\\colortbl;\\red255\\green0\\blue0;}\\uc1\\b\\i Hello World}";
+ *
+ *
+ * @see Transfer
+ */
+public class RTFTransfer : ByteArrayTransfer {
+
+ private static RTFTransfer _instance;
+ private static const String CF_RTF = "Rich Text Format"; //$NON-NLS-1$
+ private static const int CF_RTFID;
+
+static this(){
+ CF_RTFID = registerType(CF_RTF);
+}
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the RTFTransfer class.
+ *
+ * @return the singleton instance of the RTFTransfer class
+ */
+public static RTFTransfer getInstance () {
+ if( _instance is null ){
+ synchronized {
+ if( _instance is null ){
+ _instance = new RTFTransfer();
+ }
+ }
+ }
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts RTF-formatted text
+ * represented by a java String
to a platform specific representation.
+ *
+ * @param object a java String
containing RTF text
+ * @param transferData an empty TransferData
object that will
+ * be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkRTF(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ // CF_RTF is stored as a null terminated byte array
+ String string = (cast(ArrayWrapperString)object).array;
+ wchar* chars = StrToWCHARz(string);
+ int codePage = OS.GetACP();
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+ if (cchMultiByte is 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ auto lpMultiByteStr = cast(PCHAR)OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars, -1, lpMultiByteStr, cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+ return;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of RTF text to a java String
.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java String
containing RTF text if the conversion was successful;
+ * otherwise null
+ *
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+ IDataObject data = transferData.pIDataObject;
+ data.AddRef();
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ FORMATETC* formatetc = transferData.formatetc;
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = getData(data, formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ auto hMem = stgmedium.unionField;
+ try {
+ auto lpMultiByteStr = cast(CHAR*) OS.GlobalLock(hMem);
+ if (lpMultiByteStr is null) return null;
+ try {
+ int codePage = OS.GetACP();
+ int cchWideChar = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+ if (cchWideChar is 0) return null;
+ wchar[] lpWideCharStr = new wchar [cchWideChar - 1];
+ OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length);
+ return new ArrayWrapperString( WCHARzToStr(lpWideCharStr.ptr));
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+}
+
+protected int[] getTypeIds(){
+ return [CF_RTFID];
+}
+
+protected String[] getTypeNames(){
+ return [CF_RTF];
+}
+
+bool checkRTF(Object object) {
+ if( auto s = cast(ArrayWrapperString)object ){
+ return s.array.length > 0 ;
+ }
+ return false;
+}
+
+protected bool validate(Object object) {
+ return checkRTF(object);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TableDragSourceEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TableDragSourceEffect.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Table
.
+ *
+ * Classes that wish to provide their own source image for a Table
can
+ * extend the TableDragSourceEffect
class, override the
+ * TableDragSourceEffect.dragStart
method and set the field
+ * DragSourceEvent.image
with their own image.
super
method to get the default drag source effect implementation.
+ *
+ * @see DragSourceEffect
+ * @see DragSourceEvent
+ * @see Sample code and further information
+ *
+ * @since 3.3
+ */
+public class TableDragSourceEffect : DragSourceEffect {
+ Image dragSourceImage = null;
+
+ /**
+ * Creates a new TableDragSourceEffect
to handle drag effect
+ * from the specified Table
.
+ *
+ * @param table the Table
that the user clicks on to initiate the drag
+ */
+ public this(Table table) {
+ super(table);
+ }
+
+ /**
+ * This implementation of dragFinished
disposes the image
+ * that was created in TableDragSourceEffect.dragStart
.
+ *
+ * Subclasses that override this method should call super.dragFinished(event)
+ * to dispose the image in the default implementation.
+ *
+ * @param event the information associated with the drag finished event
+ */
+ public void dragFinished(DragSourceEvent event) {
+ if (dragSourceImage !is null) dragSourceImage.dispose();
+ dragSourceImage = null;
+ }
+
+ /**
+ * This implementation of dragStart
will create a default
+ * image that will be used during the drag. The image should be disposed
+ * when the drag is completed in the TableDragSourceEffect.dragFinished
+ * method.
+ *
+ * Subclasses that override this method should call super.dragStart(event)
+ * to use the image from the default implementation.
+ *
+ * @param event the information associated with the drag start event
+ */
+ public void dragStart(DragSourceEvent event) {
+ event.image = getDragSourceImage(event);
+ }
+
+ Image getDragSourceImage(DragSourceEvent event) {
+ if (dragSourceImage !is null) dragSourceImage.dispose();
+ dragSourceImage = null;
+ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+ SHDRAGIMAGE shdi;
+ int DI_GETDRAGIMAGE = OS.RegisterWindowMessage ( "ShellGetDragImage"w.ptr ); //$NON-NLS-1$
+ if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, &shdi) !is 0) {
+ if ((control.getStyle() & SWT.MIRRORED) !is 0) {
+ event.x += shdi.sizeDragImage.cx - shdi.ptOffset.x;
+ } else {
+ event.x += shdi.ptOffset.x;
+ }
+ event.y += shdi.ptOffset.y;
+ auto hImage = shdi.hbmpDragImage;
+ if (hImage !is null) {
+ BITMAP bm;
+ OS.GetObject (hImage, BITMAP.sizeof, &bm);
+ int srcWidth = bm.bmWidth;
+ int srcHeight = bm.bmHeight;
+
+ /* Create resources */
+ auto hdc = OS.GetDC (null);
+ auto srcHdc = OS.CreateCompatibleDC (hdc);
+ auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage);
+ auto memHdc = OS.CreateCompatibleDC (hdc);
+ BITMAPINFOHEADER bmiHeader;
+ bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+ bmiHeader.biWidth = srcWidth;
+ bmiHeader.biHeight = -srcHeight;
+ bmiHeader.biPlanes = 1;
+ bmiHeader.biBitCount = 32;
+ bmiHeader.biCompression = OS.BI_RGB;
+ void* pBits;
+ auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)&bmiHeader, OS.DIB_RGB_COLORS, &pBits, null, 0);
+ if (memDib is null) SWT.error (SWT.ERROR_NO_HANDLES);
+ auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
+
+ BITMAP dibBM;
+ OS.GetObject (memDib, BITMAP.sizeof, &dibBM);
+ int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
+
+ /* Get the foreground pixels */
+ OS.BitBlt (memHdc, 0, 0, srcWidth, srcHeight, srcHdc, 0, 0, OS.SRCCOPY);
+ //byte[] srcData = new byte [sizeInBytes];
+ //OS.MoveMemory (srcData, dibBM.bmBits, sizeInBytes);
+ byte[] srcData = (cast(byte*) dibBM.bmBits)[ 0 .. BITMAPINFOHEADER.sizeof ];
+
+ PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+ ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData);
+ if (shdi.crColorKey is -1) {
+ byte[] alphaData = new byte[srcWidth * srcHeight];
+ int spinc = dibBM.bmWidthBytes - srcWidth * 4;
+ int ap = 0, sp = 3;
+ for (int y = 0; y < srcHeight; ++y) {
+ for (int x = 0; x < srcWidth; ++x) {
+ alphaData [ap++] = srcData [sp];
+ sp += 4;
+ }
+ sp += spinc;
+ }
+ data.alphaData = alphaData;
+ } else {
+ data.transparentPixel = shdi.crColorKey << 8;
+ }
+ dragSourceImage = new Image(control.getDisplay(), data);
+ OS.SelectObject (memHdc, oldMemBitmap);
+ OS.DeleteDC (memHdc);
+ OS.DeleteObject (memDib);
+ OS.SelectObject (srcHdc, oldSrcBitmap);
+ OS.DeleteDC (srcHdc);
+ OS.ReleaseDC (null, hdc);
+ OS.DeleteObject (hImage);
+ return dragSourceImage;
+ }
+ }
+ return null;
+ }
+ Table table = cast(Table) control;
+ //TEMPORARY CODE
+ if (table.isListening (SWT.EraseItem) || table.isListening (SWT.PaintItem)) return null;
+ TableItem[] selection = table.getSelection();
+ if (selection.length is 0) return null;
+ int /*long*/ tableImageList = OS.SendMessage (table.handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+ if (tableImageList !is 0) {
+ int count = Math.min(selection.length, 10);
+ Rectangle bounds = selection[0].getBounds(0);
+ for (int i = 1; i < count; i++) {
+ bounds = bounds.makeUnion(selection[i].getBounds(0));
+ }
+ auto hDC = OS.GetDC(null);
+ auto hDC1 = OS.CreateCompatibleDC(hDC);
+ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+ if ((table.getStyle() & SWT.RIGHT_TO_LEFT) !is 0) {
+ OS.SetLayout(hDC1, OS.LAYOUT_RTL | OS.LAYOUT_BITMAPORIENTATIONPRESERVED);
+ }
+ }
+ auto bitmap = OS.CreateCompatibleBitmap(hDC, bounds.width, bounds.height);
+ auto hOldBitmap = OS.SelectObject(hDC1, bitmap);
+ RECT rect;
+ rect.right = bounds.width;
+ rect.bottom = bounds.height;
+ auto hBrush = OS.GetStockObject(OS.WHITE_BRUSH);
+ OS.FillRect(hDC1, &rect, hBrush);
+ for (int i = 0; i < count; i++) {
+ TableItem selected = selection[i];
+ Rectangle cell = selected.getBounds(0);
+ POINT pt;
+ HANDLE imageList = cast(HANDLE) OS.SendMessage (table.handle, OS.LVM_CREATEDRAGIMAGE, table.indexOf(selected), &pt);
+ OS.ImageList_Draw(imageList, 0, hDC1, cell.x - bounds.x, cell.y - bounds.y, OS.ILD_SELECTED);
+ OS.ImageList_Destroy(imageList);
+ }
+ OS.SelectObject(hDC1, hOldBitmap);
+ OS.DeleteDC (hDC1);
+ OS.ReleaseDC (null, hDC);
+ Display display = table.getDisplay();
+ dragSourceImage = Image.win32_new(display, SWT.BITMAP, bitmap);
+ return dragSourceImage;
+ }
+ return null;
+ }
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TableDropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TableDropTargetEffect.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Table
.
+ *
+ * Classes that wish to provide their own drag under effect for a Table
+ * can extend the TableDropTargetEffect
and override any applicable methods
+ * in TableDropTargetEffect
to display their own drag under effect.
super
method to get the default drag under effect implementation.
+ *
+ * The feedback value is either one of the FEEDBACK constants defined in
+ * class DND
which is applicable to instances of this class,
+ * or it must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
effect constants.
+ *
+ *
TableDropTargetEffect
to handle the drag under effect on the specified
+ * Table
.
+ *
+ * @param table the Table
over which the user positions the cursor to drop the data
+ */
+ public this(Table table) {
+ super(table);
+ }
+
+ int checkEffect(int effect) {
+ // Some effects are mutually exclusive. Make sure that only one of the mutually exclusive effects has been specified.
+ if ((effect & DND.FEEDBACK_SELECT) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE;
+ if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER;
+ return effect;
+ }
+
+ /**
+ * 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 enter event
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ */
+ public void dragEnter(DropTargetEvent event) {
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ dropHighlight = null;
+ }
+
+ /**
+ * 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
+ */
+ public void dragLeave(DropTargetEvent event) {
+ Table table = cast(Table) control;
+ auto handle = table.handle;
+ if (dropHighlight !is null) {
+ LVITEM lvItem;
+ lvItem.stateMask = OS.LVIS_DROPHILITED;
+ OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, &lvItem);
+ dropHighlight = null;
+ }
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+
+ /**
+ * This implementation of dragOver
provides a default drag under effect
+ * for the feedback specified in event.feedback
. The class description
+ * lists the FEEDBACK constants that are applicable to the class.
+ *
+ * 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
+ */
+ public void dragOver(DropTargetEvent event) {
+ Table table = cast(Table) getControl();
+ int effect = checkEffect(event.feedback);
+ auto handle = table.handle;
+ Point coordinates = new Point(event.x, event.y);
+ coordinates = table.toControl(coordinates);
+ LVHITTESTINFO pinfo;
+ pinfo.pt.x = coordinates.x;
+ pinfo.pt.y = coordinates.y;
+ OS.SendMessage(handle, OS.LVM_HITTEST, 0, &pinfo);
+ if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ } else {
+ if (pinfo.iItem !is -1 && scrollIndex is pinfo.iItem && scrollBeginTime !is 0) {
+ if (System.currentTimeMillis() >= scrollBeginTime) {
+ int top = Math.max (0, OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0));
+ int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+ int index = (scrollIndex - 1 < top) ? Math.max(0, scrollIndex - 1) : Math.min(count - 1, scrollIndex + 1);
+ bool scroll = true;
+ if (pinfo.iItem is top) {
+ scroll = pinfo.iItem !is index;
+ } else {
+ RECT itemRect;
+ itemRect.left = OS.LVIR_BOUNDS;
+ if (OS.SendMessage (handle, OS.LVM_GETITEMRECT, pinfo.iItem, &itemRect) !is 0) {
+ RECT rect;
+ OS.GetClientRect (handle, &rect);
+ POINT pt;
+ 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) {
+ OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 0);
+ table.redraw();
+ }
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+ } else {
+ scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+ scrollIndex = pinfo.iItem;
+ }
+ }
+
+ if (pinfo.iItem !is -1 && (effect & DND.FEEDBACK_SELECT) !is 0) {
+ TableItem item = table.getItem(pinfo.iItem);
+ if (dropHighlight !is item) {
+ LVITEM lvItem;
+ lvItem.stateMask = OS.LVIS_DROPHILITED;
+ OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, &lvItem);
+ lvItem.state = OS.LVIS_DROPHILITED;
+ OS.SendMessage(handle, OS.LVM_SETITEMSTATE, pinfo.iItem, &lvItem);
+ dropHighlight = item;
+ }
+ } else {
+ if (dropHighlight !is null) {
+ LVITEM lvItem;
+ lvItem.stateMask = OS.LVIS_DROPHILITED;
+ OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, &lvItem);
+ dropHighlight = null;
+ }
+ }
+ }
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TextTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TextTransfer.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit 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 : ByteArrayTransfer {
+
+ private static TextTransfer _instance;
+ private static const String CF_UNICODETEXT = "CF_UNICODETEXT"; //$NON-NLS-1$
+ private static const String CF_TEXT = "CF_TEXT"; //$NON-NLS-1$
+ private static const int CF_UNICODETEXTID = COM.CF_UNICODETEXT;
+ private static const int CF_TEXTID = COM.CF_TEXT;
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the TextTransfer class.
+ *
+ * @return the singleton instance of the TextTransfer class
+ */
+public static TextTransfer getInstance () {
+ if( _instance is null ){
+ synchronized {
+ if( _instance is null ){
+ _instance = new TextTransfer();
+ }
+ }
+ }
+ 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 that will
+ * be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkText(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.result = COM.E_FAIL;
+ String string = (cast(ArrayWrapperString)object).array;
+ switch (transferData.type) {
+ case COM.CF_UNICODETEXT: {
+ wchar[] chars = StrToWCHARs(0,string, true);
+ int charCount = chars.length;
+ int byteCount = chars.length * 2;
+ auto newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, byteCount);
+ OS.MoveMemory(newPtr, chars.ptr, byteCount);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = newPtr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+ break;
+ }
+ case COM.CF_TEXT: {
+ wchar[] chars = StrToWCHARs(0,string, true);
+ int count = chars.length;
+ int codePage = OS.GetACP();
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, null, 0, null, null);
+ if (cchMultiByte is 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ auto lpMultiByteStr = cast(CHAR*)OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, lpMultiByteStr, cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+ break;
+ }
+ default:
+ }
+ return;
+}
+
+/**
+ * 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#javaToNative
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+
+ IDataObject data = transferData.pIDataObject;
+ data.AddRef();
+ FORMATETC* formatetc = transferData.formatetc;
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = getData(data, formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ auto hMem = stgmedium.unionField;
+ try {
+ switch (transferData.type) {
+ case CF_UNICODETEXTID: {
+ /* Ensure byteCount is a multiple of 2 bytes */
+ int size = OS.GlobalSize(hMem) / 2 * 2;
+ if (size is 0) return null;
+ wchar[] chars = new wchar[size/2];
+ auto ptr = OS.GlobalLock(hMem);
+ if (ptr is null) return null;
+ try {
+ OS.MoveMemory(chars.ptr, ptr, size);
+ int length_ = chars.length;
+ for (int i=0; iTransfer
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 + * @see Drag and Drop snippets + * @see SWT Example: DNDExample + * @see Sample code and further information + */ +public abstract class Transfer { + +private static final int RETRY_LIMIT = 10; +/* + * Feature in Windows. When another application has control + * of the clipboard, the clipboard is locked and it's not + * possible to retrieve data until the other application is + * finished. To allow other applications to get the + * data, use PeekMessage() to enable cross thread + * message sends. + */ +int getData(IDataObject dataObject, FORMATETC* pFormatetc, STGMEDIUM* pmedium) { + if (dataObject.GetData(pFormatetc, pmedium) is COM.S_OK) return COM.S_OK; + try {tango.core.Thread.Thread.sleep(0.050);} catch (Exception t) {} + int result = dataObject.GetData(pFormatetc, pmedium); + int retryCount = 0; + while (result !is COM.S_OK && retryCount++ < RETRY_LIMIT) { + MSG msg; + OS.PeekMessage(&msg, null, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD); + try {tango.core.Thread.Thread.sleep(0.050);} catch (Exception t) {} + result = dataObject.GetData(pFormatetc, pmedium); + } + return result; +} + +/** + * Returns a list of the platform specific data types that can be converted using + * this transfer agent. + * + *Only the data type fields of the TransferData
objects are filled
+ * in.
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 data
+ * type fields of the TransferData
object need to be filled in
+ *
+ * @return true if the transferData data type can be converted using this transfer
+ * agent
+ */
+abstract public bool isSupportedType(TransferData transferData);
+
+/**
+ * Returns the platform specific ids of the data types that can be converted using
+ * this transfer agent.
+ *
+ * @return the platform specific ids of the data types that can be converted using
+ * this transfer agent
+ */
+abstract protected int[] getTypeIds();
+
+/**
+ * Returns the platform specific names of the data types that can be converted
+ * using this transfer agent.
+ *
+ * @return the platform specific names of the data types that can be converted
+ * using this transfer agent.
+ */
+abstract protected String[] getTypeNames();
+
+/**
+ * Converts a java representation of data to a platform specific representation of
+ * the data.
+ *
+ * On a successful conversion, the transferData.result field will be set as follows: + *
If this transfer agent is unable to perform the conversion, the transferData.result + * field will be set to a failure value as follows: + *
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 null
null
then
+ * null
is returned. The type of Object that is returned is
+ * dependent on the Transfer
subclass.
+ */
+abstract public Object nativeToJava(TransferData transferData);
+
+/**
+ * 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) { + // Look name up in the registry + // If name is not in registry, add it and return assigned value. + // If name already exists in registry, return its assigned value + TCHAR* chFormatName = StrToTCHARz(0, formatName); + return OS.RegisterClipboardFormat(chFormatName); +} + +/** + * 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 + */ +public bool validate(Object object) { + return true; +} +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TransferData.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TransferData.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank BenoitTransferData
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.
+ * + * @see Sample code and further information + */ +public class TransferData { + /** + * 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. + *
+ */ + public int type; + + /** + * The formatetc structure is a generalized data transfer format, enhanced to + * encompass a target device, the aspect, or view of the data, and + * a storage medium. + * (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 FORMATETC* formatetc; + + /** + * The stgmedium structure is a generalized global memory handle used for + * data transfer operations. + * (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 STGMEDIUM* stgmedium; + + /** + * The result field contains the result of converting a + * java data type into a platform specific value. + * (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. + *
+ *The value of result is 1 if the conversion was successful. + * The value of result is 0 if the conversion failed.
+ */ + public int result = COM.E_FAIL; + + /** + * The pIDataObject is the address of an IDataObject OLE Interface which + * provides access to the data associated with the transfer. + * (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 IDataObject pIDataObject; + + static bool sameType(TransferData data1, TransferData data2) { + if (data1 is data2) return true; + if (data1 is null || data2 is null) return false; + return (data1.type is data2.type && + data1.formatetc.cfFormat is data2.formatetc.cfFormat && + data1.formatetc.dwAspect is data2.formatetc.dwAspect && + data1.formatetc.tymed is data2.formatetc.tymed); + } + +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDragSourceEffect.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDragSourceEffect.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,202 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 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 + * Port to the D programming language: + * Frank BenoitTree
.
+ *
+ * Classes that wish to provide their own source image for a Tree
can
+ * extend TreeDragSourceEffect
class and override the TreeDragSourceEffect.dragStart
+ * method and set the field DragSourceEvent.image
with their own image.
super
method to get the default drag under effect implementation.
+ *
+ * @see DragSourceEffect
+ * @see DragSourceEvent
+ * @see Sample code and further information
+ *
+ * @since 3.3
+ */
+public class TreeDragSourceEffect : DragSourceEffect {
+ Image dragSourceImage = null;
+
+ /**
+ * Creates a new TreeDragSourceEffect
to handle drag effect
+ * from the specified Tree
.
+ *
+ * @param tree the Tree
that the user clicks on to initiate the drag
+ */
+ public this(Tree tree) {
+ super(tree);
+ }
+
+ /**
+ * This implementation of dragFinished
disposes the image
+ * that was created in TreeDragSourceEffect.dragStart
.
+ *
+ * Subclasses that override this method should call super.dragFinished(event)
+ * to dispose the image in the default implementation.
+ *
+ * @param event the information associated with the drag finished event
+ */
+ public void dragFinished(DragSourceEvent event) {
+ if (dragSourceImage !is null) dragSourceImage.dispose();
+ dragSourceImage = null;
+ }
+
+ /**
+ * This implementation of dragStart
will create a default
+ * image that will be used during the drag. The image should be disposed
+ * when the drag is completed in the TreeDragSourceEffect.dragFinished
+ * method.
+ *
+ * Subclasses that override this method should call super.dragStart(event)
+ * to use the image from the default implementation.
+ *
+ * @param event the information associated with the drag start event
+ */
+ public void dragStart(DragSourceEvent event) {
+ event.image = getDragSourceImage(event);
+ }
+
+ Image getDragSourceImage(DragSourceEvent event) {
+ if (dragSourceImage !is null) dragSourceImage.dispose();
+ dragSourceImage = null;
+ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+ SHDRAGIMAGE shdi;
+ int DI_GETDRAGIMAGE = OS.RegisterWindowMessage ("ShellGetDragImage"w.ptr); //$NON-NLS-1$
+ if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, &shdi) !is 0) {
+ if ((control.getStyle() & SWT.MIRRORED) !is 0) {
+ event.x += shdi.sizeDragImage.cx - shdi.ptOffset.x;
+ } else {
+ event.x += shdi.ptOffset.x;
+ }
+ event.y += shdi.ptOffset.y;
+ auto hImage = shdi.hbmpDragImage;
+ if (hImage !is null) {
+ BITMAP bm;
+ OS.GetObject (hImage, BITMAP.sizeof, &bm);
+ int srcWidth = bm.bmWidth;
+ int srcHeight = bm.bmHeight;
+
+ /* Create resources */
+ auto hdc = OS.GetDC (null);
+ auto srcHdc = OS.CreateCompatibleDC (hdc);
+ auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage);
+ auto memHdc = OS.CreateCompatibleDC (hdc);
+ BITMAPINFOHEADER bmiHeader;
+ bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+ bmiHeader.biWidth = srcWidth;
+ bmiHeader.biHeight = -srcHeight;
+ bmiHeader.biPlanes = 1;
+ bmiHeader.biBitCount = 32;
+ bmiHeader.biCompression = OS.BI_RGB;
+ void* pBits;
+ auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)&bmiHeader, OS.DIB_RGB_COLORS, &pBits, null, 0);
+ if (memDib is null) SWT.error (SWT.ERROR_NO_HANDLES);
+ auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
+
+ BITMAP dibBM;
+ OS.GetObject (memDib, BITMAP.sizeof, &dibBM);
+ int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
+
+ /* Get the foreground pixels */
+ OS.BitBlt (memHdc, 0, 0, srcWidth, srcHeight, srcHdc, 0, 0, OS.SRCCOPY);
+ byte[] srcData = (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ];
+
+ PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+ ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData);
+ if (shdi.crColorKey is -1) {
+ byte[] alphaData = new byte[srcWidth * srcHeight];
+ int spinc = dibBM.bmWidthBytes - srcWidth * 4;
+ int ap = 0, sp = 3;
+ for (int y = 0; y < srcHeight; ++y) {
+ for (int x = 0; x < srcWidth; ++x) {
+ alphaData [ap++] = srcData [sp];
+ sp += 4;
+ }
+ sp += spinc;
+ }
+ data.alphaData = alphaData;
+ } else {
+ data.transparentPixel = shdi.crColorKey << 8;
+ }
+ dragSourceImage = new Image (control.getDisplay (), data);
+ OS.SelectObject (memHdc, oldMemBitmap);
+ OS.DeleteDC (memHdc);
+ OS.DeleteObject (memDib);
+ OS.SelectObject (srcHdc, oldSrcBitmap);
+ OS.DeleteDC (srcHdc);
+ OS.ReleaseDC (null, hdc);
+ OS.DeleteObject (hImage);
+ return dragSourceImage;
+ }
+ }
+ return null;
+ }
+
+ Tree tree = cast(Tree) control;
+ //TEMPORARY CODE
+ if (tree.isListening (SWT.EraseItem) || tree.isListening (SWT.PaintItem)) return null;
+ TreeItem[] selection = tree.getSelection();
+ if (selection.length is 0) return null;
+ auto treeImageList = OS.SendMessage (tree.handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
+ if (treeImageList !is 0) {
+ int count = Math.min(selection.length, 10);
+ Rectangle bounds = selection[0].getBounds(0);
+ for (int i = 1; i < count; i++) {
+ bounds = bounds.makeUnion(selection[i].getBounds(0));
+ }
+ auto hDC = OS.GetDC(tree.handle);
+ auto hDC1 = OS.CreateCompatibleDC(hDC);
+ auto bitmap = OS.CreateCompatibleBitmap(hDC, bounds.width, bounds.height);
+ auto hOldBitmap = OS.SelectObject(hDC1, bitmap);
+ RECT rect;
+ rect.right = bounds.width;
+ rect.bottom = bounds.height;
+ auto hBrush = OS.GetStockObject(OS.WHITE_BRUSH);
+ OS.FillRect(hDC1, &rect, hBrush);
+ for (int i = 0; i < count; i++) {
+ TreeItem selected = selection[i];
+ Rectangle cell = selected.getBounds(0);
+ HANDLE imageList = cast(HANDLE) OS.SendMessage(tree.handle, OS.TVM_CREATEDRAGIMAGE, 0, selected.handle);
+ OS.ImageList_Draw(imageList, 0, hDC1, cell.x - bounds.x, cell.y - bounds.y, OS.ILD_SELECTED);
+ OS.ImageList_Destroy(imageList);
+ }
+ OS.SelectObject(hDC1, hOldBitmap);
+ OS.DeleteDC (hDC1);
+ OS.ReleaseDC (tree.handle, hDC);
+ Display display = tree.getDisplay();
+ dragSourceImage = Image.win32_new(display, SWT.BITMAP, bitmap);
+ return dragSourceImage;
+ }
+ return null;
+ }
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDropTargetEffect.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Tree
.
+ *
+ * Classes that wish to provide their own drag under effect for a Tree
+ * can extend the TreeDropTargetEffect
class and override any applicable methods
+ * in TreeDropTargetEffect
to display their own drag under effect.
super
method to get the default drag under effect implementation.
+ *
+ * The feedback value is either one of the FEEDBACK constants defined in
+ * class DND
which is applicable to instances of this class,
+ * or it must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
effect constants.
+ *
+ *
+ * Note: Only one of the styles FEEDBACK_SELECT, FEEDBACK_INSERT_BEFORE or + * FEEDBACK_INSERT_AFTER may be specified. + *
+ * + * @see DropTargetAdapter + * @see DropTargetEvent + * @see Sample code and further information + * + * @since 3.3 + */ +public class TreeDropTargetEffect : DropTargetEffect { + static final int SCROLL_HYSTERESIS = 200; // milli seconds + static final int EXPAND_HYSTERESIS = 1000; // milli seconds + + int /*long*/ dropIndex; + int scrollIndex; + long scrollBeginTime; + int /*long*/ expandIndex; + long expandBeginTime; + TreeItem insertItem; + bool insertBefore; + + /** + * Creates a newTreeDropTargetEffect
to handle the drag under effect on the specified
+ * Tree
.
+ *
+ * @param tree the Tree
over which the user positions the cursor to drop the data
+ */
+ public this(Tree tree) {
+ super(tree);
+ }
+
+ int checkEffect(int effect) {
+ // Some effects are mutually exclusive. Make sure that only one of the mutually exclusive effects has been specified.
+ if ((effect & DND.FEEDBACK_SELECT) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE;
+ if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER;
+ return effect;
+ }
+
+ /**
+ * 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 enter event
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ */
+ public void dragEnter(DropTargetEvent event) {
+ dropIndex = -1;
+ insertItem = null;
+ expandBeginTime = 0;
+ expandIndex = -1;
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+
+ /**
+ * 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
+ */
+ public void dragLeave(DropTargetEvent event) {
+ Tree tree = cast(Tree) control;
+ auto handle = tree.handle;
+ if (dropIndex !is -1) {
+ TVITEM tvItem;
+ tvItem.hItem = cast(HTREEITEM) dropIndex;
+ tvItem.mask = OS.TVIF_STATE;
+ tvItem.stateMask = OS.TVIS_DROPHILITED;
+ tvItem.state = 0;
+ OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+ dropIndex = -1;
+ }
+ if (insertItem !is null) {
+ tree.setInsertMark(null, false);
+ insertItem = null;
+ }
+ expandBeginTime = 0;
+ expandIndex = -1;
+ scrollBeginTime = 0;
+ scrollIndex = -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_INSERT_BEFORE
+ * @see DND#FEEDBACK_INSERT_AFTER
+ * @see DND#FEEDBACK_SCROLL
+ */
+ public void dragOver(DropTargetEvent event) {
+ Tree tree = cast(Tree) getControl();
+ int effect = checkEffect(event.feedback);
+ auto handle = tree.handle;
+ Point coordinates = new Point(event.x, event.y);
+ coordinates = tree.toControl(coordinates);
+ TVHITTESTINFO lpht;
+ lpht.pt.x = coordinates.x;
+ lpht.pt.y = coordinates.y;
+ OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
+ auto hItem = lpht.hItem;
+ if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ } else {
+ if (hItem !is cast(HTREEITEM)-1 && cast(HTREEITEM)scrollIndex is hItem && scrollBeginTime !is 0) {
+ if (System.currentTimeMillis() >= scrollBeginTime) {
+ auto topItem = cast(HTREEITEM)OS.SendMessage(handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+ auto nextItem = cast(HTREEITEM)OS.SendMessage(handle, OS.TVM_GETNEXTITEM, hItem is topItem ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE, hItem);
+ bool scroll = true;
+ if (hItem is topItem) {
+ scroll = nextItem !is null;
+ } else {
+ RECT itemRect;
+ if (OS.TreeView_GetItemRect (handle, nextItem, &itemRect, true)) {
+ RECT rect;
+ OS.GetClientRect (handle, &rect);
+ POINT pt;
+ 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) {
+ OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, nextItem);
+ tree.redraw();
+ }
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+ } else {
+ scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+ scrollIndex = cast(int)hItem;
+ }
+ }
+ if ((effect & DND.FEEDBACK_EXPAND) is 0) {
+ expandBeginTime = 0;
+ expandIndex = -1;
+ } else {
+ if (cast(int)hItem !is -1 && expandIndex is cast(int)hItem && expandBeginTime !is 0) {
+ if (System.currentTimeMillis() >= expandBeginTime) {
+ if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem) !is 0) {
+ TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, cast(int)hItem);
+ if (item !is null && !item.getExpanded()) {
+ item.setExpanded(true);
+ tree.redraw();
+ Event expandEvent = new Event ();
+ expandEvent.item = item;
+ tree.notifyListeners(SWT.Expand, expandEvent);
+ }
+ }
+ expandBeginTime = 0;
+ expandIndex = -1;
+ }
+ } else {
+ expandBeginTime = System.currentTimeMillis() + EXPAND_HYSTERESIS;
+ expandIndex = cast(int)hItem;
+ }
+ }
+ if (dropIndex !is -1 && (dropIndex !is cast(int)hItem || (effect & DND.FEEDBACK_SELECT) is 0)) {
+ TVITEM tvItem;
+ tvItem.hItem = cast(HTREEITEM) dropIndex;
+ tvItem.mask = OS.TVIF_STATE;
+ tvItem.stateMask = OS.TVIS_DROPHILITED;
+ tvItem.state = 0;
+ OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+ dropIndex = -1;
+ }
+ if (cast(int)hItem !is -1 && cast(int)hItem !is dropIndex && (effect & DND.FEEDBACK_SELECT) !is 0) {
+ TVITEM tvItem;
+ tvItem.hItem = cast(HTREEITEM) hItem;
+ tvItem.mask = OS.TVIF_STATE;
+ tvItem.stateMask = OS.TVIS_DROPHILITED;
+ tvItem.state = OS.TVIS_DROPHILITED;
+ OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+ dropIndex = cast(int)hItem;
+ }
+ if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0 || (effect & DND.FEEDBACK_INSERT_AFTER) !is 0) {
+ bool before = (effect & DND.FEEDBACK_INSERT_BEFORE) !is 0;
+ /*
+ * Bug in Windows. When TVM_SETINSERTMARK is used to set
+ * an insert mark for a tree and an item is expanded or
+ * collapsed near the insert mark, the tree does not redraw
+ * the insert mark properly. The fix is to hide and show
+ * the insert mark whenever an item is expanded or collapsed.
+ * Since the insert mark can not be queried from the tree,
+ * use the Tree API rather than calling the OS directly.
+ */
+ TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, cast(int)hItem);
+ if (item !is null) {
+ if (item !is insertItem || before !is insertBefore) {
+ tree.setInsertMark(item, before);
+ }
+ insertItem = item;
+ insertBefore = before;
+ } else {
+ if (insertItem !is null) {
+ tree.setInsertMark(null, false);
+ }
+ insertItem = null;
+ }
+ } else {
+ if (insertItem !is null) {
+ tree.setInsertMark(null, false);
+ }
+ insertItem = null;
+ }
+ }
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/URLTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/URLTransfer.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 20007 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
+ * Port to the D programming language:
+ * Frank Benoit 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. The string
+ * must contain a fully specified url.
+ *
+ * An example of a java String
containing a URL is shown below:
+ * String url = "http://www.eclipse.org";
+ *
+ *
+ * @see Transfer
+ */
+public class URLTransfer : ByteArrayTransfer {
+
+ static URLTransfer _instance;
+ static const String CFSTR_INETURL = "UniformResourceLocator"; //$NON-NLS-1$
+ static const int CFSTR_INETURLID;
+
+static this(){
+ CFSTR_INETURLID = registerType(CFSTR_INETURL);
+}
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the URLTransfer class.
+ *
+ * @return the singleton instance of the URLTransfer class
+ */
+public static URLTransfer getInstance () {
+ if( _instance is null ){
+ synchronized {
+ if( _instance is null ){
+ _instance = new URLTransfer();
+ }
+ }
+ }
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts a URL
+ * represented by a java String
to a platform specific representation.
+ *
+ * @param object a java String
containing a URL
+ * @param transferData an empty TransferData
object that will
+ * be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkURL(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.result = COM.E_FAIL;
+ // URL is stored as a null terminated byte array
+ String url = (cast(ArrayWrapperString)object).array;
+ int codePage = OS.GetACP();
+ wchar[] chars = StrToWCHARs(codePage, url, true );
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, null, 0, null, null);
+ if (cchMultiByte is 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ auto lpMultiByteStr = cast(CHAR*)OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, lpMultiByteStr, cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+ return;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform
+ * specific representation of a URL to a java String
.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java String
containing a URL if the conversion was successful;
+ * otherwise null
+ *
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+ IDataObject data = transferData.pIDataObject;
+ data.AddRef();
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ FORMATETC* formatetc = transferData.formatetc;
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = getData(data, formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ auto hMem = stgmedium.unionField;
+ try {
+ auto lpMultiByteStr = cast(CHAR*)OS.GlobalLock(hMem);
+ if (lpMultiByteStr is null) return null;
+ try {
+ int codePage = OS.GetACP();
+ int cchWideChar = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+ if (cchWideChar is 0) return null;
+ wchar[] lpWideCharStr = new wchar [cchWideChar - 1];
+ OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length);
+ return new ArrayWrapperString( WCHARzToStr( lpWideCharStr.ptr) );
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+}
+
+protected int[] getTypeIds(){
+ return [CFSTR_INETURLID];
+}
+
+protected String[] getTypeNames(){
+ return [CFSTR_INETURL];
+}
+
+bool checkURL(Object object) {
+ return object !is null && (null !is cast(ArrayWrapperString)object) && (cast(ArrayWrapperString)object).array.length > 0;
+
+}
+
+protected bool validate(Object object) {
+ return checkURL(object);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/all.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/all.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,32 @@
+module org.eclipse.swt.dnd.all;
+
+public import org.eclipse.swt.dnd.ByteArrayTransfer;
+public import org.eclipse.swt.dnd.Clipboard;
+public import org.eclipse.swt.dnd.DND;
+public import org.eclipse.swt.dnd.DNDEvent;
+public import org.eclipse.swt.dnd.DNDListener;
+public import org.eclipse.swt.dnd.DragSource;
+public import org.eclipse.swt.dnd.DragSourceAdapter;
+public import org.eclipse.swt.dnd.DragSourceEffect;
+public import org.eclipse.swt.dnd.DragSourceEvent;
+public import org.eclipse.swt.dnd.DragSourceListener;
+public import org.eclipse.swt.dnd.DropTarget;
+public import org.eclipse.swt.dnd.DropTargetAdapter;
+public import org.eclipse.swt.dnd.DropTargetEffect;
+public import org.eclipse.swt.dnd.DropTargetEvent;
+public import org.eclipse.swt.dnd.DropTargetListener;
+public import org.eclipse.swt.dnd.FileTransfer;
+public import org.eclipse.swt.dnd.HTMLTransfer;
+public import org.eclipse.swt.dnd.ImageTransfer;
+public import org.eclipse.swt.dnd.OleEnumFORMATETC;
+public import org.eclipse.swt.dnd.RTFTransfer;
+public import org.eclipse.swt.dnd.TableDragSourceEffect;
+public import org.eclipse.swt.dnd.TableDropTargetEffect;
+public import org.eclipse.swt.dnd.TextTransfer;
+public import org.eclipse.swt.dnd.Transfer;
+public import org.eclipse.swt.dnd.TransferData;
+public import org.eclipse.swt.dnd.TreeDragSourceEffect;
+public import org.eclipse.swt.dnd.TreeDropTargetEffect;
+public import org.eclipse.swt.dnd.URLTransfer;
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ArmEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ArmEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a widget using the
+ * addArmListener
method and removed using
+ * the removeArmListener
method. When the
+ * widget is armed, the widgetArmed method will be invoked.
+ *
ControlListener
interface.
+ *
+ * Classes that wish to deal with ControlEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
Shell
s).
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the move
+ */
+public void controlMoved(ControlEvent e) {
+}
+
+/**
+ * Sent when the size (width, height) of a control changes.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the resize
+ */
+public void controlResized(ControlEvent e) {
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ControlEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ControlEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addControlListener
method and removed using
+ * the removeControlListener
method. When a
+ * control is moved or resized, the appropriate method will
+ * be invoked.
+ *
Shell
s).
+ *
+ * @param e an event containing information about the move
+ */
+public void controlMoved(ControlEvent e);
+
+/**
+ * Sent when the size (width, height) of a control changes.
+ *
+ * @param e an event containing information about the resize
+ */
+public void controlResized(ControlEvent e);
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DisposeEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DisposeEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a widget using the
+ * addDisposeListener
method and removed using
+ * the removeDisposeListener
method. When a
+ * widget is disposed, the widgetDisposed method will
+ * be invoked.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addDragDetectListener
method and removed using
+ * the removeDragDetectListener
method. When the
+ * drag is detected, the drageDetected method will be invoked.
+ *
ExpandListener
interface.
+ *
+ * Classes that wish to deal with ExpandEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
ExpandItem
s being expanded or collapsed.
+ *
+ * @see ExpandListener
+ * @see Sample code and further information
+ *
+ * @since 3.2
+ */
+
+public class ExpandEvent : SelectionEvent {
+
+ //static final long serialVersionUID = 3976735856884987356L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+ super(e);
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ExpandListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ExpandListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit ExpandItem
s.
+ *
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a ExpandBar
+ * control using the addExpandListener
method and
+ * removed using the removeExpandListener
method.
+ * When a item of the ExpandBar
is expanded or
+ * collapsed, the appropriate method will be invoked.
+ *
FocusListener
interface.
+ *
+ * Classes that wish to deal with FocusEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addFocusListener
method and removed using
+ * the removeFocusListener
method. When a
+ * control gains or loses focus, the appropriate method
+ * will be invoked.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addHelpListener
method and removed using
+ * the removeHelpListener
method. When help
+ * is requested for a control, the helpRequested method
+ * will be invoked.
+ *
KeyListener
interface.
+ *
+ * Classes that wish to deal with KeyEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ * When a key listener is added to a control, the control + * will take part in widget traversal. By default, all + * traversal keys (such as the tab key and so on) are + * delivered to the control. In order for a control to take + * part in traversal, it should listen for traversal events. + * Otherwise, the user can traverse into a control but not + * out. Note that native controls such as table and tree + * implement key traversal in the operating system. It is + * not necessary to add traversal listeners for these controls, + * unless you want to override the default traversal. + *
+ * + * @see KeyListener + * @see TraverseListener + * @see Sample code and further information + */ + +public class KeyEvent : TypedEvent { + + /** + * the character represented by the key that was typed. + * This is the final character that results after all modifiers have been + * applied. For example, when the user types Ctrl+A, the character value + * is 0x01. It is important that applications do not attempt to modify the + * character value based on a stateMask (such as SWT.CTRL) or the resulting + * character will not be correct. + */ + public wchar character = '\0'; + + /** + * the key code of the key that was typed, + * as defined by the key code constants in classSWT
.
+ * When the character field of the event is ambiguous, this field
+ * contains the unicode value of the original character. For example,
+ * typing Ctrl+M or Return both result in the character '\r' but the
+ * keyCode field will also contain '\r' when Return was typed.
+ *
+ * @see org.eclipse.swt.SWT
+ */
+ public int keyCode;
+
+ /**
+ * the state of the keyboard modifier keys at the time
+ * the event was generated, as defined by the key code
+ * constants in class SWT
.
+ *
+ * @see org.eclipse.swt.SWT
+ */
+ public int stateMask;
+
+ /**
+ * A flag indicating whether the operation should be allowed.
+ * Setting this field to false
will cancel the operation.
+ */
+ public bool doit;
+
+ static final long serialVersionUID = 3256442491011412789L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+ super(e);
+ this.character = e.character;
+ this.keyCode = e.keyCode;
+ this.stateMask = e.stateMask;
+ this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+ return Format( "{} character={} keyCode={} stateMask={} doit={}}",
+ super.toString[ 0 .. $-2 ],
+ character, keyCode, stateMask, doit );
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/KeyListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/KeyListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addKeyListener
method and removed using
+ * the removeKeyListener
method. When a
+ * key is pressed or released, the appropriate method will
+ * be invoked.
+ *
MenuListener
interface.
+ *
+ * Classes that wish to deal with MenuEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
false
will cancel the operation.
+ */
+ public bool doit;
+
+ //private static final long serialVersionUID = -3061660596590828941L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+ super(e);
+ this.x = e.x;
+ this.y = e.y;
+ this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+ return Format( "{} x={} y={} doit={}}", super.toString[ 0 .. $-2 ], x, y, doit );
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuDetectListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuDetectListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a control or TrayItem
+ * using the addMenuDetectListener
method and
+ * removed using the removeMenuDetectListener
method.
+ * When the context menu trigger occurs, the
+ * menuDetected
method will be invoked.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a menu using the
+ * addMenuListener
method and removed using
+ * the removeMenuListener
method. When the
+ * menu is hidden or shown, the appropriate method will
+ * be invoked.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a text widget using the
+ * addModifyListener
method and removed using
+ * the removeModifyListener
method. When the
+ * text is modified, the modifyText method will be invoked.
+ *
MouseListener
interface.
+ *
+ * Classes that wish to deal with MouseEvent
s
+ * which occur as mouse buttons are pressed and released can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ * Note: The button
field is an integer that
+ * represents the mouse button number. This is not the same
+ * as the SWT
mask constants BUTTONx
.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addMouseListener
method and removed using
+ * the removeMouseListener
method. When a
+ * mouse button is pressed or released, the appropriate method
+ * will be invoked.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addMouseMoveListener
method and removed using
+ * the removeMouseMoveListener
method. As the
+ * mouse moves, the mouseMove method will be invoked.
+ *
MouseTrackListener
interface.
+ *
+ * Classes that wish to deal with MouseEvent
s which
+ * occur as the mouse pointer passes (or hovers) over controls can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addMouseTrackListener
method and removed using
+ * the removeMouseTrackListener
method. When the
+ * mouse pointer passes into or out of the area of the screen
+ * covered by a control or pauses while over a control, the
+ * appropriate method will be invoked.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addMouseWheelListener
method and removed using
+ * the removeMouseWheelListener
method. When the
+ * mouse wheel is scrolled the mouseScrolled
method
+ * will be invoked.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addPaintListener
method and removed using
+ * the removePaintListener
method. When a
+ * paint event occurs, the paintControl method will be
+ * invoked.
+ *
SelectionListener
interface.
+ *
+ * Classes that wish to deal with SelectionEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ * Note: The fields that are filled in depend on the widget. + *
+ * + * @see SelectionListener + * @see Sample code and further information + */ + +public class SelectionEvent : TypedEvent { + + /** + * The item that was selected. + */ + public Widget item; + + /** + * Extra detail information about the selection, depending on the widget. + * + *Sash
ScrollBar and Slider
Table and Tree
Text
CoolItem and ToolItem
false
will cancel the
+ * operation, depending on the widget.
+ */
+ public bool doit;
+
+ //static final long serialVersionUID = 3976735856884987953L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+ super(e);
+ this.item = e.item;
+ this.x = e.x;
+ this.y = e.y;
+ this.width = e.width;
+ this.height = e.height;
+ this.detail = e.detail;
+ this.stateMask = e.stateMask;
+ this.text = e.text;
+ this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+ return Format( "{} item={} detail={} x={} y={} width={} height={} stateMask={} text={} doit={}}",
+ super.toString[ 0 .. $-2 ],
+ item,
+ detail,
+ x,
+ y,
+ width,
+ height,
+ stateMask,
+ text,
+ doit );
+}
+}
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/SelectionListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/SelectionListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addSelectionListener
method and removed using
+ * the removeSelectionListener
method. When
+ * selection occurs in a control the appropriate method
+ * will be invoked.
+ *
+ * For example, selection occurs in a List when the user selects + * an item or items with the keyboard or mouse. On some platforms, + * the event occurs when a mouse button or key is pressed. On others, + * it happens when the mouse or key is released. The exact key or + * mouse gesture that causes this event is platform specific. + *
+ * + * @param e an event containing information about the selection + */ +public void widgetSelected(SelectionEvent e); + +/** + * Sent when default selection occurs in the control. + *+ * For example, on some platforms default selection occurs in a List + * when the user double-clicks an item or types return in a Text. + * On some platforms, the event occurs when a mouse button or key is + * pressed. On others, it happens when the mouse or key is released. + * The exact key or mouse gesture that causes this event is platform + * specific. + *
+ * + * @param e an event containing information about the default selection + */ +public void widgetDefaultSelected(SelectionEvent e); +} + + +/// SWT extension +private class _DgSelectionListenerT(Dg,T...) : SelectionListener { + + alias ParameterTupleOf!(Dg) DgArgs; + static assert( is(DgArgs == Tuple!(SelectionEvent,T)), + "Delegate args not correct: "~DgArgs.stringof~" vs. (Event,"~T.stringof~")" ); + + Dg dg; + T t; + int type; + + private this( int type, Dg dg, T t ){ + this.type = type; + this.dg = dg; + static if( T.length > 0 ){ + this.t = t; + } + } + + public void widgetSelected(SelectionEvent e){ + if( type is SelectionListener.SELECTION ){ + dg(e,t); + } + } + public void widgetDefaultSelected(SelectionEvent e){ + if( type is SelectionListener.DEFAULTSELECTION ){ + dg(e,t); + } + } +} + +SelectionListener dgSelectionListener( Dg, T... )( int type, Dg dg, T args ){ + return new _DgSelectionListenerT!( Dg, T )( type, dg, args ); +} + +SelectionListener dgSelectionListenerWidgetSelected( Dg, T... )( Dg dg, T args ){ + return dgSelectionListener( SelectionListener.SELECTION, dg, args ); +} +SelectionListener dgSelectionListenerWidgetDefaultSelected( Dg, T... )( Dg dg, T args ){ + return dgSelectionListener( SelectionListener.DEFAULTSELECTION, dg, args ); +} + diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellAdapter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellAdapter.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank BenoitShellListener
interface.
+ *
+ * Classes that wish to deal with ShellEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
false
will cancel the operation.
+ */
+ public bool doit;
+
+ //static final long serialVersionUID = 3257569490479888441L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+ super(e);
+ this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+ return Format( "{} doit={}}", super.toString[ 0 .. $-2 ], doit );
+}
+}
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit Shell
s.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a shell using the
+ * addShellListener
method and removed using
+ * the removeShellListener
method. When the
+ * state of the shell changes, the appropriate method will
+ * be invoked.
+ *
+ * The traversal event allows fine control over keyboard traversal
+ * in a control both to implement traversal and override the default
+ * traversal behavior defined by the system. This is achieved using
+ * two fields, detail
and doit
.
+ *
+ * When a control is traversed, a traverse event is sent. The detail
+ * describes the type of traversal and the doit field indicates the default
+ * behavior of the system. For example, when a right arrow key is pressed
+ * in a text control, the detail field is TRAVERSE_ARROW_NEXT
+ * and the doit field is false
, indicating that the system
+ * will not traverse to the next tab item and the arrow key will be
+ * delivered to the text control. If the same key is pressed in a radio
+ * button, the doit field will be true
, indicating that
+ * traversal is to proceed to the next tab item, possibly another radio
+ * button in the group and that the arrow key is not to be delivered
+ * to the radio button.
+ *
+ * How can the traversal event be used to implement traversal?
+ * When a tab key is pressed in a canvas, the detail field will be
+ * TRAVERSE_TAB_NEXT
and the doit field will be
+ * false
. The default behavior of the system is to
+ * provide no traversal for canvas controls. This means that by
+ * default in a canvas, a key listener will see every key that the
+ * user types, including traversal keys. To understand why this
+ * is so, it is important to understand that only the widget implementor
+ * can decide which traversal is appropriate for the widget. Returning
+ * to the TRAVERSE_TAB_NEXT
example, a text widget implemented
+ * by a canvas would typically want to use the tab key to insert a
+ * tab character into the widget. A list widget implementation, on the
+ * other hand, would like the system default traversal behavior. Using
+ * only the doit flag, both implementations are possible. The text widget
+ * implementor sets doit to false
, ensuring that the system
+ * will not traverse and that the tab key will be delivered to key listeners.
+ * The list widget implementor sets doit to true
, indicating
+ * that the system should perform tab traversal and that the key should not
+ * be delivered to the list widget.
+ *
+ * How can the traversal event be used to override system traversal?
+ * When the return key is pressed in a single line text control, the
+ * detail field is TRAVERSE_RETURN
and the doit field
+ * is true
. This means that the return key will be processed
+ * by the default button, not the text widget. If the text widget has
+ * a default selection listener, it will not run because the return key
+ * will be processed by the default button. Imagine that the text control
+ * is being used as an in-place editor and return is used to dispose the
+ * widget. Setting doit to false
will stop the system from
+ * activating the default button but the key will be delivered to the text
+ * control, running the key and selection listeners for the text. How
+ * can TRAVERSE_RETURN
be implemented so that the default button
+ * will not be activated and the text widget will not see the return key?
+ * This is achieved by setting doit to true
, and the detail
+ * to TRAVERSE_NONE
.
+ *
+ * Note: A widget implementor will typically implement traversal using + * only the doit flag to either enable or disable system traversal. + *
+ * + * @see TraverseListener + * @see Sample code and further information + */ + +public final class TraverseEvent : KeyEvent { + + /** + * The traversal type. + *TRAVERSE_NONE
+ * causes no traversal action to be taken.
+ *
+ * When used in conjunction with the doit
field, the
+ * traversal detail field can be useful when overriding the default
+ * traversal mechanism for a control. For example, setting the doit
+ * field to false
will cancel the operation and allow
+ * the traversal key stroke to be delivered to the control. Setting
+ * the doit field to true
indicates that the traversal
+ * described by the detail field is to be performed.
+ */
+ public int detail;
+
+ //static final long serialVersionUID = 3257565105301239349L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+ super(e);
+ this.detail = e.detail;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+ return Format( "{} detail={}}", super.toString[ 0 .. $-2 ], detail );
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TraverseListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TraverseListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * addTraverseListener
method and removed using
+ * the removeTraverseListener
method. When a
+ * traverse event occurs in a control, the keyTraversed method
+ * will be invoked.
+ *
+ * A traverse event occurs when the user presses a traversal
+ * key. Traversal keys are typically tab and arrow keys, along
+ * with certain other keys on some platforms. Traversal key
+ * constants beginning with TRAVERSE_
are defined
+ * in the SWT
class.
+ *
TreeListener
interface.
+ *
+ * Classes that wish to deal with TreeEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a tree control using the
+ * addTreeListener
method and removed using
+ * the removeTreeListener
method. When a branch
+ * of the tree is expanded or collapsed, the appropriate method
+ * will be invoked.
+ *
+ * After creating an instance of a class that :
+ * this interface it can be added to a text control using the
+ * addVerifyListener
method and removed using
+ * the removeVerifyListener
method. When the
+ * text is about to be modified, the verifyText method
+ * will be invoked.
+ *
+ * A verify event occurs after the user has done something + * to modify the text (typically typed a key), but before + * the text is modified. The doit field in the verify event + * indicates whether or not to modify the text. + *
+ * + * @param e an event containing information about the verify + */ +public void verifyText(VerifyEvent e); +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/all.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/all.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,54 @@ +module org.eclipse.swt.events.all; + +public import org.eclipse.swt.events.ArmEvent; +public import org.eclipse.swt.events.ArmListener; +public import org.eclipse.swt.events.ControlAdapter; +public import org.eclipse.swt.events.ControlEvent; +public import org.eclipse.swt.events.ControlListener; +public import org.eclipse.swt.events.DisposeEvent; +public import org.eclipse.swt.events.DisposeListener; +public import org.eclipse.swt.events.DragDetectEvent; +public import org.eclipse.swt.events.DragDetectListener; +public import org.eclipse.swt.events.ExpandAdapter; +public import org.eclipse.swt.events.ExpandEvent; +public import org.eclipse.swt.events.ExpandListener; +public import org.eclipse.swt.events.FocusAdapter; +public import org.eclipse.swt.events.FocusEvent; +public import org.eclipse.swt.events.FocusListener; +public import org.eclipse.swt.events.HelpEvent; +public import org.eclipse.swt.events.HelpListener; +public import org.eclipse.swt.events.KeyAdapter; +public import org.eclipse.swt.events.KeyEvent; +public import org.eclipse.swt.events.KeyListener; +public import org.eclipse.swt.events.MenuAdapter; +public import org.eclipse.swt.events.MenuDetectEvent; +public import org.eclipse.swt.events.MenuDetectListener; +public import org.eclipse.swt.events.MenuEvent; +public import org.eclipse.swt.events.MenuListener; +public import org.eclipse.swt.events.ModifyEvent; +public import org.eclipse.swt.events.ModifyListener; +public import org.eclipse.swt.events.MouseAdapter; +public import org.eclipse.swt.events.MouseEvent; +public import org.eclipse.swt.events.MouseListener; +public import org.eclipse.swt.events.MouseMoveListener; +public import org.eclipse.swt.events.MouseTrackAdapter; +public import org.eclipse.swt.events.MouseTrackListener; +public import org.eclipse.swt.events.MouseWheelListener; +public import org.eclipse.swt.events.PaintEvent; +public import org.eclipse.swt.events.PaintListener; +public import org.eclipse.swt.events.SelectionAdapter; +public import org.eclipse.swt.events.SelectionEvent; +public import org.eclipse.swt.events.SelectionListener; +public import org.eclipse.swt.events.ShellAdapter; +public import org.eclipse.swt.events.ShellEvent; +public import org.eclipse.swt.events.ShellListener; +public import org.eclipse.swt.events.TraverseEvent; +public import org.eclipse.swt.events.TraverseListener; +public import org.eclipse.swt.events.TreeAdapter; +public import org.eclipse.swt.events.TreeEvent; +public import org.eclipse.swt.events.TreeListener; +public import org.eclipse.swt.events.TypedEvent; +public import org.eclipse.swt.events.VerifyEvent; +public import org.eclipse.swt.events.VerifyListener; + + diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Color.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Color.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,340 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank BenoitRGB
.
+ *
+ * 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.
+ *
+ * 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 COLORREF handle; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this(Device device) { + super(device); +} + +/** + * 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 IllegalArgumentExceptionRGB
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 IllegalArgumentExceptiontrue
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+public bool equals (Object object) {
+ if (object is this) return true;
+ if (!(cast(Color)object)) return false;
+ Color color = cast(Color) object;
+ return device is color.device && (handle & 0xFFFFFF) is (color.handle & 0xFFFFFF);
+}
+
+/**
+ * Returns the amount of blue in the color, from 0 to 255.
+ *
+ * @return the blue component of the color
+ *
+ * @exception SWTException RGB
representing the receiver.
+ *
+ * @return the RGB for the color
+ *
+ * @exception SWTException 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;
+}
+
+/**
+ * Allocates the operating system resources associated
+ * with the receiver.
+ *
+ * @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 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 bool isDisposed() {
+ return handle is -1;
+}
+
+/**
+ * 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 Format( "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.
+ *
+ * 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.
+ *
+ * Note: Only one of the above styles may be specified. + *
+ * + * @see Cursor snippets + * @see Sample code and further information + */ + +public final class Cursor : Resource { + + alias Resource.init_ init_; + + /** + * 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 HCURSOR handle; + + bool isIcon; + + /** + * data used to create a HAND cursor. + */ + static const byte[] HAND_SOURCE = [ + cast(byte)0xf9,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x3f,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x07,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x03,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x00,cast(byte)0xff,cast(byte)0xff, + + cast(byte)0x10,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0x80,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0xc0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0xe0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0xf8,cast(byte)0x00,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xfc,cast(byte)0x01,cast(byte)0xff,cast(byte)0xff, + + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff + ]; + static const byte[] HAND_MASK = [ + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0xc0,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0xd8,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0xd8,cast(byte)0x00,cast(byte)0x00, + + cast(byte)0x07,cast(byte)0xdb,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x67,cast(byte)0xfb,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x3f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x1f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x0f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x07,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x03,cast(byte)0xfe,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00 + ]; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this(Device device) { + super(device); +} + +/** + * 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+ * 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+ * 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 IllegalArgumentExceptiontrue
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+public override int opEquals (Object object) {
+ if (object is this) return true;
+ if (!(cast(Cursor)object)) return false;
+ Cursor cursor = cast(Cursor) object;
+ return device is cursor.device && handle is cursor.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
+ *
+ * @see #equals
+ */
+public override hash_t toHash () {
+ return cast(hash_t)handle;
+}
+
+/**
+ * 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
+ */
+override public bool isDisposed() {
+ return handle is 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 "Cursor {*DISPOSED*}";
+ return Format( "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.
+ *
+ * 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 HPALETTE hPalette; + int [] colorRefCount; + + /* System Font */ + Font systemFont; + + /* Font Enumeration */ + int nFonts = 256; + LOGFONT* [] logFonts; + TEXTMETRIC metrics; + int[] pixels; + + /* Scripts */ + SCRIPT_PROPERTIES*[] scripts; + + /* Advanced Graphics */ + ULONG_PTR gdipToken; + + bool disposed; + + /* + * 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; + + +/* +* TEMPORARY CODE. +*/ +static synchronized Device getDevice () { + if (DeviceFinder !is 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 this() { + 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 this(DeviceData data) { + synchronized (Device.classinfo) { + debug_ = DEBUG; + tracking = DEBUG; + if (data !is null) { + debug_ = data.debug_; + tracking = data.tracking; + } + if (tracking) { + errors = new Exception [128]; + objects = new Object [128]; + trackingLock = new Object (); + } + create (data); + init_ (); + gdipToken = 0; + } +} + +/** + * Throws anSWTException
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
+ * This method is called before init
.
+ *
+ * Subclasses are supposed to reimplement this method and not
+ * call the super
implementation.
+ *
+ * This method is called after release
.
+ *
+ * Subclasses are supposed to reimplement this method and not
+ * call the super
implementation.
+ *
true
when sent the message
+ * isDisposed()
.
+ *
+ * @see #release
+ * @see #destroy
+ * @see #checkDevice
+ */
+public void dispose () {
+ synchronized (Device.classinfo) {
+ if (isDisposed()) return;
+ checkDevice ();
+ release ();
+ destroy ();
+ disposed = true;
+ if (tracking) {
+ synchronized (trackingLock) {
+ printErrors ();
+ objects = null;
+ errors = null;
+ trackingLock = null;
+ }
+ }
+ }
+}
+
+void dispose_Object (Object object) {
+ synchronized (trackingLock) {
+ for (int i=0; iDeviceData
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 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 + * 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 SWTExceptiontrue
if the underlying window system prints out
+ * warning messages on the console, and setWarnings
+ * had previously been called with true
.
+ *
+ * @return true
if warnings are being handled, and false
otherwise
+ *
+ * @exception SWTException
+ * This method is called after create
.
+ *
+ * If subclasses reimplement this method, they must
+ * call the super
implementation.
+ *
+ * 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.
+ *
+ * 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.
+ *
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 bool isDisposed () {
+ synchronized (Device.classinfo) {
+ return disposed;
+ }
+}
+
+/**
+ * Loads the font specified by a file. The font will be
+ * present in the list of fonts available to the application.
+ *
+ * @param path the font file path
+ * @return whether the font was successfully loaded
+ *
+ * @exception SWTException
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.
+ *
false
prevents these
+ * messages from being printed. If the argument is true
then
+ * message printing is not blocked.
+ *
+ * @param warnings true
if warnings should be printed, and false
otherwise
+ *
+ * @exception SWTException 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 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. + *
+ * + * @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.
+ *
+ * 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.
+ *
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.
+ *
+ * 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 HFONT handle; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this(Device device) { + super(device); +} + +/** + * 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+ * 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 IllegalArgumentExceptiontrue
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+public int opEquals(Object object) {
+ if (object is this) return true;
+ if ( auto font = cast(Font)object ){
+ return device is font.device && handle is font.handle;
+ }
+ return false;
+}
+
+/**
+ * Returns an array of FontData
s 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 true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+override public hash_t toHash () {
+ return cast(hash_t)handle;
+}
+
+void init_ (FontData fd) {
+ if (fd is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ LOGFONT* logFont = &fd.data;
+ int lfHeight = logFont.lfHeight;
+ logFont.lfHeight = device.computePixels(fd.height);
+ handle = OS.CreateFontIndirect(logFont);
+ logFont.lfHeight = lfHeight;
+ if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * 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
+ */
+override public bool isDisposed() {
+ return handle is 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 "Font {*DISPOSED*}";
+ return Format( "Font {{{}}", handle );
+//
+// LOGFONT logFont;
+// OS.GetObject(handle, LOGFONT.sizeof, &logFont);
+// char[] name = .TCHARzToStr( logFont.lfFaceName.ptr, -1 );
+//
+// return Format( "Font {{{}, {}}", handle, name );
+}
+
+/**
+ * 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.
+ *
+ * For platform-independent behaviour, use the get and set methods + * corresponding to the following properties: + *
FontData
+ * corresponds to a Windows LOGFONT
structure whose fields
+ * may be retrieved and modified.FontData
correspond
+ * to the entries in the font's XLFD name and may be retrieved and modified.
+ * dispose()
method is provided.
+ *
+ * @see Font
+ * @see Sample code and further information
+ */
+
+public final class FontData {
+
+ /**
+ * A Win32 LOGFONT 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 LOGFONT data; + + /** + * The height of the font data in points + * (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 float height; + + /** + * The locales of the font + */ + String lang, country, variant; + + private static FontData s_this; + +/** + * Constructs a new uninitialized font data. + */ +public this() { + // We set the charset field so that + // wildcard searching will work properly + // out of the box + data.lfCharSet = cast(byte)OS.DEFAULT_CHARSET; + height = 12; +} + +/** + * Constructs a new font data given the WindowsLOGFONT
+ * that it should represent.
+ *
+ * @param data the LOGFONT
for the result
+ */
+this(LOGFONT* data, float height) {
+ this.data = *data;
+ this.height = height;
+}
+
+/**
+ * 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 aFontData
(must not be null)
+ *
+ * @exception IllegalArgumentException true
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+override public int opEquals (Object object) {
+ if (object is this) return true;
+ if( auto fd = cast(FontData)object ){
+ LOGFONT* lf = &fd.data;
+ return data.lfCharSet is lf.lfCharSet &&
+ /*
+ * This code is intentionally commented. When creating
+ * a FontData, lfHeight is not necessarily set. Instead
+ * we check the height field which is always set.
+ */
+ // data.lfHeight is lf.lfHeight &&
+ height is fd.height &&
+ data.lfWidth is lf.lfWidth &&
+ data.lfEscapement is lf.lfEscapement &&
+ data.lfOrientation is lf.lfOrientation &&
+ data.lfWeight is lf.lfWeight &&
+ data.lfItalic is lf.lfItalic &&
+ data.lfUnderline is lf.lfUnderline &&
+ data.lfStrikeOut is lf.lfStrikeOut &&
+ data.lfCharSet is lf.lfCharSet &&
+ data.lfOutPrecision is lf.lfOutPrecision &&
+ data.lfClipPrecision is lf.lfClipPrecision &&
+ data.lfQuality is lf.lfQuality &&
+ data.lfPitchAndFamily is lf.lfPitchAndFamily &&
+ getName() ==/*eq*/ fd.getName();
+ }
+ return false;
+}
+
+extern (Windows) static int EnumLocalesProc(TCHAR* lpLocaleString) {
+
+ /* Get the locale ID */
+ int length_ = 8;
+ String str = .TCHARzToStr( cast(TCHAR*)lpLocaleString, length_);
+ int lcid = Integer.parseInt(str, 16);
+
+ TCHAR[] buffer = new TCHAR[length_];
+
+ /* Check the language */
+ int size = OS.GetLocaleInfo(lcid, OS.LOCALE_SISO639LANGNAME, buffer.ptr, length_);
+ if (size <= 0 || s_this.lang !=/*eq*/ .TCHARzToStr( buffer.ptr ).substring(0, size - 1)) return 1;
+
+ /* Check the country */
+ if (s_this.country !is null) {
+ size = OS.GetLocaleInfo(lcid, OS.LOCALE_SISO3166CTRYNAME, buffer.ptr, length_);
+ if (size <= 0 || s_this.country !=/*eq*/ .TCHARzToStr( buffer.ptr ).substring(0, size - 1)) return 1;
+ }
+
+ /* Get the charset */
+ size = OS.GetLocaleInfo(lcid, OS.LOCALE_IDEFAULTANSICODEPAGE, buffer.ptr, length_);
+ if (size <= 0) return 1;
+ int cp = Integer.parseInt(.TCHARzToStr(buffer.ptr).substring(0, size - 1));
+ CHARSETINFO lpCs;
+ OS.TranslateCharsetInfo(cast(DWORD*)cp, &lpCs, OS.TCI_SRCCODEPAGE);
+ s_this.data.lfCharSet = cast(BYTE)lpCs.ciCharset;
+
+ return 0;
+}
+
+/**
+ * Returns the height of the receiver in points.
+ *
+ * @return the height of this FontData
+ *
+ * @see #setHeight(int)
+ */
+public int getHeight() {
+ return cast(int)(0.5f + height);
+}
+
+/*public*/ float getHeightF() {
+ 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 theString
representing a Locale object
+ * @since 3.0
+ */
+public String getLocale () {
+ StringBuffer buffer = new StringBuffer ();
+ char sep = '_';
+ if (lang !is null) {
+ buffer.append (lang);
+ buffer.append (sep);
+ }
+ if (country !is null) {
+ buffer.append (country);
+ buffer.append (sep);
+ }
+ if (variant !is null) {
+ buffer.append (variant);
+ }
+
+ String result = buffer.toString ();
+ int length_ = result.length;
+ if (length_ > 0) {
+ if (result.charAt (length_ - 1) is 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 .TCHARzToStr( data.lfFaceName.ptr, -1 );
+}
+
+/**
+ * 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() {
+ int style = SWT.NORMAL;
+ if (data.lfWeight is 700) style |= SWT.BOLD;
+ if (data.lfItalic !is 0) style |= SWT.ITALIC;
+ 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
+ */
+override public hash_t toHash () {
+ String name = getName();
+ return data.lfCharSet ^ getHeight() ^ data.lfWidth ^ data.lfEscapement ^
+ data.lfOrientation ^ data.lfWeight ^ data.lfItalic ^data.lfUnderline ^
+ data.lfStrikeOut ^ data.lfCharSet ^ data.lfOutPrecision ^
+ data.lfClipPrecision ^ data.lfQuality ^ data.lfPitchAndFamily ^
+ typeid(String).getHash(&name);
+}
+
+/**
+ * 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 + * 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 theString
representing a Locale object
+ * @see java.util.Locale#toString
+ */
+public void setLocale(String locale) {
+ lang = country = variant = null;
+ if (locale !is null) {
+ char sep = '_';
+ int length_ = locale.length;
+ int firstSep, secondSep;
+
+ firstSep = locale.indexOf(sep);
+ if (firstSep is -1) {
+ firstSep = secondSep = length_;
+ } else {
+ secondSep = locale.indexOf(sep, firstSep + 1);
+ if (secondSep is -1) secondSep = length_;
+ }
+ 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);
+ }
+ if (lang is null) {
+ data.lfCharSet = cast(byte)OS.DEFAULT_CHARSET;
+ } else {
+ synchronized(this.classinfo){
+ s_this = this;
+ OS.EnumSystemLocales(&EnumLocalesProc, OS.LCID_SUPPORTED);
+ s_this = null;
+ }
+ }
+}
+
+/**
+ * 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: + *
+ * On platforms that do not support font foundries, only the face name
+ * (for example, "courier") is used in setName()
and
+ * getName()
.
+ *
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) {
+ if ((style & SWT.BOLD) is SWT.BOLD) {
+ data.lfWeight = 700;
+ } else {
+ data.lfWeight = 0;
+ }
+ if ((style & SWT.ITALIC) is SWT.ITALIC) {
+ data.lfItalic = 1;
+ } else {
+ data.lfItalic = 0;
+ }
+}
+
+/**
+ * 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
+ */
+override public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("1|"); //$NON-NLS-1$
+ buffer.append(getName());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(getHeightF()));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(getStyle()));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append("WINDOWS|1|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfHeight));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfWidth));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfEscapement));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfOrientation));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfWeight));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfItalic));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfUnderline));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfStrikeOut));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfCharSet));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfOutPrecision));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfClipPrecision));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfQuality));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(to!(String)(data.lfPitchAndFamily));
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(getName());
+ 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.
+ *
LOGFONT
for the font data
+ * @param height the height of the font data
+ * @return a new font data object containing the specified LOGFONT
and height
+ */
+public static FontData win32_new(LOGFONT* data, float height) {
+ return new FontData(data, height);
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/FontMetrics.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/FontMetrics.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit FontMetrics
are obtained from GC
s
+ * using the getFontMetrics()
method.
+ *
+ * @see GC#getFontMetrics
+ * @see Sample code and further information
+ */
+
+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 TEXTMETRIC handle; + +/** + * Prevents instances from being created outside the package. + */ +this() { +} + +/** + * 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 + * @returntrue
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+override public int opEquals (Object object) {
+ if (object is this) return true;
+ if( auto metricObj = cast(FontMetrics)object ){
+ auto metric = metricObj.handle;
+ return handle.tmHeight is metric.tmHeight &&
+ handle.tmAscent is metric.tmAscent &&
+ handle.tmDescent is metric.tmDescent &&
+ handle.tmInternalLeading is metric.tmInternalLeading &&
+ handle.tmExternalLeading is metric.tmExternalLeading &&
+ handle.tmAveCharWidth is metric.tmAveCharWidth &&
+ handle.tmMaxCharWidth is metric.tmMaxCharWidth &&
+ handle.tmWeight is metric.tmWeight &&
+ handle.tmOverhang is metric.tmOverhang &&
+ handle.tmDigitizedAspectX is metric.tmDigitizedAspectX &&
+ handle.tmDigitizedAspectY is metric.tmDigitizedAspectY &&
+ // handle.tmFirstChar is metric.tmFirstChar &&
+ // handle.tmLastChar is metric.tmLastChar &&
+ // handle.tmDefaultChar is metric.tmDefaultChar &&
+ // handle.tmBreakChar is metric.tmBreakChar &&
+ handle.tmItalic is metric.tmItalic &&
+ handle.tmUnderlined is metric.tmUnderlined &&
+ handle.tmStruckOut is metric.tmStruckOut &&
+ handle.tmPitchAndFamily is metric.tmPitchAndFamily &&
+ handle.tmCharSet is metric.tmCharSet;
+ }
+ return false;
+}
+
+/**
+ * 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.tmAscent - handle.tmInternalLeading;
+}
+
+/**
+ * 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() {
+ return handle.tmAveCharWidth;
+}
+
+/**
+ * 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.tmDescent;
+}
+
+/**
+ * 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.tmHeight;
+}
+
+/**
+ * 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.tmInternalLeading;
+}
+
+/**
+ * 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 hash_t toHash() {
+ return handle.tmHeight ^ handle.tmAscent ^ handle.tmDescent ^
+ handle.tmInternalLeading ^ handle.tmExternalLeading ^
+ handle.tmAveCharWidth ^ handle.tmMaxCharWidth ^ handle.tmWeight ^
+ handle.tmOverhang ^ handle.tmDigitizedAspectX ^ handle.tmDigitizedAspectY ^
+// handle.tmFirstChar ^ handle.tmLastChar ^ handle.tmDefaultChar ^ handle.tmBreakChar ^
+ handle.tmItalic ^ handle.tmUnderlined ^ handle.tmStruckOut ^
+ handle.tmPitchAndFamily ^ handle.tmCharSet;
+}
+
+/**
+ * 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.
+ *
TEXTMETRIC
containing information about a font
+ * @return a new font metrics object containing the specified TEXTMETRIC
+ */
+public static FontMetrics win32_new(TEXTMETRIC* handle) {
+ FontMetrics fontMetrics = new FontMetrics();
+ fontMetrics.handle = *handle;
+ return fontMetrics;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GC.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GC.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,4932 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit 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
.
+ * + * 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 + * @see GC snippets + * @see SWT Examples: GraphicsExample, PaintExample + * @see Sample code and further information + */ + +public final class GC : Resource { + + alias Resource.init_ init_; + + /** + * 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 HDC handle; + + Drawable drawable; + GCData data; + + static const int FOREGROUND = 1 << 0; + static const int BACKGROUND = 1 << 1; + static const int FONT = 1 << 2; + static const int LINE_STYLE = 1 << 3; + static const int LINE_WIDTH = 1 << 4; + static const int LINE_CAP = 1 << 5; + static const int LINE_JOIN = 1 << 6; + static const int LINE_MITERLIMIT = 1 << 7; + static const int FOREGROUND_TEXT = 1 << 8; + static const int BACKGROUND_TEXT = 1 << 9; + static const int BRUSH = 1 << 10; + static const int PEN = 1 << 11; + static const int NULL_BRUSH = 1 << 12; + static const int NULL_PEN = 1 << 13; + static const int DRAW_OFFSET = 1 << 14; + + static const int DRAW = FOREGROUND | LINE_STYLE | LINE_WIDTH | LINE_CAP | LINE_JOIN | LINE_MITERLIMIT | PEN | NULL_BRUSH | DRAW_OFFSET; + static const int FILL = BACKGROUND | BRUSH | NULL_PEN; + + static const float[] LINE_DOT_ZERO = [3, 3]; + static const float[] LINE_DASH_ZERO = [18, 6]; + static const float[] LINE_DASHDOT_ZERO = [9, 6, 3, 6]; + static const float[] LINE_DASHDOTDOT_ZERO = [9, 3, 3, 3, 3, 3]; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this() { +} + +/** + * Constructs a new instance of this class which has been + * configured to draw on the specified drawable. Sets the + * foreground color, background color and font 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+ * 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 IllegalArgumentExceptionSWT.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 true
paint events will be generated for old and obscured areas
+ *
+ * @exception SWTException
+ * 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.
+ *
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
+ * 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.
+ *
+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param path the path to draw + * + * @exception IllegalArgumentExceptionx
, 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 SWTExceptionx
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 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 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 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 SWTException 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 SWTException 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:
+ *
true
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+public bool equals (Object object) {
+ return (object is this) || (null !is (cast(GC)object) && (handle is (cast(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.
+ *
+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param path the path to fill + * + * @exception IllegalArgumentException+ * 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 SWTExceptiontrue
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.
+ *
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 null
.
+ *
+ * @return the receiver's background pattern
+ *
+ * @exception SWTException + * 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 SWTExceptionSWT.FILL_EVEN_ODD
or SWT.FILL_WINDING
.
+ *
+ * @return the receiver's fill rule
+ *
+ * @exception SWTException null
.
+ *
+ * @return the receiver's foreground pattern
+ *
+ * @exception SWTException
+ * 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.
+ *
SWT.DEFAULT
, SWT.NONE
,
+ * SWT.LOW
or SWT.HIGH
.
+ *
+ * @return the receiver's interpolation setting
+ *
+ * @exception SWTException SWT.CAP_FLAT
, SWT.CAP_ROUND
,
+ * or SWT.CAP_SQUARE
.
+ *
+ * @return the cap style used for drawing lines
+ *
+ * @exception SWTException null
.
+ *
+ * @return the line dash style used for drawing lines
+ *
+ * @exception SWTException SWT.JOIN_MITER
, SWT.JOIN_ROUND
,
+ * or SWT.JOIN_BEVEL
.
+ *
+ * @return the join style used for drawing lines
+ *
+ * @exception SWTException 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 drawLine
, drawRectangle
,
+ * drawPolyline
, and so forth.
+ *
+ * @return the receiver's line width
+ *
+ * @exception SWTException + * 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 SWTExceptionSWT.DEFAULT
, SWT.OFF
or
+ * SWT.ON
. Note that this controls anti-aliasing
+ * only for text drawing operations.
+ *
+ * @return the anti-aliasing setting
+ *
+ * @exception SWTException 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 true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @exception SWTException 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 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
+ */
+override public bool isDisposed() {
+ return handle is null;
+}
+
+float measureSpace(Gdip.Font font, Gdip.StringFormat format) {
+ Gdip.PointF pt;
+ Gdip.RectF bounds;
+ Gdip.Graphics_MeasureString(data.gdipGraphics, (" "w).ptr, 1, font, pt, format, bounds);
+ return bounds.Width;
+}
+
+/**
+ * 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 SWTExceptionSWT.DEFAULT
, SWT.OFF
+ * or SWT.ON
. Note that this controls anti-aliasing for all
+ * non-text drawing operations.
+ * + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param antialias the anti-aliasing setting + * + * @exception IllegalArgumentExceptionSWT.DEFAULT
,
+ * SWT.OFF
or SWT.ON
+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * @param alpha the alpha value + * + * @exception SWTExceptionnull
.
+ * + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param pattern the new background pattern + * + * @exception IllegalArgumentException+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param path the clipping path. + * + * @exception IllegalArgumentExceptionnull
for the
+ * rectangle reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param rect the clipping rectangle or null
+ *
+ * @exception SWTException null
for the
+ * region reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param region the clipping region or null
+ *
+ * @exception IllegalArgumentException SWT.FILL_EVEN_ODD
or SWT.FILL_WINDING
.
+ *
+ * @param rule the new fill rule
+ *
+ * @exception IllegalArgumentException SWT.FILL_EVEN_ODD
+ * or SWT.FILL_WINDING
null
.
+ * + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * @param pattern the new foreground pattern + * + * @exception IllegalArgumentExceptionSWT.DEFAULT
, SWT.NONE
,
+ * SWT.LOW
or SWT.HIGH
.
+ * + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param interpolation the new interpolation setting + * + * @exception IllegalArgumentExceptionSWT.DEFAULT
,
+ * SWT.NONE
, SWT.LOW
or SWT.HIGH
+ * + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * @param attributes the line attributes + * + * @exception IllegalArgumentExceptionSWT.CAP_FLAT
, SWT.CAP_ROUND
,
+ * or SWT.CAP_SQUARE
.
+ *
+ * @param cap the cap style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException 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 SWT.JOIN_MITER
, SWT.JOIN_ROUND
,
+ * or SWT.JOIN_BEVEL
.
+ *
+ * @param join the join style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException 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 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 SWTExceptiontrue
, 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 iftrue
, then xor mode is used, otherwise source copy mode is used
+ *
+ * @exception SWTException SWT.DEFAULT
, SWT.OFF
+ * or SWT.ON
. Note that this controls anti-aliasing only
+ * for all text drawing operations.
+ * + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param antialias the anti-aliasing setting + * + * @exception IllegalArgumentExceptionSWT.DEFAULT
,
+ * SWT.OFF
or SWT.ON
null
, the current transform is set to
+ * the identity transform.
+ * + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param transform the transform to set + * + * @exception IllegalArgumentException+ * 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 SWTException+ * 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 SWTException+ * 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 specifying how to process the text + * @return a point containing the extent of the string + * + * @exception SWTException
+ * 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.
+ *
GC
+ */
+public static GC win32_new(Drawable drawable, GCData data) {
+ GC gc = new GC();
+ auto hDC = drawable.internal_new_GC(data);
+ gc.disposeChecking = false;
+ gc.device = data.device;
+ gc.init_(drawable, data, hDC);
+ 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.
+ *
GC
+ */
+public static GC win32_new(HDC hDC, GCData data) {
+ GC gc = new GC();
+ gc.disposeChecking = false;
+ gc.device = data.device;
+ data.style |= SWT.LEFT_TO_RIGHT;
+ if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+ int flags = OS.GetLayout (hDC);
+ if ((flags & OS.LAYOUT_RTL) !is 0) {
+ data.style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED;
+ }
+ }
+ gc.init_(null, data, hDC);
+ return gc;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GCData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GCData.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit + * 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. + *
+ * @see Sample code and further information + */ + +public final class GCData { + public Device device; + public int style, state = -1; + public int foreground = -1; + public int background = -1; + public Font font; + public Pattern foregroundPattern; + public Pattern backgroundPattern; + public int lineStyle = SWT.LINE_SOLID; + public float lineWidth; + public int lineCap = SWT.CAP_FLAT; + public int lineJoin = SWT.JOIN_MITER; + public float lineDashesOffset; + public float[] lineDashes; + public float lineMiterLimit = 10; + public int alpha = 0xFF; + + public Image image; + public HPEN hPen, hOldPen; + public HBRUSH hBrush, hOldBrush; + public HBITMAP hNullBitmap; + public HWND hwnd; + public PAINTSTRUCT* ps; + public int layout = -1; + public Gdip.Graphics gdipGraphics; + public Gdip.Pen gdipPen; + public Gdip.Brush gdipBrush; + public Gdip.SolidBrush gdipFgBrush; + public Gdip.SolidBrush gdipBgBrush; + public Gdip.Font gdipFont; + public float gdipXOffset, gdipYOffset; + public int uiState = 0; + public bool focusDrawn; +} + diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GlyphMetrics.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GlyphMetrics.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank Benoit+ * The hashCode() method in this class uses the values of the public + * fields to compute the hash value. When storing instances of the + * class in hashed collections, do not modify these fields after the + * object has been inserted. + *
+ *
+ * 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.
+ *
true
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals (Object object) {
+ if (object is this) return true;
+ if (auto metrics = cast(GlyphMetrics)object ){
+ return metrics.ascent == ascent && metrics.descent == descent && metrics.width == width;
+ }
+ 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 override hash_t toHash () {
+ return ascent ^ descent ^ width;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the GlyphMetrics
+ */
+public override String toString () {
+ return Format( "GlyphMetrics {{{}, {}, {}}", ascent, descent, width ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Image.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Image.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit 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.
+ *
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 HGDIOBJ handle; + + /** + * specifies the transparent pixel + */ + int transparentPixel = -1, transparentColor = -1; + + /** + * the GC which is drawing on the image + */ + GC memGC; + + /** + * the alpha data for the image + */ + byte[] alphaData; + + /** + * the global alpha value to be used for every pixel + */ + int alpha = -1; + + /** + * the image data used to create this image if it is a + * icon. Used only in WinCE + */ + ImageData data; + + /** + * width of the image + */ + int width = -1; + + /** + * height of the image + */ + int height = -1; + + /** + * specifies the default scanline padding + */ + static const int DEFAULT_SCANLINE_PAD = 4; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this (Device device) { + super(device); +} + +/** + * 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 IllegalArgumentExceptionIMAGE_COPY
, IMAGE_DISABLE
or IMAGE_GRAY
+ *
+ * @exception IllegalArgumentException IMAGE_COPY
, IMAGE_DISABLE
or IMAGE_GRAY
+ * 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 IllegalArgumentExceptionImageData
.
+ *
+ * @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 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
+ * 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 is 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
+ * 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
true
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+override public int opEquals (Object object) {
+ if (object is this) return true;
+ if (!(cast(Image)object)) return false;
+ Image image = cast(Image) object;
+ return device is image.device && handle is 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
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 true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+override public hash_t toHash () {
+ return cast(hash_t)handle;
+}
+
+void init_(int width, int height) {
+ if (width <= 0 || height <= 0) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ type = SWT.BITMAP;
+ auto hDC = device.internal_new_GC(null);
+ handle = OS.CreateCompatibleBitmap(hDC, width, height);
+ /*
+ * Feature in Windows. CreateCompatibleBitmap() may fail
+ * for large images. The fix is to create a DIB section
+ * in that case.
+ */
+ if (handle is null) {
+ int bits = OS.GetDeviceCaps(hDC, OS.BITSPIXEL);
+ int planes = OS.GetDeviceCaps(hDC, OS.PLANES);
+ int depth = bits * planes;
+ if (depth < 16) depth = 16;
+ handle = createDIB(width, height, depth);
+ }
+ if (handle !is null) {
+ auto memDC = OS.CreateCompatibleDC(hDC);
+ auto hOldBitmap = OS.SelectObject(memDC, handle);
+ OS.PatBlt(memDC, 0, 0, width, height, OS.PATCOPY);
+ OS.SelectObject(memDC, hOldBitmap);
+ OS.DeleteDC(memDC);
+ }
+ device.internal_dispose_GC(hDC, null);
+ if (handle is null) {
+ SWT.error(SWT.ERROR_NO_HANDLES, null, device.getLastError());
+ }
+}
+
+static HGDIOBJ createDIB(int width, int height, int depth) {
+ BITMAPINFOHEADER bmiHeader;
+ bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+ bmiHeader.biWidth = width;
+ bmiHeader.biHeight = -height;
+ bmiHeader.biPlanes = 1;
+ bmiHeader.biBitCount = cast(short)depth;
+ static 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.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+ /* Set the rgb colors into the bitmap info */
+ static if (OS.IsWinCE) {
+ int redMask = 0xFF00;
+ int greenMask = 0xFF0000;
+ int blueMask = 0xFF000000;
+ /* big endian */
+ int offset = BITMAPINFOHEADER.sizeof;
+ bmi[offset] = cast(byte)((redMask & 0xFF000000) >> 24);
+ bmi[offset + 1] = cast(byte)((redMask & 0xFF0000) >> 16);
+ bmi[offset + 2] = cast(byte)((redMask & 0xFF00) >> 8);
+ bmi[offset + 3] = cast(byte)((redMask & 0xFF) >> 0);
+ bmi[offset + 4] = cast(byte)((greenMask & 0xFF000000) >> 24);
+ bmi[offset + 5] = cast(byte)((greenMask & 0xFF0000) >> 16);
+ bmi[offset + 6] = cast(byte)((greenMask & 0xFF00) >> 8);
+ bmi[offset + 7] = cast(byte)((greenMask & 0xFF) >> 0);
+ bmi[offset + 8] = cast(byte)((blueMask & 0xFF000000) >> 24);
+ bmi[offset + 9] = cast(byte)((blueMask & 0xFF0000) >> 16);
+ bmi[offset + 10] = cast(byte)((blueMask & 0xFF00) >> 8);
+ bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0);
+ }
+
+ void* pBits;
+ return OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+}
+
+/**
+ * Feature in WinCE. GetIconInfo is not available in WinCE.
+ * The workaround is to cache the object ImageData for images
+ * of type SWT.ICON. The bitmaps hbmMask and hbmColor can then
+ * be reconstructed by using our version of getIconInfo.
+ * This function takes an ICONINFO object and sets the fields
+ * hbmMask and hbmColor with the corresponding bitmaps it has
+ * created.
+ * Note. These bitmaps must be freed - as they would have to be
+ * if the regular GetIconInfo had been used.
+ */
+static void GetIconInfo(Image image, ICONINFO* info) {
+ int[] result = init_(image.device, null, image.data);
+ info.hbmColor = cast(HBITMAP)result[0];
+ info.hbmMask = cast(HBITMAP)result[1];
+}
+
+static int[] init_(Device device, Image image, ImageData i) {
+
+ /*
+ * 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 ((OS.IsWin95 && i.depth is 1 && i.getTransparencyType() !is SWT.TRANSPARENCY_MASK) || i.depth is 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 is 0x7C00 && greenMask is 0x3E0 && blueMask is 0x1F)) {
+ newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+ }
+ break;
+ case 24:
+ if (!(redMask is 0xFF && greenMask is 0xFF00 && blueMask is 0xFF0000)) {
+ newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+ }
+ break;
+ case 32:
+ if (!(redMask is 0xFF00 && greenMask is 0xFF0000 && blueMask is 0xFF000000)) {
+ newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+ }
+ break;
+ default:
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+ }
+ if (newPalette !is 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 !is -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();
+ bool useBitfields = OS.IsWinCE && (i.depth is 16 || i.depth is 32);
+ BITMAPINFOHEADER bmiHeader;
+ bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+ bmiHeader.biWidth = i.width;
+ bmiHeader.biHeight = -i.height;
+ bmiHeader.biPlanes = 1;
+ bmiHeader.biBitCount = cast(short)i.depth;
+ if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS;
+ else bmiHeader.biCompression = OS.BI_RGB;
+ bmiHeader.biClrUsed = rgbs is 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.ptr, &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() is ImageData.LSB_FIRST) {
+ bmi[offset] = cast(byte)((redMask & 0xFF) >> 0);
+ bmi[offset + 1] = cast(byte)((redMask & 0xFF00) >> 8);
+ bmi[offset + 2] = cast(byte)((redMask & 0xFF0000) >> 16);
+ bmi[offset + 3] = cast(byte)((redMask & 0xFF000000) >> 24);
+ bmi[offset + 4] = cast(byte)((greenMask & 0xFF) >> 0);
+ bmi[offset + 5] = cast(byte)((greenMask & 0xFF00) >> 8);
+ bmi[offset + 6] = cast(byte)((greenMask & 0xFF0000) >> 16);
+ bmi[offset + 7] = cast(byte)((greenMask & 0xFF000000) >> 24);
+ bmi[offset + 8] = cast(byte)((blueMask & 0xFF) >> 0);
+ bmi[offset + 9] = cast(byte)((blueMask & 0xFF00) >> 8);
+ bmi[offset + 10] = cast(byte)((blueMask & 0xFF0000) >> 16);
+ bmi[offset + 11] = cast(byte)((blueMask & 0xFF000000) >> 24);
+ } else {
+ bmi[offset] = cast(byte)((redMask & 0xFF000000) >> 24);
+ bmi[offset + 1] = cast(byte)((redMask & 0xFF0000) >> 16);
+ bmi[offset + 2] = cast(byte)((redMask & 0xFF00) >> 8);
+ bmi[offset + 3] = cast(byte)((redMask & 0xFF) >> 0);
+ bmi[offset + 4] = cast(byte)((greenMask & 0xFF000000) >> 24);
+ bmi[offset + 5] = cast(byte)((greenMask & 0xFF0000) >> 16);
+ bmi[offset + 6] = cast(byte)((greenMask & 0xFF00) >> 8);
+ bmi[offset + 7] = cast(byte)((greenMask & 0xFF) >> 0);
+ bmi[offset + 8] = cast(byte)((blueMask & 0xFF000000) >> 24);
+ bmi[offset + 9] = cast(byte)((blueMask & 0xFF0000) >> 16);
+ bmi[offset + 10] = cast(byte)((blueMask & 0xFF00) >> 8);
+ bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0);
+ }
+ }
+ } else {
+ for (int j = 0; j < rgbs.length; j++) {
+ bmi[offset] = cast(byte)rgbs[j].blue;
+ bmi[offset + 1] = cast(byte)rgbs[j].green;
+ bmi[offset + 2] = cast(byte)rgbs[j].red;
+ bmi[offset + 3] = 0;
+ offset += 4;
+ }
+ }
+ void* pBits;
+ auto hDib = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+ if (hDib is null) 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 !is 4 && (i.bytesPerLine % 4 !is 0)) {
+ data = ImageData.convertPad(data, i.width, i.height, i.depth, i.scanlinePad, 4);
+ }
+ OS.MoveMemory(pBits, data.ptr, data.length);
+
+ int /*long*/ [] result = null;
+ if (i.getTransparencyType() is SWT.TRANSPARENCY_MASK) {
+ /* Get the HDC for the device */
+ auto hDC = device.internal_new_GC(null);
+
+ /* Create the color bitmap */
+ auto hdcSrc = OS.CreateCompatibleDC(hDC);
+ OS.SelectObject(hdcSrc, hDib);
+ auto hBitmap = OS.CreateCompatibleBitmap(hDC, i.width, i.height);
+ if (hBitmap is null) SWT.error(SWT.ERROR_NO_HANDLES);
+ auto 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);
+ auto hMask = OS.CreateBitmap(i.width, i.height, 1, 1, maskData.ptr);
+ if (hMask is null) 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 is null) {
+ result = [ cast(int) hBitmap, cast(int) hMask];
+ } else {
+ /* Create the icon */
+ ICONINFO info;
+ info.fIcon = true;
+ info.hbmColor = hBitmap;
+ info.hbmMask = hMask;
+ auto hIcon = OS.CreateIconIndirect(&info);
+ if (hIcon is null) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.DeleteObject(hBitmap);
+ OS.DeleteObject(hMask);
+ image.handle = hIcon;
+ image.type = SWT.ICON;
+ static if (OS.IsWinCE) image.data = i;
+ }
+ } else {
+ if (image is null) {
+ result = [ cast(int) hDib];
+ } else {
+ image.handle = hDib;
+ image.type = SWT.BITMAP;
+ image.transparentPixel = i.transparentPixel;
+ if (image.transparentPixel is -1) {
+ image.alpha = i.alpha;
+ if (i.alpha is -1 && i.alphaData !is null) {
+ int length = i.alphaData.length;
+ image.alphaData = new byte[length];
+ System.arraycopy(i.alphaData, 0, image.alphaData, 0, length);
+ }
+ }
+ }
+ }
+ return result;
+}
+
+static int[] 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 !is -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] ==/*eq*/ black) break;
+ blackIndex++;
+ }
+ if (blackIndex is 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 is -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] is 0) imagePixels[i] = blackIndex;
+ }
+ imageData.setPixels(0, y, source.width, imagePixels, 0);
+ }
+ }
+ imageData.maskPad = mask.scanlinePad;
+ imageData.maskData = mask.data;
+ return init_(device, image, imageData);
+}
+void init_(ImageData i) {
+ if (i is 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.
+ *
+ * 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.
+ *
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 bool isDisposed() {
+ return handle is 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
+ * 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.
+ *
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 win32_new(Device device, int type, HGDIOBJ handle) {
+ Image image = new Image(device);
+ image.disposeChecking = false;
+ image.type = type;
+ image.handle = handle;
+ return image;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageData.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,3676 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Image
.
+ *
+ * Note that the public fields x
, y
,
+ * disposalMethod
and delayTime
are
+ * typically only used when the image is in a set of images used
+ * for animation.
+ *
+ * Note that a depth of 8 or less does not necessarily + * mean that the image is palette indexed, or + * conversely that a depth greater than 8 means that + * the image is direct color. Check the associated + * PaletteData's isDirect field for such determinations. + */ + public int depth; + + /** + * The scanline padding. + *
+ * If one scanline of the image is not a multiple of + * this number, it will be padded with zeros until it is. + *
+ */ + public int scanlinePad; + + /** + * The number of bytes per scanline. + *+ * This is a multiple of the scanline padding. + *
+ */ + public int bytesPerLine; + + /** + * The pixel data of the image. + *+ * Note that for 16 bit depth images the pixel data is stored + * in least significant byte order; however, for 24bit and + * 32bit depth images the pixel data is stored in most + * significant byte order. + *
+ */ + public byte[] data; + + /** + * The color table for the image. + */ + public PaletteData palette; + + /** + * The transparent pixel. + *+ * Pixels with this value are transparent. + *
+ * The default is -1 which means 'no transparent pixel'. + *
+ */ + public int transparentPixel; + + /** + * An icon-specific field containing the data from the icon mask. + *+ * This is a 1 bit bitmap stored with the most significant + * bit first. The number of bytes per scanline is + * '((width + 7) / 8 + (maskPad - 1)) / maskPad * maskPad'. + *
+ * The default is null which means 'no transparency mask'. + *
+ */ + public byte[] maskData; + + /** + * An icon-specific field containing the scanline pad of the mask. + *+ * If one scanline of the transparency mask is not a + * multiple of this number, it will be padded with zeros until + * it is. + *
+ */ + public int maskPad; + + /** + * The alpha data of the image. + *+ * Every pixel can have an alpha blending value that + * varies from 0, meaning fully transparent, to 255 meaning + * fully opaque. The number of bytes per scanline is + * 'width'. + *
+ */ + public byte[] alphaData; + + /** + * The global alpha value to be used for every pixel. + *
+ * If this value is set, the alphaData
field
+ * is ignored and when the image is rendered each pixel
+ * will be blended with the background an amount
+ * proportional to this value.
+ *
+ * The default is -1 which means 'no global alpha value' + *
+ */ + public int alpha; + + /** + * The type of file from which the image was read. + * + * It is expressed as one of the following values: + *IMAGE_BMP
IMAGE_BMP_RLE
IMAGE_GIF
IMAGE_ICO
IMAGE_JPEG
IMAGE_PNG
DM_UNSPECIFIED
DM_FILL_NONE
DM_FILL_BACKGROUND
DM_FILL_PREVIOUS
ImageData
loaded from the specified
+ * input stream. Throws an error if an error occurs while loading
+ * the image, or if the image has 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 ImageData loadImageData (Class clazz, String string) { + * InputStream stream = clazz.getResourceAsStream (string); + * if (stream is null) return null; + * ImageData imageData = null; + * try { + * imageData = new ImageData (stream); + * } catch (SWTException ex) { + * } finally { + * try { + * stream.close (); + * } catch (IOException ex) {} + * } + * return imageData; + * } + *+ * + * @param stream the input stream to load the image from (must not be null) + * + * @exception IllegalArgumentException
ImageData
loaded from a file with the
+ * specified name. Throws an error if an error occurs loading the
+ * image, or if the image has an unsupported type.
+ *
+ * This constructor is provided for convenience when loading a single
+ * image only. If the file contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * ImageLoader.load()
.
+ *
+ * This method is for internal use, and is not described further. + *
+ */ +this( + int width, int height, int depth, PaletteData palette, + int scanlinePad, byte[] data, int maskPad, byte[] maskData, + byte[] alphaData, int alpha, int transparentPixel, int type, + int x, int y, int disposalMethod, int delayTime) +{ + if (palette is null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (!(depth is 1 || depth is 2 || depth is 4 || depth is 8 + || depth is 16 || depth is 24 || depth is 32)) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + if (width <= 0 || height <= 0) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + if (scanlinePad is 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO); + + int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) + / scanlinePad * scanlinePad; + + /* + * When the image is being loaded from a PNG, we need to use the theoretical minimum + * number of bytes per line to check whether there is enough data, because the actual + * number of bytes per line is calculated based on the given depth, which may be larger + * than the actual depth of the PNG. + */ + int minBytesPerLine = type is SWT.IMAGE_PNG ? ((((width + 7) / 8) + 3) / 4) * 4 : bytesPerLine; + if (data !is null && data.length < minBytesPerLine * height) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + setAllFields( + width, + height, + depth, + scanlinePad, + bytesPerLine, + data !is null ? data : new byte[bytesPerLine * height], + palette, + transparentPixel, + maskData, + maskPad, + alphaData, + alpha, + type, + x, + y, + disposalMethod, + delayTime); +} + +/** + * Initializes all fields in the receiver. This method must be called + * by all public constructors to ensure that all fields are initialized + * for a new ImageData object. If a new field is added to the class, + * then it must be added to this method. + *+ * This method is for internal use, and is not described further. + *
+ */ +void setAllFields(int width, int height, int depth, int scanlinePad, + int bytesPerLine, byte[] data, PaletteData palette, int transparentPixel, + byte[] maskData, int maskPad, byte[] alphaData, int alpha, + int type, int x, int y, int disposalMethod, int delayTime) { + + this.width = width; + this.height = height; + this.depth = depth; + this.scanlinePad = scanlinePad; + this.bytesPerLine = bytesPerLine; + this.data = data; + this.palette = palette; + this.transparentPixel = transparentPixel; + this.maskData = maskData; + this.maskPad = maskPad; + this.alphaData = alphaData; + this.alpha = alpha; + this.type = type; + this.x = x; + this.y = y; + this.disposalMethod = disposalMethod; + this.delayTime = delayTime; +} + +/** + * Invokes internal SWT functionality to create a new instance of + * this class. + *
+ * IMPORTANT: This method is not part of the public
+ * API for ImageData
. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is subject
+ * to change without notice, and should never be called from
+ * application code.
+ *
+ * This method is for internal use, and is not described further. + *
+ */ +public static ImageData internal_new( + int width, int height, int depth, PaletteData palette, + int scanlinePad, byte[] data, int maskPad, byte[] maskData, + byte[] alphaData, int alpha, int transparentPixel, int type, + int x, int y, int disposalMethod, int delayTime) +{ + return new ImageData( + width, height, depth, palette, scanlinePad, data, maskPad, maskData, + alphaData, alpha, transparentPixel, type, x, y, disposalMethod, delayTime); +} + +ImageData colorMaskImage(int pixel) { + ImageData mask = new ImageData(width, height, 1, bwPalette(), + 2, null, 0, null, null, -1, -1, SWT.IMAGE_UNDEFINED, + 0, 0, 0, 0); + int[] row = new int[width]; + for (int y = 0; y < height; y++) { + getPixels(0, y, width, row, 0); + for (int i = 0; i < width; i++) { + if (pixel !is -1 && row[i] is pixel) { + row[i] = 0; + } else { + row[i] = 1; + } + } + mask.setPixels(0, y, width, row, 0); + } + return mask; +} + +static byte[] checkData(byte [] data) { + if (data is null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + return data; +} + +/** + * Returns a new instance of the same class as the receiver, + * whose slots have been filled in with copies of + * the values in the slots of the receiver. That is, the + * returned object is a deep copy of the receiver. + * + * @return a copy of the receiver. + */ +public Object clone() { + byte[] cloneData = new byte[data.length]; + System.arraycopy(data, 0, cloneData, 0, data.length); + byte[] cloneMaskData = null; + if (maskData !is null) { + cloneMaskData = new byte[maskData.length]; + System.arraycopy(maskData, 0, cloneMaskData, 0, maskData.length); + } + byte[] cloneAlphaData = null; + if (alphaData !is null) { + cloneAlphaData = new byte[alphaData.length]; + System.arraycopy(alphaData, 0, cloneAlphaData, 0, alphaData.length); + } + return new ImageData( + width, + height, + depth, + palette, + scanlinePad, + cloneData, + maskPad, + cloneMaskData, + cloneAlphaData, + alpha, + transparentPixel, + type, + x, + y, + disposalMethod, + delayTime); +} + +/** + * Returns the alpha value at offsetx
in
+ * scanline y
in the receiver's alpha data.
+ * The alpha value is between 0 (transparent) and
+ * 255 (opaque).
+ *
+ * @param x the x coordinate of the pixel to get the alpha value of
+ * @param y the y coordinate of the pixel to get the alpha value of
+ * @return the alpha value at the given coordinates
+ *
+ * @exception IllegalArgumentException getWidth
alpha values starting at offset
+ * x
in scanline y
in the receiver's alpha
+ * data starting at startIndex
. The alpha values
+ * are unsigned, between (byte)0
(transparent) and
+ * (byte)255
(opaque).
+ *
+ * @param x the x position of the pixel to begin getting alpha values
+ * @param y the y position of the pixel to begin getting alpha values
+ * @param getWidth the width of the data to get
+ * @param alphas the buffer in which to put the alpha values
+ * @param startIndex the offset into the image to begin getting alpha values
+ *
+ * @exception IndexOutOfBoundsException if getWidth is too large
+ * @exception IllegalArgumentException x
in
+ * scanline y
in the receiver's data.
+ *
+ * @param x the x position of the pixel to get
+ * @param y the y position of the pixel to get
+ * @return the pixel at the given coordinates
+ *
+ * @exception IllegalArgumentException getWidth
pixel values starting at offset
+ * x
in scanline y
in the receiver's
+ * data starting at startIndex
.
+ *
+ * @param x the x position of the first pixel to get
+ * @param y the y position of the first pixel to get
+ * @param getWidth the width of the data to get
+ * @param pixels the buffer in which to put the pixels
+ * @param startIndex the offset into the byte array to begin storing pixels
+ *
+ * @exception IndexOutOfBoundsException if getWidth is too large
+ * @exception IllegalArgumentException getWidth
pixel values starting at offset
+ * x
in scanline y
in the receiver's
+ * data starting at startIndex
.
+ *
+ * @param x the x position of the first pixel to get
+ * @param y the y position of the first pixel to get
+ * @param getWidth the width of the data to get
+ * @param pixels the buffer in which to put the pixels
+ * @param startIndex the offset into the buffer to begin storing pixels
+ *
+ * @exception IndexOutOfBoundsException if getWidth is too large
+ * @exception IllegalArgumentException RGB
s which comprise the
+ * indexed color table of the receiver, or null if the receiver
+ * has a direct color model.
+ *
+ * @return the RGB values for the image or null if direct color
+ *
+ * @see PaletteData#getRGBs()
+ */
+public RGB[] getRGBs() {
+ return palette.getRGBs();
+}
+
+/**
+ * Returns an ImageData
which specifies the
+ * transparency mask information for the receiver. If the
+ * receiver has no transparency or is not an icon, returns
+ * an opaque mask.
+ *
+ * @return the transparency mask
+ */
+public ImageData getTransparencyMask() {
+ if (getTransparencyType() is SWT.TRANSPARENCY_MASK) {
+ return new ImageData(width, height, 1, bwPalette(), maskPad, maskData);
+ } else {
+ return colorMaskImage(transparentPixel);
+ }
+}
+
+/**
+ * Returns the image transparency type, which will be one of
+ * SWT.TRANSPARENCY_NONE
, SWT.TRANSPARENCY_MASK
,
+ * SWT.TRANSPARENCY_PIXEL
or SWT.TRANSPARENCY_ALPHA
.
+ *
+ * @return the receiver's transparency type
+ */
+public int getTransparencyType() {
+ if (maskData !is null) return SWT.TRANSPARENCY_MASK;
+ if (transparentPixel !is -1) return SWT.TRANSPARENCY_PIXEL;
+ if (alphaData !is null) return SWT.TRANSPARENCY_ALPHA;
+ return SWT.TRANSPARENCY_NONE;
+}
+
+/**
+ * Returns the byte order of the receiver.
+ *
+ * @return MSB_FIRST or LSB_FIRST
+ */
+int getByteOrder() {
+ return depth !is 16 ? MSB_FIRST : LSB_FIRST;
+}
+
+/**
+ * Returns a copy of the receiver which has been stretched or
+ * shrunk to the specified size. If either the width or height
+ * is negative, the resulting image will be inverted in the
+ * associated axis.
+ *
+ * @param width the width of the new ImageData
+ * @param height the height of the new ImageData
+ * @return a scaled copy of the image
+ */
+public ImageData scaledTo(int width, int height) {
+ /* Create a destination image with no data */
+ bool flipX = (width < 0);
+ if (flipX) width = - width;
+ bool flipY = (height < 0);
+ if (flipY) height = - height;
+
+ ImageData dest = new ImageData(
+ width, height, depth, palette,
+ scanlinePad, null, 0, null,
+ null, -1, transparentPixel, type,
+ x, y, disposalMethod, delayTime);
+
+ /* Scale the image contents */
+ if (palette.isDirect) blit(BLIT_SRC,
+ this.data, this.depth, this.bytesPerLine, this.getByteOrder(), 0, 0, this.width, this.height, 0, 0, 0,
+ ALPHA_OPAQUE, null, 0, 0, 0,
+ dest.data, dest.depth, dest.bytesPerLine, dest.getByteOrder(), 0, 0, dest.width, dest.height, 0, 0, 0,
+ flipX, flipY);
+ else blit(BLIT_SRC,
+ this.data, this.depth, this.bytesPerLine, this.getByteOrder(), 0, 0, this.width, this.height, null, null, null,
+ ALPHA_OPAQUE, null, 0, 0, 0,
+ dest.data, dest.depth, dest.bytesPerLine, dest.getByteOrder(), 0, 0, dest.width, dest.height, null, null, null,
+ flipX, flipY);
+
+ /* Scale the image mask or alpha */
+ if (maskData !is null) {
+ dest.maskPad = this.maskPad;
+ int destBpl = (dest.width + 7) / 8;
+ destBpl = (destBpl + (dest.maskPad - 1)) / dest.maskPad * dest.maskPad;
+ dest.maskData = new byte[destBpl * dest.height];
+ int srcBpl = (this.width + 7) / 8;
+ srcBpl = (srcBpl + (this.maskPad - 1)) / this.maskPad * this.maskPad;
+ blit(BLIT_SRC,
+ this.maskData, 1, srcBpl, MSB_FIRST, 0, 0, this.width, this.height, null, null, null,
+ ALPHA_OPAQUE, null, 0, 0, 0,
+ dest.maskData, 1, destBpl, MSB_FIRST, 0, 0, dest.width, dest.height, null, null, null,
+ flipX, flipY);
+ } else if (alpha !is -1) {
+ dest.alpha = this.alpha;
+ } else if (alphaData !is null) {
+ dest.alphaData = new byte[dest.width * dest.height];
+ blit(BLIT_SRC,
+ this.alphaData, 8, this.width, MSB_FIRST, 0, 0, this.width, this.height, null, null, null,
+ ALPHA_OPAQUE, null, 0, 0, 0,
+ dest.alphaData, 8, dest.width, MSB_FIRST, 0, 0, dest.width, dest.height, null, null, null,
+ flipX, flipY);
+ }
+ return dest;
+}
+
+/**
+ * Sets the alpha value at offset x
in
+ * scanline y
in the receiver's alpha data.
+ * The alpha value must be between 0 (transparent)
+ * and 255 (opaque).
+ *
+ * @param x the x coordinate of the alpha value to set
+ * @param y the y coordinate of the alpha value to set
+ * @param alpha the value to set the alpha to
+ *
+ * @exception IllegalArgumentException x
in
+ * scanline y
in the receiver's alpha data to the
+ * values from the array alphas
starting at
+ * startIndex
. The alpha values must be between
+ * (byte)0
(transparent) and (byte)255
(opaque)
+ *
+ * @param x the x coordinate of the pixel to being setting the alpha values
+ * @param y the y coordinate of the pixel to being setting the alpha values
+ * @param putWidth the width of the alpha values to set
+ * @param alphas the alpha values to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IndexOutOfBoundsException if putWidth is too large
+ * @exception IllegalArgumentException x
in
+ * scanline y
in the receiver's data.
+ *
+ * @param x the x coordinate of the pixel to set
+ * @param y the y coordinate of the pixel to set
+ * @param pixelValue the value to set the pixel to
+ *
+ * @exception IllegalArgumentException x
in
+ * scanline y
in the receiver's data to the
+ * values from the array pixels
starting at
+ * startIndex
.
+ *
+ * @param x the x position of the pixel to set
+ * @param y the y position of the pixel to set
+ * @param putWidth the width of the pixels to set
+ * @param pixels the pixels to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IndexOutOfBoundsException if putWidth is too large
+ * @exception IllegalArgumentException x
in
+ * scanline y
in the receiver's data to the
+ * values from the array pixels
starting at
+ * startIndex
.
+ *
+ * @param x the x position of the pixel to set
+ * @param y the y position of the pixel to set
+ * @param putWidth the width of the pixels to set
+ * @param pixels the pixels to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IndexOutOfBoundsException if putWidth is too large
+ * @exception IllegalArgumentException + * Note: When the source and destination depth, order and masks + * are pairwise equal and the blitter operation is BLIT_SRC, + * the masks are ignored. Hence when not changing the image + * data format, 0 may be specified for the masks. + *
+ * + * @param op the blitter operation: a combination of BLIT_xxx flags + * (see BLIT_xxx constants) + * @param srcData the source byte array containing image data + * @param srcDepth the source depth: one of 8, 16, 24, 32 + * @param srcStride the source number of bytes per line + * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST; + * ignored if srcDepth is not 16 or 32 + * @param srcX the top-left x-coord of the source blit region + * @param srcY the top-left y-coord of the source blit region + * @param srcWidth the width of the source blit region + * @param srcHeight the height of the source blit region + * @param srcRedMask the source red channel mask + * @param srcGreenMask the source green channel mask + * @param srcBlueMask the source blue channel mask + * @param alphaMode the alpha blending or mask mode, may be + * an integer 0-255 for global alpha; ignored if BLIT_ALPHA + * not specified in the blitter operations + * (see ALPHA_MODE_xxx constants) + * @param alphaData the alpha blending or mask data, varies depending + * on the value of alphaMode and sometimes ignored + * @param alphaStride the alpha data number of bytes per line + * @param alphaX the top-left x-coord of the alpha blit region + * @param alphaY the top-left y-coord of the alpha blit region + * @param destData the destination byte array containing image data + * @param destDepth the destination depth: one of 8, 16, 24, 32 + * @param destStride the destination number of bytes per line + * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST; + * ignored if destDepth is not 16 or 32 + * @param destX the top-left x-coord of the destination blit region + * @param destY the top-left y-coord of the destination blit region + * @param destWidth the width of the destination blit region + * @param destHeight the height of the destination blit region + * @param destRedMask the destination red channel mask + * @param destGreenMask the destination green channel mask + * @param destBlueMask the destination blue channel mask + * @param flipX if true the resulting image is flipped along the vertical axis + * @param flipY if true the resulting image is flipped along the horizontal axis + */ +static void blit(int op, + byte[] srcData, int srcDepth, int srcStride, int srcOrder, + int srcX, int srcY, int srcWidth, int srcHeight, + int srcRedMask, int srcGreenMask, int srcBlueMask, + int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY, + byte[] destData, int destDepth, int destStride, int destOrder, + int destX, int destY, int destWidth, int destHeight, + int destRedMask, int destGreenMask, int destBlueMask, + bool flipX, bool flipY) { + + static_this(); + + if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; + + // these should be supplied as params later + const int srcAlphaMask = 0, destAlphaMask = 0; + + /*** Prepare scaling data ***/ + int dwm1 = destWidth - 1; + int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0; + int dhm1 = destHeight - 1; + int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0; + + /*** Prepare source-related data ***/ + int sbpp, stype; + switch (srcDepth) { + case 8: + sbpp = 1; + stype = TYPE_GENERIC_8; + break; + case 16: + sbpp = 2; + stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB; + break; + case 24: + sbpp = 3; + stype = TYPE_GENERIC_24; + break; + case 32: + sbpp = 4; + stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; + break; + default: + //throw new IllegalArgumentException("Invalid source type"); + return; + } + int spr = srcY * srcStride + srcX * sbpp; + + /*** Prepare destination-related data ***/ + int dbpp, dtype; + switch (destDepth) { + case 8: + dbpp = 1; + dtype = TYPE_GENERIC_8; + break; + case 16: + dbpp = 2; + dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB; + break; + case 24: + dbpp = 3; + dtype = TYPE_GENERIC_24; + break; + case 32: + dbpp = 4; + dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; + break; + default: + //throw new IllegalArgumentException("Invalid destination type"); + return; + } + int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp; + int dprxi = (flipX) ? -dbpp : dbpp; + int dpryi = (flipY) ? -destStride : destStride; + + /*** Prepare special processing data ***/ + int apr; + if ((op & BLIT_ALPHA) !is 0) { + switch (alphaMode) { + case ALPHA_MASK_UNPACKED: + case ALPHA_CHANNEL_SEPARATE: + if (alphaData is null) alphaMode = 0x10000; + apr = alphaY * alphaStride + alphaX; + break; + case ALPHA_MASK_PACKED: + if (alphaData is null) alphaMode = 0x10000; + alphaStride <<= 3; + apr = alphaY * alphaStride + alphaX; + break; + case ALPHA_MASK_INDEX: + //throw new IllegalArgumentException("Invalid alpha type"); + return; + case ALPHA_MASK_RGB: + if (alphaData is null) alphaMode = 0x10000; + apr = 0; + break; + default: + alphaMode = (alphaMode << 16) / 255; // prescale + case ALPHA_CHANNEL_SOURCE: + apr = 0; + break; + } + } else { + alphaMode = 0x10000; + apr = 0; + } + + /*** Blit ***/ + int dp = dpr; + int sp = spr; + if ((alphaMode is 0x10000) && (stype is dtype) && + (srcRedMask is destRedMask) && (srcGreenMask is destGreenMask) && + (srcBlueMask is destBlueMask) && (srcAlphaMask is destAlphaMask)) { + /*** Fast blit (straight copy) ***/ + switch (sbpp) { + case 1: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + destData[dp] = srcData[sp]; + sp += (sfx >>> 16); + } + } + break; + case 2: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + destData[dp] = srcData[sp]; + destData[dp + 1] = srcData[sp + 1]; + sp += (sfx >>> 16) * 2; + } + } + break; + case 3: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + destData[dp] = srcData[sp]; + destData[dp + 1] = srcData[sp + 1]; + destData[dp + 2] = srcData[sp + 2]; + sp += (sfx >>> 16) * 3; + } + } + break; + case 4: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + destData[dp] = srcData[sp]; + destData[dp + 1] = srcData[sp + 1]; + destData[dp + 2] = srcData[sp + 2]; + destData[dp + 3] = srcData[sp + 3]; + sp += (sfx >>> 16) * 4; + } + } + break; + default: + } + return; + } + /*** Comprehensive blit (apply transformations) ***/ + int srcRedShift = getChannelShift(srcRedMask); + byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)]; + int srcGreenShift = getChannelShift(srcGreenMask); + byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)]; + int srcBlueShift = getChannelShift(srcBlueMask); + byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)]; + int srcAlphaShift = getChannelShift(srcAlphaMask); + byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)]; + + int destRedShift = getChannelShift(destRedMask); + int destRedWidth = getChannelWidth(destRedMask, destRedShift); + byte[] destReds = ANY_TO_EIGHT[destRedWidth]; + int destRedPreShift = 8 - destRedWidth; + int destGreenShift = getChannelShift(destGreenMask); + int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift); + byte[] destGreens = ANY_TO_EIGHT[destGreenWidth]; + int destGreenPreShift = 8 - destGreenWidth; + int destBlueShift = getChannelShift(destBlueMask); + int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift); + byte[] destBlues = ANY_TO_EIGHT[destBlueWidth]; + int destBluePreShift = 8 - destBlueWidth; + int destAlphaShift = getChannelShift(destAlphaMask); + int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift); + byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth]; + int destAlphaPreShift = 8 - destAlphaWidth; + + int ap = apr, alpha = alphaMode; + int r = 0, g = 0, b = 0, a = 0; + int rq = 0, gq = 0, bq = 0, aq = 0; + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, + sp = spr += (sfy >>> 16) * srcStride, + ap = apr += (sfy >>> 16) * alphaStride, + sfy = (sfy & 0xffff) + sfyi, + dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, + dp += dprxi, + sfx = (sfx & 0xffff) + sfxi) { + /*** READ NEXT PIXEL ***/ + switch (stype) { + case TYPE_GENERIC_8: { + int data = srcData[sp] & 0xff; + sp += (sfx >>> 16); + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_16_MSB: { + int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff); + sp += (sfx >>> 16) * 2; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_16_LSB: { + int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff); + sp += (sfx >>> 16) * 2; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_24: { + int data = (( ((srcData[sp] & 0xff) << 8) | + (srcData[sp + 1] & 0xff)) << 8) | + (srcData[sp + 2] & 0xff); + sp += (sfx >>> 16) * 3; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_32_MSB: { + int data = (( (( ((srcData[sp] & 0xff) << 8) | + (srcData[sp + 1] & 0xff)) << 8) | + (srcData[sp + 2] & 0xff)) << 8) | + (srcData[sp + 3] & 0xff); + sp += (sfx >>> 16) * 4; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_32_LSB: { + int data = (( (( ((srcData[sp + 3] & 0xff) << 8) | + (srcData[sp + 2] & 0xff)) << 8) | + (srcData[sp + 1] & 0xff)) << 8) | + (srcData[sp] & 0xff); + sp += (sfx >>> 16) * 4; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + default: + } + + /*** DO SPECIAL PROCESSING IF REQUIRED ***/ + switch (alphaMode) { + case ALPHA_CHANNEL_SEPARATE: + alpha = ((alphaData[ap] & 0xff) << 16) / 255; + ap += (sfx >> 16); + break; + case ALPHA_CHANNEL_SOURCE: + alpha = (a << 16) / 255; + break; + case ALPHA_MASK_UNPACKED: + alpha = (alphaData[ap] !is 0) ? 0x10000 : 0; + ap += (sfx >> 16); + break; + case ALPHA_MASK_PACKED: + alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000; + ap += (sfx >> 16); + break; + case ALPHA_MASK_RGB: + alpha = 0x10000; + for (int i = 0; i < alphaData.length; i += 3) { + if ((r is alphaData[i]) && (g is alphaData[i + 1]) && (b is alphaData[i + 2])) { + alpha = 0x0000; + break; + } + } + break; + default: + } + if (alpha !is 0x10000) { + if (alpha is 0x0000) continue; + switch (dtype) { + case TYPE_GENERIC_8: { + int data = destData[dp] & 0xff; + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_16_MSB: { + int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_16_LSB: { + int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_24: { + int data = (( ((destData[dp] & 0xff) << 8) | + (destData[dp + 1] & 0xff)) << 8) | + (destData[dp + 2] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_32_MSB: { + int data = (( (( ((destData[dp] & 0xff) << 8) | + (destData[dp + 1] & 0xff)) << 8) | + (destData[dp + 2] & 0xff)) << 8) | + (destData[dp + 3] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_32_LSB: { + int data = (( (( ((destData[dp + 3] & 0xff) << 8) | + (destData[dp + 2] & 0xff)) << 8) | + (destData[dp + 1] & 0xff)) << 8) | + (destData[dp] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + default: + } + // Perform alpha blending + a = aq + ((a - aq) * alpha >> 16); + r = rq + ((r - rq) * alpha >> 16); + g = gq + ((g - gq) * alpha >> 16); + b = bq + ((b - bq) * alpha >> 16); + } + + /*** WRITE NEXT PIXEL ***/ + int data = + (r >>> destRedPreShift << destRedShift) | + (g >>> destGreenPreShift << destGreenShift) | + (b >>> destBluePreShift << destBlueShift) | + (a >>> destAlphaPreShift << destAlphaShift); + switch (dtype) { + case TYPE_GENERIC_8: { + destData[dp] = cast(byte) data; + } break; + case TYPE_GENERIC_16_MSB: { + destData[dp] = cast(byte) (data >>> 8); + destData[dp + 1] = cast(byte) (data & 0xff); + } break; + case TYPE_GENERIC_16_LSB: { + destData[dp] = cast(byte) (data & 0xff); + destData[dp + 1] = cast(byte) (data >>> 8); + } break; + case TYPE_GENERIC_24: { + destData[dp] = cast(byte) (data >>> 16); + destData[dp + 1] = cast(byte) (data >>> 8); + destData[dp + 2] = cast(byte) (data & 0xff); + } break; + case TYPE_GENERIC_32_MSB: { + destData[dp] = cast(byte) (data >>> 24); + destData[dp + 1] = cast(byte) (data >>> 16); + destData[dp + 2] = cast(byte) (data >>> 8); + destData[dp + 3] = cast(byte) (data & 0xff); + } break; + case TYPE_GENERIC_32_LSB: { + destData[dp] = cast(byte) (data & 0xff); + destData[dp + 1] = cast(byte) (data >>> 8); + destData[dp + 2] = cast(byte) (data >>> 16); + destData[dp + 3] = cast(byte) (data >>> 24); + } break; + default: + } + } + } +} + +/** + * Blits an index palette image into an index palette image. + *+ * Note: The source and destination red, green, and blue + * arrays may be null if no alpha blending or dither is to be + * performed. + *
+ * + * @param op the blitter operation: a combination of BLIT_xxx flags + * (see BLIT_xxx constants) + * @param srcData the source byte array containing image data + * @param srcDepth the source depth: one of 1, 2, 4, 8 + * @param srcStride the source number of bytes per line + * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST; + * ignored if srcDepth is not 1 + * @param srcX the top-left x-coord of the source blit region + * @param srcY the top-left y-coord of the source blit region + * @param srcWidth the width of the source blit region + * @param srcHeight the height of the source blit region + * @param srcReds the source palette red component intensities + * @param srcGreens the source palette green component intensities + * @param srcBlues the source palette blue component intensities + * @param alphaMode the alpha blending or mask mode, may be + * an integer 0-255 for global alpha; ignored if BLIT_ALPHA + * not specified in the blitter operations + * (see ALPHA_MODE_xxx constants) + * @param alphaData the alpha blending or mask data, varies depending + * on the value of alphaMode and sometimes ignored + * @param alphaStride the alpha data number of bytes per line + * @param alphaX the top-left x-coord of the alpha blit region + * @param alphaY the top-left y-coord of the alpha blit region + * @param destData the destination byte array containing image data + * @param destDepth the destination depth: one of 1, 2, 4, 8 + * @param destStride the destination number of bytes per line + * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST; + * ignored if destDepth is not 1 + * @param destX the top-left x-coord of the destination blit region + * @param destY the top-left y-coord of the destination blit region + * @param destWidth the width of the destination blit region + * @param destHeight the height of the destination blit region + * @param destReds the destination palette red component intensities + * @param destGreens the destination palette green component intensities + * @param destBlues the destination palette blue component intensities + * @param flipX if true the resulting image is flipped along the vertical axis + * @param flipY if true the resulting image is flipped along the horizontal axis + */ +static void blit(int op, + byte[] srcData, int srcDepth, int srcStride, int srcOrder, + int srcX, int srcY, int srcWidth, int srcHeight, + byte[] srcReds, byte[] srcGreens, byte[] srcBlues, + int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY, + byte[] destData, int destDepth, int destStride, int destOrder, + int destX, int destY, int destWidth, int destHeight, + byte[] destReds, byte[] destGreens, byte[] destBlues, + bool flipX, bool flipY) { + + static_this(); + + if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; + + /*** Prepare scaling data ***/ + int dwm1 = destWidth - 1; + int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0; + int dhm1 = destHeight - 1; + int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0; + + /*** Prepare source-related data ***/ + int stype; + switch (srcDepth) { + case 8: + stype = TYPE_INDEX_8; + break; + case 4: + srcStride <<= 1; + stype = TYPE_INDEX_4; + break; + case 2: + srcStride <<= 2; + stype = TYPE_INDEX_2; + break; + case 1: + srcStride <<= 3; + stype = (srcOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; + break; + default: + //throw new IllegalArgumentException("Invalid source type"); + return; + } + int spr = srcY * srcStride + srcX; + + /*** Prepare destination-related data ***/ + int dtype; + switch (destDepth) { + case 8: + dtype = TYPE_INDEX_8; + break; + case 4: + destStride <<= 1; + dtype = TYPE_INDEX_4; + break; + case 2: + destStride <<= 2; + dtype = TYPE_INDEX_2; + break; + case 1: + destStride <<= 3; + dtype = (destOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; + break; + default: + //throw new IllegalArgumentException("Invalid source type"); + return; + } + int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX); + int dprxi = (flipX) ? -1 : 1; + int dpryi = (flipY) ? -destStride : destStride; + + /*** Prepare special processing data ***/ + int apr; + if ((op & BLIT_ALPHA) !is 0) { + switch (alphaMode) { + case ALPHA_MASK_UNPACKED: + case ALPHA_CHANNEL_SEPARATE: + if (alphaData is null) alphaMode = 0x10000; + apr = alphaY * alphaStride + alphaX; + break; + case ALPHA_MASK_PACKED: + if (alphaData is null) alphaMode = 0x10000; + alphaStride <<= 3; + apr = alphaY * alphaStride + alphaX; + break; + case ALPHA_MASK_INDEX: + case ALPHA_MASK_RGB: + if (alphaData is null) alphaMode = 0x10000; + apr = 0; + break; + default: + alphaMode = (alphaMode << 16) / 255; // prescale + case ALPHA_CHANNEL_SOURCE: + apr = 0; + break; + } + } else { + alphaMode = 0x10000; + apr = 0; + } + bool ditherEnabled = (op & BLIT_DITHER) !is 0; + + /*** Blit ***/ + int dp = dpr; + int sp = spr; + int ap = apr; + int destPaletteSize = 1 << destDepth; + if ((destReds !is null) && (destReds.length < destPaletteSize)) destPaletteSize = destReds.length; + byte[] paletteMapping = null; + bool isExactPaletteMapping = true; + switch (alphaMode) { + case 0x10000: + /*** If the palettes and formats are equivalent use a one-to-one mapping ***/ + if ((stype is dtype) && + (srcReds is destReds) && (srcGreens is destGreens) && (srcBlues is destBlues)) { + paletteMapping = ONE_TO_ONE_MAPPING; + break; + /*** If palettes have not been supplied, supply a suitable mapping ***/ + } else if ((srcReds is null) || (destReds is null)) { + if (srcDepth <= destDepth) { + paletteMapping = ONE_TO_ONE_MAPPING; + } else { + paletteMapping = new byte[1 << srcDepth]; + int mask = (0xff << destDepth) >>> 8; + for (int i = 0; i < paletteMapping.length; ++i) paletteMapping[i] = cast(byte)(i & mask); + } + break; + } + case ALPHA_MASK_UNPACKED: + case ALPHA_MASK_PACKED: + case ALPHA_MASK_INDEX: + case ALPHA_MASK_RGB: + /*** Generate a palette mapping ***/ + int srcPaletteSize = 1 << srcDepth; + paletteMapping = new byte[srcPaletteSize]; + if ((srcReds !is null) && (srcReds.length < srcPaletteSize)) srcPaletteSize = srcReds.length; + for (int i = 0, r, g, b, index; i < srcPaletteSize; ++i) { + r = srcReds[i] & 0xff; + g = srcGreens[i] & 0xff; + b = srcBlues[i] & 0xff; + index = 0; + int minDistance = 0x7fffffff; + for (int j = 0, dr, dg, db, distance; j < destPaletteSize; ++j) { + dr = (destReds[j] & 0xff) - r; + dg = (destGreens[j] & 0xff) - g; + db = (destBlues[j] & 0xff) - b; + distance = dr * dr + dg * dg + db * db; + if (distance < minDistance) { + index = j; + if (distance is 0) break; + minDistance = distance; + } + } + paletteMapping[i] = cast(byte)index; + if (minDistance !is 0) isExactPaletteMapping = false; + } + break; + default: + } + if ((paletteMapping !is null) && (isExactPaletteMapping || ! ditherEnabled)) { + if ((stype is dtype) && (alphaMode is 0x10000)) { + /*** Fast blit (copy w/ mapping) ***/ + switch (stype) { + case TYPE_INDEX_8: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + destData[dp] = paletteMapping[srcData[sp] & 0xff]; + sp += (sfx >>> 16); + } + } + break; + case TYPE_INDEX_4: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + int v; + if ((sp & 1) !is 0) v = paletteMapping[srcData[sp >> 1] & 0x0f]; + else v = (srcData[sp >> 1] >>> 4) & 0x0f; + sp += (sfx >>> 16); + if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | v); + else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (v << 4)); + } + } + break; + case TYPE_INDEX_2: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + int index = paletteMapping[(srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03]; + sp += (sfx >>> 16); + int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift)); + } + } + break; + case TYPE_INDEX_1_MSB: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + int index = paletteMapping[(srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01]; + sp += (sfx >>> 16); + int shift = 7 - (dp & 7); + destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); + } + } + break; + case TYPE_INDEX_1_LSB: + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { + int index = paletteMapping[(srcData[sp >> 3] >>> (sp & 7)) & 0x01]; + sp += (sfx >>> 16); + int shift = dp & 7; + destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); + } + } + break; + default: + } + } else { + /*** Convert between indexed modes using mapping and mask ***/ + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, + sp = spr += (sfy >>> 16) * srcStride, + sfy = (sfy & 0xffff) + sfyi, + dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, + dp += dprxi, + sfx = (sfx & 0xffff) + sfxi) { + int index; + /*** READ NEXT PIXEL ***/ + switch (stype) { + case TYPE_INDEX_8: + index = srcData[sp] & 0xff; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_4: + if ((sp & 1) !is 0) index = srcData[sp >> 1] & 0x0f; + else index = (srcData[sp >> 1] >>> 4) & 0x0f; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_2: + index = (srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_1_MSB: + index = (srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_1_LSB: + index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01; + sp += (sfx >>> 16); + break; + default: + return; + } + /*** APPLY MASK ***/ + switch (alphaMode) { + case ALPHA_MASK_UNPACKED: { + byte mask = alphaData[ap]; + ap += (sfx >> 16); + if (mask is 0) continue; + } break; + case ALPHA_MASK_PACKED: { + int mask = alphaData[ap >> 3] & (1 << (ap & 7)); + ap += (sfx >> 16); + if (mask is 0) continue; + } break; + case ALPHA_MASK_INDEX: { + int i = 0; + while (i < alphaData.length) { + if (index is (alphaData[i] & 0xff)) break; + } + if (i < alphaData.length) continue; + } break; + case ALPHA_MASK_RGB: { + byte r = srcReds[index], g = srcGreens[index], b = srcBlues[index]; + int i = 0; + while (i < alphaData.length) { + if ((r is alphaData[i]) && (g is alphaData[i + 1]) && (b is alphaData[i + 2])) break; + i += 3; + } + if (i < alphaData.length) continue; + } break; + default: + } + index = paletteMapping[index] & 0xff; + + /*** WRITE NEXT PIXEL ***/ + switch (dtype) { + case TYPE_INDEX_8: + destData[dp] = cast(byte) index; + break; + case TYPE_INDEX_4: + if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | index); + else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (index << 4)); + break; + case TYPE_INDEX_2: { + int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift)); + } break; + case TYPE_INDEX_1_MSB: { + int shift = 7 - (dp & 7); + destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); + } break; + case TYPE_INDEX_1_LSB: { + int shift = dp & 7; + destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); + } break; + default: + } + } + } + } + return; + } + + /*** Comprehensive blit (apply transformations) ***/ + int alpha = alphaMode; + int index = 0; + int indexq = 0; + int lastindex = 0, lastr = -1, lastg = -1, lastb = -1; + int[] rerr, gerr, berr; + if (ditherEnabled) { + rerr = new int[destWidth + 2]; + gerr = new int[destWidth + 2]; + berr = new int[destWidth + 2]; + } else { + rerr = null; gerr = null; berr = null; + } + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, + sp = spr += (sfy >>> 16) * srcStride, + ap = apr += (sfy >>> 16) * alphaStride, + sfy = (sfy & 0xffff) + sfyi, + dp = dpr += dpryi) { + int lrerr = 0, lgerr = 0, lberr = 0; + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, + dp += dprxi, + sfx = (sfx & 0xffff) + sfxi) { + /*** READ NEXT PIXEL ***/ + switch (stype) { + case TYPE_INDEX_8: + index = srcData[sp] & 0xff; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_4: + if ((sp & 1) !is 0) index = srcData[sp >> 1] & 0x0f; + else index = (srcData[sp >> 1] >>> 4) & 0x0f; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_2: + index = (srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_1_MSB: + index = (srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_1_LSB: + index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01; + sp += (sfx >>> 16); + break; + default: + } + + /*** DO SPECIAL PROCESSING IF REQUIRED ***/ + int r = srcReds[index] & 0xff, g = srcGreens[index] & 0xff, b = srcBlues[index] & 0xff; + switch (alphaMode) { + case ALPHA_CHANNEL_SEPARATE: + alpha = ((alphaData[ap] & 0xff) << 16) / 255; + ap += (sfx >> 16); + break; + case ALPHA_MASK_UNPACKED: + alpha = (alphaData[ap] !is 0) ? 0x10000 : 0; + ap += (sfx >> 16); + break; + case ALPHA_MASK_PACKED: + alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000; + ap += (sfx >> 16); + break; + case ALPHA_MASK_INDEX: { // could speed up using binary search if we sorted the indices + int i = 0; + while (i < alphaData.length) { + if (index is (alphaData[i] & 0xff)) break; + } + if (i < alphaData.length) continue; + } break; + case ALPHA_MASK_RGB: { + int i = 0; + while (i < alphaData.length) { + if ((r is (alphaData[i] & 0xff)) && + (g is (alphaData[i + 1] & 0xff)) && + (b is (alphaData[i + 2] & 0xff))) break; + i += 3; + } + if (i < alphaData.length) continue; + } break; + default: + } + if (alpha !is 0x10000) { + if (alpha is 0x0000) continue; + switch (dtype) { + case TYPE_INDEX_8: + indexq = destData[dp] & 0xff; + break; + case TYPE_INDEX_4: + if ((dp & 1) !is 0) indexq = destData[dp >> 1] & 0x0f; + else indexq = (destData[dp >> 1] >>> 4) & 0x0f; + break; + case TYPE_INDEX_2: + indexq = (destData[dp >> 2] >>> (6 - (dp & 3) * 2)) & 0x03; + break; + case TYPE_INDEX_1_MSB: + indexq = (destData[dp >> 3] >>> (7 - (dp & 7))) & 0x01; + break; + case TYPE_INDEX_1_LSB: + indexq = (destData[dp >> 3] >>> (dp & 7)) & 0x01; + break; + default: + } + // Perform alpha blending + int rq = destReds[indexq] & 0xff; + int gq = destGreens[indexq] & 0xff; + int bq = destBlues[indexq] & 0xff; + r = rq + ((r - rq) * alpha >> 16); + g = gq + ((g - gq) * alpha >> 16); + b = bq + ((b - bq) * alpha >> 16); + } + + /*** MAP COLOR TO THE PALETTE ***/ + if (ditherEnabled) { + // Floyd-Steinberg error diffusion + r += rerr[dx] >> 4; + if (r < 0) r = 0; else if (r > 255) r = 255; + g += gerr[dx] >> 4; + if (g < 0) g = 0; else if (g > 255) g = 255; + b += berr[dx] >> 4; + if (b < 0) b = 0; else if (b > 255) b = 255; + rerr[dx] = lrerr; + gerr[dx] = lgerr; + berr[dx] = lberr; + } + if (r !is lastr || g !is lastg || b !is lastb) { + // moving the variable declarations out seems to make the JDK JIT happier... + for (int j = 0, dr, dg, db, distance, minDistance = 0x7fffffff; j < destPaletteSize; ++j) { + dr = (destReds[j] & 0xff) - r; + dg = (destGreens[j] & 0xff) - g; + db = (destBlues[j] & 0xff) - b; + distance = dr * dr + dg * dg + db * db; + if (distance < minDistance) { + lastindex = j; + if (distance is 0) break; + minDistance = distance; + } + } + lastr = r; lastg = g; lastb = b; + } + if (ditherEnabled) { + // Floyd-Steinberg error diffusion, cont'd... + int dxm1 = dx - 1, dxp1 = dx + 1; + int acc; + rerr[dxp1] += acc = (lrerr = r - (destReds[lastindex] & 0xff)) + lrerr + lrerr; + rerr[dx] += acc += lrerr + lrerr; + rerr[dxm1] += acc + lrerr + lrerr; + gerr[dxp1] += acc = (lgerr = g - (destGreens[lastindex] & 0xff)) + lgerr + lgerr; + gerr[dx] += acc += lgerr + lgerr; + gerr[dxm1] += acc + lgerr + lgerr; + berr[dxp1] += acc = (lberr = b - (destBlues[lastindex] & 0xff)) + lberr + lberr; + berr[dx] += acc += lberr + lberr; + berr[dxm1] += acc + lberr + lberr; + } + + /*** WRITE NEXT PIXEL ***/ + switch (dtype) { + case TYPE_INDEX_8: + destData[dp] = cast(byte) lastindex; + break; + case TYPE_INDEX_4: + if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | lastindex); + else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4)); + break; + case TYPE_INDEX_2: { + int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift)); + } break; + case TYPE_INDEX_1_MSB: { + int shift = 7 - (dp & 7); + destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); + } break; + case TYPE_INDEX_1_LSB: { + int shift = dp & 7; + destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); + } break; + default: + } + } + } +} + +/** + * Blits an index palette image into a direct palette image. + *+ * Note: The source and destination masks and palettes must + * always be fully specified. + *
+ * + * @param op the blitter operation: a combination of BLIT_xxx flags + * (see BLIT_xxx constants) + * @param srcData the source byte array containing image data + * @param srcDepth the source depth: one of 1, 2, 4, 8 + * @param srcStride the source number of bytes per line + * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST; + * ignored if srcDepth is not 1 + * @param srcX the top-left x-coord of the source blit region + * @param srcY the top-left y-coord of the source blit region + * @param srcWidth the width of the source blit region + * @param srcHeight the height of the source blit region + * @param srcReds the source palette red component intensities + * @param srcGreens the source palette green component intensities + * @param srcBlues the source palette blue component intensities + * @param alphaMode the alpha blending or mask mode, may be + * an integer 0-255 for global alpha; ignored if BLIT_ALPHA + * not specified in the blitter operations + * (see ALPHA_MODE_xxx constants) + * @param alphaData the alpha blending or mask data, varies depending + * on the value of alphaMode and sometimes ignored + * @param alphaStride the alpha data number of bytes per line + * @param alphaX the top-left x-coord of the alpha blit region + * @param alphaY the top-left y-coord of the alpha blit region + * @param destData the destination byte array containing image data + * @param destDepth the destination depth: one of 8, 16, 24, 32 + * @param destStride the destination number of bytes per line + * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST; + * ignored if destDepth is not 16 or 32 + * @param destX the top-left x-coord of the destination blit region + * @param destY the top-left y-coord of the destination blit region + * @param destWidth the width of the destination blit region + * @param destHeight the height of the destination blit region + * @param destRedMask the destination red channel mask + * @param destGreenMask the destination green channel mask + * @param destBlueMask the destination blue channel mask + * @param flipX if true the resulting image is flipped along the vertical axis + * @param flipY if true the resulting image is flipped along the horizontal axis + */ +static void blit(int op, + byte[] srcData, int srcDepth, int srcStride, int srcOrder, + int srcX, int srcY, int srcWidth, int srcHeight, + byte[] srcReds, byte[] srcGreens, byte[] srcBlues, + int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY, + byte[] destData, int destDepth, int destStride, int destOrder, + int destX, int destY, int destWidth, int destHeight, + int destRedMask, int destGreenMask, int destBlueMask, + bool flipX, bool flipY) { + + static_this(); + + if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; + + // these should be supplied as params later + int destAlphaMask = 0; + + /*** Prepare scaling data ***/ + int dwm1 = destWidth - 1; + int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0; + int dhm1 = destHeight - 1; + int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0; + + /*** Prepare source-related data ***/ + int stype; + switch (srcDepth) { + case 8: + stype = TYPE_INDEX_8; + break; + case 4: + srcStride <<= 1; + stype = TYPE_INDEX_4; + break; + case 2: + srcStride <<= 2; + stype = TYPE_INDEX_2; + break; + case 1: + srcStride <<= 3; + stype = (srcOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; + break; + default: + //throw new IllegalArgumentException("Invalid source type"); + return; + } + int spr = srcY * srcStride + srcX; + + /*** Prepare destination-related data ***/ + int dbpp, dtype; + switch (destDepth) { + case 8: + dbpp = 1; + dtype = TYPE_GENERIC_8; + break; + case 16: + dbpp = 2; + dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB; + break; + case 24: + dbpp = 3; + dtype = TYPE_GENERIC_24; + break; + case 32: + dbpp = 4; + dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; + break; + default: + //throw new IllegalArgumentException("Invalid destination type"); + return; + } + int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp; + int dprxi = (flipX) ? -dbpp : dbpp; + int dpryi = (flipY) ? -destStride : destStride; + + /*** Prepare special processing data ***/ + int apr; + if ((op & BLIT_ALPHA) !is 0) { + switch (alphaMode) { + case ALPHA_MASK_UNPACKED: + case ALPHA_CHANNEL_SEPARATE: + if (alphaData is null) alphaMode = 0x10000; + apr = alphaY * alphaStride + alphaX; + break; + case ALPHA_MASK_PACKED: + if (alphaData is null) alphaMode = 0x10000; + alphaStride <<= 3; + apr = alphaY * alphaStride + alphaX; + break; + case ALPHA_MASK_INDEX: + case ALPHA_MASK_RGB: + if (alphaData is null) alphaMode = 0x10000; + apr = 0; + break; + default: + alphaMode = (alphaMode << 16) / 255; // prescale + case ALPHA_CHANNEL_SOURCE: + apr = 0; + break; + } + } else { + alphaMode = 0x10000; + apr = 0; + } + + /*** Comprehensive blit (apply transformations) ***/ + int destRedShift = getChannelShift(destRedMask); + int destRedWidth = getChannelWidth(destRedMask, destRedShift); + byte[] destReds = ANY_TO_EIGHT[destRedWidth]; + int destRedPreShift = 8 - destRedWidth; + int destGreenShift = getChannelShift(destGreenMask); + int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift); + byte[] destGreens = ANY_TO_EIGHT[destGreenWidth]; + int destGreenPreShift = 8 - destGreenWidth; + int destBlueShift = getChannelShift(destBlueMask); + int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift); + byte[] destBlues = ANY_TO_EIGHT[destBlueWidth]; + int destBluePreShift = 8 - destBlueWidth; + int destAlphaShift = getChannelShift(destAlphaMask); + int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift); + byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth]; + int destAlphaPreShift = 8 - destAlphaWidth; + + int dp = dpr; + int sp = spr; + int ap = apr, alpha = alphaMode; + int r = 0, g = 0, b = 0, a = 0, index = 0; + int rq = 0, gq = 0, bq = 0, aq = 0; + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, + sp = spr += (sfy >>> 16) * srcStride, + ap = apr += (sfy >>> 16) * alphaStride, + sfy = (sfy & 0xffff) + sfyi, + dp = dpr += dpryi) { + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, + dp += dprxi, + sfx = (sfx & 0xffff) + sfxi) { + /*** READ NEXT PIXEL ***/ + switch (stype) { + case TYPE_INDEX_8: + index = srcData[sp] & 0xff; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_4: + if ((sp & 1) !is 0) index = srcData[sp >> 1] & 0x0f; + else index = (srcData[sp >> 1] >>> 4) & 0x0f; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_2: + index = (srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_1_MSB: + index = (srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01; + sp += (sfx >>> 16); + break; + case TYPE_INDEX_1_LSB: + index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01; + sp += (sfx >>> 16); + break; + default: + } + + /*** DO SPECIAL PROCESSING IF REQUIRED ***/ + r = srcReds[index] & 0xff; + g = srcGreens[index] & 0xff; + b = srcBlues[index] & 0xff; + switch (alphaMode) { + case ALPHA_CHANNEL_SEPARATE: + alpha = ((alphaData[ap] & 0xff) << 16) / 255; + ap += (sfx >> 16); + break; + case ALPHA_MASK_UNPACKED: + alpha = (alphaData[ap] !is 0) ? 0x10000 : 0; + ap += (sfx >> 16); + break; + case ALPHA_MASK_PACKED: + alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000; + ap += (sfx >> 16); + break; + case ALPHA_MASK_INDEX: { // could speed up using binary search if we sorted the indices + int i = 0; + while (i < alphaData.length) { + if (index is (alphaData[i] & 0xff)) break; + } + if (i < alphaData.length) continue; + } break; + case ALPHA_MASK_RGB: { + int i = 0; + while (i < alphaData.length) { + if ((r is (alphaData[i] & 0xff)) && + (g is (alphaData[i + 1] & 0xff)) && + (b is (alphaData[i + 2] & 0xff))) break; + i += 3; + } + if (i < alphaData.length) continue; + } break; + default: + } + if (alpha !is 0x10000) { + if (alpha is 0x0000) continue; + switch (dtype) { + case TYPE_GENERIC_8: { + int data = destData[dp] & 0xff; + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_16_MSB: { + int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_16_LSB: { + int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_24: { + int data = (( ((destData[dp] & 0xff) << 8) | + (destData[dp + 1] & 0xff)) << 8) | + (destData[dp + 2] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_32_MSB: { + int data = (( (( ((destData[dp] & 0xff) << 8) | + (destData[dp + 1] & 0xff)) << 8) | + (destData[dp + 2] & 0xff)) << 8) | + (destData[dp + 3] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_32_LSB: { + int data = (( (( ((destData[dp + 3] & 0xff) << 8) | + (destData[dp + 2] & 0xff)) << 8) | + (destData[dp + 1] & 0xff)) << 8) | + (destData[dp] & 0xff); + rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; + gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; + bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; + aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; + } break; + default: + } + // Perform alpha blending + a = aq + ((a - aq) * alpha >> 16); + r = rq + ((r - rq) * alpha >> 16); + g = gq + ((g - gq) * alpha >> 16); + b = bq + ((b - bq) * alpha >> 16); + } + + /*** WRITE NEXT PIXEL ***/ + int data = + (r >>> destRedPreShift << destRedShift) | + (g >>> destGreenPreShift << destGreenShift) | + (b >>> destBluePreShift << destBlueShift) | + (a >>> destAlphaPreShift << destAlphaShift); + switch (dtype) { + case TYPE_GENERIC_8: { + destData[dp] = cast(byte) data; + } break; + case TYPE_GENERIC_16_MSB: { + destData[dp] = cast(byte) (data >>> 8); + destData[dp + 1] = cast(byte) (data & 0xff); + } break; + case TYPE_GENERIC_16_LSB: { + destData[dp] = cast(byte) (data & 0xff); + destData[dp + 1] = cast(byte) (data >>> 8); + } break; + case TYPE_GENERIC_24: { + destData[dp] = cast(byte) (data >>> 16); + destData[dp + 1] = cast(byte) (data >>> 8); + destData[dp + 2] = cast(byte) (data & 0xff); + } break; + case TYPE_GENERIC_32_MSB: { + destData[dp] = cast(byte) (data >>> 24); + destData[dp + 1] = cast(byte) (data >>> 16); + destData[dp + 2] = cast(byte) (data >>> 8); + destData[dp + 3] = cast(byte) (data & 0xff); + } break; + case TYPE_GENERIC_32_LSB: { + destData[dp] = cast(byte) (data & 0xff); + destData[dp + 1] = cast(byte) (data >>> 8); + destData[dp + 2] = cast(byte) (data >>> 16); + destData[dp + 3] = cast(byte) (data >>> 24); + } break; + default: + } + } + } +} + +/** + * Blits a direct palette image into an index palette image. + *+ * Note: The source and destination masks and palettes must + * always be fully specified. + *
+ * + * @param op the blitter operation: a combination of BLIT_xxx flags + * (see BLIT_xxx constants) + * @param srcData the source byte array containing image data + * @param srcDepth the source depth: one of 8, 16, 24, 32 + * @param srcStride the source number of bytes per line + * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST; + * ignored if srcDepth is not 16 or 32 + * @param srcX the top-left x-coord of the source blit region + * @param srcY the top-left y-coord of the source blit region + * @param srcWidth the width of the source blit region + * @param srcHeight the height of the source blit region + * @param srcRedMask the source red channel mask + * @param srcGreenMask the source green channel mask + * @param srcBlueMask the source blue channel mask + * @param alphaMode the alpha blending or mask mode, may be + * an integer 0-255 for global alpha; ignored if BLIT_ALPHA + * not specified in the blitter operations + * (see ALPHA_MODE_xxx constants) + * @param alphaData the alpha blending or mask data, varies depending + * on the value of alphaMode and sometimes ignored + * @param alphaStride the alpha data number of bytes per line + * @param alphaX the top-left x-coord of the alpha blit region + * @param alphaY the top-left y-coord of the alpha blit region + * @param destData the destination byte array containing image data + * @param destDepth the destination depth: one of 1, 2, 4, 8 + * @param destStride the destination number of bytes per line + * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST; + * ignored if destDepth is not 1 + * @param destX the top-left x-coord of the destination blit region + * @param destY the top-left y-coord of the destination blit region + * @param destWidth the width of the destination blit region + * @param destHeight the height of the destination blit region + * @param destReds the destination palette red component intensities + * @param destGreens the destination palette green component intensities + * @param destBlues the destination palette blue component intensities + * @param flipX if true the resulting image is flipped along the vertical axis + * @param flipY if true the resulting image is flipped along the horizontal axis + */ +static void blit(int op, + byte[] srcData, int srcDepth, int srcStride, int srcOrder, + int srcX, int srcY, int srcWidth, int srcHeight, + int srcRedMask, int srcGreenMask, int srcBlueMask, + int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY, + byte[] destData, int destDepth, int destStride, int destOrder, + int destX, int destY, int destWidth, int destHeight, + byte[] destReds, byte[] destGreens, byte[] destBlues, + bool flipX, bool flipY) { + + static_this(); + + if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; + + // these should be supplied as params later + int srcAlphaMask = 0; + + /*** Prepare scaling data ***/ + int dwm1 = destWidth - 1; + int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0; + int dhm1 = destHeight - 1; + int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0; + + /*** Prepare source-related data ***/ + int sbpp, stype; + switch (srcDepth) { + case 8: + sbpp = 1; + stype = TYPE_GENERIC_8; + break; + case 16: + sbpp = 2; + stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB; + break; + case 24: + sbpp = 3; + stype = TYPE_GENERIC_24; + break; + case 32: + sbpp = 4; + stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; + break; + default: + //throw new IllegalArgumentException("Invalid source type"); + return; + } + int spr = srcY * srcStride + srcX * sbpp; + + /*** Prepare destination-related data ***/ + int dtype; + switch (destDepth) { + case 8: + dtype = TYPE_INDEX_8; + break; + case 4: + destStride <<= 1; + dtype = TYPE_INDEX_4; + break; + case 2: + destStride <<= 2; + dtype = TYPE_INDEX_2; + break; + case 1: + destStride <<= 3; + dtype = (destOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; + break; + default: + //throw new IllegalArgumentException("Invalid source type"); + return; + } + int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX); + int dprxi = (flipX) ? -1 : 1; + int dpryi = (flipY) ? -destStride : destStride; + + /*** Prepare special processing data ***/ + int apr; + if ((op & BLIT_ALPHA) !is 0) { + switch (alphaMode) { + case ALPHA_MASK_UNPACKED: + case ALPHA_CHANNEL_SEPARATE: + if (alphaData is null) alphaMode = 0x10000; + apr = alphaY * alphaStride + alphaX; + break; + case ALPHA_MASK_PACKED: + if (alphaData is null) alphaMode = 0x10000; + alphaStride <<= 3; + apr = alphaY * alphaStride + alphaX; + break; + case ALPHA_MASK_INDEX: + //throw new IllegalArgumentException("Invalid alpha type"); + return; + case ALPHA_MASK_RGB: + if (alphaData is null) alphaMode = 0x10000; + apr = 0; + break; + default: + alphaMode = (alphaMode << 16) / 255; // prescale + case ALPHA_CHANNEL_SOURCE: + apr = 0; + break; + } + } else { + alphaMode = 0x10000; + apr = 0; + } + bool ditherEnabled = (op & BLIT_DITHER) !is 0; + + /*** Comprehensive blit (apply transformations) ***/ + int srcRedShift = getChannelShift(srcRedMask); + byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)]; + int srcGreenShift = getChannelShift(srcGreenMask); + byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)]; + int srcBlueShift = getChannelShift(srcBlueMask); + byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)]; + int srcAlphaShift = getChannelShift(srcAlphaMask); + byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)]; + + int dp = dpr; + int sp = spr; + int ap = apr, alpha = alphaMode; + int r = 0, g = 0, b = 0, a = 0; + int indexq = 0; + int lastindex = 0, lastr = -1, lastg = -1, lastb = -1; + int[] rerr, gerr, berr; + int destPaletteSize = 1 << destDepth; + if ((destReds !is null) && (destReds.length < destPaletteSize)) destPaletteSize = destReds.length; + if (ditherEnabled) { + rerr = new int[destWidth + 2]; + gerr = new int[destWidth + 2]; + berr = new int[destWidth + 2]; + } else { + rerr = null; gerr = null; berr = null; + } + for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, + sp = spr += (sfy >>> 16) * srcStride, + ap = apr += (sfy >>> 16) * alphaStride, + sfy = (sfy & 0xffff) + sfyi, + dp = dpr += dpryi) { + int lrerr = 0, lgerr = 0, lberr = 0; + for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, + dp += dprxi, + sfx = (sfx & 0xffff) + sfxi) { + /*** READ NEXT PIXEL ***/ + switch (stype) { + case TYPE_GENERIC_8: { + int data = srcData[sp] & 0xff; + sp += (sfx >>> 16); + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_16_MSB: { + int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff); + sp += (sfx >>> 16) * 2; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_16_LSB: { + int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff); + sp += (sfx >>> 16) * 2; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_24: { + int data = (( ((srcData[sp] & 0xff) << 8) | + (srcData[sp + 1] & 0xff)) << 8) | + (srcData[sp + 2] & 0xff); + sp += (sfx >>> 16) * 3; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_32_MSB: { + int data = (( (( ((srcData[sp] & 0xff) << 8) | + (srcData[sp + 1] & 0xff)) << 8) | + (srcData[sp + 2] & 0xff)) << 8) | + (srcData[sp + 3] & 0xff); + sp += (sfx >>> 16) * 4; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + case TYPE_GENERIC_32_LSB: { + int data = (( (( ((srcData[sp + 3] & 0xff) << 8) | + (srcData[sp + 2] & 0xff)) << 8) | + (srcData[sp + 1] & 0xff)) << 8) | + (srcData[sp] & 0xff); + sp += (sfx >>> 16) * 4; + r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; + g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; + b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; + a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; + } break; + default: + } + + /*** DO SPECIAL PROCESSING IF REQUIRED ***/ + switch (alphaMode) { + case ALPHA_CHANNEL_SEPARATE: + alpha = ((alphaData[ap] & 0xff) << 16) / 255; + ap += (sfx >> 16); + break; + case ALPHA_CHANNEL_SOURCE: + alpha = (a << 16) / 255; + break; + case ALPHA_MASK_UNPACKED: + alpha = (alphaData[ap] !is 0) ? 0x10000 : 0; + ap += (sfx >> 16); + break; + case ALPHA_MASK_PACKED: + alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000; + ap += (sfx >> 16); + break; + case ALPHA_MASK_RGB: + alpha = 0x10000; + for (int i = 0; i < alphaData.length; i += 3) { + if ((r is alphaData[i]) && (g is alphaData[i + 1]) && (b is alphaData[i + 2])) { + alpha = 0x0000; + break; + } + } + break; + default: + } + if (alpha !is 0x10000) { + if (alpha is 0x0000) continue; + switch (dtype) { + case TYPE_INDEX_8: + indexq = destData[dp] & 0xff; + break; + case TYPE_INDEX_4: + if ((dp & 1) !is 0) indexq = destData[dp >> 1] & 0x0f; + else indexq = (destData[dp >> 1] >>> 4) & 0x0f; + break; + case TYPE_INDEX_2: + indexq = (destData[dp >> 2] >>> (6 - (dp & 3) * 2)) & 0x03; + break; + case TYPE_INDEX_1_MSB: + indexq = (destData[dp >> 3] >>> (7 - (dp & 7))) & 0x01; + break; + case TYPE_INDEX_1_LSB: + indexq = (destData[dp >> 3] >>> (dp & 7)) & 0x01; + break; + default: + } + // Perform alpha blending + int rq = destReds[indexq] & 0xff; + int gq = destGreens[indexq] & 0xff; + int bq = destBlues[indexq] & 0xff; + r = rq + ((r - rq) * alpha >> 16); + g = gq + ((g - gq) * alpha >> 16); + b = bq + ((b - bq) * alpha >> 16); + } + + /*** MAP COLOR TO THE PALETTE ***/ + if (ditherEnabled) { + // Floyd-Steinberg error diffusion + r += rerr[dx] >> 4; + if (r < 0) r = 0; else if (r > 255) r = 255; + g += gerr[dx] >> 4; + if (g < 0) g = 0; else if (g > 255) g = 255; + b += berr[dx] >> 4; + if (b < 0) b = 0; else if (b > 255) b = 255; + rerr[dx] = lrerr; + gerr[dx] = lgerr; + berr[dx] = lberr; + } + if (r !is lastr || g !is lastg || b !is lastb) { + // moving the variable declarations out seems to make the JDK JIT happier... + for (int j = 0, dr, dg, db, distance, minDistance = 0x7fffffff; j < destPaletteSize; ++j) { + dr = (destReds[j] & 0xff) - r; + dg = (destGreens[j] & 0xff) - g; + db = (destBlues[j] & 0xff) - b; + distance = dr * dr + dg * dg + db * db; + if (distance < minDistance) { + lastindex = j; + if (distance is 0) break; + minDistance = distance; + } + } + lastr = r; lastg = g; lastb = b; + } + if (ditherEnabled) { + // Floyd-Steinberg error diffusion, cont'd... + int dxm1 = dx - 1, dxp1 = dx + 1; + int acc; + rerr[dxp1] += acc = (lrerr = r - (destReds[lastindex] & 0xff)) + lrerr + lrerr; + rerr[dx] += acc += lrerr + lrerr; + rerr[dxm1] += acc + lrerr + lrerr; + gerr[dxp1] += acc = (lgerr = g - (destGreens[lastindex] & 0xff)) + lgerr + lgerr; + gerr[dx] += acc += lgerr + lgerr; + gerr[dxm1] += acc + lgerr + lgerr; + berr[dxp1] += acc = (lberr = b - (destBlues[lastindex] & 0xff)) + lberr + lberr; + berr[dx] += acc += lberr + lberr; + berr[dxm1] += acc + lberr + lberr; + } + + /*** WRITE NEXT PIXEL ***/ + switch (dtype) { + case TYPE_INDEX_8: + destData[dp] = cast(byte) lastindex; + break; + case TYPE_INDEX_4: + if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | lastindex); + else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4)); + break; + case TYPE_INDEX_2: { + int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift)); + } break; + case TYPE_INDEX_1_MSB: { + int shift = 7 - (dp & 7); + destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); + } break; + case TYPE_INDEX_1_LSB: { + int shift = dp & 7; + destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); + } break; + default: + } + } + } +} + +/** + * Computes the required channel shift from a mask. + */ +static int getChannelShift(int mask) { + if (mask is 0) return 0; + int i; + for (i = 0; ((mask & 1) is 0) && (i < 32); ++i) { + mask >>>= 1; + } + return i; +} + +/** + * Computes the required channel width (depth) from a mask. + */ +static int getChannelWidth(int mask, int shift) { + if (mask is 0) return 0; + int i; + mask >>>= shift; + for (i = shift; ((mask & 1) !is 0) && (i < 32); ++i) { + mask >>>= 1; + } + return i - shift; +} + +/** + * Extracts a field from packed RGB data given a mask for that field. + */ +static byte getChannelField(int data, int mask) { + static_this(); + int shift = getChannelShift(mask); + return ANY_TO_EIGHT[getChannelWidth(mask, shift)][(data & mask) >>> shift]; +} + +/** + * Creates an ImageData containing one band's worth of a gradient filled + * block. Ifvertical
is true, the band must be tiled
+ * horizontally to fill a region, otherwise it must be tiled vertically.
+ *
+ * @param width the width of the region to be filled
+ * @param height the height of the region to be filled
+ * @param vertical if true sweeps from top to bottom, else
+ * sweeps from left to right
+ * @param fromRGB the color to start with
+ * @param toRGB the color to end with
+ * @param redBits the number of significant red bits, 0 for palette modes
+ * @param greenBits the number of significant green bits, 0 for palette modes
+ * @param blueBits the number of significant blue bits, 0 for palette modes
+ * @return the new ImageData
+ */
+static ImageData createGradientBand(
+ int width, int height, bool vertical,
+ RGB fromRGB, RGB toRGB,
+ int redBits, int greenBits, int blueBits) {
+ /* Gradients are drawn as tiled bands */
+ int bandWidth, bandHeight, bitmapDepth;
+ byte[] bitmapData;
+ PaletteData paletteData;
+ /* Select an algorithm depending on the depth of the screen */
+ if (redBits !is 0 && greenBits !is 0 && blueBits !is 0) {
+ paletteData = new PaletteData(0x0000ff00, 0x00ff0000, 0xff000000);
+ bitmapDepth = 32;
+ if (redBits >= 8 && greenBits >= 8 && blueBits >= 8) {
+ /* Precise color */
+ int steps;
+ if (vertical) {
+ bandWidth = 1;
+ bandHeight = height;
+ steps = bandHeight > 1 ? bandHeight - 1 : 1;
+ } else {
+ bandWidth = width;
+ bandHeight = 1;
+ steps = bandWidth > 1 ? bandWidth - 1 : 1;
+ }
+ int bytesPerLine = bandWidth * 4;
+ bitmapData = new byte[bandHeight * bytesPerLine];
+ buildPreciseGradientChannel(fromRGB.blue, toRGB.blue, steps, bandWidth, bandHeight, vertical, bitmapData, 0, bytesPerLine);
+ buildPreciseGradientChannel(fromRGB.green, toRGB.green, steps, bandWidth, bandHeight, vertical, bitmapData, 1, bytesPerLine);
+ buildPreciseGradientChannel(fromRGB.red, toRGB.red, steps, bandWidth, bandHeight, vertical, bitmapData, 2, bytesPerLine);
+ } else {
+ /* Dithered color */
+ int steps;
+ if (vertical) {
+ bandWidth = (width < 8) ? width : 8;
+ bandHeight = height;
+ steps = bandHeight > 1 ? bandHeight - 1 : 1;
+ } else {
+ bandWidth = width;
+ bandHeight = (height < 8) ? height : 8;
+ steps = bandWidth > 1 ? bandWidth - 1 : 1;
+ }
+ int bytesPerLine = bandWidth * 4;
+ bitmapData = new byte[bandHeight * bytesPerLine];
+ buildDitheredGradientChannel(fromRGB.blue, toRGB.blue, steps, bandWidth, bandHeight, vertical, bitmapData, 0, bytesPerLine, blueBits);
+ buildDitheredGradientChannel(fromRGB.green, toRGB.green, steps, bandWidth, bandHeight, vertical, bitmapData, 1, bytesPerLine, greenBits);
+ buildDitheredGradientChannel(fromRGB.red, toRGB.red, steps, bandWidth, bandHeight, vertical, bitmapData, 2, bytesPerLine, redBits);
+ }
+ } else {
+ /* Dithered two tone */
+ paletteData = new PaletteData([ fromRGB, toRGB ]);
+ bitmapDepth = 8;
+ int blendi;
+ if (vertical) {
+ bandWidth = (width < 8) ? width : 8;
+ bandHeight = height;
+ blendi = (bandHeight > 1) ? 0x1040000 / (bandHeight - 1) + 1 : 1;
+ } else {
+ bandWidth = width;
+ bandHeight = (height < 8) ? height : 8;
+ blendi = (bandWidth > 1) ? 0x1040000 / (bandWidth - 1) + 1 : 1;
+ }
+ int bytesPerLine = (bandWidth + 3) & -4;
+ bitmapData = new byte[bandHeight * bytesPerLine];
+ if (vertical) {
+ for (int dy = 0, blend = 0, dp = 0; dy < bandHeight;
+ ++dy, blend += blendi, dp += bytesPerLine) {
+ for (int dx = 0; dx < bandWidth; ++dx) {
+ bitmapData[dp + dx] = (blend + DITHER_MATRIX[dy & 7][dx]) <
+ 0x1000000 ? cast(byte)0 : cast(byte)1;
+ }
+ }
+ } else {
+ for (int dx = 0, blend = 0; dx < bandWidth; ++dx, blend += blendi) {
+ for (int dy = 0, dptr = dx; dy < bandHeight; ++dy, dptr += bytesPerLine) {
+ bitmapData[dptr] = (blend + DITHER_MATRIX[dy][dx & 7]) <
+ 0x1000000 ? cast(byte)0 : cast(byte)1;
+ }
+ }
+ }
+ }
+ return new ImageData(bandWidth, bandHeight, bitmapDepth, paletteData, 4, bitmapData);
+}
+
+/*
+ * Fill in gradated values for a color channel
+ */
+static final void buildPreciseGradientChannel(int from, int to, int steps,
+ int bandWidth, int bandHeight, bool vertical,
+ byte[] bitmapData, int dp, int bytesPerLine) {
+ int val = from << 16;
+ int inc = ((to << 16) - val) / steps + 1;
+ if (vertical) {
+ for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
+ bitmapData[dp] = cast(byte)(val >>> 16);
+ val += inc;
+ }
+ } else {
+ for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
+ bitmapData[dp] = cast(byte)(val >>> 16);
+ val += inc;
+ }
+ }
+}
+
+/*
+ * Fill in dithered gradated values for a color channel
+ */
+static final void buildDitheredGradientChannel(int from, int to, int steps,
+ int bandWidth, int bandHeight, bool vertical,
+ byte[] bitmapData, int dp, int bytesPerLine, int bits) {
+ int mask = 0xff00 >>> bits;
+ int val = from << 16;
+ int inc = ((to << 16) - val) / steps + 1;
+ if (vertical) {
+ for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
+ for (int dx = 0, dptr = dp; dx < bandWidth; ++dx, dptr += 4) {
+ int thresh = DITHER_MATRIX[dy & 7][dx] >>> bits;
+ int temp = val + thresh;
+ if (temp > 0xffffff) bitmapData[dptr] = -1;
+ else bitmapData[dptr] = cast(byte)((temp >>> 16) & mask);
+ }
+ val += inc;
+ }
+ } else {
+ for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
+ for (int dy = 0, dptr = dp; dy < bandHeight; ++dy, dptr += bytesPerLine) {
+ int thresh = DITHER_MATRIX[dy][dx & 7] >>> bits;
+ int temp = val + thresh;
+ if (temp > 0xffffff) bitmapData[dptr] = -1;
+ else bitmapData[dptr] = cast(byte)((temp >>> 16) & mask);
+ }
+ val += inc;
+ }
+ }
+}
+
+/**
+ * Renders a gradient onto a GC.
+ * + * This is a GC helper. + *
+ * + * @param gc the GC to render the gradient onto + * @param device the device the GC belongs to + * @param x the top-left x coordinate of the region to be filled + * @param y the top-left y coordinate of the region to be filled + * @param width the width of the region to be filled + * @param height the height of the region to be filled + * @param vertical if true sweeps from top to bottom, else + * sweeps from left to right + * @param fromRGB the color to start with + * @param toRGB the color to end with + * @param redBits the number of significant red bits, 0 for palette modes + * @param greenBits the number of significant green bits, 0 for palette modes + * @param blueBits the number of significant blue bits, 0 for palette modes + */ +static void fillGradientRectangle(GC gc, Device device, + int x, int y, int width, int height, bool vertical, + RGB fromRGB, RGB toRGB, + int redBits, int greenBits, int blueBits) { + /* Create the bitmap and tile it */ + ImageData band = createGradientBand(width, height, vertical, + fromRGB, toRGB, redBits, greenBits, blueBits); + Image image = new Image(device, band); + if ((band.width is 1) || (band.height is 1)) { + gc.drawImage(image, 0, 0, band.width, band.height, x, y, width, height); + } else { + if (vertical) { + for (int dx = 0; dx < width; dx += band.width) { + int blitWidth = width - dx; + if (blitWidth > band.width) blitWidth = band.width; + gc.drawImage(image, 0, 0, blitWidth, band.height, dx + x, y, blitWidth, band.height); + } + } else { + for (int dy = 0; dy < height; dy += band.height) { + int blitHeight = height - dy; + if (blitHeight > band.height) blitHeight = band.height; + gc.drawImage(image, 0, 0, band.width, blitHeight, x, dy + y, band.width, blitHeight); + } + } + } + image.dispose(); +} + +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageDataLoader.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageDataLoader.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit+ * Currently supported image formats are: + *
ImageLoaders
can be used to:
+ * imageLoaderListeners
field.
+ */
+void reset() {
+ data = null;
+ logicalScreenWidth = 0;
+ logicalScreenHeight = 0;
+ backgroundPixel = -1;
+ repeatCount = 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 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 IMAGE_BMP
IMAGE_BMP_RLE
IMAGE_GIF
IMAGE_ICO
IMAGE_JPEG
IMAGE_PNG
IMAGE_BMP
IMAGE_BMP_RLE
IMAGE_GIF
IMAGE_ICO
IMAGE_JPEG
IMAGE_PNG
+ * 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
true
if the receiver has image loader
+ * listeners, and false
otherwise.
+ *
+ * @return true
if there are ImageLoaderListener
s, and false
otherwise
+ *
+ * @see #addImageLoaderListener(ImageLoaderListener)
+ * @see #removeImageLoaderListener(ImageLoaderListener)
+ */
+public bool hasListeners() {
+ return imageLoaderListeners.length > 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;
+ foreach( listener; imageLoaderListeners ){
+ listener.imageDataLoaded(event);
+ }
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoaderEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoaderEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit + * Notes: + *
endOfImage
flag in the event will be set to true
+ * after each individual image is loaded.endOfImage
flag is false, then this is a
+ * partially complete copy of the current ImageData
,
+ * otherwise this is a completely loaded ImageData
+ */
+ public ImageData imageData;
+
+ /**
+ * the zero-based count of image data increments -- this is
+ * equivalent to the number of events that have been generated
+ * while loading a particular image
+ */
+ public int incrementCount;
+
+ /**
+ * If this flag is true, then the current image data has been
+ * completely loaded, otherwise the image data is only partially
+ * loaded, and further ImageLoader events will occur unless an
+ * exception is thrown
+ */
+ public bool endOfImage;
+
+ //static final long serialVersionUID = 3257284738325558065L;
+
+/**
+ * Constructs a new instance of this class given the event source and
+ * the values to store in its fields.
+ *
+ * @param source the ImageLoader that was loading when the event occurred
+ * @param imageData the image data for the event
+ * @param incrementCount the image data increment for the event
+ * @param endOfImage the end of image flag for the event
+ */
+public this(ImageLoader source, ImageData imageData, int incrementCount, bool endOfImage) {
+ super(source);
+ this.imageData = imageData;
+ this.incrementCount = incrementCount;
+ this.endOfImage = endOfImage;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString () {
+ return Format( "ImageLoaderEvent {source={} imageData={} incrementCount={} endOfImage={}}", source, imageData, incrementCount, endOfImage); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoaderListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoaderListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * After creating an instance of a class that implements
+ * this interface it can be added to an image loader using the
+ * addImageLoaderListener
method and removed using
+ * the removeImageLoaderListener
method. When
+ * image data is either partially or completely loaded, this
+ * method will be invoked.
+ *
+ * The timing of when this method is called varies depending on + * the format of the image being loaded. + *
+ * + * @param e an event containing information about the image loading operation + */ +public void imageDataLoaded(ImageLoaderEvent e); + +} diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/LineAttributes.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/LineAttributes.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank BenoitLineAttributes
defines a set of line attributes that
+ * can be modified in a GC.
+ *
+ * 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.
+ *
+ * Depending on the depth of the image, the PaletteData can take one + * of two forms, indicated by the isDirect field: + *
+ *false
, this palette is an indexed
+ * palette which maps pixel values to RGBs. The actual RGB values
+ * may be retrieved by using the getRGBs() method.
+ * true
, this palette is a direct color
+ * palette. Instead of containing RGB values, it contains red,
+ * green and blue mask and shift information which indicates how
+ * the color components may be extracted from a given pixel.
+ * This means that the RGB value is actually encoded in the pixel value.
+ * + * In this case, the shift data is the number of bits required to shift + * the RGB value to the left in order to align the high bit of the + * corresponding mask with the high bit of the first byte. This number + * may be negative, so care must be taken when shifting. For example, + * with a red mask of 0xFF0000, the red shift would be -16. With a red + * mask of 0x1F, the red shift would be 3. + *
+ *RGB
s for the palette
+ *
+ * @exception IllegalArgumentException RGB
.
+ *
+ * @param rgb the RGB to get the pixel value for
+ * @return the pixel value for the given RGB
+ *
+ * @exception IllegalArgumentException RGB
corresponding to the given pixel value.
+ *
+ * @param pixel the pixel to get the RGB value for
+ * @return the RGB value for the given pixel
+ *
+ * @exception IllegalArgumentException RGB
s for the receiver or null
+ */
+public RGB[] getRGBs() {
+ return colors;
+}
+
+/**
+ * Computes the shift value for a given mask.
+ *
+ * @param mask the mask to compute the shift for
+ * @return the shift amount
+ *
+ * @see PaletteData
+ */
+int shiftForMask(int mask) {
+ for (int i = 31; i >= 0; i--) {
+ if (((mask >> i) & 0x1) !is 0) return 7 - i;
+ }
+ return 32;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Path.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Path.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,622 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * 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.
+ *
+ * This class requires the operating system's advanced graphics subsystem + * which may not be available on some platforms. + *
+ * + * @see Path, Pattern snippets + * @see SWT Example: GraphicsExample + * @see Sample code and further information + * + * @since 3.1 + */ +public class Path : Resource { + + alias Resource.init_ init_; + + /** + * 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 Gdip.Path handle; + + Gdip.PointF currentPoint, startPoint; + +/** + * Constructs a new empty Path. + *+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param device the device on which to allocate the path + * + * @exception IllegalArgumentExceptionpath
. If
+ * flatness
is less than or equal to zero, an unflatten
+ * copy of the path is created. Otherwise, it specifies the maximum
+ * error between the path and its flatten copy. Smaller numbers give
+ * better approximation.
+ * + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param device the device on which to allocate the path + * @param path the path to make a copy + * @param flatness the flatness value + * + * @exception IllegalArgumentException+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param device the device on which to allocate the path + * @param data the data for the path + * + * @exception IllegalArgumentException
+ * 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.
+ *
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
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
+ */
+override public bool isDisposed() {
+ return handle is 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
+ * 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.
+ *
+ * This class requires the operating system's advanced graphics subsystem + * which may not be available on some platforms. + *
+ * + * @see Path, Pattern snippets + * @see SWT Example: GraphicsExample + * @see Sample code and further information + * + * @since 3.1 + */ +public class Pattern : Resource { + alias Resource.init_ init_; + /** + * 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 Gdip.Brush handle; + +/** + * Constructs a new Pattern given an image. Drawing with the resulting + * pattern will cause the image to be tiled over the resulting area. + *+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param device the device on which to allocate the pattern + * @param image the image that the pattern will draw + * + * @exception IllegalArgumentException+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @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+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @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 IllegalArgumentExceptiontrue
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
+ * The coordinate space for rectangles and points is considered
+ * to have increasing values downward and to the right from its
+ * origin making this the normal, computer graphics oriented notion
+ * of (x, y) coordinates rather than the strict mathematical one.
+ *
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ *
+ * Application code does not need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ *
+ * Application code does not need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no
+ * The coordinate space for rectangles and points is considered
+ * to have increasing values downward and to the right from its
+ * origin making this the normal, computer graphics oriented notion
+ * of (x, y) coordinates rather than the strict mathematical one.
+ *
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ *
+ * Application code does not need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no
+ * The union of two rectangles is the smallest single rectangle
+ * that completely covers both of the areas covered by the two
+ * given rectangles.
+ *
+ * The intersection of two rectangles is the rectangle that
+ * covers the area which is contained within both rectangles.
+ *
+ * Two rectangles intersect if the area of the rectangle
+ * representing their intersection is not empty.
+ *
+ * Two rectangles intersect if the area of the rectangle
+ * representing their intersection is not empty.
+ *
+ * A rectangle is considered to cover area in the
+ * (x, y) coordinate plane if both its width and height are
+ * non-zero.
+ *
+ * The union of two rectangles is the smallest single rectangle
+ * that completely covers both of the areas covered by the two
+ * given rectangles.
+ *
+ * Application code must explicitly invoke the
+ * 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.
+ *
+ * You must dispose the region when it is no longer required.
+ *
+ * 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
+ * IMPORTANT: This method is not part of the public
+ * API for
+ * 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.
+ *
+ * This method gets the dispose state for the resource.
+ * When a resource has been disposed, it is an error to
+ * invoke any other method using the resource.
+ *
+ * @return
+ * 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
+ * You must dispose the text layout when it is no longer required.
+ *
+ * The parameter true
when the Pattern is disposed, and false
otherwise
+ */
+override public bool isDisposed() {
+ return handle is 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 "Pattern {*DISPOSED*}";
+ return Format( "Pattern {{{}}", handle );
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Point.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Point.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit dispose()
method is provided.
+ * true
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals (Object object) {
+ if (object is this) return true;
+ if ( auto p = cast(Point)object ){
+ return (p.x is this.x) && (p.y is this.y);
+ }
+ 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)
+ */
+override public hash_t toHash () {
+ return x ^ y;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the point
+ */
+override public String toString () {
+ return Format( "Point {{{}, {}}", x, y );; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+}
+
+}
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/RGB.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/RGB.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit dispose()
method is provided.
+ *
+ *
+ */
+public this (int red, int green, int blue) {
+ if ((red > 255) || (red < 0) ||
+ (green > 255) || (green < 0) ||
+ (blue > 255) || (blue < 0))
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+}
+
+/**
+* Constructs an instance of this class with the given
+* hue, saturation, and brightness.
+*
+* @param hue the hue value for the HSB color (from 0 to 360)
+* @param saturation the saturation value for the HSB color (from 0 to 1)
+* @param brightness the brightness value for the HSB color (from 0 to 1)
+*
+* @exception IllegalArgumentException
+*
+*
+* @since 3.2
+*/
+public this (float hue, float saturation, float brightness) {
+ if (hue < 0 || hue > 360 || saturation < 0 || saturation > 1 ||
+ brightness < 0 || brightness > 1) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ float r, g, b;
+ if (saturation is 0) {
+ r = g = b = brightness;
+ } else {
+ if (hue is 360) hue = 0;
+ hue /= 60;
+ int i = cast(int)hue;
+ float f = hue - i;
+ float p = brightness * (1 - saturation);
+ float q = brightness * (1 - saturation * f);
+ float t = brightness * (1 - saturation * (1 - f));
+ switch(i) {
+ case 0:
+ r = brightness;
+ g = t;
+ b = p;
+ break;
+ case 1:
+ r = q;
+ g = brightness;
+ b = p;
+ break;
+ case 2:
+ r = p;
+ g = brightness;
+ b = t;
+ break;
+ case 3:
+ r = p;
+ g = q;
+ b = brightness;
+ break;
+ case 4:
+ r = t;
+ g = p;
+ b = brightness;
+ break;
+ case 5:
+ default:
+ r = brightness;
+ g = p;
+ b = q;
+ break;
+ }
+ }
+ red = cast(int)(r * 255 + 0.5);
+ green = cast(int)(g * 255 + 0.5);
+ blue = cast(int)(b * 255 + 0.5);
+}
+
+/**
+ * Returns the hue, saturation, and brightness of the color.
+ *
+ * @return color space values in float format (hue, saturation, brightness)
+ *
+ * @since 3.2
+ */
+public float[] getHSB() {
+ float r = red / 255f;
+ float g = green / 255f;
+ float b = blue / 255f;
+ float max = Math.max(Math.max(r, g), b);
+ float min = Math.min(Math.min(r, g), b);
+ float delta = max - min;
+ float hue = 0;
+ float brightness = max;
+ float saturation = max is 0 ? 0 : (max - min) / max;
+ if (delta !is 0) {
+ if (r is max) {
+ hue = (g - b) / delta;
+ } else {
+ if (g is max) {
+ hue = 2 + (b - r) / delta;
+ } else {
+ hue = 4 + (r - g) / delta;
+ }
+ }
+ hue *= 60;
+ if (hue < 0) hue += 360;
+ }
+ return [ hue, saturation, brightness ];
+}
+
+/**
+ * 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 override int opEquals(Object object) {
+ if (object is this) return true;
+ if( auto rgb = cast(RGB) object ){
+ return (rgb.red is this.red) && (rgb.green is this.green) && (rgb.blue is this.blue);
+ }
+ 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)
+ */
+override public hash_t toHash() {
+ return (blue << 16) | (green << 8) | red;
+}
+
+/**
+ * Returns a String containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a String representation of the RGB
+ */
+public override String toString() {
+ return Format( "RGB {{{}, {}, {}}", red, green, blue ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Rectangle.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Rectangle.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,353 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit dispose()
method is provided.
+ *
+ *
+ */
+public void add (Rectangle rect) {
+ if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int left = x < rect.x ? x : rect.x;
+ int top = y < rect.y ? y : rect.y;
+ int lhs = x + width;
+ int rhs = rect.x + rect.width;
+ int right = lhs > rhs ? lhs : rhs;
+ lhs = y + height;
+ rhs = rect.y + rect.height;
+ int bottom = lhs > rhs ? lhs : rhs;
+ x = left; y = top; width = right - left; height = bottom - top;
+}
+
+/**
+ * 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 rectangle contains the point and false
otherwise
+ */
+public bool contains (int x, int y) {
+ return (x >= this.x) && (y >= this.y) && ((x - this.x) < width) && ((y - this.y) < height);
+}
+
+/**
+ * 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 rectangle contains the point and false
otherwise
+ *
+ * @exception IllegalArgumentException
+ *
+ */
+public bool contains (Point pt) {
+ if (pt is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return contains(pt.x, pt.y);
+}
+
+/**
+ * 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 override int opEquals (Object object) {
+ if (object is this) return true;
+ if( auto r = cast(Rectangle) object ){
+ return (r.x is this.x) && (r.y is this.y) && (r.width is this.width) && (r.height is this.height);
+ }
+ 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 override hash_t toHash () {
+ return x ^ y ^ width ^ height;
+}
+
+/**
+ * Destructively replaces the x, y, width and height values
+ * in the receiver with ones which represent the intersection of the
+ * rectangles specified by the receiver and the given rectangle.
+ *
+ * @param rect the rectangle to intersect with the receiver
+ *
+ * @exception IllegalArgumentException
+ *
+ *
+ * since 3.0
+ */
+public void intersect (Rectangle rect) {
+ if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (this is rect) return;
+ int left = x > rect.x ? x : rect.x;
+ int top = y > rect.y ? y : rect.y;
+ int lhs = x + width;
+ int rhs = rect.x + rect.width;
+ int right = lhs < rhs ? lhs : rhs;
+ lhs = y + height;
+ rhs = rect.y + rect.height;
+ int bottom = lhs < rhs ? lhs : rhs;
+ x = right < left ? 0 : left;
+ y = bottom < top ? 0 : top;
+ width = right < left ? 0 : right - left;
+ height = bottom < top ? 0 : bottom - top;
+}
+
+/**
+ * Returns a new rectangle which represents the intersection
+ * of the receiver and the given rectangle.
+ *
+ *
+ */
+public Rectangle intersection (Rectangle rect) {
+ if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (this is rect) return new Rectangle (x, y, width, height);
+ int left = x > rect.x ? x : rect.x;
+ int top = y > rect.y ? y : rect.y;
+ int lhs = x + width;
+ int rhs = rect.x + rect.width;
+ int right = lhs < rhs ? lhs : rhs;
+ lhs = y + height;
+ rhs = rect.y + rect.height;
+ int bottom = lhs < rhs ? lhs : rhs;
+ return new Rectangle (
+ right < left ? 0 : left,
+ bottom < top ? 0 : top,
+ right < left ? 0 : right - left,
+ bottom < top ? 0 : bottom - top);
+}
+
+/**
+ * Returns true
if the rectangle described by the
+ * arguments intersects with the receiver and false
+ * otherwise.
+ * true
if the rectangle intersects with the receiver, and false
otherwise
+ *
+ * @exception IllegalArgumentException
+ *
+ *
+ * @see #intersection(Rectangle)
+ * @see #isEmpty()
+ *
+ * @since 3.0
+ */
+public bool intersects (int x, int y, int width, int height) {
+ return (x < this.x + this.width) && (y < this.y + this.height) &&
+ (x + width > this.x) && (y + height > this.y);
+}
+
+/**
+ * Returns true
if the given rectangle intersects
+ * with the receiver and false
otherwise.
+ * true
if the rectangle intersects with the receiver, and false
otherwise
+ *
+ * @exception IllegalArgumentException
+ *
+ *
+ * @see #intersection(Rectangle)
+ * @see #isEmpty()
+ */
+public bool intersects (Rectangle rect) {
+ if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return rect is this || intersects (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * 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.
+ * true
if the receiver is empty, and false
otherwise
+ */
+public bool isEmpty () {
+ return (width <= 0) || (height <= 0);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the rectangle
+ */
+public override String toString () {
+ return Format( "Rectangle {{{}, {}, {}, {}}", x, y, width, height ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+}
+
+/**
+ * Returns a new rectangle which represents the union of
+ * the receiver and the given rectangle.
+ *
+ *
+ *
+ * @see #add(Rectangle)
+ */
+public Rectangle makeUnion (Rectangle rect) {
+ if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int left = x < rect.x ? x : rect.x;
+ int top = y < rect.y ? y : rect.y;
+ int lhs = x + width;
+ int rhs = rect.x + rect.width;
+ int right = lhs > rhs ? lhs : rhs;
+ lhs = y + height;
+ rhs = rect.y + rect.height;
+ int bottom = lhs > rhs ? lhs : rhs;
+ return new Rectangle (left, top, right - left, bottom - top);
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Region.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Region.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,612 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Region.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ */
+public this () {
+ this(null);
+}
+
+/**
+ * Constructs a new empty region.
+ *
+ *
+ * @exception SWTError
+ *
+ *
+ * @see #dispose
+ *
+ * @since 3.0
+ */
+public this (Device device) {
+ super(device);
+ handle = OS.CreateRectRgn (0, 0, 0, 0);
+ if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+ init_();
+}
+
+/**
+ * Constructs a new region given a handle to the operating
+ * system resources that it should represent.
+ *
+ * @param handle the handle for the result
+ */
+this(Device device, HRGN handle) {
+ super(device);
+ this.handle = 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.0
+*
+ */
+public void add (int[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+ auto polyRgn = OS.CreatePolygonRgn(cast(POINT*)pointArray.ptr, pointArray.length / 2, OS.ALTERNATE);
+ OS.CombineRgn (handle, handle, polyRgn, OS.RGN_OR);
+ OS.DeleteObject (polyRgn);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ */
+public void add (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect is 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @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);
+ auto rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+ OS.CombineRgn (handle, handle, rectRgn, OS.RGN_OR);
+ OS.DeleteObject (rectRgn);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ */
+public void add (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ OS.CombineRgn (handle, handle, region.handle, OS.RGN_OR);
+}
+
+/**
+ * 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
+ *
+ */
+public bool contains (int x, int y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return cast(bool) OS.PtInRegion (handle, 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
+ *
+ * @exception SWTException
+ *
+ */
+public bool contains (Point pt) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pt is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return contains(pt.x, pt.y);
+}
+
+void destroy () {
+ OS.DeleteObject(handle);
+ handle = 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 int opEquals (Object object) {
+ if (this is object) return true;
+ if (!(cast(Region)object)) return false;
+ Region rgn = cast(Region)object;
+ return handle is 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
+ *
+ *
+ * @see Rectangle#union
+ */
+public Rectangle getBounds() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ RECT rect;
+ OS.GetRgnBox(handle, &rect);
+ return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+
+/**
+ * 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 hash_t toHash () {
+ return cast(hash_t)handle;
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.0
+ */
+public void intersect (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect is 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @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);
+ auto rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+ OS.CombineRgn (handle, handle, rectRgn, OS.RGN_AND);
+ OS.DeleteObject (rectRgn);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.0
+ */
+public void intersect (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ OS.CombineRgn (handle, handle, region.handle, OS.RGN_AND);
+}
+
+/**
+ * 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
+ *
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public bool intersects (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ RECT r;
+ OS.SetRect (&r, x, y, x + width, y + height);
+ return cast(bool) OS.RectInRegion (handle, &r);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public bool intersects (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect is 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.
+ * true
when the region is disposed, and false
otherwise
+ */
+override public bool isDisposed() {
+ return handle is 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
+ *
+ */
+public bool isEmpty () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ RECT rect;
+ auto result = OS.GetRgnBox (handle, &rect);
+ if (result is OS.NULLREGION) return true;
+ return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.0
+ */
+public void subtract (int[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+ auto polyRgn = OS.CreatePolygonRgn(cast(POINT*)pointArray.ptr, pointArray.length / 2, OS.ALTERNATE);
+ OS.CombineRgn (handle, handle, polyRgn, OS.RGN_DIFF);
+ OS.DeleteObject (polyRgn);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.0
+ */
+public void subtract (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect is 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @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);
+ auto rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+ OS.CombineRgn (handle, handle, rectRgn, OS.RGN_DIFF);
+ OS.DeleteObject (rectRgn);
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.0
+ */
+public void subtract (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ OS.CombineRgn (handle, handle, region.handle, OS.RGN_DIFF);
+}
+
+/**
+ * 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
+ *
+ *
+ * @since 3.1
+ */
+public void translate (int x, int y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.OffsetRgn (handle, 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
+ *
+ * @exception SWTException
+ *
+ *
+ * @since 3.1
+ */
+public void translate (Point pt) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pt is 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
+ */
+override public String toString () {
+ if (isDisposed()) return "Region {*DISPOSED*}";
+ return Format( "Region {{{}}", handle );
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new region.
+ * 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.
+ * Device
where this resource was
+ * created.
+ *
+ * @return Device
the device of the receiver
+ *
+ * @since 3.2
+ */
+public Device getDevice() {
+ Device device = this.device;
+ if (device is null || isDisposed ()) SWT.error (SWT.ERROR_GRAPHIC_DISPOSED);
+ return device;
+}
+
+void init_() {
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Returns true
if the resource has been disposed,
+ * and false
otherwise.
+ * true
when the resource is disposed and false
otherwise
+ */
+public abstract bool isDisposed();
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/TextLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/TextLayout.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,3170 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit TextLayout
is a graphic object that represents
+ * styled text.
+ * TextLayout#dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ *
+ * @see #dispose()
+ */
+public this (Device device) {
+ static_this();
+ super(device);
+ wrapWidth = ascent = descent = -1;
+ lineSpacing = 0;
+ orientation = SWT.LEFT_TO_RIGHT;
+ styles = new StyleItem[2];
+ styles[0] = new StyleItem();
+ styles[1] = new StyleItem();
+ stylesCount = 2;
+ text = ""; //$NON-NLS-1$
+ wtext = ""w;
+ void* ppv;
+ OS.OleInitialize(null);
+ if (OS.CoCreateInstance(CLSID_CMultiLanguage.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_IMLangFontLink2.ptr, cast(void*)&ppv) is OS.S_OK) {
+ mLangFontLink2 = ppv;
+ }
+ init_();
+}
+
+void breakRun(StyleItem run) {
+ if (run.psla !is null) return;
+ wchar[] chars = segmentsWText[ index8to16[ run.start ] .. index8to16[ run.start + run.length ] ];
+ auto hHeap = OS.GetProcessHeap();
+ run.psla = cast(SCRIPT_LOGATTR*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, SCRIPT_LOGATTR.sizeof * chars.length);
+ if (run.psla is null) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.ScriptBreak(chars.ptr, chars.length, &run.analysis, run.psla);
+}
+
+void checkLayout () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+}
+
+/*
+* Compute the runs: itemize, shape, place, and reorder the runs.
+* Break paragraphs into lines, wraps the text, and initialize caches.
+*/
+void computeRuns (GC gc) {
+ if (runs !is null) return;
+ auto hDC = gc !is null ? gc.handle : device.internal_new_GC(null);
+ auto srcHdc = OS.CreateCompatibleDC(hDC);
+ allRuns = itemize();
+ for (int i=0; i
+ *
+ * @exception IllegalArgumentException
+ *
+ */
+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
+ *
+ * @exception IllegalArgumentException
+ *
+ */
+public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) {
+ draw(gc, x, y, selectionStart, selectionEnd, selectionForeground, selectionBackground, 0);
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ * flags
can include one of SWT.DELIMITER_SELECTION
+ * or SWT.FULL_SELECTION
to specify the selection behavior on all lines except
+ * for the last line, and can also include SWT.LAST_LINE_SELECTION
to extend
+ * the specified selection behavior to the last line.
+ *
+ *
+ * @exception IllegalArgumentException
+ *
+ *
+ * @since 3.3
+ */
+public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground, int flags) {
+ checkLayout();
+ computeRuns(gc);
+ if (gc is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (selectionForeground !is null && selectionForeground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (selectionBackground !is null && selectionBackground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int length = text.length;
+ int wlength = wtext.length;
+ if (length is 0 && flags is 0) return;
+ auto hdc = gc.handle;
+ Rectangle clip = gc.getClipping();
+ GCData data = gc.data;
+ auto gdipGraphics = data.gdipGraphics;
+ auto foreground = data.foreground;
+ auto alpha = data.alpha;
+ bool gdip = gdipGraphics !is null && (alpha !is 0xFF || data.foregroundPattern !is null);
+ HRGN clipRgn;
+ float[] lpXform = null;
+ Gdip.Rect gdipRect;
+ if (gdipGraphics !is null && !gdip) {
+ auto matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+ if (matrix is null) SWT.error(SWT.ERROR_NO_HANDLES);
+ Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+ auto identity_ = gc.identity();
+ Gdip.Matrix_Invert(identity_);
+ Gdip.Matrix_Multiply(matrix, identity_, Gdip.MatrixOrderAppend);
+ Gdip.Matrix_delete(identity_);
+ if (!Gdip.Matrix_IsIdentity(matrix)) {
+ lpXform = new float[6];
+ Gdip.Matrix_GetElements(matrix, lpXform.ptr);
+ }
+ Gdip.Matrix_delete(matrix);
+ if ((data.style & SWT.MIRRORED) !is 0 && lpXform !is null) {
+ gdip = true;
+ lpXform = null;
+ } else {
+ Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
+ auto rgn = Gdip.Region_new();
+ Gdip.Graphics_GetClip(gdipGraphics, rgn);
+ if (!Gdip.Region_IsInfinite(rgn, gdipGraphics)) {
+ clipRgn = Gdip.Region_GetHRGN(rgn, gdipGraphics);
+ }
+ Gdip.Region_delete(rgn);
+ Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
+ hdc = Gdip.Graphics_GetHDC(gdipGraphics);
+ }
+ }
+ Gdip.Brush foregroundBrush;
+ int state = 0;
+ if (gdip) {
+ gc.checkGC(GC.FOREGROUND);
+ foregroundBrush = gc.getFgBrush();
+ } else {
+ state = OS.SaveDC(hdc);
+ if ((data.style & SWT.MIRRORED) !is 0) {
+ OS.SetLayout(hdc, OS.GetLayout(hdc) | OS.LAYOUT_RTL);
+ }
+ if (lpXform !is null) {
+ OS.SetGraphicsMode(hdc, OS.GM_ADVANCED);
+ OS.SetWorldTransform(hdc, cast(XFORM*)lpXform.ptr);
+ }
+ if (clipRgn !is null) {
+ OS.SelectClipRgn(hdc, clipRgn);
+ OS.DeleteObject(clipRgn);
+ }
+ }
+ bool hasSelection = selectionStart <= selectionEnd && selectionStart !is -1 && selectionEnd !is -1;
+ if (hasSelection || (flags & SWT.LAST_LINE_SELECTION) !is 0) {
+ selectionStart = Math.min(Math.max(0, selectionStart), length - 1);
+ selectionEnd = Math.min(Math.max(0, selectionEnd), length - 1);
+ if (selectionForeground is null) selectionForeground = device.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
+ if (selectionBackground is null) selectionBackground = device.getSystemColor(SWT.COLOR_LIST_SELECTION);
+ selectionStart = translateOffset(selectionStart);
+ selectionEnd = translateOffset(selectionEnd);
+ }
+ RECT rect;
+ Gdip.Brush selBrush;
+ Gdip.Pen selPen;
+ Gdip.Brush selBrushFg;
+
+ if (hasSelection || (flags & SWT.LAST_LINE_SELECTION) !is 0) {
+ if (gdip) {
+ auto bg = selectionBackground.handle;
+ auto argb = ((alpha & 0xFF) << 24) | ((bg >> 16) & 0xFF) | (bg & 0xFF00) | ((bg & 0xFF) << 16);
+ auto color = Gdip.Color_new(argb);
+ selBrush = cast(Gdip.Brush)Gdip.SolidBrush_new(color);
+ Gdip.Color_delete(color);
+ auto fg = selectionForeground.handle;
+ argb = ((alpha & 0xFF) << 24) | ((fg >> 16) & 0xFF) | (fg & 0xFF00) | ((fg & 0xFF) << 16);
+ color = Gdip.Color_new(argb);
+ selBrushFg = cast(Gdip.Brush)Gdip.SolidBrush_new(color);
+ selPen = cast(Gdip.Pen) Gdip.Pen_new( cast(Gdip.Brush)selBrushFg, 1);
+ Gdip.Color_delete(color);
+ } else {
+ selBrush = cast(Gdip.Brush)OS.CreateSolidBrush(selectionBackground.handle);
+ selPen = cast(Gdip.Pen)OS.CreatePen(OS.PS_SOLID, 1, selectionForeground.handle);
+ }
+ }
+ int offset = (orientation & SWT.RIGHT_TO_LEFT) !is 0 ? -1 : 0;
+ OS.SetBkMode(hdc, OS.TRANSPARENT);
+ for (int line=0; lineSWT.CENTER
or
+ * SWT.RIGHT
.
+ *
+ * @return the alignment used to positioned text horizontally
+ *
+ * @exception SWTException
+ *
+ */
+public int getAlignment () {
+ checkLayout();
+ return alignment;
+}
+
+/**
+ * Returns the ascent of the receiver.
+ *
+ * @return the ascent
+ *
+ * @exception SWTException
+ *
+ *
+ * @see #getDescent()
+ * @see #setDescent(int)
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getAscent () {
+ checkLayout();
+ return ascent;
+}
+
+/**
+ * Returns the bounds of the receiver. The width returned is either the
+ * width of the longest line or the width set using {@link TextLayout#setWidth(int)}.
+ * To obtain the text bounds of a line use {@link TextLayout#getLineBounds(int)}.
+ *
+ * @return the bounds of the receiver
+ *
+ * @exception SWTException
+ *
+ *
+ * @see #setWidth(int)
+ * @see #getLineBounds(int)
+ */
+public Rectangle getBounds () {
+ checkLayout();
+ computeRuns(null);
+ int width = 0;
+ if (wrapWidth !is -1) {
+ width = wrapWidth;
+ } else {
+ for (int line=0; line
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 SWT.MOVEMENT_CHAR
,
+ * SWT.MOVEMENT_CLUSTER
, SWT.MOVEMENT_WORD
,
+ * SWT.MOVEMENT_WORD_END
or SWT.MOVEMENT_WORD_START
.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the next offset
+ *
+ * @exception IllegalArgumentException 1
1
SWT.MOVEMENT_CHAR
,
+ * SWT.MOVEMENT_CLUSTER
or SWT.MOVEMENT_WORD
,
+ * SWT.MOVEMENT_WORD_END
or SWT.MOVEMENT_WORD_START
.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the previous offset
+ *
+ * @exception IllegalArgumentException TextStyle
.
+ *
+ * @return the ranges, an array of offsets representing the start and end of each
+ * text style.
+ *
+ * @exception SWTException null
if not set
+ *
+ * @exception IllegalArgumentException 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. + *
+ * + * @returntrue
when the text layout is disposed and false
otherwise
+ */
+override public bool isDisposed () {
+ return device is null;
+}
+
+/*
+ * Itemize the receiver text
+ */
+StyleItem[] itemize () {
+ // SWT: itemize is the process of finding changes in direction
+ getSegmentsText(segmentsText, segmentsWText );
+ int length = segmentsText.length;
+ SCRIPT_CONTROL scriptControl;
+ SCRIPT_STATE scriptState;
+ final int MAX_ITEM = length + 1;
+
+ if ((orientation & SWT.RIGHT_TO_LEFT) !is 0) {
+ scriptState.uBidiLevel = 1;
+ scriptState.fArabicNumContext = true;
+ SCRIPT_DIGITSUBSTITUTE psds;
+ OS.ScriptRecordDigitSubstitution(OS.LOCALE_USER_DEFAULT, &psds);
+ OS.ScriptApplyDigitSubstitution(&psds, &scriptControl, &scriptState);
+ }
+
+ auto hHeap = OS.GetProcessHeap();
+ auto pItems = cast(SCRIPT_ITEM*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, MAX_ITEM * SCRIPT_ITEM.sizeof);
+ if (pItems is null) SWT.error(SWT.ERROR_NO_HANDLES);
+ int pcItems;
+ wchar[] chars = segmentsWText;
+ OS.ScriptItemize(chars.ptr, chars.length, MAX_ITEM, &scriptControl, &scriptState, pItems, &pcItems);
+// if (hr is E_OUTOFMEMORY) //TODO handle it
+ // SWT pcItems is not inclusive the trailing item
+
+ StyleItem[] runs = merge(pItems, pcItems);
+ OS.HeapFree(hHeap, 0, pItems);
+ return runs;
+}
+
+/*
+ * Merge styles ranges and script items
+ */
+StyleItem[] merge (SCRIPT_ITEM* items, int itemCount) {
+ if (styles.length > stylesCount) {
+ StyleItem[] newStyles = new StyleItem[stylesCount];
+ System.arraycopy(styles, 0, newStyles, 0, stylesCount);
+ styles = newStyles;
+ }
+ int count = 0, start = 0, end = segmentsText.length, itemIndex = 0, styleIndex = 0;
+ StyleItem[] runs = new StyleItem[itemCount + stylesCount];
+ SCRIPT_ITEM* scriptItem;
+ bool linkBefore = false;
+ while (start < end) {
+ StyleItem item = new StyleItem();
+ item.start = start;
+ item.style = styles[styleIndex].style;
+ runs[count++] = item;
+ scriptItem = items + itemIndex;
+ item.analysis = scriptItem.a;
+ if (linkBefore) {
+ item.analysis.fLinkBefore = true;
+ linkBefore = false;
+ }
+ //scriptItem.a = new SCRIPT_ANALYSIS();
+ scriptItem = items + (itemIndex + 1);
+ int itemLimit = index16to8[scriptItem.iCharPos];
+ int styleLimit = translateOffset(styles[styleIndex + 1].start);
+ if (styleLimit <= itemLimit) {
+ styleIndex++;
+ start = styleLimit;
+ if (start < itemLimit && 0 < start && start < end) {
+ dchar pChar = segmentsText[ segmentsText.getAbsoluteCodePointOffset(start, -1) ..$].firstCodePoint();
+ dchar tChar = segmentsText[start ..$].firstCodePoint();
+ if (Compatibility.isLetter(pChar) && Compatibility.isLetter(tChar)) {
+ item.analysis.fLinkAfter = true;
+ linkBefore = true;
+ }
+ }
+ }
+ if (itemLimit <= styleLimit) {
+ itemIndex++;
+ start = itemLimit;
+ }
+ item.length = start - item.start;
+ }
+ StyleItem item = new StyleItem();
+ item.start = end;
+ scriptItem = items + itemCount;
+ item.analysis = scriptItem.a;
+ runs[count++] = item;
+ if (runs.length !is count) {
+ StyleItem[] result = new StyleItem[count];
+ System.arraycopy(runs, 0, result, 0, count);
+ return result;
+ }
+ return runs;
+}
+
+/*
+ * Reorder the run
+ */
+StyleItem[] reorder (StyleItem[] runs, bool terminate) {
+ int length_ = runs.length;
+ if (length_ <= 1) return runs;
+ ubyte[] bidiLevels = new ubyte[length_];
+ for (int i=0; iSWT.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.
+ *
-1
which means that the
+ * ascent is calculated from the line fonts.
+ *
+ * @param ascent the new ascent
+ *
+ * @exception IllegalArgumentException -1
-1
which means that the
+ * descent is calculated from the line fonts.
+ *
+ * @param descent the new descent
+ *
+ * @exception IllegalArgumentException -1
SWT.LEFT_TO_RIGHT
or SWT.RIGHT_TO_LEFT
.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException
+ * 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.
+ *
-1
which means wrapping is disabled.
+ *
+ * @param width the new width
+ *
+ * @exception IllegalArgumentException 0
or less than -1
TextStyle
defines a set of styles that can be applied
+ * to a range of text.
+ * + * The hashCode() method in this class uses the values of the public + * fields to compute the hash value. When storing instances of the + * class in hashed collections, do not modify these fields after the + * object has been inserted. + *
+ *
+ * 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.
+ *
SWT.UNDERLINE_SINGLE
.
+ *
+ *
+ * @since 3.1
+ */
+ public bool underline;
+
+ /**
+ * the underline color of the style
+ *
+ * @since 3.4
+ */
+ public Color underlineColor;
+
+ /**
+ * the underline style. This style is ignored when
+ * underline
is false.
+ *
+ * This value should be one of SWT.UNDERLINE_SINGLE
,
+ * SWT.UNDERLINE_DOUBLE
, SWT.UNDERLINE_ERROR
,
+ * or SWT.UNDERLINE_SQUIGGLE
.
+ *
SWT.NONE
.
+ *
+ * This value should be one of SWT.BORDER_SOLID
,
+ * SWT.BORDER_DASH
,SWT.BORDER_DOT
or
+ * SWT.NONE
.
+ *
null
if none
+ * @param foreground the foreground color of the style, null
if none
+ * @param background the background color of the style, null
if none
+ */
+public this (Font font, Color foreground, Color background) {
+ if (font !is null && font.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ if (foreground !is null && foreground.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ if (background !is null && background.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ this.font = font;
+ this.foreground = foreground;
+ this.background = background;
+}
+
+
+/**
+ * Create a new text style from an existing text style.
+ *
+ * @param style the style to copy
+ *
+ * @since 3.4
+ */
+public this (TextStyle style) {
+ if (style is null) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ font = style.font;
+ foreground = style.foreground;
+ background = style.background;
+ underline = style.underline;
+ underlineColor = style.underlineColor;
+ underlineStyle = style.underlineStyle;
+ strikeout = style.strikeout;
+ strikeoutColor = style.strikeoutColor;
+ borderStyle = style.borderStyle;
+ borderColor = style.borderColor;
+ metrics = style.metrics;
+ rise = style.rise;
+}
+
+/**
+ * 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 override int opEquals(Object object) {
+ if (object is this) return true;
+ if (object is null) return false;
+ if (!(cast(TextStyle)object)) return false;
+ TextStyle style = cast(TextStyle)object;
+ if (foreground !is null) {
+ if ( foreground !is style.foreground ) return false;
+ } else if (style.foreground !is null) return false;
+ if (background !is null) {
+ if ( background !is style.background ) return false;
+ } else if (style.background !is null) return false;
+ if (font !is null) {
+ if (font !is style.font) return false;
+ } else if (style.font !is null) return false;
+ if (metrics !is null || style.metrics !is null) return false;
+ if (underline !is style.underline) return false;
+ if (underlineStyle !is style.underlineStyle) return false;
+ if (borderStyle !is style.borderStyle) return false;
+ if (strikeout !is style.strikeout) return false;
+ if (rise !is style.rise) return false;
+ if (underlineColor !is null) {
+ if (!underlineColor.equals(style.underlineColor)) return false;
+ } else if (style.underlineColor !is null) return false;
+ if (strikeoutColor !is null) {
+ if (!strikeoutColor.equals(style.strikeoutColor)) return false;
+ } else if (style.strikeoutColor !is null) return false;
+ if (underlineStyle !is style.underlineStyle) return false;
+ if (borderColor !is null) {
+ if (!borderColor.equals(style.borderColor)) return false;
+ } else if (style.borderColor !is null) return false;
+ return true;
+}
+
+/**
+ * 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 override hash_t toHash() {
+ int hash = 0;
+ if (foreground !is null) hash ^= foreground.toHash();
+ if (background !is null) hash ^= background.toHash();
+ if (font !is null) hash ^= font.toHash();
+ if (metrics !is null) hash ^= metrics.toHash();
+ if (underline) hash ^= hash;
+ if (strikeout) hash ^= hash;
+ hash ^= rise;
+ if (underlineColor !is null) hash ^= underlineColor.hashCode();
+ if (strikeoutColor !is null) hash ^= strikeoutColor.hashCode();
+ if (borderColor !is null) hash ^= borderColor.hashCode();
+ hash ^= underlineStyle;
+ return hash;
+}
+
+bool isAdherentBorder(TextStyle style) {
+ if (this is style) return true;
+ if (style is null) return false;
+ if (borderStyle !is style.borderStyle) return false;
+ if (borderColor !is null) {
+ if (!borderColor.equals(style.borderColor)) return false;
+ } else if (style.borderColor !is null) return false;
+ return true;
+}
+
+bool isAdherentUnderline(TextStyle style) {
+ if (this is style) return true;
+ if (style is null) return false;
+ if (underline !is style.underline) return false;
+ if (underlineStyle !is style.underlineStyle) return false;
+ if (underlineColor !is null) {
+ if (!underlineColor.equals(style.underlineColor)) return false;
+ } else if (style.underlineColor !is null) return false;
+ return true;
+}
+
+bool isAdherentStrikeout(TextStyle style) {
+ if (this is style) return true;
+ if (style is null) return false;
+ if (strikeout !is style.strikeout) return false;
+ if (strikeoutColor !is null) {
+ if (!strikeoutColor.equals(style.strikeoutColor)) return false;
+ } else if (style.strikeoutColor !is null) return false;
+ return true;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the TextStyle
+ */
+override public String toString () {
+ String buffer = "TextStyle {";
+ int startLength = buffer.length;
+ if (font !is null) {
+ if (buffer.length > startLength) buffer ~= ", ";
+ buffer ~= "font=";
+ buffer ~= font.toString;
+ }
+ if (foreground !is null) {
+ if (buffer.length > startLength) buffer ~= ", ";
+ buffer ~= "foreground=";
+ buffer ~= foreground.toString;
+ }
+ if (background !is null) {
+ if (buffer.length > startLength) buffer ~= ", ";
+ buffer ~= "background=";
+ buffer ~= background.toString;
+ }
+ if (underline) {
+ if (buffer.length > startLength) buffer ~= ", ";
+ buffer ~= "underlined";
+ }
+ if (strikeout) {
+ if (buffer.length > startLength) buffer ~= ", ";
+ buffer ~= "striked out";
+ }
+ if (rise !is 0) {
+ if (buffer.length > startLength) buffer ~= ", ";
+ buffer ~= "rise=";
+ buffer ~= to!(String)(rise);
+ }
+ if (metrics !is null) {
+ if (buffer.length > startLength) buffer ~= ", ";
+ buffer ~= "metrics=";
+ buffer ~= metrics.toString;
+ }
+ buffer ~= "}";
+ return buffer;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Transform.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Transform.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,379 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * 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.
+ *
+ * This class requires the operating system's advanced graphics subsystem + * which may not be available on some platforms. + *
+ * + * @see SWT Example: GraphicsExample + * @see Sample code and further information + * + * @since 3.1 + */ +public class Transform : Resource { + alias Resource.init_ init_; + /** + * 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 Gdip.Matrix handle; + +/** + * Constructs a new identity Transform. + *+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param device the device on which to allocate the Transform + * + * @exception IllegalArgumentException+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @param device the device on which to allocate the Transform + * @param elements an array of floats that describe the transformation matrix + * + * @exception IllegalArgumentException+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * + * @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 IllegalArgumentExceptiontrue
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
+ */
+override public bool isDisposed() {
+ return handle is 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 bool isIdentity() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return cast(bool) Gdip.Matrix_IsIdentity(handle);
+}
+
+/**
+ * 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
+ * + * @param hwnd the handle of the Control that is listening for keyboard language + * changes + * @param runnable the code that should be executed when a keyboard language change + * occurs + */ +public static void addLanguageListener (HWND hwnd, Runnable runnable) { + languageMap[hwnd] = runnable; + subclass(hwnd); +} +public static void addLanguageListener (Control control, Runnable runnable) { + addLanguageListener(control.handle, runnable); +} +/** + * Proc used for OS.EnumSystemLanguageGroups call during isBidiPlatform test. + */ +static extern(Windows) int EnumSystemLanguageGroupsProc(uint lpLangGrpId, wchar* lpLangGrpIdString, wchar* lpLangGrpName, uint options, int lParam) { + if (lpLangGrpId is OS.LGRPID_HEBREW) { + isBidiPlatform_ = 1; + return 0; + } + if (lpLangGrpId is OS.LGRPID_ARABIC) { + isBidiPlatform_ = 1; + return 0; + } + return 1; +} +/** + * Wraps the ExtTextOut function. + *
+ * + * @param gc the gc to use for rendering + * @param renderBuffer the glyphs to render as an array of characters + * @param renderDx the width of each glyph in renderBuffer + * @param x x position to start rendering + * @param y y position to start rendering + */ +public static void drawGlyphs(GC gc, wchar[] renderBuffer, int[] renderDx, int x, int y) { + int length_ = renderDx.length; + + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) { + if (OS.GetLayout (gc.handle) !is 0) { + reverse(renderDx); + renderDx[length_-1]--; //fixes bug 40006 + reverse(renderBuffer); + } + } + // render transparently to avoid overlapping segments. fixes bug 40006 + int oldBkMode = OS.SetBkMode(gc.handle, OS.TRANSPARENT); + OS.ExtTextOutW(gc.handle, x, y, ETO_GLYPH_INDEX , null, renderBuffer.ptr, renderBuffer.length, renderDx.ptr); + OS.SetBkMode(gc.handle, oldBkMode); +} +/** + * Return ordering and rendering information for the given text. Wraps the GetFontLanguageInfo + * and GetCharacterPlacement functions. + *
+ *
+ * @param gc the GC to use for measuring of this line, input parameter
+ * @param text text that bidi data should be calculated for, input parameter
+ * @param order an array of integers representing the visual position of each character in
+ * the text array, output parameter
+ * @param classBuffer an array of integers representing the type (e.g., ARABIC, HEBREW,
+ * LOCALNUMBER) of each character in the text array, input/output parameter
+ * @param dx an array of integers representing the pixel width of each glyph in the returned
+ * glyph buffer, output parameter
+ * @param flags an integer representing rendering flag information, input parameter
+ * @param offsets text segments that should be measured and reordered separately, input
+ * parameter. See org.eclipse.swt.custom.BidiSegmentEvent for details.
+ * @return buffer with the glyphs that should be rendered for the given text
+ */
+public static char[] getRenderInfo(GC gc, String text, int[] order, byte[] classBuffer, int[] dx, int flags, int [] offsets) {
+ auto fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
+ auto hHeap = OS.GetProcessHeap();
+ int[8] lpCs;
+ int cs = OS.GetTextCharset(gc.handle);
+ bool isRightOriented = false;
+ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+ isRightOriented = OS.GetLayout(gc.handle) !is 0;
+ }
+ OS.TranslateCharsetInfo( cast(uint*)cs, cast(CHARSETINFO*)lpCs.ptr, OS.TCI_SRCCHARSET);
+ TCHAR[] textBuffer = StrToTCHARs(lpCs[1], text, false);
+ int byteCount = textBuffer.length;
+ bool linkBefore = (flags & LINKBEFORE) is LINKBEFORE;
+ bool linkAfter = (flags & LINKAFTER) is LINKAFTER;
+
+ GCP_RESULTS result;
+ result.lStructSize = GCP_RESULTS.sizeof;
+ result.nGlyphs = byteCount;
+ auto lpOrder = result.lpOrder = cast(uint*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
+ auto lpDx = result.lpDx = cast(int*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
+ auto lpClass = result.lpClass = cast(CHAR*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+ auto lpGlyphs = result.lpGlyphs = cast(wchar*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 2);
+
+ // set required dwFlags
+ int dwFlags = 0;
+ int glyphFlags = 0;
+ // Always reorder. We assume that if we are calling this function we're
+ // on a platform that supports bidi. Fixes 20690.
+ dwFlags |= GCP_REORDER;
+ if ((fontLanguageInfo & GCP_LIGATE) is GCP_LIGATE) {
+ dwFlags |= GCP_LIGATE;
+ glyphFlags |= 0;
+ }
+ if ((fontLanguageInfo & GCP_GLYPHSHAPE) is GCP_GLYPHSHAPE) {
+ dwFlags |= GCP_GLYPHSHAPE;
+ if (linkBefore) {
+ glyphFlags |= GCPGLYPH_LINKBEFORE;
+ }
+ if (linkAfter) {
+ glyphFlags |= GCPGLYPH_LINKAFTER;
+ }
+ }
+ byte[] lpGlyphs2;
+ if (linkBefore || linkAfter) {
+ lpGlyphs2 = new byte[2];
+ lpGlyphs2[0]=cast(byte)glyphFlags;
+ lpGlyphs2[1]=cast(byte)(glyphFlags >> 8);
+ }
+ else {
+ lpGlyphs2 = [cast(byte) glyphFlags];
+ }
+ OS.MoveMemory(result.lpGlyphs, lpGlyphs2.ptr, lpGlyphs2.length);
+
+ if ((flags & CLASSIN) is CLASSIN) {
+ // set classification values for the substring
+ dwFlags |= GCP_CLASSIN;
+ OS.MoveMemory(result.lpClass, classBuffer.ptr, classBuffer.length);
+ }
+
+ wchar[] glyphBuffer = new wchar[result.nGlyphs];
+ int glyphCount = 0;
+ for (int i=0; i
+ *
+ * @return an integer representing the active keyboard language (KEYBOARD_BIDI,
+ * KEYBOARD_NON_BIDI)
+ */
+public static int getKeyboardLanguage() {
+ int layout = cast(int) OS.GetKeyboardLayout(0);
+ int langID = OS.PRIMARYLANGID(OS.LOWORD(layout));
+ if (langID is LANG_HEBREW) return KEYBOARD_BIDI;
+ if (langID is LANG_ARABIC) return KEYBOARD_BIDI;
+ // return non-bidi for all other languages
+ return KEYBOARD_NON_BIDI;
+}
+/**
+ * Return the languages that are installed for the keyboard.
+ *
+ *
+ * @return integer array with an entry for each installed language
+ */
+static void*[] getKeyboardLanguageList() {
+ int maxSize = 10;
+ void*[] tempList = new void*[maxSize];
+ int size = OS.GetKeyboardLayoutList(maxSize, tempList.ptr);
+ void*[] list = new void*[size];
+ System.arraycopy(tempList, 0, list, 0, size);
+ return list;
+}
+/**
+ * Return whether or not the platform supports a bidi language. Determine this
+ * by looking at the languages that are installed.
+ *
+ *
+ * @return true if bidi is supported, false otherwise. Always
+ * false on Windows CE.
+ */
+public static bool isBidiPlatform() {
+ if (OS.IsWinCE) return false;
+ if (isBidiPlatform_ !is -1) return isBidiPlatform_ is 1; // already set
+
+ isBidiPlatform_ = 0;
+
+ // The following test is a workaround for bug report 27629. On WinXP,
+ // both bidi and complex script (e.g., Thai) languages must be installed
+ // at the same time. Since the bidi platform calls do not support
+ // double byte characters, there is no way to run Eclipse using the
+ // complex script languages on XP, so constrain this test to answer true
+ // only if a bidi input language is defined. Doing so will allow complex
+ // script languages to work (e.g., one can install bidi and complex script
+ // languages, but only install the Thai keyboard).
+ if (!isKeyboardBidi()) return false;
+
+ //Callback callback = null;
+ //try {
+ //callback = new Callback (Class.forName (CLASS_NAME), "EnumSystemLanguageGroupsProc", 5); //$NON-NLS-1$
+ //int lpEnumSystemLanguageGroupsProc = callback.getAddress ();
+ //if (lpEnumSystemLanguageGroupsProc is 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+ OS.EnumSystemLanguageGroups(&EnumSystemLanguageGroupsProc, OS.LGRPID_INSTALLED, 0);
+ //callback.dispose ();
+ //} catch (ClassNotFoundException e) {
+ //if (callback !is null) callback.dispose();
+ //}
+ if (isBidiPlatform_ is 1) return true;
+ // need to look at system code page for NT & 98 platforms since EnumSystemLanguageGroups is
+ // not supported for these platforms
+ String codePage = to!(String)(OS.GetACP());
+ if (CD_PG_ARABIC==/*eq*/codePage || CD_PG_HEBREW==/*eq*/codePage) {
+ isBidiPlatform_ = 1;
+ }
+ return isBidiPlatform_ is 1;
+}
+/**
+ * Return whether or not the keyboard supports input of a bidi language. Determine this
+ * by looking at the languages that are installed for the keyboard.
+ *
+ *
+ * @return true if bidi is supported, false otherwise.
+ */
+public static bool isKeyboardBidi() {
+ void*[] list = getKeyboardLanguageList();
+ for (int i=0; i
+ *
+ * @param language integer representing language. One of
+ * KEYBOARD_BIDI, KEYBOARD_NON_BIDI.
+ */
+public static void setKeyboardLanguage(int language) {
+ // don't switch the keyboard if it doesn't need to be
+ if (language is getKeyboardLanguage()) return;
+
+ if (language is KEYBOARD_BIDI) {
+ // get the list of active languages
+ void*[] list = getKeyboardLanguageList();
+ // set to first bidi language
+ for (int i=0; i
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms. Under this scheme, classes need to
+ * implement CloneableCompatibility instead of java.lang.Cloneable.
+ *
+ * Note: java.lang.Cloneable is not part of CLDC.
+ *
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms.
+ *
+ * IMPORTANT: some of the methods have been modified from their
+ * J2SE parents. Refer to the description of each method for
+ * specific changes.
+ *
+ * IMPORTANT: the j2me version has an additional restriction on
+ * the argument. length must be between -32767 and 32767 (inclusive).
+ *
+ * IMPORTANT: the j2me version has an additional restriction on
+ * the argument. length must be between -32767 and 32767 (inclusive).
+ *
+ * IMPORTANT: the j2me version has an additional restriction on
+ * the arguments. p must be within the range 0 - 32767 (inclusive).
+ * q must be within the range 1 - 32767 (inclusive).
+ *
+ * The new process inherits the environment of the caller.
+ *
+ * The new process inherits the environment of the caller.
+ *
+ *
+ * @param progArray array containing the program to execute and its arguments
+ *
+ * @exception ProcessException
+ * if the program cannot be executed
+ */
+public static void exec(String[] progArray) {
+ auto proc = new Process( progArray );
+ proc.execute;
+}
+
+const ImportData[] SWTMessagesBundleData = [
+ getImportData!( "swt.internal.SWTMessages.properties" ),
+ getImportData!( "swt.internal.SWTMessages_ar.properties" ),
+ getImportData!( "swt.internal.SWTMessages_cs.properties" ),
+ getImportData!( "swt.internal.SWTMessages_da.properties" ),
+ getImportData!( "swt.internal.SWTMessages_de.properties" ),
+ getImportData!( "swt.internal.SWTMessages_el.properties" ),
+ getImportData!( "swt.internal.SWTMessages_es.properties" ),
+ getImportData!( "swt.internal.SWTMessages_fi.properties" ),
+ getImportData!( "swt.internal.SWTMessages_fr.properties" ),
+ getImportData!( "swt.internal.SWTMessages_hu.properties" ),
+ getImportData!( "swt.internal.SWTMessages_it.properties" ),
+ getImportData!( "swt.internal.SWTMessages_iw.properties" ),
+ getImportData!( "swt.internal.SWTMessages_ja.properties" ),
+ getImportData!( "swt.internal.SWTMessages_ko.properties" ),
+ getImportData!( "swt.internal.SWTMessages_nl.properties" ),
+ getImportData!( "swt.internal.SWTMessages_no.properties" ),
+ getImportData!( "swt.internal.SWTMessages_pl.properties" ),
+ getImportData!( "swt.internal.SWTMessages_pt_BR.properties" ),
+ getImportData!( "swt.internal.SWTMessages_pt.properties" ),
+ getImportData!( "swt.internal.SWTMessages_ru.properties" ),
+ getImportData!( "swt.internal.SWTMessages_sv.properties" ),
+ getImportData!( "swt.internal.SWTMessages_tr.properties" ),
+ getImportData!( "swt.internal.SWTMessages_zh_HK.properties" ),
+ getImportData!( "swt.internal.SWTMessages_zh.properties" ),
+ getImportData!( "swt.internal.SWTMessages_zh_TW.properties" )
+];
+
+private static ResourceBundle msgs = null;
+
+/**
+ * Returns the NLS'ed message for the given argument. This is only being
+ * called from SWT.
+ *
+ * @param key the key to look up
+ * @return the message for the given key
+ *
+ * @see SWT#getMessage(String)
+ */
+public static String getMessage(String key) {
+ String answer = key;
+
+ if (key is null) {
+ SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (msgs is null) {
+ try {
+ msgs = ResourceBundle.getBundle(SWTMessagesBundleData); //$NON-NLS-1$
+ } catch (MissingResourceException ex) {
+ answer = key ~ " (no resource bundle)"; //$NON-NLS-1$
+ }
+ }
+ if (msgs !is null) {
+ try {
+ answer = msgs.getString(key);
+ } catch (MissingResourceException ex2) {}
+ }
+ return answer;
+}
+
+public static String getMessage(String key, Object[] args) {
+ String answer = key;
+
+ if (key is null || args is null) {
+ SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (msgs is null) {
+ try {
+ msgs = ResourceBundle.getBundle(SWTMessagesBundleData); //$NON-NLS-1$
+ } catch (MissingResourceException ex) {
+ answer = key ~ " (no resource bundle)"; //$NON-NLS-1$
+ }
+ }
+ if (msgs !is null) {
+ try {
+ char[] frmt = msgs.getString(key);
+ switch( args.length ){
+ case 0: answer = Format(frmt); break;
+ case 1: answer = Format(frmt, args[0]); break;
+ case 2: answer = Format(frmt, args[0], args[1]); break;
+ case 3: answer = Format(frmt, args[0], args[1], args[2]); break;
+ case 4: answer = Format(frmt, args[0], args[1], args[2], args[3]); break;
+ case 5: answer = Format(frmt, args[0], args[1], args[2], args[3], args[4]); break;
+ default:
+ implMissing(__FILE__, __LINE__ );
+ }
+ } catch (MissingResourceException ex2) {}
+ }
+ return answer;
+}
+
+
+/**
+ * Interrupt the current thread.
+ *
+ * Note that this is not available on CLDC.
+ *
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms. Under this scheme, classes need to
+ * implement SWTEventListener instead of java.util.EventListener.
+ *
+ * Note: java.util.EventListener is not part of CDC and CLDC.
+ *
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms. Under this scheme, classes need to
+ * extend SWTEventObject instead of java.util.EventObject.
+ *
+ * Note: java.util.EventObject is not part of CDC and CLDC.
+ *
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms. Under this scheme, classes need to
+ * implement SerializableCompatibility instead of
+ * java.io.Serializable.
+ *
+ * Note: java.io.Serializable is not part of CLDC.
+ *
+ * Answer the number of bytes actually read or -1 if no bytes were read and
+ * end of stream was encountered. This implementation reads bytes from
+ * the pushback buffer first, then the target stream if more bytes are required
+ * to satisfy
+ * The bytes are pushed so that they would be read back b[0], b[1], etc.
+ * If the push back buffer cannot handle the bytes copied from
+ * Initially, the controls will all be as tall as the tallest control,
+ * and as wide as the widest.
+ * Example code: first a
+ *
+ * A
+ *
+ */
+public final class Compatibility {
+
+/**
+ * Returns the PI constant as a double.
+ */
+public static const real PI = Math.PI;
+
+static const real toRadians = PI / 180;
+
+/**
+ * Answers the length of the side adjacent to the given angle
+ * of a right triangle. In other words, it returns the integer
+ * conversion of length * cos (angle).
+ *
+ *
+ */
+public static int pow2(int n) {
+ if (n >= 1 && n <= 30)
+ return 2 << (n - 1);
+ else if (n != 0) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ return 1;
+}
+
+/**
+ * Create an DeflaterOutputStream if such things are supported.
+ *
+ * @param stream the output stream
+ * @return a deflater stream or null
+ * @exception IOException
+ *
+ * @since 3.4
+ */
+public static OutputStream newDeflaterOutputStream(OutputStream stream) {
+ //DWT_TODO
+ implMissing(__FILE__,__LINE__);
+ return null;
+ //return new DeflaterOutputStream(stream);
+}
+
+/**
+ * Open a file if such things are supported.
+ *
+ * @param filename the name of the file to open
+ * @return a stream on the file if it could be opened.
+ * @exception IOException
+ */
+public static InputStream newFileInputStream(String filename) {
+ return new FileInputStream(filename);
+}
+
+/**
+ * Open a file if such things are supported.
+ *
+ * @param filename the name of the file to open
+ * @return a stream on the file if it could be opened.
+ * @exception IOException
+ */
+public static OutputStream newFileOutputStream(String filename) {
+ return new FileOutputStream(filename);
+}
+
+/**
+ * Create an InflaterInputStream if such things are supported.
+ *
+ * @param stream the input stream
+ * @return a inflater stream or null
+ * @exception IOException
+ *
+ * @since 3.3
+ */
+public static InflaterInputStream newInflaterInputStream(InputStream stream) {
+ return new InflaterInputStream(stream);
+}
+
+/**
+ * Answers whether the character is a letter.
+ *
+ * @param c the character
+ * @return true when the character is a letter
+ */
+public static bool isLetter(dchar c) {
+ return Unicode.isLetter(c);
+}
+
+/**
+ * Answers whether the character is a letter or a digit.
+ *
+ * @param c the character
+ * @return true when the character is a letter or a digit
+ */
+public static bool isLetterOrDigit(dchar c) {
+ return Unicode.isLetterOrDigit(c);
+}
+
+/**
+ * Answers whether the character is a Unicode space character.
+ *
+ * @param c the character
+ * @return true when the character is a Unicode space character
+ */
+public static bool isSpaceChar(dchar c) {
+ return Unicode.isSpace(c);
+}
+
+/**
+ * Answers whether the character is a whitespace character.
+ *
+ * @param c the character to test
+ * @return true if the character is whitespace
+ */
+public static bool isWhitespace(dchar c) {
+ return Unicode.isWhitespace(c);
+}
+
+/**
+ * Execute a program in a separate platform process if the
+ * underlying platform support this.
+ * name
is used to load the library. If this fails,
+ * name
is used in another attempt to load the library,
+ * this time ignoring the SWT version encoding scheme.
+ *
+ * @param name the name of the library to load
+ */
+public static void loadLibrary (String name) {
+ loadLibrary (name, true);
+}
+
+/**
+ * Loads the shared library that matches the version of the
+ * Java code which is currently running. SWT shared libraries
+ * follow an encoding scheme where the major, minor and revision
+ * numbers are embedded in the library name and this along with
+ * name
is used to load the library. If this fails,
+ * name
is used in another attempt to load the library,
+ * this time ignoring the SWT version encoding scheme.
+ *
+ * @param name the name of the library to load
+ * @param mapName true if the name should be mapped, false otherwise
+ */
+public static void loadLibrary (String name, boolean mapName) {
+ String prop = System.getProperty ("sun.arch.data.model"); //$NON-NLS-1$
+ if (prop is null) prop = System.getProperty ("com.ibm.vm.bitmode"); //$NON-NLS-1$
+ if (prop !is null) {
+ if ("32".equals (prop)) { //$NON-NLS-1$
+ if (0x1FFFFFFFFL is (int /*long*/)0x1FFFFFFFFL) {
+ throw new UnsatisfiedLinkError ("Cannot load 64-bit SWT libraries on 32-bit JVM"); //$NON-NLS-1$
+ }
+ }
+ if ("64".equals (prop)) { //$NON-NLS-1$
+ if (0x1FFFFFFFFL !is (int /*long*/)0x1FFFFFFFFL) {
+ throw new UnsatisfiedLinkError ("Cannot load 32-bit SWT libraries on 64-bit JVM"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /* Compute the library name and mapped name */
+ String libName1, libName2, mappedName1, mappedName2;
+ if (mapName) {
+ String version = System.getProperty ("swt.version"); //$NON-NLS-1$
+ if (version == null) {
+ version = "" + MAJOR_VERSION; //$NON-NLS-1$
+ /* Force 3 digits in minor version number */
+ if (MINOR_VERSION < 10) {
+ version += "00"; //$NON-NLS-1$
+ } else {
+ if (MINOR_VERSION < 100) version += "0"; //$NON-NLS-1$
+ }
+ version += MINOR_VERSION;
+ /* No "r" until first revision */
+ if (REVISION > 0) version += "r" + REVISION; //$NON-NLS-1$
+ }
+ libName1 = name + "-" + Platform.PLATFORM + "-" + version; //$NON-NLS-1$ //$NON-NLS-2$
+ libName2 = name + "-" + Platform.PLATFORM; //$NON-NLS-1$
+ mappedName1 = System.mapLibraryName (libName1);
+ mappedName2 = System.mapLibraryName (libName2);
+ } else {
+ libName1 = libName2 = mappedName1 = mappedName2 = name;
+ }
+
+ /* Try loading library from swt library path */
+ String path = System.getProperty ("swt.library.path"); //$NON-NLS-1$
+ if (path != null) {
+ path = new File (path).getAbsolutePath ();
+ if (load (path + SEPARATOR + mappedName1)) return;
+ if (mapName && load (path + SEPARATOR + mappedName2)) return;
+ }
+
+ /* Try loading library from java library path */
+ if (load (libName1)) return;
+ if (mapName && load (libName2)) return;
+
+ /* Try loading library from the tmp directory if swt library path is not specified */
+ if (path == null) {
+ path = System.getProperty ("java.io.tmpdir"); //$NON-NLS-1$
+ path = new File (path).getAbsolutePath ();
+ if (load (path + SEPARATOR + mappedName1)) return;
+ if (mapName && load (path + SEPARATOR + mappedName2)) return;
+ }
+
+ /* Try extracting and loading library from jar */
+ if (path != null) {
+ if (extract (path + SEPARATOR + mappedName1, mappedName1)) return;
+ if (mapName && extract (path + SEPARATOR + mappedName2, mappedName2)) return;
+ }
+
+ /* Failed to find the library */
+ throw new UnsatisfiedLinkError ("no " + libName1 + " or " + libName2 + " in swt.library.path, java.library.path or the jar file"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+}
++/
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Lock.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Lock.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit buf
. A value
+ * equal to buf.length indicates no bytes available. A value of
+ * 0 indicates the buffer is full.
+ */
+ protected int pos;
+
+
+ public this(InputStream input) {
+ this(input, 512);
+ }
+
+ public this(InputStream input, int bufferSize) {
+ host = input;
+ if (bufferSize > 0) {
+ buf = new byte[bufferSize];
+ pos = bufferSize;
+ }
+ else throw new IllegalArgumentException("bufferSize must be greater zero" );
+ }
+
+ public void close() {
+ buf = null;
+ if (host !is null) {
+ host.close();
+ host = null;
+ }
+ }
+
+ /**
+ * Answer how many bytes were read.
+ */
+ public int getPosition() {
+ return position;
+ }
+
+ /**
+ * Answers how many bytes are available for reading without blocking
+ */
+ public override int available() {
+ if (buf is null) throw new IOException("buf is null");
+ return (buf.length - pos) + host.available();
+ }
+
+ /**
+ * Answer the next byte of the input stream.
+ */
+ public override int read() {
+ if (buf is null) throw new IOException("buf is null");
+ if (pos < buf.length) {
+ position++;
+ return (buf[pos++] & 0xFF);
+ }
+ int c = host.read();
+ if (c !is -1 ) position++;
+ return c;
+ }
+
+ /**
+ * Don't imitate the JDK behaviour of reading a random number
+ * of bytes when you can actually read them all.
+ */
+ public override int read(byte b[], int off, int len) {
+ int read = 0, count;
+ while (read !is len && (count = readData(b, off, len - read)) !is -1) {
+ off += count;
+ read += count;
+ }
+ position += read;
+ if (read is 0 && read !is len) return -1;
+ return read;
+ }
+
+ /**
+ * Reads at most length
bytes from this LEDataInputStream and
+ * stores them in byte array buffer
starting at offset
.
+ * count
.
+ * buffer
to store the read bytes.
+ * @param length the maximum number of bytes to store in buffer
.
+ *
+ * @return int the number of bytes actually read or -1 if end of stream.
+ *
+ * @exception java.io.IOException if an IOException occurs.
+ */
+ private int readData(byte[] buffer, int offset, int len) {
+ if (buf is null) throw new IOException("buf is null");
+ if (offset < 0 || offset > buffer.length ||
+ len < 0 || (len > buffer.length - offset)) {
+ throw new ArrayBoundsException(__FILE__,__LINE__);
+ }
+
+ int cacheCopied = 0;
+ int newOffset = offset;
+
+ // Are there pushback bytes available?
+ int available = buf.length - pos;
+ if (available > 0) {
+ cacheCopied = (available >= len) ? len : available;
+ System.arraycopy(buf, pos, buffer, newOffset, cacheCopied);
+ newOffset += cacheCopied;
+ pos += cacheCopied;
+ }
+
+ // Have we copied enough?
+ if (cacheCopied is len) return len;
+
+ int inCopied = host.read( buffer, newOffset, len - cacheCopied );
+ if( inCopied is -1 ) inCopied = -1;
+ if (inCopied > 0 ) return inCopied + cacheCopied;
+ if (cacheCopied is 0) return inCopied;
+ return cacheCopied;
+ }
+
+ /**
+ * Answer an integer comprised of the next
+ * four bytes of the input stream.
+ */
+ public int readInt() {
+ byte[4] buf = void;
+ read(buf);
+ return ((buf[3] & 0xFF) << 24) |
+ ((buf[2] & 0xFF) << 16) |
+ ((buf[1] & 0xFF) << 8) |
+ (buf[0] & 0xFF);
+ }
+
+ /**
+ * Answer a short comprised of the next
+ * two bytes of the input stream.
+ */
+ public short readShort() {
+ byte[2] buf = void;
+ read(buf);
+ return cast(short)(((buf[1] & 0xFF) << 8) | (buf[0] & 0xFF));
+ }
+
+ /**
+ * Push back the entire content of the given buffer b
.
+ * b
,
+ * an IOException will be thrown and no byte will be pushed back.
+ * FillLayout
is the simplest layout class. It lays out
+ * controls in a single row or column, forcing them to be the same size.
+ * FillLayout
does not wrap,
+ * but you can specify margins and spacing. You might use it to
+ * lay out buttons in a task bar or tool bar, or to stack checkboxes
+ * in a Group
. FillLayout
can also be used
+ * when a Composite
only has one child. For example,
+ * if a Shell
has a single Group
child,
+ * FillLayout
will cause the Group
to
+ * completely fill the Shell
(if margins are 0).
+ * FillLayout
is created and
+ * its type field is set, and then the layout is set into the
+ * Composite
. Note that in a FillLayout
,
+ * children are always the same size, and they fill all available space.
+ *
+ * FillLayout fillLayout = new FillLayout();
+ * fillLayout.type = SWT.VERTICAL;
+ * shell.setLayout(fillLayout);
+ *
+ *
+ *
+ */
+ public int type = SWT.HORIZONTAL;
+
+ /**
+ * marginWidth specifies the number of pixels of horizontal margin
+ * that will be placed along the left and right edges of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.0
+ */
+ public int marginWidth = 0;
+
+ /**
+ * marginHeight specifies the number of pixels of vertical margin
+ * that will be placed along the top and bottom edges of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.0
+ */
+ public int marginHeight = 0;
+
+ /**
+ * spacing specifies the number of pixels between the edge of one cell
+ * and the edge of its neighbouring cell.
+ *
+ * The default value is 0.
+ *
+ * @since 3.0
+ */
+ public int spacing = 0;
+
+/**
+ * Constructs a new instance of this class.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance of this class given the type.
+ *
+ * @param type the type of fill layout
+ *
+ * @since 2.0
+ */
+public this (int type) {
+ this.type = type;
+}
+
+override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache) {
+ Control [] children = composite.getChildren ();
+ int count = children.length;
+ int maxWidth = 0, maxHeight = 0;
+ for (int i=0; iFormLayout
.
+ * FormAttachments
are set into the top, bottom, left,
+ * and right fields of the FormData
for a control.
+ * For example:
+ *
+ * FormData data = new FormData();
+ * data.top = new FormAttachment(0,5);
+ * data.bottom = new FormAttachment(100,-5);
+ * data.left = new FormAttachment(0,5);
+ * data.right = new FormAttachment(100,-5);
+ * button.setLayoutData(data);
+ *
+ * FormAttachment
defines where to attach the side of
+ * a control by using the equation, y = ax + b. The "a" term represents
+ * a fraction of the parent composite's width (from the left) or height
+ * (from the top). It can be defined using a numerator and denominator,
+ * or just a percentage value. If a percentage is used, the denominator
+ * is set to 100. The "b" term in the equation represents an offset, in
+ * pixels, from the attachment position. For example:
+ *
+ * FormAttachment attach = new FormAttachment (20, -5);
+ *
+ * specifies that the side to which the FormAttachment
+ * object belongs will lie at 20% of the parent composite, minus 5 pixels.
+ *
+ * Control sides can also be attached to another control. + * For example: + *
+ * FormAttachment attach = new FormAttachment (button, 10); + *+ * specifies that the side to which the
FormAttachment
+ * object belongs will lie in the same position as the adjacent side of
+ * the button
control, plus 10 pixels. The control side can
+ * also be attached to the opposite side of the specified control.
+ * For example:
+ * + * FormData data = new FormData (); + * data.left = new FormAttachment (button, 0, SWT.LEFT); + *+ * specifies that the left side of the control will lie in the same position + * as the left side of the
button
control. The control can also
+ * be attached in a position that will center the control on the specified
+ * control. For example:
+ * + * data.left = new FormAttachment (button, 0, SWT.CENTER); + *+ * specifies that the left side of the control will be positioned so that it is + * centered between the left and right sides of the
button
control.
+ * If the alignment is not specified, the default is to attach to the adjacent side.
+ *
+ *
+ * @see FormLayout
+ * @see FormData
+ * @see Sample code and further information
+ *
+ * @since 2.0
+ */
+public final class FormAttachment {
+ /**
+ * numerator specifies the numerator of the "a" term in the
+ * equation, y = ax + b, which defines the attachment.
+ */
+ public int numerator;
+
+ /**
+ * denominator specifies the denominator of the "a" term in the
+ * equation, y = ax + b, which defines the attachment.
+ *
+ * The default value is 100.
+ */
+ public int denominator = 100;
+
+ /**
+ * offset specifies the offset, in pixels, of the control side
+ * from the attachment position.
+ * If the offset is positive, then the control side is offset
+ * to the right of or below the attachment position. If it is
+ * negative, then the control side is offset to the left of or
+ * above the attachment position.
+ *
+ * This is equivalent to the "b" term in the equation y = ax + b.
+ * The default value is 0.
+ */
+ public int offset;
+
+ /**
+ * control specifies the control to which the control side is
+ * attached.
+ */
+ public Control control;
+
+ /**
+ * alignment specifies the alignment of the control side that is
+ * attached to a control.
+ * + * For top and bottom attachments, TOP, BOTTOM and CENTER are used. For left + * and right attachments, LEFT, RIGHT and CENTER are used. If any other case + * occurs, the default will be used instead. + *
+ * + *FormLayout
.
+ *
+ * To set a FormData
object into a control, you use the
+ * setLayoutData ()
method. To define attachments for the
+ * FormData
, set the fields directly, like this:
+ *
+ * FormData data = new FormData(); + * data.left = new FormAttachment(0,5); + * data.right = new FormAttachment(100,-5); + * button.setLayoutData(formData); + *+ * + *
+ * FormData
contains the FormAttachments
for
+ * each edge of the control that the FormLayout
uses to
+ * determine the size and position of the control. FormData
+ * objects also allow you to set the width and height of controls within
+ * a FormLayout
.
+ *
FormAttachments
+ * to optionally configure the left, top, right and bottom edges of
+ * each child.
+ *
+ * The following example code creates a FormLayout
and then sets
+ * it into a Shell
:
+ *
+ * Display display = new Display (); + * Shell shell = new Shell(display); + * FormLayout layout = new FormLayout(); + * layout.marginWidth = 3; + * layout.marginHeight = 3; + * shell.setLayout(layout); + *+ * + *
+ * To use a FormLayout
, create a FormData
with
+ * FormAttachment
for each child of Composite
.
+ * The following example code attaches button1
to the top
+ * and left edge of the composite and button2
to the right
+ * edge of button1
and the top and right edges of the
+ * composite:
+ *
+ * FormData data1 = new FormData(); + * data1.left = new FormAttachment(0, 0); + * data1.top = new FormAttachment(0, 0); + * button1.setLayoutData(data1); + * FormData data2 = new FormData(); + * data2.left = new FormAttachment(button1); + * data2.top = new FormAttachment(0, 0); + * data2.right = new FormAttachment(100, 0); + * button2.setLayoutData(data2); + *+ * + *
+ * Each side of a child control can be attached to a position in the parent
+ * composite, or to other controls within the Composite
by
+ * creating instances of FormAttachment
and setting them into
+ * the top, bottom, left, and right fields of the child's FormData
.
+ *
+ * If a side is not given an attachment, it is defined as not being attached
+ * to anything, causing the child to remain at its preferred size. If a child
+ * is given no attachment on either the left or the right or top or bottom, it is
+ * automatically attached to the left and top of the composite respectively.
+ * The following code positions button1
and button2
+ * but relies on default attachments:
+ *
+ * FormData data2 = new FormData(); + * data2.left = new FormAttachment(button1); + * data2.right = new FormAttachment(100, 0); + * button2.setLayoutData(data2); + *+ * + *
+ * IMPORTANT: Do not define circular attachments. For example, do not attach
+ * the right edge of button1
to the left edge of button2
+ * and then attach the left edge of button2
to the right edge of
+ * button1
. This will over constrain the layout, causing undefined
+ * behavior. The algorithm will terminate, but the results are undefined.
+ *
GridData
is the layout data object associated with
+ * GridLayout
. To set a GridData
object into a
+ * control, you use the Control.setLayoutData(Object)
method.
+ *
+ * There are two ways to create a GridData
object with certain
+ * fields set. The first is to set the fields directly, like this:
+ *
+ * GridData gridData = new GridData(); + * gridData.horizontalAlignment = GridData.FILL; + * gridData.grabExcessHorizontalSpace = true; + * button1.setLayoutData(gridData); + *+ * The second is to take advantage of convenience style bits defined + * by
GridData
:
+ * + * button1.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + *+ * + *
+ * NOTE: Do not reuse GridData
objects. Every control in a
+ * Composite
that is managed by a GridLayout
+ * must have a unique GridData
object. If the layout data
+ * for a control in a GridLayout
is null at layout time,
+ * a unique GridData
object is created for it.
+ *
grabExcessHorizontalSpace specifies whether the width of the cell
+ * changes depending on the size of the parent Composite. If
+ * grabExcessHorizontalSpace is true
, the following rules
+ * apply to the width of the cell:
The default value is false.
+ * + * @see GridData#minimumWidth + * @see GridData#widthHint + */ + public bool grabExcessHorizontalSpace = false; + + /** + *grabExcessVerticalSpace specifies whether the height of the cell
+ * changes depending on the size of the parent Composite. If
+ * grabExcessVerticalSpace is true
, the following rules
+ * apply to the height of the cell:
The default value is false.
+ * + * @see GridData#minimumHeight + * @see GridData#heightHint + */ + public bool grabExcessVerticalSpace = false; + + /** + * minimumWidth specifies the minimum width in pixels. This value + * applies only if grabExcessHorizontalSpace is true. A value of + * SWT.DEFAULT means that the minimum width will be the result + * of Control.computeSize(int, int, bool) where wHint is + * determined by GridData.widthHint. + * + * The default value is 0. + * + * @since 3.1 + * @see Control#computeSize(int, int, bool) + * @see GridData#widthHint + */ + public int minimumWidth = 0; + + /** + * minimumHeight specifies the minimum height in pixels. This value + * applies only if grabExcessVerticalSpace is true. A value of + * SWT.DEFAULT means that the minimum height will be the result + * of Control.computeSize(int, int, bool) where hHint is + * determined by GridData.heightHint. + * + * The default value is 0. + * + * @since 3.1 + * @see Control#computeSize(int, int, bool) + * @see GridData#heightHint + */ + public int minimumHeight = 0; + + /** + * exclude informs the layout to ignore this control when sizing + * and positioning controls. If this value istrue
,
+ * the size and position of the control will not be managed by the
+ * layout. If this value is false
, the size and
+ * position of the control will be computed and assigned.
+ *
+ * The default value is false
.
+ *
+ * @since 3.1
+ */
+ public bool exclude = false;
+
+ /**
+ * Value for horizontalAlignment or verticalAlignment.
+ * Position the control at the top or left of the cell.
+ * Not recommended. Use SWT.BEGINNING, SWT.TOP or SWT.LEFT instead.
+ */
+ public static const int BEGINNING = SWT.BEGINNING;
+
+ /**
+ * Value for horizontalAlignment or verticalAlignment.
+ * Position the control in the vertical or horizontal center of the cell
+ * Not recommended. Use SWT.CENTER instead.
+ */
+ public static const int CENTER = 2;
+
+ /**
+ * Value for horizontalAlignment or verticalAlignment.
+ * Position the control at the bottom or right of the cell
+ * Not recommended. Use SWT.END, SWT.BOTTOM or SWT.RIGHT instead.
+ */
+ public static const int END = 3;
+
+ /**
+ * Value for horizontalAlignment or verticalAlignment.
+ * Resize the control to fill the cell horizontally or vertically.
+ * Not recommended. Use SWT.FILL instead.
+ */
+ public static const int FILL = SWT.FILL;
+
+ /**
+ * Style bit for new GridData(int)
.
+ * Position the control at the top of the cell.
+ * Not recommended. Use
+ * new GridData(int, SWT.BEGINNING, bool, bool)
+ * instead.
+ */
+ public static const int VERTICAL_ALIGN_BEGINNING = 1 << 1;
+
+ /**
+ * Style bit for new GridData(int)
to position the
+ * control in the vertical center of the cell.
+ * Not recommended. Use
+ * new GridData(int, SWT.CENTER, bool, bool)
+ * instead.
+ */
+ public static const int VERTICAL_ALIGN_CENTER = 1 << 2;
+
+ /**
+ * Style bit for new GridData(int)
to position the
+ * control at the bottom of the cell.
+ * Not recommended. Use
+ * new GridData(int, SWT.END, bool, bool)
+ * instead.
+ */
+ public static const int VERTICAL_ALIGN_END = 1 << 3;
+
+ /**
+ * Style bit for new GridData(int)
to resize the
+ * control to fill the cell vertically.
+ * Not recommended. Use
+ * new GridData(int, SWT.FILL, bool, bool)
+ * instead
+ */
+ public static const int VERTICAL_ALIGN_FILL = 1 << 4;
+
+ /**
+ * Style bit for new GridData(int)
to position the
+ * control at the left of the cell.
+ * Not recommended. Use
+ * new GridData(SWT.BEGINNING, int, bool, bool)
+ * instead.
+ */
+ public static const int HORIZONTAL_ALIGN_BEGINNING = 1 << 5;
+
+ /**
+ * Style bit for new GridData(int)
to position the
+ * control in the horizontal center of the cell.
+ * Not recommended. Use
+ * new GridData(SWT.CENTER, int, bool, bool)
+ * instead.
+ */
+ public static const int HORIZONTAL_ALIGN_CENTER = 1 << 6;
+
+ /**
+ * Style bit for new GridData(int)
to position the
+ * control at the right of the cell.
+ * Not recommended. Use
+ * new GridData(SWT.END, int, bool, bool)
+ * instead.
+ */
+ public static const int HORIZONTAL_ALIGN_END = 1 << 7;
+
+ /**
+ * Style bit for new GridData(int)
to resize the
+ * control to fill the cell horizontally.
+ * Not recommended. Use
+ * new GridData(SWT.FILL, int, bool, bool)
+ * instead.
+ */
+ public static const int HORIZONTAL_ALIGN_FILL = 1 << 8;
+
+ /**
+ * Style bit for new GridData(int)
to resize the
+ * control to fit the remaining horizontal space.
+ * Not recommended. Use
+ * new GridData(int, int, true, bool)
+ * instead.
+ */
+ public static const int GRAB_HORIZONTAL = 1 << 9;
+
+ /**
+ * Style bit for new GridData(int)
to resize the
+ * control to fit the remaining vertical space.
+ * Not recommended. Use
+ * new GridData(int, int, bool, true)
+ * instead.
+ */
+ public static const int GRAB_VERTICAL = 1 << 10;
+
+ /**
+ * Style bit for new GridData(int)
to resize the
+ * control to fill the cell vertically and to fit the remaining
+ * vertical space.
+ * FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL
+ * Not recommended. Use
+ * new GridData(int, SWT.FILL, bool, true)
+ * instead.
+ */
+ public static const int FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL;
+
+ /**
+ * Style bit for new GridData(int)
to resize the
+ * control to fill the cell horizontally and to fit the remaining
+ * horizontal space.
+ * FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL
+ * Not recommended. Use
+ * new GridData(SWT.FILL, int, true, bool)
+ * instead.
+ */
+ public static const int FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL;
+
+ /**
+ * Style bit for new GridData(int)
to resize the
+ * control to fill the cell horizontally and vertically and
+ * to fit the remaining horizontal and vertical space.
+ * FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL
+ * Not recommended. Use
+ * new GridData(SWT.FILL, SWT.FILL, true, true)
+ * instead.
+ */
+ public static const int FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL;
+
+ int cacheWidth = -1, cacheHeight = -1;
+ int defaultWhint, defaultHhint, defaultWidth = -1, defaultHeight = -1;
+ int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;
+
+/**
+ * Constructs a new instance of GridData using
+ * default values.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance based on the GridData style.
+ * This constructor is not recommended.
+ *
+ * @param style the GridData style
+ */
+public this (int style) {
+ if ((style & VERTICAL_ALIGN_BEGINNING) !is 0) verticalAlignment = BEGINNING;
+ if ((style & VERTICAL_ALIGN_CENTER) !is 0) verticalAlignment = CENTER;
+ if ((style & VERTICAL_ALIGN_FILL) !is 0) verticalAlignment = FILL;
+ if ((style & VERTICAL_ALIGN_END) !is 0) verticalAlignment = END;
+ if ((style & HORIZONTAL_ALIGN_BEGINNING) !is 0) horizontalAlignment = BEGINNING;
+ if ((style & HORIZONTAL_ALIGN_CENTER) !is 0) horizontalAlignment = CENTER;
+ if ((style & HORIZONTAL_ALIGN_FILL) !is 0) horizontalAlignment = FILL;
+ if ((style & HORIZONTAL_ALIGN_END) !is 0) horizontalAlignment = END;
+ grabExcessHorizontalSpace = (style & GRAB_HORIZONTAL) !is 0;
+ grabExcessVerticalSpace = (style & GRAB_VERTICAL) !is 0;
+}
+
+/**
+ * Constructs a new instance of GridData according to the parameters.
+ *
+ * @param horizontalAlignment how control will be positioned horizontally within a cell,
+ * one of: SWT.BEGINNING (or SWT.LEFT), SWT.CENTER, SWT.END (or SWT.RIGHT), or SWT.FILL
+ * @param verticalAlignment how control will be positioned vertically within a cell,
+ * one of: SWT.BEGINNING (or SWT.TOP), SWT.CENTER, SWT.END (or SWT.BOTTOM), or SWT.FILL
+ * @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
+ * @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
+ *
+ * @since 3.0
+ */
+public this (int horizontalAlignment, int verticalAlignment, bool grabExcessHorizontalSpace, bool grabExcessVerticalSpace) {
+ this (horizontalAlignment, verticalAlignment, grabExcessHorizontalSpace, grabExcessVerticalSpace, 1, 1);
+}
+
+/**
+ * Constructs a new instance of GridData according to the parameters.
+ *
+ * @param horizontalAlignment how control will be positioned horizontally within a cell,
+ * one of: SWT.BEGINNING (or SWT.LEFT), SWT.CENTER, SWT.END (or SWT.RIGHT), or SWT.FILL
+ * @param verticalAlignment how control will be positioned vertically within a cell,
+ * one of: SWT.BEGINNING (or SWT.TOP), SWT.CENTER, SWT.END (or SWT.BOTTOM), or SWT.FILL
+ * @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
+ * @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
+ * @param horizontalSpan the number of column cells that the control will take up
+ * @param verticalSpan the number of row cells that the control will take up
+ *
+ * @since 3.0
+ */
+public this (int horizontalAlignment, int verticalAlignment, bool grabExcessHorizontalSpace, bool grabExcessVerticalSpace, int horizontalSpan, int verticalSpan) {
+ this.horizontalAlignment = horizontalAlignment;
+ this.verticalAlignment = verticalAlignment;
+ this.grabExcessHorizontalSpace = grabExcessHorizontalSpace;
+ this.grabExcessVerticalSpace = grabExcessVerticalSpace;
+ this.horizontalSpan = horizontalSpan;
+ this.verticalSpan = verticalSpan;
+}
+
+/**
+ * Constructs a new instance of GridData according to the parameters.
+ * A value of SWT.DEFAULT indicates that no minimum width or
+ * no minimum height is specified.
+ *
+ * @param width a minimum width for the column
+ * @param height a minimum height for the row
+ *
+ * @since 3.0
+ */
+public this (int width, int height) {
+ this.widthHint = width;
+ this.heightHint = height;
+}
+
+void computeSize (Control control, int wHint, int hHint, bool flushCache) {
+ if (cacheWidth !is -1 && cacheHeight !is -1) return;
+ if (wHint is this.widthHint && hHint is this.heightHint) {
+ if (defaultWidth is -1 || defaultHeight is -1 || wHint !is defaultWhint || hHint !is defaultHhint) {
+ Point size = control.computeSize (wHint, hHint, flushCache);
+ defaultWhint = wHint;
+ defaultHhint = hHint;
+ defaultWidth = size.x;
+ defaultHeight = size.y;
+ }
+ cacheWidth = defaultWidth;
+ cacheHeight = defaultHeight;
+ return;
+ }
+ if (currentWidth is -1 || currentHeight is -1 || wHint !is currentWhint || hHint !is currentHhint) {
+ Point size = control.computeSize (wHint, hHint, flushCache);
+ currentWhint = wHint;
+ currentHhint = hHint;
+ currentWidth = size.x;
+ currentHeight = size.y;
+ }
+ cacheWidth = currentWidth;
+ cacheHeight = currentHeight;
+}
+
+void flushCache () {
+ cacheWidth = cacheHeight = -1;
+ defaultWidth = defaultHeight = -1;
+ currentWidth = currentHeight = -1;
+}
+
+String getName () {
+ String string = this.classinfo.name;
+ int index = string.lastIndexOf('.');
+ if (index is -1 ) return string;
+ return string[ index + 1 .. string.length ];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the GridData object
+ */
+override public String toString () {
+ String hAlign = "";
+ switch (horizontalAlignment) {
+ case SWT.FILL: hAlign = "SWT.FILL"; break;
+ case SWT.BEGINNING: hAlign = "SWT.BEGINNING"; break;
+ case SWT.LEFT: hAlign = "SWT.LEFT"; break;
+ case SWT.END: hAlign = "SWT.END"; break;
+ case END: hAlign = "GridData.END"; break;
+ case SWT.RIGHT: hAlign = "SWT.RIGHT"; break;
+ case SWT.CENTER: hAlign = "SWT.CENTER"; break;
+ case CENTER: hAlign = "GridData.CENTER"; break;
+ default: hAlign = "Undefined "~to!(String)(horizontalAlignment); break;
+ }
+ String vAlign = "";
+ switch (verticalAlignment) {
+ case SWT.FILL: vAlign = "SWT.FILL"; break;
+ case SWT.BEGINNING: vAlign = "SWT.BEGINNING"; break;
+ case SWT.TOP: vAlign = "SWT.TOP"; break;
+ case SWT.END: vAlign = "SWT.END"; break;
+ case END: vAlign = "GridData.END"; break;
+ case SWT.BOTTOM: vAlign = "SWT.BOTTOM"; break;
+ case SWT.CENTER: vAlign = "SWT.CENTER"; break;
+ case CENTER: vAlign = "GridData.CENTER"; break;
+ default: vAlign = "Undefined "~to!(String)(verticalAlignment); break;
+ }
+ String string = getName()~" {";
+ string ~= "horizontalAlignment="~to!(String)(hAlign)~" ";
+ if (horizontalIndent !is 0) string ~= "horizontalIndent="~to!(String)(horizontalIndent)~" ";
+ if (horizontalSpan !is 1) string ~= "horizontalSpan="~to!(String)(horizontalSpan)~" ";
+ if (grabExcessHorizontalSpace) string ~= "grabExcessHorizontalSpace="~to!(String)(grabExcessHorizontalSpace)~" ";
+ if (widthHint !is SWT.DEFAULT) string ~= "widthHint="~to!(String)(widthHint)~" ";
+ if (minimumWidth !is 0) string ~= "minimumWidth="~to!(String)(minimumWidth)~" ";
+ string ~= "verticalAlignment="~vAlign~" ";
+ if (verticalIndent !is 0) string ~= "verticalIndent="~to!(String)(verticalIndent)~" ";
+ if (verticalSpan !is 1) string ~= "verticalSpan="~to!(String)(verticalSpan)~" ";
+ if (grabExcessVerticalSpace) string ~= "grabExcessVerticalSpace="~to!(String)(grabExcessVerticalSpace)~" ";
+ if (heightHint !is SWT.DEFAULT) string ~= "heightHint="~to!(String)(heightHint)~" ";
+ if (minimumHeight !is 0) string ~= "minimumHeight="~to!(String)(minimumHeight)~" ";
+ if (exclude) string ~= "exclude="~to!(String)(exclude)~" ";
+ string = string.trim();
+ string ~= "}";
+ return string;
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/GridLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/GridLayout.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,761 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit Composite
in a grid.
+ *
+ * GridLayout
has a number of configuration fields, and the
+ * controls it lays out can have an associated layout data object, called
+ * GridData
. The power of GridLayout
lies in the
+ * ability to configure GridData
for each control in the layout.
+ *
+ * The following code creates a shell managed by a GridLayout
+ * with 3 columns:
+ *
+ * Display display = new Display(); + * Shell shell = new Shell(display); + * GridLayout gridLayout = new GridLayout(); + * gridLayout.numColumns = 3; + * shell.setLayout(gridLayout); + *+ * The
numColumns
field is the most important field in a
+ * GridLayout
. Widgets are laid out in columns from left
+ * to right, and a new row is created when numColumns
+ 1
+ * controls are added to the Composite.
+ *
+ *
+ * @see GridData
+ * @see GridLayout snippets
+ * @see SWT Example: LayoutExample
+ * @see Sample code and further information
+ */
+public final class GridLayout : Layout {
+
+ /**
+ * numColumns specifies the number of cell columns in the layout.
+ * If numColumns has a value less than 1, the layout will not
+ * set the size and position of any controls.
+ *
+ * The default value is 1.
+ */
+ public int numColumns = 1;
+
+ /**
+ * makeColumnsEqualWidth specifies whether all columns in the layout
+ * will be forced to have the same width.
+ *
+ * The default value is false.
+ */
+ public bool makeColumnsEqualWidth = false;
+
+ /**
+ * marginWidth specifies the number of pixels of horizontal margin
+ * that will be placed along the left and right edges of the layout.
+ *
+ * The default value is 5.
+ */
+ public int marginWidth = 5;
+
+ /**
+ * marginHeight specifies the number of pixels of vertical margin
+ * that will be placed along the top and bottom edges of the layout.
+ *
+ * The default value is 5.
+ */
+ public int marginHeight = 5;
+
+ /**
+ * marginLeft specifies the number of pixels of horizontal margin
+ * that will be placed along the left edge of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.1
+ */
+ public int marginLeft = 0;
+
+ /**
+ * marginTop specifies the number of pixels of vertical margin
+ * that will be placed along the top edge of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.1
+ */
+ public int marginTop = 0;
+
+ /**
+ * marginRight specifies the number of pixels of horizontal margin
+ * that will be placed along the right edge of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.1
+ */
+ public int marginRight = 0;
+
+ /**
+ * marginBottom specifies the number of pixels of vertical margin
+ * that will be placed along the bottom edge of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.1
+ */
+ public int marginBottom = 0;
+
+ /**
+ * horizontalSpacing specifies the number of pixels between the right
+ * edge of one cell and the left edge of its neighbouring cell to
+ * the right.
+ *
+ * The default value is 5.
+ */
+ public int horizontalSpacing = 5;
+
+ /**
+ * verticalSpacing specifies the number of pixels between the bottom
+ * edge of one cell and the top edge of its neighbouring cell underneath.
+ *
+ * The default value is 5.
+ */
+ public int verticalSpacing = 5;
+
+/**
+ * Constructs a new instance of this class.
+ */
+public this () {}
+
+/**
+ * Constructs a new instance of this class given the
+ * number of columns, and whether or not the columns
+ * should be forced to have the same width.
+ * If numColumns has a value less than 1, the layout will not
+ * set the size and position of any controls.
+ *
+ * @param numColumns the number of columns in the grid
+ * @param makeColumnsEqualWidth whether or not the columns will have equal width
+ *
+ * @since 2.0
+ */
+public this (int numColumns, bool makeColumnsEqualWidth) {
+ this.numColumns = numColumns;
+ this.makeColumnsEqualWidth = makeColumnsEqualWidth;
+}
+
+override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache_) {
+ Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache_);
+ if (wHint !is SWT.DEFAULT) size.x = wHint;
+ if (hHint !is SWT.DEFAULT) size.y = hHint;
+ return size;
+}
+
+override protected bool flushCache (Control control) {
+ Object data = control.getLayoutData ();
+ if (data !is null) (cast(GridData) data).flushCache ();
+ return true;
+}
+
+GridData getData (Control [][] grid, int row, int column, int rowCount, int columnCount, bool first) {
+ Control control = grid [row] [column];
+ if (control !is null) {
+ GridData data = cast(GridData) control.getLayoutData ();
+ int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+ int vSpan = Math.max (1, data.verticalSpan);
+ int i = first ? row + vSpan - 1 : row - vSpan + 1;
+ int j = first ? column + hSpan - 1 : column - hSpan + 1;
+ if (0 <= i && i < rowCount) {
+ if (0 <= j && j < columnCount) {
+ if (control is grid [i][j]) return data;
+ }
+ }
+ }
+ return null;
+}
+
+override protected void layout (Composite composite, bool flushCache_) {
+ Rectangle rect = composite.getClientArea ();
+ layout (composite, true, rect.x, rect.y, rect.width, rect.height, flushCache_);
+}
+
+Point layout (Composite composite, bool move, int x, int y, int width, int height, bool flushCache_) {
+ if (numColumns < 1) {
+ return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
+ }
+ Control [] children = composite.getChildren ();
+ int count = 0;
+ for (int i=0; i 0) {
+ if (data.cacheWidth < data.minimumWidth) {
+ int trim = 0;
+ //TEMPORARY CODE
+ if ( auto sa = cast(Scrollable)child ) {
+ Rectangle rect = sa.computeTrim (0, 0, 0, 0);
+ trim = rect.width;
+ } else {
+ trim = child.getBorderWidth () * 2;
+ }
+ data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
+ data.computeSize (child, Math.max (0, data.minimumWidth - trim), data.heightHint, false);
+ }
+ }
+ if (data.grabExcessVerticalSpace && data.minimumHeight > 0) {
+ data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight);
+ }
+ }
+
+ /* Build the grid */
+ int row = 0, column = 0, rowCount = 0, columnCount = numColumns;
+ Control [][] grid = new Control [][]( 4, columnCount );
+ for (int i=0; i= grid.length) {
+ Control [][] newGrid = new Control[][]( lastRow + 4, columnCount );
+ SimpleType!(Control[]).arraycopy (grid, 0, newGrid, 0, grid.length);
+ grid = newGrid;
+ }
+ if (grid [row] is null) {
+ grid [row] = new Control [columnCount];
+ }
+ while (column < columnCount && grid [row] [column] !is null) {
+ column++;
+ }
+ int endCount = column + hSpan;
+ if (endCount <= columnCount) {
+ int index = column;
+ while (index < endCount && grid [row] [index] is null) {
+ index++;
+ }
+ if (index is endCount) break;
+ column = index;
+ }
+ if (column + hSpan >= columnCount) {
+ column = 0;
+ row++;
+ }
+ }
+ for (int j=0; j 1) {
+ int spanWidth = 0, spanMinWidth = 0, spanExpandCount = 0;
+ for (int k=0; k 0) {
+ if (makeColumnsEqualWidth) {
+ int equalWidth = (w + spanWidth) / hSpan;
+ int remainder = (w + spanWidth) % hSpan, last = -1;
+ for (int k = 0; k < hSpan; k++) {
+ widths [last=j-k] = Math.max (equalWidth, widths [j-k]);
+ }
+ if (last > -1) widths [last] += remainder;
+ } else {
+ if (spanExpandCount is 0) {
+ widths [j] += w;
+ } else {
+ int delta = w / spanExpandCount;
+ int remainder = w % spanExpandCount, last = -1;
+ for (int k = 0; k < hSpan; k++) {
+ if (expandColumn [j-k]) {
+ widths [last=j-k] += delta;
+ }
+ }
+ if (last > -1) widths [last] += remainder;
+ }
+ }
+ }
+ if (!data.grabExcessHorizontalSpace || data.minimumWidth !is 0) {
+ w = !data.grabExcessHorizontalSpace || data.minimumWidth is SWT.DEFAULT ? data.cacheWidth : data.minimumWidth;
+ w += data.horizontalIndent - spanMinWidth - (hSpan - 1) * horizontalSpacing;
+ if (w > 0) {
+ if (spanExpandCount is 0) {
+ minWidths [j] += w;
+ } else {
+ int delta = w / spanExpandCount;
+ int remainder = w % spanExpandCount, last = -1;
+ for (int k = 0; k < hSpan; k++) {
+ if (expandColumn [j-k]) {
+ minWidths [last=j-k] += delta;
+ }
+ }
+ if (last > -1) minWidths [last] += remainder;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (makeColumnsEqualWidth) {
+ int minColumnWidth = 0;
+ int columnWidth = 0;
+ for (int i=0; i 0;
+ widths [i] = columnWidth;
+ }
+ } else {
+ if (width !is SWT.DEFAULT && expandCount > 0) {
+ int totalWidth = 0;
+ for (int i=0; i minWidths [j]) {
+ widths [last = j] = widths [j] + delta;
+ } else {
+ widths [j] = minWidths [j];
+ expandColumn [j] = false;
+ c--;
+ }
+ }
+ }
+ if (last > -1) widths [last] += remainder;
+
+ for (int j=0; j 1) {
+ if (!data.grabExcessHorizontalSpace || data.minimumWidth !is 0) {
+ int spanWidth = 0, spanExpandCount = 0;
+ for (int k=0; k 0) {
+ if (spanExpandCount is 0) {
+ widths [j] += w;
+ } else {
+ int delta2 = w / spanExpandCount;
+ int remainder2 = w % spanExpandCount, last2 = -1;
+ for (int k = 0; k < hSpan; k++) {
+ if (expandColumn [j-k]) {
+ widths [last2=j-k] += delta2;
+ }
+ }
+ if (last2 > -1) widths [last2] += remainder2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (c is 0) break;
+ totalWidth = 0;
+ for (int i=0; i currentWidth)) {
+ int trim = 0;
+ if ( auto sa = cast(Scrollable)child ) {
+ Rectangle rect = sa.computeTrim (0, 0, 0, 0);
+ trim = rect.width;
+ } else {
+ trim = child.getBorderWidth () * 2;
+ }
+ data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
+ data.computeSize (child, Math.max (0, currentWidth - trim), data.heightHint, false);
+ if (data.grabExcessVerticalSpace && data.minimumHeight > 0) {
+ data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight);
+ }
+ if (flush is null) flush = new GridData [count];
+ flush [flushLength++] = data;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Row heights */
+ int availableHeight = height - verticalSpacing * (rowCount - 1) - (marginTop + marginHeight * 2 + marginBottom);
+ expandCount = 0;
+ int [] heights = new int [rowCount];
+ int [] minHeights = new int [rowCount];
+ bool [] expandRow = new bool [rowCount];
+ for (int i=0; i 1) {
+ int spanHeight = 0, spanMinHeight = 0, spanExpandCount = 0;
+ for (int k=0; k 0) {
+ if (spanExpandCount is 0) {
+ heights [i] += h;
+ } else {
+ int delta = h / spanExpandCount;
+ int remainder = h % spanExpandCount, last = -1;
+ for (int k = 0; k < vSpan; k++) {
+ if (expandRow [i-k]) {
+ heights [last=i-k] += delta;
+ }
+ }
+ if (last > -1) heights [last] += remainder;
+ }
+ }
+ if (!data.grabExcessVerticalSpace || data.minimumHeight !is 0) {
+ h = !data.grabExcessVerticalSpace || data.minimumHeight is SWT.DEFAULT ? data.cacheHeight : data.minimumHeight;
+ h += data.verticalIndent - spanMinHeight - (vSpan - 1) * verticalSpacing;
+ if (h > 0) {
+ if (spanExpandCount is 0) {
+ minHeights [i] += h;
+ } else {
+ int delta = h / spanExpandCount;
+ int remainder = h % spanExpandCount, last = -1;
+ for (int k = 0; k < vSpan; k++) {
+ if (expandRow [i-k]) {
+ minHeights [last=i-k] += delta;
+ }
+ }
+ if (last > -1) minHeights [last] += remainder;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (height !is SWT.DEFAULT && expandCount > 0) {
+ int totalHeight = 0;
+ for (int i=0; i minHeights [i]) {
+ heights [last = i] = heights [i] + delta;
+ } else {
+ heights [i] = minHeights [i];
+ expandRow [i] = false;
+ c--;
+ }
+ }
+ }
+ if (last > -1) heights [last] += remainder;
+
+ for (int i=0; i 1) {
+ if (!data.grabExcessVerticalSpace || data.minimumHeight !is 0) {
+ int spanHeight = 0, spanExpandCount = 0;
+ for (int k=0; k 0) {
+ if (spanExpandCount is 0) {
+ heights [i] += h;
+ } else {
+ int delta2 = h / spanExpandCount;
+ int remainder2 = h % spanExpandCount, last2 = -1;
+ for (int k = 0; k < vSpan; k++) {
+ if (expandRow [i-k]) {
+ heights [last2=i-k] += delta2;
+ }
+ }
+ if (last2 > -1) heights [last2] += remainder2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (c is 0) break;
+ totalHeight = 0;
+ for (int i=0; i
+ *******************************************************************************/
+module org.eclipse.swt.layout.RowData;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ * Each control controlled by a RowLayout
can have its initial
+ * width and height specified by setting a RowData
object
+ * into the control.
+ *
+ * The following code uses a RowData
object to change the initial
+ * size of a Button
in a Shell
:
+ *
+ * Display display = new Display();
+ * Shell shell = new Shell(display);
+ * shell.setLayout(new RowLayout());
+ * Button button1 = new Button(shell, SWT.PUSH);
+ * button1.setText("Button 1");
+ * button1.setLayoutData(new RowData(50, 40));
+ *
+ *
+ *
+ * @see RowLayout
+ * @see Sample code and further information
+ */
+public final class RowData {
+ /**
+ * width specifies the desired width in pixels. This value
+ * is the wHint passed into Control.computeSize(int, int, bool)
+ * to determine the preferred size of the control.
+ *
+ * The default value is SWT.DEFAULT.
+ *
+ * @see org.eclipse.swt.widgets.Control#computeSize(int, int, bool)
+ */
+ public int width = SWT.DEFAULT;
+ /**
+ * height specifies the preferred height in pixels. This value
+ * is the hHint passed into Control.computeSize(int, int, bool)
+ * to determine the preferred size of the control.
+ *
+ * The default value is SWT.DEFAULT.
+ *
+ * @see org.eclipse.swt.widgets.Control#computeSize(int, int, bool)
+ */
+ public int height = SWT.DEFAULT;
+
+ /**
+ * exclude informs the layout to ignore this control when sizing
+ * and positioning controls. If this value is true
,
+ * the size and position of the control will not be managed by the
+ * layout. If this value is false
, the size and
+ * position of the control will be computed and assigned.
+ *
+ * The default value is false
.
+ *
+ * @since 3.1
+ */
+ public bool exclude = false;
+
+/**
+ * Constructs a new instance of RowData using
+ * default values.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance of RowData according to the parameters.
+ * A value of SWT.DEFAULT indicates that no minimum width or
+ * no minimum height is specified.
+ *
+ * @param width a minimum width for the control
+ * @param height a minimum height for the control
+ */
+public this (int width, int height) {
+ this.width = width;
+ this.height = height;
+}
+
+/**
+ * Constructs a new instance of RowData according to the parameter.
+ * A value of SWT.DEFAULT indicates that no minimum width or
+ * no minimum height is specified.
+ *
+ * @param point a point whose x coordinate specifies a minimum width for the control
+ * and y coordinate specifies a minimum height for the control
+ */
+public this (Point point) {
+ this (point.x, point.y);
+}
+
+String getName () {
+ String string = this.classinfo.name;
+ int index = string.lastIndexOf('.');
+ if (index is -1 ) return string;
+ return string[ index + 1 .. string.length ];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the RowData object
+ */
+override public String toString () {
+ String string = getName ()~" {";
+ if (width !is SWT.DEFAULT) string ~= "width="~to!(String)(width)~" ";
+ if (height !is SWT.DEFAULT) string ~= "height="~to!(String)(height)~" ";
+ if (exclude) string ~= "exclude="~to!(String)(exclude)~" ";
+ string = string.trim();
+ string ~= "}";
+ return string;
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/RowLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/RowLayout.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,516 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.layout.RowLayout;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.layout.RowData;
+import tango.util.Convert;
+import Math = tango.math.Math;
+import java.lang.all;
+
+
+/**
+ * Instances of this class determine the size and position of the
+ * children of a Composite
by placing them either in
+ * horizontal rows or vertical columns within the parent Composite
.
+ *
+ * RowLayout
aligns all controls in one row if the
+ * type
is set to horizontal, and one column if it is
+ * set to vertical. It has the ability to wrap, and provides configurable
+ * margins and spacing. RowLayout
has a number of configuration
+ * fields. In addition, the height and width of each control in a
+ * RowLayout
can be specified by setting a RowData
+ * object into the control using setLayoutData ()
.
+ *
+ *
+ * The following example code creates a RowLayout
, sets all
+ * of its fields to non-default values, and then sets it into a
+ * Shell
.
+ *
+ * RowLayout rowLayout = new RowLayout();
+ * rowLayout.wrap = false;
+ * rowLayout.pack = false;
+ * rowLayout.justify = true;
+ * rowLayout.type = SWT.VERTICAL;
+ * rowLayout.marginLeft = 5;
+ * rowLayout.marginTop = 5;
+ * rowLayout.marginRight = 5;
+ * rowLayout.marginBottom = 5;
+ * rowLayout.spacing = 0;
+ * shell.setLayout(rowLayout);
+ *
+ * If you are using the default field values, you only need one line of code:
+ *
+ * shell.setLayout(new RowLayout());
+ *
+ *
+ *
+ * @see RowData
+ * @see RowLayout snippets
+ * @see SWT Example: LayoutExample
+ * @see Sample code and further information
+ */
+public final class RowLayout : Layout {
+
+ /**
+ * type specifies whether the layout places controls in rows or
+ * columns.
+ *
+ * The default value is HORIZONTAL.
+ *
+ * Possible values are:
+ * - HORIZONTAL: Position the controls horizontally from left to right
+ * - VERTICAL: Position the controls vertically from top to bottom
+ *
+ *
+ * @since 2.0
+ */
+ public int type = SWT.HORIZONTAL;
+
+ /**
+ * marginWidth specifies the number of pixels of horizontal margin
+ * that will be placed along the left and right edges of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.0
+ */
+ public int marginWidth = 0;
+
+ /**
+ * marginHeight specifies the number of pixels of vertical margin
+ * that will be placed along the top and bottom edges of the layout.
+ *
+ * The default value is 0.
+ *
+ * @since 3.0
+ */
+ public int marginHeight = 0;
+
+ /**
+ * spacing specifies the number of pixels between the edge of one cell
+ * and the edge of its neighbouring cell.
+ *
+ * The default value is 3.
+ */
+ public int spacing = 3;
+
+ /**
+ * wrap specifies whether a control will be wrapped to the next
+ * row if there is insufficient space on the current row.
+ *
+ * The default value is true.
+ */
+ public bool wrap = true;
+
+ /**
+ * pack specifies whether all controls in the layout take
+ * their preferred size. If pack is false, all controls will
+ * have the same size which is the size required to accommodate the
+ * largest preferred height and the largest preferred width of all
+ * the controls in the layout.
+ *
+ * The default value is true.
+ */
+ public bool pack = true;
+
+ /**
+ * fill specifies whether the controls in a row should be
+ * all the same height for horizontal layouts, or the same
+ * width for vertical layouts.
+ *
+ * The default value is false.
+ *
+ * @since 3.0
+ */
+ public bool fill = false;
+
+ /**
+ * center specifies whether the controls in a row should be
+ * centered vertically in each cell for horizontal layouts,
+ * or centered horizontally in each cell for vertical layouts.
+ *
+ * The default value is false.
+ *
+ * @since 3.4
+ */
+ public bool center = false;
+
+ /**
+ * justify specifies whether the controls in a row should be
+ * fully justified, with any extra space placed between the controls.
+ *
+ * The default value is false.
+ */
+ public bool justify = false;
+
+ /**
+ * marginLeft specifies the number of pixels of horizontal margin
+ * that will be placed along the left edge of the layout.
+ *
+ * The default value is 3.
+ */
+ public int marginLeft = 3;
+
+ /**
+ * marginTop specifies the number of pixels of vertical margin
+ * that will be placed along the top edge of the layout.
+ *
+ * The default value is 3.
+ */
+ public int marginTop = 3;
+
+ /**
+ * marginRight specifies the number of pixels of horizontal margin
+ * that will be placed along the right edge of the layout.
+ *
+ * The default value is 3.
+ */
+ public int marginRight = 3;
+
+ /**
+ * marginBottom specifies the number of pixels of vertical margin
+ * that will be placed along the bottom edge of the layout.
+ *
+ * The default value is 3.
+ */
+ public int marginBottom = 3;
+
+/**
+ * Constructs a new instance of this class.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance of this class given the type.
+ *
+ * @param type the type of row layout
+ *
+ * @since 2.0
+ */
+public this (int type) {
+ this.type = type;
+}
+
+override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache_) {
+ Point extent;
+ if (type is SWT.HORIZONTAL) {
+ extent = layoutHorizontal (composite, false, (wHint !is SWT.DEFAULT) && wrap, wHint, flushCache_);
+ } else {
+ extent = layoutVertical (composite, false, (hHint !is SWT.DEFAULT) && wrap, hHint, flushCache_);
+ }
+ if (wHint !is SWT.DEFAULT) extent.x = wHint;
+ if (hHint !is SWT.DEFAULT) extent.y = hHint;
+ return extent;
+}
+
+Point computeSize (Control control, bool flushCache_) {
+ int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
+ RowData data = cast(RowData) control.getLayoutData ();
+ if (data !is null) {
+ wHint = data.width;
+ hHint = data.height;
+ }
+ return control.computeSize (wHint, hHint, flushCache_);
+}
+
+override protected bool flushCache (Control control) {
+ return true;
+}
+
+String getName () {
+ String string = this.classinfo.name;
+ int index = string.lastIndexOf('.');
+ if (index is -1 ) return string;
+ return string[ index + 1 .. string.length ];
+}
+
+override protected void layout (Composite composite, bool flushCache_) {
+ Rectangle clientArea = composite.getClientArea ();
+ if (type is SWT.HORIZONTAL) {
+ layoutHorizontal (composite, true, wrap, clientArea.width, flushCache_);
+ } else {
+ layoutVertical (composite, true, wrap, clientArea.height, flushCache_);
+ }
+}
+
+Point layoutHorizontal (Composite composite, bool move, bool wrap, int width, bool flushCache_) {
+ Control [] children = composite.getChildren ();
+ int count = 0;
+ for (int i=0; i width)) {
+ wrapped = true;
+ if (move && (justify || fill || center)) wraps [i - 1] = maxHeight;
+ x = marginLeft + marginWidth;
+ y += spacing + maxHeight;
+ if (pack) maxHeight = 0;
+ }
+ if (pack || fill || center) {
+ maxHeight = Math.max (maxHeight, childHeight);
+ }
+ if (move) {
+ int childX = x + clientX, childY = y + clientY;
+ if (justify || fill || center) {
+ bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
+ } else {
+ child.setBounds (childX, childY, childWidth, childHeight);
+ }
+ }
+ x += spacing + childWidth;
+ maxX = Math.max (maxX, x);
+ }
+ maxX = Math.max (clientX + marginLeft + marginWidth, maxX - spacing);
+ if (!wrapped) maxX += marginRight + marginWidth;
+ if (move && (justify || fill || center)) {
+ int space = 0, margin = 0;
+ if (!wrapped) {
+ space = Math.max (0, (width - maxX) / (count + 1));
+ margin = Math.max (0, ((width - maxX) % (count + 1)) / 2);
+ } else {
+ if (fill || justify || center) {
+ int last = 0;
+ if (count > 0) wraps [count - 1] = maxHeight;
+ for (int i=0; i height)) {
+ wrapped = true;
+ if (move && (justify || fill || center)) wraps [i - 1] = maxWidth;
+ x += spacing + maxWidth;
+ y = marginTop + marginHeight;
+ if (pack) maxWidth = 0;
+ }
+ if (pack || fill || center) {
+ maxWidth = Math.max (maxWidth, childWidth);
+ }
+ if (move) {
+ int childX = x + clientX, childY = y + clientY;
+ if (justify || fill || center) {
+ bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
+ } else {
+ child.setBounds (childX, childY, childWidth, childHeight);
+ }
+ }
+ y += spacing + childHeight;
+ maxY = Math.max (maxY, y);
+ }
+ maxY = Math.max (clientY + marginTop + marginHeight, maxY - spacing);
+ if (!wrapped) maxY += marginBottom + marginHeight;
+ if (move && (justify || fill || center)) {
+ int space = 0, margin = 0;
+ if (!wrapped) {
+ space = Math.max (0, (height - maxY) / (count + 1));
+ margin = Math.max (0, ((height - maxY) % (count + 1)) / 2);
+ } else {
+ if (fill || justify || center) {
+ int last = 0;
+ if (count > 0) wraps [count - 1] = maxWidth;
+ for (int i=0; i
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OLE;
+
+import java.io.File;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.win32.OS;
+
+import java.lang.all;
+import tango.util.Convert;
+/**
+ *
+ * OLE contains all the constants used to create an ActiveX Control or an OLE Document.
+ *
+ * Definitions for these constants can be found in MSDN.
+ *
+ */
+public class OLE : SWT {
+
+ public static const int S_FALSE = 1; // Used for functions that semantically return a bool FALSE result to indicate that the function succeeded.
+ public static const int S_OK = 0; // Function succeeded.
+ public static const int E_FAIL = -2147467259; // Unspecified failure.
+ public static const int E_INVALIDARG = -2147024809; // Invalid argument
+ public static const int E_NOINTERFACE = -2147467262; // QueryInterface did not recognize the requested interface.
+ public static const int E_NOTIMPL = -2147467263; // Not implemented
+
+ public static const String IID_IUNKNOWN = "{00000000-0000-0000-C000-000000000046}"; //$NON-NLS-1$
+ public static const String IID_IDISPATCH = "{00020400-0000-0000-C000-000000000046}"; //$NON-NLS-1$
+
+ // Verbs that can be invoked on this client
+ public static const int OLEIVERB_DISCARDUNDOSTATE = -6; // close the OLE object and discard the undo state
+ public static const int OLEIVERB_HIDE = -3; // hide the OLE object
+ public static const int OLEIVERB_INPLACEACTIVATE = -5; // open the OLE for editing in-place
+ public static const int OLEIVERB_OPEN = -2; // open the OLE object for editing in a separate window
+ public static const int OLEIVERB_PRIMARY = 0; // opens the OLE object for editing
+ public static const int OLEIVERB_PROPERTIES = -7; // request the OLE object properties dialog
+ public static const int OLEIVERB_SHOW = -1; // show the OLE object
+ public static const int OLEIVERB_UIACTIVATE = -4; // activate the UI for the OLE object
+
+ public static const int PROPERTY_CHANGING = 0;
+ public static const int PROPERTY_CHANGED = 1;
+
+ /**
+ * Error code for OleError - No specific error information available
+ */
+ public static const int HRESULT_UNSPECIFIED = 0;
+ /**
+ * Error code for OleError - Failed to create file
+ */
+ public static const int ERROR_CANNOT_CREATE_FILE = 1000;
+ /**
+ * Error code for OleError - Failed to create Ole Client
+ */
+ public static const int ERROR_CANNOT_CREATE_OBJECT = 1001;
+ /**
+ * Error code for OleError - File does not exist, is not accessible to user or does not have the correct format
+ */
+ public static const int ERROR_CANNOT_OPEN_FILE = 1002;
+ /**
+ * Error code for OleError - Failed to find requested interface on OLE Object
+ */
+ public static const int ERROR_INTERFACE_NOT_FOUND = 1003;
+ /**
+ * Error code for OleError - Class ID not found in registry
+ */
+ public static const int ERROR_INVALID_CLASSID = 1004;
+ /**
+ * Error code for OleError - Failed to get the class factory for the specified classID
+ */
+ public static const int ERROR_CANNOT_ACCESS_CLASSFACTORY = 1005;
+ /**
+ * Error code for OleError - Failed to create Licensed instance
+ */
+ public static const int ERROR_CANNOT_CREATE_LICENSED_OBJECT = 1006;
+ /**
+ * Error code for OleError - Out of Memory
+ */
+ public static const int ERROR_OUT_OF_MEMORY = 1007;
+ /**
+ * Error code for OleError - Failed to change Variant type
+ */
+ public static const int ERROR_CANNOT_CHANGE_VARIANT_TYPE = 1010;
+ /**
+ * Error code for OleError - Invalid address received for Ole Interface
+ */
+ public static const int ERROR_INVALID_INTERFACE_ADDRESS = 1011;
+ /**
+ * Error code for OleError - Unable to find Application
+ */
+ public static const int ERROR_APPLICATION_NOT_FOUND = 1013;
+ /**
+ * Error code for OleError - Action can not be performed
+ */
+ public static const int ERROR_ACTION_NOT_PERFORMED = 1014;
+
+ public static const int OLECMDF_SUPPORTED = 1;
+ public static const int OLECMDF_ENABLED = 2;
+ public static const int OLECMDF_LATCHED = 4;
+ public static const int OLECMDF_NINCHED = 8;
+
+ public static const int OLECMDTEXTF_NONE = 0;
+ public static const int OLECMDTEXTF_NAME = 1;
+ public static const int OLECMDTEXTF_STATUS = 2;
+
+ public static const int OLECMDEXECOPT_DODEFAULT = 0;
+ public static const int OLECMDEXECOPT_PROMPTUSER = 1;
+ public static const int OLECMDEXECOPT_DONTPROMPTUSER = 2;
+ public static const int OLECMDEXECOPT_SHOWHELP = 3;
+
+ public static const int OLECMDID_OPEN = 1;
+ public static const int OLECMDID_NEW = 2;
+ public static const int OLECMDID_SAVE = 3;
+ public static const int OLECMDID_SAVEAS = 4;
+ public static const int OLECMDID_SAVECOPYAS = 5;
+ public static const int OLECMDID_PRINT = 6;
+ public static const int OLECMDID_PRINTPREVIEW = 7;
+ public static const int OLECMDID_PAGESETUP = 8;
+ public static const int OLECMDID_SPELL = 9;
+ public static const int OLECMDID_PROPERTIES = 10;
+ public static const int OLECMDID_CUT = 11;
+ public static const int OLECMDID_COPY = 12;
+ public static const int OLECMDID_PASTE = 13;
+ public static const int OLECMDID_PASTESPECIAL = 14;
+ public static const int OLECMDID_UNDO = 15;
+ public static const int OLECMDID_REDO = 16;
+ public static const int OLECMDID_SELECTALL = 17;
+ public static const int OLECMDID_CLEARSELECTION = 18;
+ public static const int OLECMDID_ZOOM = 19;
+ public static const int OLECMDID_GETZOOMRANGE = 20;
+ public static const int OLECMDID_UPDATECOMMANDS = 21;
+ public static const int OLECMDID_REFRESH = 22;
+ public static const int OLECMDID_STOP = 23;
+ public static const int OLECMDID_HIDETOOLBARS = 24;
+ public static const int OLECMDID_SETPROGRESSMAX = 25;
+ public static const int OLECMDID_SETPROGRESSPOS = 26;
+ public static const int OLECMDID_SETPROGRESSTEXT = 27;
+ public static const int OLECMDID_SETTITLE = 28;
+ public static const int OLECMDID_SETDOWNLOADSTATE = 29;
+ public static const int OLECMDID_STOPDOWNLOAD = 30;
+
+ /* Ole Property Description flags */
+ public static int VARFLAG_FREADONLY = 0x1;
+ public static int VARFLAG_FSOURCE = 0x2;
+ public static int VARFLAG_FBINDABLE = 0x4;
+ public static int VARFLAG_FREQUESTEDIT = 0x8;
+ public static int VARFLAG_FDISPLAYBIND = 0x10;
+ public static int VARFLAG_FDEFAULTBIND = 0x20;
+ public static int VARFLAG_FHIDDEN = 0x40;
+ public static int VARFLAG_FRESTRICTED = 0x80;
+ public static int VARFLAG_FDEFAULTCOLLELEM = 0x100;
+ public static int VARFLAG_FUIDEFAULT = 0x200;
+ public static int VARFLAG_FNONBROWSABLE = 0x400;
+ public static int VARFLAG_FREPLACEABLE = 0x800;
+ public static int VARFLAG_FIMMEDIATEBIND = 0x1000;
+
+ /* Ole Property Description kind */
+ public static int VAR_PERINSTANCE = 0;
+ public static int VAR_STATIC = 1;
+ public static int VAR_CONST = 2;
+ public static int VAR_DISPATCH = 3;
+
+ /* Ole Parameter Description flags */
+ public static short IDLFLAG_NONE = 0;
+ public static short IDLFLAG_FIN = 1;
+ public static short IDLFLAG_FOUT = 2;
+ public static short IDLFLAG_FLCID = 4;
+ public static short IDLFLAG_FRETVAL = 8;
+
+ /* Ole Description types */
+ public static const short VT_BOOL = 11; // bool; True=-1, False=0.
+ public static const short VT_BSTR = 8; // Binary String.
+ public static const short VT_BYREF = 16384; // By reference - must be combined with one of the other VT values
+ public static const short VT_CY = 6; // Currency.
+ public static const short VT_DATE = 7; // Date.
+ public static const short VT_DISPATCH = 9; // IDispatch
+ public static const short VT_EMPTY = 0; // Not specified.
+ public static const short VT_ERROR = 10; // Scodes.
+ public static const short VT_I2 = 2; // 2-byte signed int.
+ public static const short VT_I4 = 3; // 4-byte signed int.
+ public static const short VT_NULL = 1; // Null.
+ public static const short VT_R4 = 4; // 4-byte real.
+ public static const short VT_R8 = 5; // 8-byte real.
+ public static const short VT_UI1 = 17; // Unsigned char.
+ public static const short VT_UI4 = 19; // Unsigned int.
+ public static const short VT_UNKNOWN = 13; // IUnknown FAR*.
+ public static const short VT_VARIANT = 12; // VARIANT FAR*.
+ public static const short VT_PTR = 26;
+ public static const short VT_USERDEFINED = 29;
+ public static const short VT_HRESULT = 25;
+ public static const short VT_DECIMAL = 14;
+ public static const short VT_I1 = 16;
+ public static const short VT_UI2 = 18;
+ public static const short VT_I8 = 20;
+ public static const short VT_UI8 = 21;
+ public static const short VT_INT = 22;
+ public static const short VT_UINT = 23;
+ public static const short VT_VOID = 24;
+ public static const short VT_SAFEARRAY = 27;
+ public static const short VT_CARRAY = 28;
+ public static const short VT_LPSTR = 30;
+ public static const short VT_LPWSTR = 31;
+ public static const short VT_RECORD = 36;
+ public static const short VT_FILETIME = 64;
+ public static const short VT_BLOB = 65;
+ public static const short VT_STREAM = 66;
+ public static const short VT_STORAGE = 67;
+ public static const short VT_STREAMED_OBJECT = 68;
+ public static const short VT_STORED_OBJECT = 69;
+ public static const short VT_BLOB_OBJECT = 70;
+ public static const short VT_CF = 71;
+ public static const short VT_CLSID = 72;
+ public static const short VT_VERSIONED_STREAM = 73;
+ public static const short VT_BSTR_BLOB = 0xfff;
+ public static const short VT_VECTOR = 0x1000;
+ public static const short VT_ARRAY = 0x2000;
+
+ /* Ole Function Description Invoke Kind values */
+ public static const int INVOKE_FUNC = 1;
+ public static const int INVOKE_PROPERTYGET = 2;
+ public static const int INVOKE_PROPERTYPUT = 4;
+ public static const int INVOKE_PROPERTYPUTREF = 8;
+
+ /* Ole Function Description function kind */
+ public static const int FUNC_VIRTUAL = 0;
+ public static const int FUNC_PUREVIRTUAL = 1;
+ public static const int FUNC_NONVIRTUAL = 2;
+ public static const int FUNC_STATIC = 3;
+ public static const int FUNC_DISPATCH = 4;
+
+ /* Ole Function Description function flags */
+ public static const short FUNCFLAG_FRESTRICTED = 1;
+ public static const short FUNCFLAG_FSOURCE = 0x2;
+ public static const short FUNCFLAG_FBINDABLE = 0x4;
+ public static const short FUNCFLAG_FREQUESTEDIT = 0x8;
+ public static const short FUNCFLAG_FDISPLAYBIND = 0x10;
+ public static const short FUNCFLAG_FDEFAULTBIND = 0x20;
+ public static const short FUNCFLAG_FHIDDEN = 0x40;
+ public static const short FUNCFLAG_FUSESGETLASTERROR = 0x80;
+ public static const short FUNCFLAG_FDEFAULTCOLLELEM = 0x100;
+ public static const short FUNCFLAG_FUIDEFAULT = 0x200;
+ public static const short FUNCFLAG_FNONBROWSABLE = 0x400;
+ public static const short FUNCFLAG_FREPLACEABLE = 0x800;
+ public static const short FUNCFLAG_FIMMEDIATEBIND = 0x1000;
+
+ /* Ole Function Description calling convention */
+ public static const int CC_FASTCALL = 0;
+ public static const int CC_CDECL = 1;
+ public static const int CC_MSCPASCAL = 2;
+ public static const int CC_PASCAL = 2;
+ public static const int CC_MACPASCAL = 3;
+ public static const int CC_STDCALL = 4;
+ public static const int CC_FPFASTCALL = 5;
+ public static const int CC_SYSCALL = 6;
+ public static const int CC_MPWCDECL = 7;
+ public static const int CC_MPWPASCAL = 8;
+ public static const int CC_MAX = 9;
+
+ static const String ERROR_NOT_IMPLEMENTED_MSG = "Required functionality not currently supported.";//$NON-NLS-1$
+ static const String ERROR_CANNOT_CREATE_FILE_MSG = "Failed to create file.";//$NON-NLS-1$
+ static const String ERROR_CANNOT_CREATE_OBJECT_MSG = "Failed to create Ole Client.";//$NON-NLS-1$
+ static const String ERROR_CANNOT_OPEN_FILE_MSG = "File does not exist, is not accessible to user or does not have the correct format.";//$NON-NLS-1$
+ static const String ERROR_INTERFACE_NOT_FOUND_MSG = "Failed to find requested interface on OLE Object.";//$NON-NLS-1$
+ static const String ERROR_INVALID_CLASSID_MSG = "Class ID not found in registry";//$NON-NLS-1$
+ static const String ERROR_CANNOT_ACCESS_CLASSFACTORY_MSG = "Failed to get the class factory for the specified classID";//$NON-NLS-1$
+ static const String ERROR_CANNOT_CREATE_LICENSED_OBJECT_MSG = "Failed to create Licensed instance";//$NON-NLS-1$
+ static const String ERROR_OUT_OF_MEMORY_MSG = "Out of Memory";//$NON-NLS-1$
+ static const String ERROR_CANNOT_CHANGE_VARIANT_TYPE_MSG = "Failed to change Variant type";//$NON-NLS-1$
+ static const String ERROR_INVALID_INTERFACE_ADDRESS_MSG = "Invalid address received for Ole Interface.";//$NON-NLS-1$
+ static const String ERROR_APPLICATION_NOT_FOUND_MSG = "Unable to find Application.";//$NON-NLS-1$
+ static const String ERROR_ACTION_NOT_PERFORMED_MSG = "Action can not be performed.";//$NON-NLS-1$
+
+
+public static void error (String file, long line, int code) {
+ error (code, 0);
+}
+public static void error (int code) {
+ error (code, 0);
+}
+public static void error (String file, long line, int code, int hresult) {
+ error (code, hresult);
+}
+public static void error (int code, int hresult) {
+
+ switch (code) {
+ /* Illegal Arguments (non-fatal) */
+ case ERROR_INVALID_INTERFACE_ADDRESS :{
+ throw new IllegalArgumentException (ERROR_INVALID_INTERFACE_ADDRESS_MSG);
+ }
+
+ /* SWT Errors (non-fatal) */
+ case ERROR_CANNOT_CREATE_FILE : {
+ String msg = ERROR_CANNOT_CREATE_FILE_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+ case ERROR_CANNOT_CREATE_OBJECT : {
+ String msg = ERROR_CANNOT_CREATE_OBJECT_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);//$NON-NLS-1$
+ }
+ case ERROR_CANNOT_OPEN_FILE : {
+ String msg = ERROR_CANNOT_OPEN_FILE_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+ case ERROR_INTERFACE_NOT_FOUND : {
+ String msg = ERROR_INTERFACE_NOT_FOUND_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+ case ERROR_INVALID_CLASSID : {
+ String msg = ERROR_INVALID_CLASSID_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+ case ERROR_CANNOT_ACCESS_CLASSFACTORY : {
+ String msg = ERROR_CANNOT_ACCESS_CLASSFACTORY_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+ case ERROR_CANNOT_CREATE_LICENSED_OBJECT : {
+ String msg = ERROR_CANNOT_CREATE_LICENSED_OBJECT_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+ case ERROR_CANNOT_CHANGE_VARIANT_TYPE : {
+ String msg = ERROR_CANNOT_CHANGE_VARIANT_TYPE_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+ case ERROR_APPLICATION_NOT_FOUND : {
+ String msg = ERROR_APPLICATION_NOT_FOUND_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+ case ERROR_ACTION_NOT_PERFORMED : {
+ String msg = ERROR_ACTION_NOT_PERFORMED_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+ throw new SWTException (code, msg);
+ }
+
+ /* OS Failure/Limit (fatal, may occur only on some platforms) */
+ case ERROR_OUT_OF_MEMORY : {
+ String msg = ERROR_ACTION_NOT_PERFORMED_MSG;
+ if (hresult !is 0) msg ~= " result = "~to!(String)(hresult); //$NON-NLS-1$
+ throw new SWTError (code, msg);
+ }
+ default:
+ }
+
+ /* Unknown/Undefined Error */
+ SWT.error(code);
+}
+
+/*
+ * Finds the OLE program id that is associated with an extension.
+ * The extension may or may not begin with a '.'. On platforms
+ * that do not support OLE, an empty string is returned.
+ *
+ * @param extension the program extension
+ * @return a string that is the OLE program id or an empty string
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when extension is null
+ *
+ */
+public static String findProgramID (String extension) {
+ if (extension is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (extension.length is 0) return ""; //$NON-NLS-1$
+
+ if (extension.charAt (0) !is '.') extension = "." ~ extension; //$NON-NLS-1$
+
+ /* Use the character encoding for the default locale */
+ TCHAR[] extensionKey = StrToTCHARs(0, extension, true);
+ String result = getKeyValue(extensionKey);
+ if (result !is null) {
+ // look for "\NotInsertable"
+ TCHAR[] notInsertableKey = StrToTCHARs(0, result~"\\NotInsertable", true); //$NON-NLS-1$
+ if (getKeyExists(notInsertableKey)) return ""; //$NON-NLS-1$
+ // look for "\Insertable"
+ TCHAR[] insertableKey = StrToTCHARs(0, result~"\\Insertable", true); //$NON-NLS-1$
+ if (getKeyExists(insertableKey)) return result;
+ // look for "\protocol\StdFileEditing\server"
+ TCHAR[] serverKey = StrToTCHARs(0, result~"\\protocol\\StdFileEditing\\server", true); //$NON-NLS-1$
+ if (getKeyExists(serverKey)) return result;
+ }
+
+ return ""; //$NON-NLS-1$
+}
+static String getKeyValue (TCHAR[] key) {
+ void* [1] phkResult;
+ if (OS.RegOpenKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) {
+ return null;
+ }
+ String result = null;
+ uint [1] lpcbData;
+ if (OS.RegQueryValueEx (phkResult [0], null, null, null, null, lpcbData.ptr) is 0) {
+ int length_ = lpcbData [0] / TCHAR.sizeof;
+ if (length_ is 0) {
+ result = "";
+ } else {
+ /* Use the character encoding for the default locale */
+ TCHAR[] lpData = NewTCHARs (0, length_);
+ if (OS.RegQueryValueEx (phkResult [0], null, null, null, cast(ubyte*)lpData.ptr, lpcbData.ptr) is 0) {
+ length_ = Math.max(0, lpData.length - 1);
+ result = TCHARsToStr( lpData[ 0 .. length_ ] );
+ }
+ }
+ }
+ if (phkResult [0] !is null) OS.RegCloseKey (phkResult [0]);
+ return result;
+}
+private static bool getKeyExists (TCHAR[] key) {
+ void* [1] phkResult;
+ if (OS.RegOpenKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) {
+ return false;
+ }
+ if (phkResult [0] !is null) OS.RegCloseKey (phkResult [0]);
+ return true;
+}
+/**
+ * Returns true if the specified file has an OLE Storage format.
+ *
+ * Note all empty files (regardless of extension) will return false.
+ *
+ * @param file the file to be checked
+ *
+ * @return true if this file has an OLE Storage format
+ */
+public static bool isOleFile(File file) {
+ if (file is null || !file.exists() || file.isDirectory())
+ return false;
+
+ return (COM.StgIsStorageFile( StrToTCHARz(file.getAbsolutePath()~"\0")) is COM.S_OK);
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleAutomation.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleAutomation.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,704 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleAutomation;
+
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.COMTYPES;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+// import org.eclipse.swt.internal.ole.win32.DISPPARAMS;
+// import org.eclipse.swt.internal.ole.win32.EXCEPINFO;
+// import org.eclipse.swt.internal.ole.win32.FUNCDESC;
+// import org.eclipse.swt.internal.ole.win32.GUID;
+// import org.eclipse.swt.internal.ole.win32.IDispatch;
+// import org.eclipse.swt.internal.ole.win32.ITypeInfo;
+// import org.eclipse.swt.internal.ole.win32.TYPEATTR;
+// import org.eclipse.swt.internal.ole.win32.VARDESC;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.ole.win32.OleClientSite;
+import org.eclipse.swt.ole.win32.OlePropertyDescription;
+import org.eclipse.swt.ole.win32.OleFunctionDescription;
+import org.eclipse.swt.ole.win32.OleParameterDescription;
+import org.eclipse.swt.ole.win32.Variant;
+import org.eclipse.swt.ole.win32.OLE;
+
+import java.lang.all;
+
+/**
+ * OleAutomation provides a generic mechanism for accessing functionality that is
+ * specific to a particular ActiveX Control or OLE Document.
+ *
+ * The OLE Document or ActiveX Control must support the IDispatch interface in order to provide
+ * OleAutomation support. The additional functionality provided by the OLE Object is specified in
+ * its IDL file. The additional methods can either be to get property values (getProperty
),
+ * to set property values (setProperty
) or to invoke a method (invoke
or
+ * invokeNoReply
). Arguments are passed around in the form of Variant
+ * objects.
+ *
+ *
Here is a sample IDL fragment:
+ *
+ *
+ * interface IMyControl : IDispatch
+ * {
+ * [propget, id(0)] HRESULT maxFileCount([retval, out] int *c);
+ * [propput, id(0)] HRESULT maxFileCount([in] int c);
+ * [id(1)] HRESULT AddFile([in] BSTR fileName);
+ * };
+ *
+ *
+ * An example of how to interact with this extended functionality is shown below:
+ *
+ *
+ * OleAutomation automation = new OleAutomation(myControlSite);
+ *
+ * // Look up the ID of the maxFileCount parameter
+ * int[] rgdispid = automation.getIDsOfNames(new String[]{"maxFileCount"});
+ * int maxFileCountID = rgdispid[0];
+ *
+ * // Set the property maxFileCount to 100:
+ * if (automation.setProperty(maxFileCountID, new Variant(100))) {
+ * System.out.println("Max File Count was successfully set.");
+ * }
+ *
+ * // Get the new value of the maxFileCount parameter:
+ * Variant pVarResult = automation.getProperty(maxFileCountID);
+ * if (pVarResult !is null) {
+ * System.out.println("Max File Count is "+pVarResult.getInt());
+ * }
+ *
+ * // Invoke the AddFile method
+ * // Look up the IDs of the AddFile method and its parameter
+ * rgdispid = automation.getIDsOfNames(new String[]{"AddFile", "fileName"});
+ * int dispIdMember = rgdispid[0];
+ * int[] rgdispidNamedArgs = new int[] {rgdispid[1]};
+ *
+ * // Convert arguments to Variant objects
+ * Variant[] rgvarg = new Variant[1];
+ * String fileName = "C:\\testfile";
+ * rgvarg[0] = new Variant(fileName);
+ *
+ * // Call the method
+ * Variant pVarResult = automation.invoke(dispIdMember, rgvarg, rgdispidNamedArgs);
+ *
+ * // Check the return value
+ * if (pVarResult is null || pVarResult.getInt() !is OLE.S_OK){
+ * System.out.println("Failed to add file "+fileName);
+ * }
+ *
+ * automation.dispose();
+ *
+ *
+ *
+ * @see OLE and ActiveX snippets
+ * @see SWT Examples: OLEExample, OleWebBrowser
+ */
+public final class OleAutomation {
+ private IDispatch objIDispatch;
+ private String exceptionDescription;
+ private ITypeInfo objITypeInfo;
+
+this(IDispatch idispatch) {
+ if (idispatch is null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
+ objIDispatch = idispatch;
+ objIDispatch.AddRef();
+
+ int result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, &objITypeInfo);
+ if (result is OLE.S_OK) {
+ objITypeInfo.AddRef();
+ }
+}
+/**
+ * Creates an OleAutomation object for the specified client.
+ *
+ * @param clientSite the site for the OLE Document or ActiveX Control whose additional functionality
+ * you need to access
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_INVALID_INTERFACE_ADDRESS when called with an invalid client site
+ *
+ */
+ public this(OleClientSite clientSite) {
+ if (clientSite is null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
+ objIDispatch = clientSite.getAutomationObject();
+
+ auto result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, &objITypeInfo);
+ if (result is OLE.S_OK) {
+ objITypeInfo.AddRef();
+ }
+ }
+/**
+ * Disposes the automation object.
+ *
+ * This method releases the IDispatch interface on the OLE Document or ActiveX Control.
+ * Do not use the OleAutomation object after it has been disposed.
+ */
+public void dispose() {
+
+ if (objIDispatch !is null){
+ objIDispatch.Release();
+ }
+ objIDispatch = null;
+
+ if (objITypeInfo !is null){
+ objITypeInfo.Release();
+ }
+ objITypeInfo = null;
+
+}
+IDispatch getAddress() {
+ return objIDispatch;
+}
+/**
+ * Returns the fully qualified name of the Help file for the given member ID.
+ *
+ * @param dispId the member ID whose Help file is being retrieved.
+ * @return a string representing the fully qualified name of a Help
+ * file or null.
+ */
+public String getHelpFile(int dispId) {
+ if (objITypeInfo is null) return null;
+ BSTR file;
+ HRESULT rc = objITypeInfo.GetDocumentation(dispId, null, null, null, &file );
+ if (rc is OLE.S_OK) {
+ String str = WCHARzToStr( file, -1 );
+ COM.SysFreeString(file);
+ return str;
+ }
+ return null;
+}
+/**
+ * Returns the documentation string for the given member ID.
+ *
+ * @param dispId the member ID in which the documentation is being retrieved.
+ * @return the documentation string if it exists; otherwise return null.
+ */
+public String getDocumentation(int dispId) {
+ if (objITypeInfo is null) return null;
+ BSTR doc;
+ HRESULT rc = objITypeInfo.GetDocumentation(dispId, null, &doc, null, null );
+ if (rc == OLE.S_OK) {
+ String s = WCHARzToStr(doc, -1);
+ COM.SysFreeString(doc);
+ return s;
+ }
+ return null;
+}
+/**
+ * Returns the property description of a variable at the given index.
+ *
+ * @param index the index of a variable whose property is being retrieved.
+ * @return an OlePropertyDescription for a variable at the given index.
+ */
+public OlePropertyDescription getPropertyDescription(int index) {
+ if (objITypeInfo is null) return null;
+ VARDESC* vardesc;
+ HRESULT rc = objITypeInfo.GetVarDesc(index, &vardesc);
+ if (rc != OLE.S_OK) return null;
+// VARDESC* vardesc = new VARDESC();
+// COM.MoveMemory(vardesc, ppVarDesc[0], VARDESC.sizeof);
+
+ OlePropertyDescription data = new OlePropertyDescription();
+ data.id = vardesc.memid;
+ data.name = getName(vardesc.memid);
+ data.type = vardesc.elemdescVar.tdesc.vt;
+ if (data.type == OLE.VT_PTR) {
+// short[] vt = new short[1];
+// COM.MoveMemory(vt, vardesc.elemdescVar.tdesc_union + 4, 2);
+ // TODO:
+ data.type = vardesc.elemdescVar.tdesc.vt;
+ }
+ data.flags = vardesc.wVarFlags;
+ data.kind = vardesc.varkind;
+ data.description = getDocumentation(vardesc.memid);
+ data.helpFile = getHelpFile(vardesc.memid);
+
+ objITypeInfo.ReleaseVarDesc(vardesc);
+ return data;
+}
+/**
+ * Returns the description of a function at the given index.
+ *
+ * @param index the index of a function whose property is being retrieved.
+ * @return an OleFunctionDescription for a function at the given index.
+ */
+public OleFunctionDescription getFunctionDescription(int index) {
+ if (objITypeInfo is null) return null;
+ FUNCDESC* funcdesc;
+ HRESULT rc = objITypeInfo.GetFuncDesc(index, &funcdesc);
+ if (rc != OLE.S_OK) return null;
+
+ OleFunctionDescription data = new OleFunctionDescription();
+
+ data.id = funcdesc.memid;
+ data.optionalArgCount = funcdesc.cParamsOpt;
+ data.invokeKind = funcdesc.invkind;
+ data.funcKind = funcdesc.funckind;
+ data.flags = funcdesc.wFuncFlags;
+ data.callingConvention = funcdesc.callconv;
+ data.documentation = getDocumentation(funcdesc.memid);
+ data.helpFile = getHelpFile(funcdesc.memid);
+
+ String[] names = getNames(funcdesc.memid, funcdesc.cParams + 1);
+ if (names.length > 0) {
+ data.name = names[0];
+ }
+ data.args = new OleParameterDescription[funcdesc.cParams];
+ for (int i = 0; i < data.args.length; i++) {
+ data.args[i] = new OleParameterDescription();
+ if (names.length > i + 1) {
+ data.args[i].name = names[i + 1];
+ }
+ short[1] vt;
+ COM.MoveMemory(vt.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16 + 4, 2);
+ if (vt[0] is OLE.VT_PTR) {
+ int[1] pTypedesc;
+ COM.MoveMemory(pTypedesc.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16, 4);
+ short[1] vt2;
+ COM.MoveMemory(vt2.ptr, pTypedesc[0] + 4, 2);
+ vt[0] = cast(short)(vt2[0] | COM.VT_BYREF);
+ }
+ data.args[i].type = vt[0];
+ short[1] wParamFlags;
+ COM.MoveMemory(wParamFlags.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16 + 12, 2);
+ data.args[i].flags = wParamFlags[0];
+ }
+
+ data.returnType = funcdesc.elemdescFunc.tdesc.vt;
+ if (data.returnType is OLE.VT_PTR) {
+ ushort[1] vt;
+ COM.MoveMemory(vt.ptr, funcdesc.elemdescFunc.tdesc.u.lpadesc, 2);
+ data.returnType = vt[0];
+ }
+
+ objITypeInfo.ReleaseFuncDesc(funcdesc);
+ return data;
+}
+/**
+ * Returns the type info of the current object referenced by the automation.
+ * The type info contains information about the object such as the function descriptions,
+ * the member descriptions and attributes of the type.
+ *
+ * @return the type info of the receiver
+ */
+public TYPEATTR* getTypeInfoAttributes() {
+ if (objITypeInfo is null) return null;
+ TYPEATTR* ppTypeAttr;
+ HRESULT rc = objITypeInfo.GetTypeAttr(&ppTypeAttr);
+ if (rc !is OLE.S_OK) return null;
+ TYPEATTR* typeattr = new TYPEATTR();
+ COM.MoveMemory(typeattr, ppTypeAttr, TYPEATTR.sizeof);
+ objITypeInfo.ReleaseTypeAttr(ppTypeAttr);
+ return typeattr;
+}
+/**
+ * Returns the name of the given member ID.
+ *
+ * @param dispId the member ID in which the name is being retrieved.
+ * @return the name if it exists; otherwise return null.
+ */
+public String getName(int dispId) {
+ if (objITypeInfo is null) return null;
+ BSTR name;
+ HRESULT rc = objITypeInfo.GetDocumentation(dispId, &name, null, null, null );
+ if (rc == OLE.S_OK) {
+ String s = WCHARzToStr(name, -1);
+ COM.SysFreeString(name);
+ return s;
+ }
+ return null;
+}
+/**
+ * Returns the name of a function and parameter names for the specified function ID.
+ *
+ * @param dispId the function ID in which the name and parameters are being retrieved.
+ * @param maxSize the maximum number of names to retrieve.
+ * @return an array of name containing the function name and the parameter names
+ */
+public String[] getNames(int dispId, int maxSize) {
+ if (objITypeInfo is null) return new String[0];
+ BSTR[] names = new BSTR[maxSize];
+ uint count;
+ HRESULT rc = objITypeInfo.GetNames(dispId, names.ptr, maxSize, &count);
+ if (rc == OLE.S_OK) {
+ String[] newNames = new String[count];
+ for(int i=0; i 0) {
+ VARIANT[] tempArgs = new VARIANT[rgvarg.length];
+ for (int i = 0; i < rgvarg.length ; ++i) {
+ rgvarg[i].getData(&tempArgs[i]);
+ }
+ // the reverse sequency
+ tempArgs.reverse;
+ pDispParams.cArgs = tempArgs.length;
+ pDispParams.rgvarg = tempArgs.ptr;
+ }
+
+ // if arguments have ids, store the ids in rgdispidNamedArgs
+ if (rgdispidNamedArgs !is null && rgdispidNamedArgs.length > 0) {
+ DISPID[] tempArgs = rgdispidNamedArgs.dup;
+ // the reverse sequency
+ tempArgs.reverse;
+ pDispParams.cNamedArgs = tempArgs.length;
+ pDispParams.rgdispidNamedArgs = tempArgs.ptr;
+ }
+
+ // invoke the method
+ EXCEPINFO excepInfo;
+ uint pArgErr;
+ VARIANT* pVarResultAddress = null;
+ if (pVarResult !is null)
+ pVarResultAddress = new VARIANT();
+
+ GUID id; // IID_NULL
+ /*
+ HRESULT Invoke(
+ [in] DISPID dispIdMember,
+ [in] REFIID riid,
+ [in] LCID lcid,
+ [in] WORD wFlags,
+ [in, out] DISPPARAMS * pDispParams,
+ [out] VARIANT * pVarResult,
+ [out] EXCEPINFO * pExcepInfo,
+ [out] UINT * puArgErr
+ );
+ */
+ HRESULT result = objIDispatch.Invoke(dispIdMember, &id, COM.LOCALE_USER_DEFAULT, wFlags, &pDispParams, pVarResultAddress, &excepInfo, &pArgErr);
+
+ if (pVarResultAddress !is null){
+ pVarResult.setData(pVarResultAddress);
+ COM.VariantClear(pVarResultAddress);
+ }
+
+ // free the Dispparams resources
+ if (pDispParams.rgvarg !is null) {
+ for (int i = 0, length = rgvarg.length; i < length; i++){
+ COM.VariantClear(&pDispParams.rgvarg[i]);
+ }
+ pDispParams.rgvarg = null;
+ }
+ pDispParams.rgdispidNamedArgs = null;
+
+ // save error string and cleanup EXCEPINFO
+ manageExcepinfo(result, &excepInfo);
+
+ return result;
+}
+/**
+ * Invokes a method on the OLE Object; the method has no parameters. In the early days of OLE,
+ * the IDispatch interface was not well defined and some applications (mainly Word) did not support
+ * a return value. For these applications, call this method instead of calling
+ * public void invoke(int dispIdMember)
.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ * value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @exception org.eclipse.swt.SWTException
+ * - ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *
+ */
+public void invokeNoReply(int dispIdMember) {
+ HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, null);
+ if (result !is COM.S_OK)
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+/**
+ * Invokes a method on the OLE Object; the method has no optional parameters. In the early days of OLE,
+ * the IDispatch interface was not well defined and some applications (mainly Word) did not support
+ * a return value. For these applications, call this method instead of calling
+ * public void invoke(int dispIdMember, Variant[] rgvarg)
.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ * value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method. All arguments are considered to be
+ * read only unless the Variant is a By Reference Variant type.
+ *
+ * @exception org.eclipse.swt.SWTException
+ * - ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *
+ */
+public void invokeNoReply(int dispIdMember, Variant[] rgvarg) {
+ int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, null, null);
+ if (result !is COM.S_OK)
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+/**
+ * Invokes a method on the OLE Object; the method has optional parameters. It is not
+ * necessary to specify all the optional parameters, only include the parameters for which
+ * you are providing values. In the early days of OLE, the IDispatch interface was not well
+ * defined and some applications (mainly Word) did not support a return value. For these
+ * applications, call this method instead of calling
+ * public void invoke(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs)
.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ * value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method. All arguments are considered to be
+ * read only unless the Variant is a By Reference Variant type.
+ *
+ * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
+ * parameter IDs must be in the same order as their corresponding values;
+ * all arguments must have an identifier - identifiers can be obtained using
+ * OleAutomation.getIDsOfNames
+ *
+ * @exception org.eclipse.swt.SWTException
+ * - ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *
+ */
+public void invokeNoReply(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) {
+ HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, null);
+ if (result !is COM.S_OK)
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+private void manageExcepinfo(int hResult, EXCEPINFO* excepInfo) {
+
+ if (hResult is COM.S_OK){
+ exceptionDescription = "No Error"; //$NON-NLS-1$
+ return;
+ }
+
+ // extract exception info
+ if (hResult is COM.DISP_E_EXCEPTION) {
+ if (excepInfo.bstrDescription !is null){
+ exceptionDescription = WCHARzToStr(excepInfo.bstrDescription);
+ } else {
+ exceptionDescription = ("OLE Automation Error Exception "); //$NON-NLS-1$
+ if (excepInfo.wCode != 0){
+ exceptionDescription ~= "code = ";
+ exceptionDescription ~= cast(int)(excepInfo.wCode); //$NON-NLS-1$
+ } else if (excepInfo.scode != 0){
+ exceptionDescription ~= "code = ";
+ exceptionDescription ~= (excepInfo.scode); //$NON-NLS-1$
+ }
+ }
+ } else {
+ exceptionDescription = ("OLE Automation Error HResult : ") ~ toHex(hResult); //$NON-NLS-1$
+ }
+
+ // cleanup EXCEPINFO struct
+ if (excepInfo.bstrDescription !is null)
+ COM.SysFreeString(excepInfo.bstrDescription);
+ if (excepInfo.bstrHelpFile !is null)
+ COM.SysFreeString(excepInfo.bstrHelpFile);
+ if (excepInfo.bstrSource !is null)
+ COM.SysFreeString(excepInfo.bstrSource);
+}
+/**
+ * Sets the property specified by the dispIdMember to a new value.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ * value for the ID can be obtained using OleAutomation.getIDsOfNames
+ * @param rgvarg the new value of the property
+ *
+ * @return true if the operation was successful
+ */
+public bool setProperty(int dispIdMember, Variant rgvarg) {
+
+ Variant[] rgvarg2 = new Variant[1];
+ rgvarg2[0] = rgvarg;
+ int[] rgdispidNamedArgs;
+ rgdispidNamedArgs ~= COM.DISPID_PROPERTYPUT;
+ ushort dwFlags = COM.DISPATCH_PROPERTYPUT;
+ if ((rgvarg.getType() & COM.VT_BYREF) == COM.VT_BYREF)
+ dwFlags = COM.DISPATCH_PROPERTYPUTREF;
+ Variant pVarResult = new Variant();
+ HRESULT result = invoke(dispIdMember, dwFlags, rgvarg2, rgdispidNamedArgs, pVarResult);
+ return (result == COM.S_OK);
+}
+/**
+ * Sets the property specified by the dispIdMember to a new value.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ * value for the ID can be obtained using OleAutomation.getIDsOfNames
+ * @param rgvarg an array of arguments for the method. All arguments are considered to be
+ * read only unless the Variant is a By Reference Variant type.
+ *
+ * @return true if the operation was successful
+ *
+ * @since 2.0
+ */
+public bool setProperty(int dispIdMember, Variant[] rgvarg) {
+ int[] rgdispidNamedArgs;
+ rgdispidNamedArgs ~= COM.DISPID_PROPERTYPUT;
+ ushort dwFlags = COM.DISPATCH_PROPERTYPUT;
+ for (int i = 0; i < rgvarg.length; i++) {
+ if ((rgvarg[i].getType() & COM.VT_BYREF) == COM.VT_BYREF)
+ dwFlags = COM.DISPATCH_PROPERTYPUTREF;
+ }
+ Variant pVarResult = new Variant();
+ HRESULT result = invoke(dispIdMember, dwFlags, rgvarg, rgdispidNamedArgs, pVarResult);
+ return (result == COM.S_OK);
+}
+}
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleClientSite.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleClientSite.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1447 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleClientSite;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.lang.all;
+
+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.Compatibility;
+// import org.eclipse.swt.internal.ole.win32.CAUUID;
+// import org.eclipse.swt.internal.ole.win32.COM;
+// import org.eclipse.swt.internal.ole.win32.COMObject;
+// import org.eclipse.swt.internal.ole.win32.GUID;
+// import org.eclipse.swt.internal.ole.win32.IDispatch;
+// import org.eclipse.swt.internal.ole.win32.IMoniker;
+// import org.eclipse.swt.internal.ole.win32.IOleCommandTarget;
+// import org.eclipse.swt.internal.ole.win32.IOleDocument;
+// import org.eclipse.swt.internal.ole.win32.IOleDocumentView;
+// import org.eclipse.swt.internal.ole.win32.IOleInPlaceObject;
+// import org.eclipse.swt.internal.ole.win32.IOleLink;
+// import org.eclipse.swt.internal.ole.win32.IOleObject;
+// import org.eclipse.swt.internal.ole.win32.IPersist;
+// import org.eclipse.swt.internal.ole.win32.IPersistStorage;
+// import org.eclipse.swt.internal.ole.win32.ISpecifyPropertyPages;
+// import org.eclipse.swt.internal.ole.win32.IStorage;
+// import org.eclipse.swt.internal.ole.win32.IStream;
+// import org.eclipse.swt.internal.ole.win32.IUnknown;
+// import org.eclipse.swt.internal.ole.win32.IViewObject2;
+// import org.eclipse.swt.internal.ole.win32.OLECMD;
+// import org.eclipse.swt.internal.ole.win32.OLEINPLACEFRAMEINFO;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.ole.win32.OLEIDL;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.ole.win32.DOCOBJ;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.ifs;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.swt.ole.win32.OleFrame;
+import org.eclipse.swt.ole.win32.Variant;
+import org.eclipse.swt.ole.win32.OLE;
+
+
+/**
+ * OleClientSite provides a site to manage an embedded OLE Document within a container.
+ *
+ * The OleClientSite provides the following capabilities:
+ *
+ * - creates the in-place editor for a blank document or opening an existing OLE Document
+ *
- lays the editor out
+ *
- provides a mechanism for activating and deactivating the Document
+ *
- provides a mechanism for saving changes made to the document
+ *
+ *
+ * This object implements the OLE Interfaces IUnknown, IOleClientSite, IAdviseSink,
+ * IOleInPlaceSite
+ *
+ *
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
- BORDER
+ *
- Events
- Dispose, Move, Resize
+ *
+ *
+ * @see OLE and ActiveX snippets
+ * @see SWT Examples: OLEExample, OleWebBrowser
+ */
+public class OleClientSite : Composite {
+
+ // Interfaces for this Ole Client Container
+ private _IUnknownImpl iUnknown;
+ private _IOleClientSiteImpl iOleClientSite;
+ private _IAdviseSinkImpl iAdviseSink;
+ private _IOleInPlaceSiteImpl iOleInPlaceSite;
+ private _IOleDocumentSiteImpl iOleDocumentSite;
+
+ protected GUID* appClsid;
+ private GUID* objClsid;
+ private int refCount;
+
+ // References to the associated Frame.
+ package OleFrame frame;
+
+ // Access to the embedded/linked Ole Object
+ protected IUnknown objIUnknown;
+ protected IOleObject objIOleObject;
+ protected IViewObject2 objIViewObject2;
+ protected IOleInPlaceObject objIOleInPlaceObject;
+ protected IOleCommandTarget objIOleCommandTarget;
+ protected IOleDocumentView objDocumentView;
+
+ // Related storage information
+ protected IStorage tempStorage; // IStorage interface of the receiver
+
+ // Internal state and style information
+ private int aspect; // the display aspect of the embedded object, e.g., DvaspectContent or DvaspectIcon
+ private int type; // Indicates the type of client that can be supported inside this container
+ private bool isStatic; // Indicates item's display is static, i.e., a bitmap, metafile, etc.
+
+ private RECT borderWidths;
+ private RECT indent;
+ private bool inUpdate = false;
+ private bool inInit = true;
+ private bool inDispose = false;
+
+ private static const String WORDPROGID = "Word.Document"; //$NON-NLS-1$
+
+ private Listener listener;
+
+ enum{
+ STATE_NONE = 0,
+ STATE_RUNNING = 1,
+ STATE_INPLACEACTIVE = 2,
+ STATE_UIACTIVE = 3,
+ STATE_ACTIVE = 4,
+ }
+ int state = STATE_NONE;
+
+protected this(Composite parent, int style) {
+ /*
+ * NOTE: this constructor should never be used by itself because it does
+ * not create an Ole Object
+ */
+ super(parent, style);
+
+ createCOMInterfaces();
+
+ // install the Ole Frame for this Client Site
+ while (parent !is null) {
+ if ( auto aframe = cast(OleFrame)parent){
+ frame = aframe;
+ break;
+ }
+ parent = parent.getParent();
+ }
+ if (frame is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_INVALID_ARGUMENT);
+ frame.AddRef();
+
+ aspect = COM.DVASPECT_CONTENT;
+ type = COM.OLEEMBEDDED;
+ isStatic = false;
+
+ listener = new class() Listener {
+ public void handleEvent(Event e) {
+ switch (e.type) {
+ case SWT.Resize :
+ case SWT.Move : onResize(e); break;
+ case SWT.Dispose : onDispose(e); break;
+ case SWT.FocusIn: onFocusIn(e); break;
+ case SWT.FocusOut: onFocusOut(e); break;
+ case SWT.Paint: onPaint(e); break;
+ case SWT.Traverse: onTraverse(e); break;
+ case SWT.KeyDown: /* required for traversal */ break;
+ default :
+ OLE.error (__FILE__, __LINE__, SWT.ERROR_NOT_IMPLEMENTED);
+ }
+ }
+ };
+
+ frame.addListener(SWT.Resize, listener);
+ frame.addListener(SWT.Move, listener);
+ addListener(SWT.Dispose, listener);
+ addListener(SWT.FocusIn, listener);
+ addListener(SWT.FocusOut, listener);
+ addListener(SWT.Paint, listener);
+ addListener(SWT.Traverse, listener);
+ addListener(SWT.KeyDown, listener);
+}
+/**
+ * Create an OleClientSite child widget using the OLE Document type associated with the
+ * specified file. The OLE Document type is determined either through header information in the file
+ * or through a Registry entry for the file extension. Use style bits to select a particular look
+ * or set of properties.
+ *
+ * @param parent a composite widget; must be an OleFrame
+ * @param style the bitwise OR'ing of widget styles
+ * @param file the file that is to be opened in this OLE Document
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when the parent is null
+ *
- ERROR_INVALID_ARGUMENT when the parent is not an OleFrame
+ * @exception SWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
- ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ *
- ERROR_CANNOT_OPEN_FILE when failed to open file
+ *
- ERROR_INTERFACE_NOT_FOUND when unable to create callbacks for OLE Interfaces
+ *
- ERROR_INVALID_CLASSID
+ *
+ */
+public this(Composite parent, int style, File file) {
+ this(parent, style);
+ try {
+
+ if (file is null || file.isDirectory() || !file.exists())
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_ARGUMENT);
+
+ // Is there an associated CLSID?
+ appClsid = new GUID();
+ TCHAR* fileName = StrToTCHARz( 0, file.getAbsolutePath() );
+ int result = COM.GetClassFile(fileName, appClsid);
+ if (result !is COM.S_OK)
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID, result);
+ // associated CLSID may not be installed on this machine
+ if (getProgramID() is null)
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID, result);
+
+ // Open a temporary storage object
+ tempStorage = createTempStorage();
+
+ // Create ole object with storage object
+ result = COM.OleCreateFromFile(appClsid, fileName, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
+ if (result !is COM.S_OK)
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+ // Init sinks
+ addObjectReferences();
+
+ if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING;
+ } catch (SWTException e) {
+ dispose();
+ disposeCOMInterfaces();
+ throw e;
+ }
+}
+/**
+ * Create an OleClientSite child widget to edit a blank document using the specified OLE Document
+ * application. Use style bits to select a particular look or set of properties.
+ *
+ * @param parent a composite widget; must be an OleFrame
+ * @param style the bitwise OR'ing of widget styles
+ * @param progId the unique program identifier of am OLE Document application;
+ * the value of the ProgID key or the value of the VersionIndependentProgID key specified
+ * in the registry for the desired OLE Document (for example, the VersionIndependentProgID
+ * for Word is Word.Document)
+ *
+ * @exception IllegalArgumentException
+ *
+ * - ERROR_NULL_ARGUMENT when the parent is null
+ *
- ERROR_INVALID_ARGUMENT when the parent is not an OleFrame
+ *
+ * @exception SWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
- ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
+ *
- ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ *
+ */
+public this(Composite parent, int style, String progId) {
+ this(parent, style);
+ try {
+ appClsid = getClassID(progId);
+ if (appClsid is null)
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID);
+
+ // Open a temporary storage object
+ tempStorage = createTempStorage();
+
+ // Create ole object with storage object
+ HRESULT result = COM.OleCreate(appClsid, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
+ if (result !is COM.S_OK)
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+ // Init sinks
+ addObjectReferences();
+
+ if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING;
+
+ } catch (SWTException e) {
+ dispose();
+ disposeCOMInterfaces();
+ throw e;
+ }
+}
+/**
+ * Create an OleClientSite child widget to edit the specified file using the specified OLE Document
+ * application. Use style bits to select a particular look or set of properties.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for OleClientSite
. 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 parent a composite widget; must be an OleFrame
+ * @param style the bitwise OR'ing of widget styles
+ * @param progId the unique program identifier of am OLE Document application;
+ * the value of the ProgID key or the value of the VersionIndependentProgID key specified
+ * in the registry for the desired OLE Document (for example, the VersionIndependentProgID
+ * for Word is Word.Document)
+ * @param file the file that is to be opened in this OLE Document
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when the parent is null
+ *
- ERROR_INVALID_ARGUMENT when the parent is not an OleFrame
+ * @exception SWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
- ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
+ *
- ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ *
- ERROR_CANNOT_OPEN_FILE when failed to open file
+ *
+ */
+public this(Composite parent, int style, String progId, File file) {
+ this(parent, style);
+ try {
+ if (file is null || file.isDirectory() || !file.exists()) OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_ARGUMENT);
+ appClsid = getClassID(progId);
+ if (appClsid is null) OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID);
+
+ // Are we opening this file with the preferred OLE object?
+ wchar* fileName = StrToWCHARz(file.getAbsolutePath());
+ GUID* fileClsid = new GUID();
+ COM.GetClassFile(fileName, fileClsid);
+
+ if (COM.IsEqualGUID(appClsid, fileClsid)){
+ // Using the same application that created file, therefore, use default mechanism.
+ tempStorage = createTempStorage();
+ // Create ole object with storage object
+ HRESULT result = COM.OleCreateFromFile(appClsid, fileName, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
+ if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+ } else {
+ // Not using the same application that created file, therefore, copy from original file to a new storage file
+ IStorage storage = null;
+ if (COM.StgIsStorageFile(fileName) is COM.S_OK) {
+ int mode = COM.STGM_READ | COM.STGM_TRANSACTED | COM.STGM_SHARE_EXCLUSIVE;
+ HRESULT result = COM.StgOpenStorage(fileName, null, mode, null, 0, &storage); //Does an AddRef if successful
+ if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+ } else {
+ // Original file is not a Storage file so copy contents to a stream in a new storage file
+ int mode = COM.STGM_READWRITE | COM.STGM_DIRECT | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
+ HRESULT result = COM.StgCreateDocfile(null, mode | COM.STGM_DELETEONRELEASE, 0, &storage); // Increments ref count if successful
+ if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+ // Create a stream on the storage object.
+ // Word does not follow the standard and does not use "CONTENTS" as the name of
+ // its primary stream
+ wchar* streamName = StrToWCHARz("CONTENTS"); //$NON-NLS-1$
+ GUID* wordGUID = getClassID(WORDPROGID);
+ if (wordGUID !is null && COM.IsEqualGUID(appClsid, wordGUID)) streamName = "WordDocument"; //$NON-NLS-1$
+ IStream stream;
+ result = storage.CreateStream(streamName, mode, 0, 0, &stream); // Increments ref count if successful
+ if (result !is COM.S_OK) {
+ storage.Release();
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+ }
+ try {
+ // Copy over data in file to named stream
+ FileInputStream fileInput = new FileInputStream(file);
+ int increment = 1024*4;
+ byte[] buffer = new byte[increment];
+ int count = 0;
+ while((count = fileInput.read(buffer)) > 0){
+ auto pv = COM.CoTaskMemAlloc(count);
+ OS.MoveMemory(pv, buffer.ptr, count);
+ result = stream.Write(pv, count, null) ;
+ COM.CoTaskMemFree(pv);
+ if (result !is COM.S_OK) {
+ fileInput.close();
+ stream.Release();
+ storage.Release();
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+ }
+ }
+ fileInput.close();
+ stream.Commit(COM.STGC_DEFAULT);
+ stream.Release();
+ } catch (IOException err) {
+ stream.Release();
+ storage.Release();
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE);
+ }
+ }
+
+ // Open a temporary storage object
+ tempStorage = createTempStorage();
+ // Copy over contents of file
+ HRESULT result = storage.CopyTo(0, null, null, tempStorage);
+ storage.Release();
+ if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+
+ // create ole client
+ result = COM.CoCreateInstance(appClsid, null, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, &COM.IIDIUnknown, cast(void**)&objIUnknown);
+ if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+ // get the persistent storage of the ole client
+ IPersistStorage iPersistStorage;
+ result = objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&iPersistStorage);
+ if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+ // load the contents of the file into the ole client site
+ result = iPersistStorage.Load(tempStorage);
+ iPersistStorage.Release();
+ if (result !is COM.S_OK)OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+ }
+
+ // Init sinks
+ addObjectReferences();
+
+ if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING;
+
+ } catch (SWTException e) {
+ dispose();
+ disposeCOMInterfaces();
+ throw e;
+ }
+}
+protected void addObjectReferences() {
+ //
+ IPersist objIPersist;
+ if (objIUnknown.QueryInterface(&COM.IIDIPersist, cast(void**)&objIPersist) is COM.S_OK) {
+ GUID* tempid = new GUID();
+ if (objIPersist.GetClassID(tempid) is COM.S_OK)
+ objClsid = tempid;
+ objIPersist.Release();
+ }
+
+ //
+ HRESULT result = objIUnknown.QueryInterface(&COM.IIDIViewObject2, cast(void**)&objIViewObject2);
+ if (result !is COM.S_OK)
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_INTERFACE_NOT_FOUND, result);
+ objIViewObject2.SetAdvise(aspect, 0, iAdviseSink);
+
+ //
+ result = objIUnknown.QueryInterface(&COM.IIDIOleObject, cast(void**)&objIOleObject);
+ if (result !is COM.S_OK)
+ OLE.error (__FILE__, __LINE__, OLE.ERROR_INTERFACE_NOT_FOUND, result);
+ objIOleObject.SetClientSite(iOleClientSite);
+ uint pdwConnection;
+ objIOleObject.Advise(iAdviseSink, &pdwConnection);
+ objIOleObject.SetHostNames("main", "main"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ // Notify the control object that it is embedded in an OLE container
+ COM.OleSetContainedObject(objIUnknown, true);
+
+ // Is OLE object linked or embedded?
+ IOleLink objIOleLink;
+ if (objIUnknown.QueryInterface(&COM.IIDIOleLink, cast(void**)&objIOleLink) is COM.S_OK) {
+ IMoniker objIMoniker;
+ if (objIOleLink.GetSourceMoniker(&objIMoniker) is COM.S_OK) {
+ objIMoniker.Release();
+ type = COM.OLELINKED;
+ objIOleLink.BindIfRunning();
+ } else {
+ isStatic = true;
+ }
+ objIOleLink.Release();
+ }
+}
+protected int AddRef() {
+ refCount++;
+ return refCount;
+}
+private int CanInPlaceActivate() {
+ if (aspect is COM.DVASPECT_CONTENT && type is COM.OLEEMBEDDED)
+ return COM.S_OK;
+
+ return COM.S_FALSE;
+}
+private int ContextSensitiveHelp(int fEnterMode) {
+ return COM.S_OK;
+}
+protected void createCOMInterfaces() {
+ iUnknown = new _IUnknownImpl(this);
+ iOleClientSite = new _IOleClientSiteImpl(this);
+ iAdviseSink = new _IAdviseSinkImpl(this);
+ iOleInPlaceSite = new _IOleInPlaceSiteImpl(this);
+ iOleDocumentSite = new _IOleDocumentSiteImpl(this);
+}
+protected IStorage createTempStorage() {
+ IStorage tmpStorage;
+ int grfMode = COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_DELETEONRELEASE;
+ HRESULT result = COM.StgCreateDocfile(null, grfMode, 0, &tmpStorage);
+ if (result !is COM.S_OK) OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_FILE, result);
+ return (tmpStorage);
+}
+/**
+ * Deactivates an active in-place object and discards the object's undo state.
+ */
+public void deactivateInPlaceClient() {
+ if (objIOleInPlaceObject !is null) {
+ objIOleInPlaceObject.InPlaceDeactivate();
+ }
+}
+private void deleteTempStorage() {
+ //Destroy this item's contents in the temp root IStorage.
+ if (tempStorage !is null){
+ tempStorage.Release();
+ }
+ tempStorage = null;
+}
+protected void disposeCOMInterfaces() {
+ iUnknown = null;
+ iOleClientSite = null;
+ iAdviseSink = null;
+ iOleInPlaceSite = null;
+ iOleDocumentSite = null;
+}
+/**
+ * Requests that the OLE Document or ActiveX Control perform an action; actions are almost always
+ * changes to the activation state.
+ *
+ * @param verb the operation that is requested. This is one of the OLE.OLEIVERB_ values
+ *
+ * @return an HRESULT value indicating the success of the operation request; OLE.S_OK indicates
+ * success
+ */
+public int doVerb(int verb) {
+ // Not all OLE clients (for example PowerPoint) can be set into the running state in the constructor.
+ // The fix is to ensure that the client is in the running state before invoking any verb on it.
+ if (state is STATE_NONE) {
+ if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING;
+ }
+ if (state is STATE_NONE || isStatic)
+ return COM.E_FAIL;
+
+ // See PR: 1FV9RZW
+ RECT rect;
+ OS.GetClientRect(handle, &rect);
+ int result = objIOleObject.DoVerb(verb, null, iOleClientSite, 0, handle, &rect);
+
+ if (state !is STATE_RUNNING && inInit) {
+ updateStorage();
+ inInit = false;
+ }
+ return result;
+}
+/**
+ * Asks the OLE Document or ActiveX Control to execute a command from a standard
+ * list of commands. The OLE Document or ActiveX Control must support the IOleCommandTarget
+ * interface. The OLE Document or ActiveX Control does not have to support all the commands
+ * in the standard list. To check if a command is supported, you can call queryStatus with
+ * the cmdID.
+ *
+ * @param cmdID the ID of a command; these are the OLE.OLECMDID_ values - a small set of common
+ * commands
+ * @param options the optional flags; these are the OLE.OLECMDEXECOPT_ values
+ * @param in the argument for the command
+ * @param out the return value of the command
+ *
+ * @return an HRESULT value; OLE.S_OK is returned if successful
+ *
+ */
+public int exec(int cmdID, int options, Variant pvaIn, Variant pvaOut) {
+
+ if (objIOleCommandTarget is null) {
+ if (objIUnknown.QueryInterface(&COM.IIDIOleCommandTarget, cast(void**)&objIOleCommandTarget) !is COM.S_OK)
+ return OLE.ERROR_INTERFACE_NOT_FOUND;
+ }
+
+ VARIANT* pIn = null;
+ VARIANT* pOut = null;
+
+ if(pvaIn){
+ pIn = new VARIANT();
+ pvaIn.getData(pIn);
+ }
+ if(pvaOut){
+ pOut = new VARIANT();
+ pvaOut.getData(pOut);
+ }
+
+ HRESULT result = objIOleCommandTarget.Exec(null, cmdID, options, pIn, pOut);
+
+ if(pIn) {
+ COM.VariantClear(pIn);
+ }
+
+ if(pOut) {
+ pvaOut.setData(pOut);
+ COM.VariantClear(pOut);
+ }
+
+ return result;
+}
+IDispatch getAutomationObject() {
+ IDispatch ppvObject;
+ if (objIUnknown.QueryInterface(&COM.IIDIDispatch, cast(void**)&ppvObject) !is COM.S_OK)
+ return null;
+ return ppvObject;
+}
+protected GUID* getClassID(String clientName) {
+ // create a GUID struct to hold the result
+ GUID* guid = new GUID();
+
+ // create a null terminated array of char
+ wchar* buffer = null;
+ if (clientName !is null) {
+ buffer = StrToWCHARz(clientName);;
+ }
+ if (COM.CLSIDFromProgID(buffer, guid) !is COM.S_OK){
+ HRESULT result = COM.CLSIDFromString(buffer, guid);
+ if (result !is COM.S_OK) return null;
+ }
+ return guid;
+}
+
+private HRESULT GetContainer(IOleContainer* ppContainer) {
+ /* Simple containers that do not support links to their embedded
+ * objects probably do not need to implement this method. Instead,
+ * they can return E_NOINTERFACE and set ppContainer to NULL.
+ */
+ if (ppContainer !is null)
+ *ppContainer = null;
+ return COM.E_NOINTERFACE;
+}
+
+private SIZE* getExtent() {
+ SIZE* sizel = new SIZE();
+ // get the current size of the embedded OLENatives object
+ if (objIOleObject !is null) {
+ if ( objIViewObject2 !is null && !COM.OleIsRunning(objIOleObject)) {
+ objIViewObject2.GetExtent(aspect, -1, null, sizel);
+ } else {
+ objIOleObject.GetExtent(aspect, sizel);
+ }
+ }
+ return xFormHimetricToPixels(sizel);
+}
+/**
+ * Returns the indent value that would be used to compute the clipping area
+ * of the active X object.
+ *
+ * NOTE: The indent value is no longer being used by the client site.
+ *
+ * @return the rectangle representing the indent
+ */
+public Rectangle getIndent() {
+ return new Rectangle(indent.left, indent.right, indent.top, indent.bottom);
+}
+/**
+ * Returns the program ID of the OLE Document or ActiveX Control.
+ *
+ * @return the program ID of the OLE Document or ActiveX Control
+ */
+public String getProgramID(){
+ if (appClsid !is null){
+ wchar* hMem;
+ if (COM.ProgIDFromCLSID(appClsid, &hMem) is COM.S_OK) {
+ int length = OS.GlobalSize(hMem);
+ auto ptr = OS.GlobalLock(hMem);
+ wchar[] buffer = new wchar[length];
+ COM.MoveMemory(buffer.ptr, ptr, length);
+ OS.GlobalUnlock(hMem);
+ OS.GlobalFree(hMem);
+
+ String result = WCHARzToStr(buffer.ptr);
+ // remove null terminator
+ //int index = result.indexOf("\0");
+ return result;//.substring(0, index);
+ }
+ }
+ return null;
+}
+int ActivateMe(IOleDocumentView pViewToActivate) {
+ if (pViewToActivate is null) {
+ void* ppvObject;
+ if (objIUnknown.QueryInterface(&COM.IIDIOleDocument, &ppvObject) !is COM.S_OK) return COM.E_FAIL;
+ IOleDocument objOleDocument = cast(IOleDocument)ppvObject;
+ if (objOleDocument.CreateView(iOleInPlaceSite, null, 0, &objDocumentView) !is COM.S_OK) return COM.E_FAIL;
+ objOleDocument.Release();
+ } else {
+ objDocumentView = pViewToActivate;
+ objDocumentView.AddRef();
+ objDocumentView.SetInPlaceSite(iOleInPlaceSite);
+ }
+ objDocumentView.UIActivate(1);//TRUE
+ RECT* rect = getRect();
+ objDocumentView.SetRect(rect);
+ objDocumentView.Show(1);//TRUE
+ return COM.S_OK;
+}
+protected int GetWindow(HWND* phwnd) {
+ if (phwnd is null)
+ return COM.E_INVALIDARG;
+ if (frame is null) {
+ *phwnd = null;
+ return COM.E_NOTIMPL;
+ }
+
+ // Copy the Window's handle into the memory passed in
+ *phwnd = frame.handle;
+ return COM.S_OK;
+}
+RECT* getRect() {
+ Point location = this.getLocation();
+ Rectangle area = frame.getClientArea();
+ RECT* rect = new RECT();
+ rect.left = location.x;
+ rect.top = location.y;
+ rect.right = location.x + area.width - borderWidths.left - borderWidths.right;
+ rect.bottom = location.y + area.height - borderWidths.top - borderWidths.bottom;
+ return rect;
+}
+
+private int GetWindowContext(IOleInPlaceFrame* ppFrame, IOleInPlaceUIWindow* ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) {
+ if (frame is null || ppFrame is null)
+ return COM.E_NOTIMPL;
+
+ // fill in frame handle
+ auto iOleInPlaceFrame = frame.getIOleInPlaceFrame();
+ *ppFrame = iOleInPlaceFrame;
+ frame.AddRef();
+
+ // null out document handle
+ if (ppDoc !is null) *ppDoc = null;
+
+ // fill in position and clipping info
+ RECT* rect = getRect();
+ if (lprcPosRect !is null) OS.MoveMemory(lprcPosRect, rect, RECT.sizeof);
+ if (lprcClipRect !is null) OS.MoveMemory(lprcClipRect, rect, RECT.sizeof);
+
+ // get frame info
+ OLEINPLACEFRAMEINFO* frameInfo = new OLEINPLACEFRAMEINFO();
+ frameInfo.cb = OLEINPLACEFRAMEINFO.sizeof;
+ frameInfo.fMDIApp = 0;
+ frameInfo.hwndFrame = frame.handle;
+ Shell shell = getShell();
+ Menu menubar = shell.getMenuBar();
+ if (menubar !is null && !menubar.isDisposed()) {
+ auto hwnd = shell.handle;
+ auto cAccel = OS.SendMessage(hwnd, OS.WM_APP, 0, 0);
+ if (cAccel !is 0) {
+ auto hAccel = cast(HACCEL) OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
+ if (hAccel !is null) {
+ frameInfo.cAccelEntries = cAccel;
+ frameInfo.haccel = hAccel;
+ }
+ }
+ }
+ COM.MoveMemory(lpFrameInfo, frameInfo, OLEINPLACEFRAMEINFO.sizeof);
+
+ return COM.S_OK;
+}
+/**
+ * Returns whether ole document is dirty by checking whether the content
+ * of the file representing the document is dirty.
+ *
+ * @return true
if the document has been modified,
+ * false
otherwise.
+ * @since 3.1
+ */
+public bool isDirty() {
+ /*
+ * Note: this method must return true unless it is absolutely clear that the
+ * contents of the Ole Document do not differ from the contents in the file
+ * on the file system.
+ */
+
+ // Get access to the persistent storage mechanism
+ IPersistStorage permStorage;
+ if (objIOleObject.QueryInterface(&COM.IIDIPersistFile, cast(void**)&permStorage) !is COM.S_OK)
+ return true;
+ // Are the contents of the permanent storage different from the file?
+ auto result = permStorage.IsDirty();
+ permStorage.Release();
+ if (result is COM.S_FALSE) return false;
+ return true;
+}
+public bool isFocusControl () {
+ checkWidget ();
+ auto focusHwnd = OS.GetFocus();
+ if (objIOleInPlaceObject is null) return (handle is focusHwnd);
+ HWND phwnd;
+ objIOleInPlaceObject.GetWindow(&phwnd);
+ while (focusHwnd !is null) {
+ if (phwnd is focusHwnd) return true;
+ focusHwnd = OS.GetParent(focusHwnd);
+ }
+ return false;
+}
+private int OnClose() {
+ return COM.S_OK;
+}
+private int OnDataChange(int pFormatetc, int pStgmed) {
+ return COM.S_OK;
+}
+private void onDispose(Event e) {
+ inDispose = true;
+ if (state !is STATE_NONE)
+ doVerb(OLE.OLEIVERB_DISCARDUNDOSTATE);
+ deactivateInPlaceClient();
+ releaseObjectInterfaces(); // Note, must release object interfaces before releasing frame
+ deleteTempStorage();
+
+ // remove listeners
+ removeListener(SWT.Dispose, listener);
+ removeListener(SWT.FocusIn, listener);
+ removeListener(SWT.Paint, listener);
+ removeListener(SWT.Traverse, listener);
+ removeListener(SWT.KeyDown, listener);
+ frame.removeListener(SWT.Resize, listener);
+ frame.removeListener(SWT.Move, listener);
+
+ frame.Release();
+ frame = null;
+}
+void onFocusIn(Event e) {
+ if (inDispose) return;
+ if (state !is STATE_UIACTIVE) doVerb(OLE.OLEIVERB_SHOW);
+ if (objIOleInPlaceObject is null) return;
+ if (isFocusControl()) return;
+ HWND phwnd;
+ objIOleInPlaceObject.GetWindow(&phwnd);
+ if (phwnd is null) return;
+ OS.SetFocus(phwnd);
+}
+void onFocusOut(Event e) {
+}
+private int OnInPlaceActivate() {
+ state = STATE_INPLACEACTIVE;
+ frame.setCurrentDocument(this);
+ if (objIOleObject is null)
+ return COM.S_OK;
+ int[] ppvObject = new int[1];
+ if (objIOleObject.QueryInterface(&COM.IIDIOleInPlaceObject, cast(void**)&objIOleInPlaceObject) is COM.S_OK) {
+ //objIOleInPlaceObject = new IOleInPlaceObject(ppvObject[0]);
+ }
+ return COM.S_OK;
+}
+private int OnInPlaceDeactivate() {
+ if (objIOleInPlaceObject !is null) objIOleInPlaceObject.Release();
+ objIOleInPlaceObject = null;
+ state = STATE_RUNNING;
+ redraw();
+ Shell shell = getShell();
+ if (isFocusControl() || frame.isFocusControl()) {
+ shell.traverse(SWT.TRAVERSE_TAB_NEXT);
+ }
+ return COM.S_OK;
+}
+private int OnPosRectChange(LPRECT lprcPosRect) {
+ Point size = getSize();
+ setExtent(size.x, size.y);
+ return COM.S_OK;
+}
+private void onPaint(Event e) {
+ if (state is STATE_RUNNING || state is STATE_INPLACEACTIVE) {
+ SIZE* size = getExtent();
+ Rectangle area = getClientArea();
+ RECT* rect = new RECT();
+ if (getProgramID().startsWith("Excel.Sheet")) { //$NON-NLS-1$
+ rect.left = area.x; rect.right = area.x + (area.height * size.cx / size.cy);
+ rect.top = area.y; rect.bottom = area.y + area.height;
+ } else {
+ rect.left = area.x; rect.right = area.x + size.cx;
+ rect.top = area.y; rect.bottom = area.y + size.cy;
+ }
+
+ auto pArea = cast(RECT*)OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, RECT.sizeof);
+ OS.MoveMemory(pArea, rect, RECT.sizeof);
+ COM.OleDraw(objIUnknown, aspect, e.gc.handle, pArea);
+ OS.GlobalFree(pArea);
+ }
+}
+private void onResize(Event e) {
+ Rectangle area = frame.getClientArea();
+ setBounds(borderWidths.left,
+ borderWidths.top,
+ area.width - borderWidths.left - borderWidths.right,
+ area.height - borderWidths.top - borderWidths.bottom);
+
+ setObjectRects();
+}
+private void OnSave() {
+}
+private int OnShowWindow(int fShow) {
+ return COM.S_OK;
+}
+private int OnUIActivate() {
+ if (objIOleInPlaceObject is null) return COM.E_FAIL;
+ state = STATE_UIACTIVE;
+ HWND phwnd;
+ if (objIOleInPlaceObject.GetWindow(&phwnd) is COM.S_OK) {
+ OS.SetWindowPos(phwnd, cast(HWND)OS.HWND_TOP, 0, 0, 0, 0, OS.SWP_NOSIZE | OS.SWP_NOMOVE);
+ }
+ return COM.S_OK;
+}
+private int OnUIDeactivate(int fUndoable) {
+ // currently, we are ignoring the fUndoable flag
+ if (frame is null || frame.isDisposed()) return COM.S_OK;
+ state = STATE_INPLACEACTIVE;
+ frame.SetActiveObject(null, null);
+ redraw();
+ Shell shell = getShell();
+ if (isFocusControl() || frame.isFocusControl()) {
+ shell.traverse(SWT.TRAVERSE_TAB_NEXT);
+ }
+ Menu menubar = shell.getMenuBar();
+ if (menubar is null || menubar.isDisposed())
+ return COM.S_OK;
+
+ auto shellHandle = shell.handle;
+ OS.SetMenu(shellHandle, menubar.handle);
+ return COM.OleSetMenuDescriptor(null, shellHandle, null, null, null);
+}
+private void onTraverse(Event event) {
+ switch (event.detail) {
+ case SWT.TRAVERSE_ESCAPE:
+ case SWT.TRAVERSE_RETURN:
+ case SWT.TRAVERSE_TAB_NEXT:
+ case SWT.TRAVERSE_TAB_PREVIOUS:
+ case SWT.TRAVERSE_PAGE_NEXT:
+ case SWT.TRAVERSE_PAGE_PREVIOUS:
+ case SWT.TRAVERSE_MNEMONIC:
+ event.doit = true;
+ break;
+ default:
+ }
+}
+private int OnViewChange(int dwAspect, int lindex) {
+ return COM.S_OK;
+}
+protected int QueryInterface(REFIID riid, void ** ppvObject) {
+
+ if (riid is null || ppvObject is null)
+ return COM.E_NOINTERFACE;
+ GUID oGuid = *riid;
+ GUID* guid = &oGuid;
+ //COM.MoveMemory(guid, riid, GUID.sizeof);
+
+ if (COM.IsEqualGUID(guid, &COM.IIDIUnknown)) {
+ *ppvObject = cast(void*)cast(IUnknown)iUnknown;
+ AddRef();
+ return COM.S_OK;
+ }
+ if (COM.IsEqualGUID(guid, &COM.IIDIAdviseSink)) {
+ *ppvObject = cast(void*)cast(IAdviseSink)iAdviseSink;
+ AddRef();
+ return COM.S_OK;
+ }
+ if (COM.IsEqualGUID(guid, &COM.IIDIOleClientSite)) {
+ *ppvObject = cast(void*)cast(IOleClientSite)iOleClientSite;
+ AddRef();
+ return COM.S_OK;
+ }
+ if (COM.IsEqualGUID(guid, &COM.IIDIOleInPlaceSite)) {
+ *ppvObject = cast(void*)cast(IOleInPlaceSite)iOleInPlaceSite;
+ AddRef();
+ return COM.S_OK;
+ }
+ if (COM.IsEqualGUID(guid, &COM.IIDIOleDocumentSite )) {
+ String progID = getProgramID();
+ if (!progID.startsWith("PowerPoint")) { //$NON-NLS-1$
+ *ppvObject = cast(void*)cast(IOleDocumentSite)iOleDocumentSite;
+ AddRef();
+ return COM.S_OK;
+ }
+ }
+ *ppvObject = null;
+ return COM.E_NOINTERFACE;
+}
+/**
+ * Returns the status of the specified command. The status is any bitwise OR'd combination of
+ * SWTOLE.OLECMDF_SUPPORTED, SWTOLE.OLECMDF_ENABLED, SWTOLE.OLECMDF_LATCHED, SWTOLE.OLECMDF_NINCHED.
+ * You can query the status of a command before invoking it with OleClientSite.exec. The
+ * OLE Document or ActiveX Control must support the IOleCommandTarget to make use of this method.
+ *
+ * @param cmd the ID of a command; these are the OLE.OLECMDID_ values - a small set of common
+ * commands
+ *
+ * @return the status of the specified command or 0 if unable to query the OLE Object; these are the
+ * OLE.OLECMDF_ values
+ */
+public int queryStatus(int cmd) {
+
+ if (objIOleCommandTarget is null) {
+ if (objIUnknown.QueryInterface(&COM.IIDIOleCommandTarget, cast(void**)&objIOleCommandTarget) !is COM.S_OK)
+ return 0;
+ }
+
+ OLECMD* olecmd = new OLECMD();
+ olecmd.cmdID = cmd;
+
+ auto result = objIOleCommandTarget.QueryStatus(null, 1, olecmd, null);
+
+ if (result !is COM.S_OK) return 0;
+
+ return olecmd.cmdf;
+}
+protected int Release() {
+ refCount--;
+
+ if (refCount is 0) {
+ disposeCOMInterfaces();
+ }
+ return refCount;
+}
+protected void releaseObjectInterfaces() {
+
+ if (objIOleInPlaceObject !is null)
+ objIOleInPlaceObject.Release();
+ objIOleInPlaceObject = null;
+
+ if (objIOleObject !is null) {
+ objIOleObject.Close(COM.OLECLOSE_NOSAVE);
+ objIOleObject.Release();
+ }
+ objIOleObject = null;
+
+ if (objDocumentView !is null){
+ objDocumentView.Release();
+ }
+ objDocumentView = null;
+
+ if (objIViewObject2 !is null) {
+ objIViewObject2.SetAdvise(aspect, 0, null);
+ objIViewObject2.Release();
+ }
+ objIViewObject2 = null;
+
+ if (objIOleCommandTarget !is null)
+ objIOleCommandTarget.Release();
+ objIOleCommandTarget = null;
+
+ if (objIUnknown !is null){
+ objIUnknown.Release();
+ }
+ objIUnknown = null;
+
+ COM.CoFreeUnusedLibraries();
+}
+/**
+ * Saves the document to the specified file and includes OLE specific information if specified.
+ * This method must only be used for files that have an OLE Storage format. For example,
+ * a word file edited with Word.Document should be saved using this method because there is
+ * formating information that should be stored in the OLE specific Storage format.
+ *
+ * @param file the file to which the changes are to be saved
+ * @param includeOleInfo the flag to indicate whether OLE specific information should be saved.
+ *
+ * @return true if the save was successful
+ */
+public bool save(File file, bool includeOleInfo) {
+ if (includeOleInfo)
+ return saveToStorageFile(file);
+ return saveToTraditionalFile(file);
+}
+private bool saveFromContents(IStream address, File file) {
+
+ bool success = false;
+
+ IStream tempContents = address;
+ tempContents.AddRef();
+
+ try {
+ FileOutputStream writer = new FileOutputStream(file);
+
+ int increment = 1024 * 4;
+ LPVOID pv = COM.CoTaskMemAlloc(increment);
+ uint pcbWritten;
+ while (tempContents.Read(pv, increment, &pcbWritten) is COM.S_OK && pcbWritten > 0) {
+ byte[] buffer = new byte[ pcbWritten];
+ OS.MoveMemory(buffer.ptr, pv, pcbWritten);
+ writer.write(buffer); // Note: if file does not exist, this will create the file the
+ // first time it is called
+ success = true;
+ }
+ COM.CoTaskMemFree(pv);
+
+ writer.close();
+
+ } catch (IOException err) {
+ }
+
+ tempContents.Release();
+
+ return success;
+}
+private bool saveFromOle10Native(IStream address, File file) {
+
+ bool success = false;
+
+ IStream tempContents = address;
+ tempContents.AddRef();
+
+ // The "\1Ole10Native" stream contains a DWORD header whose value is the length
+ // of the native data that follows.
+ LPVOID pv = COM.CoTaskMemAlloc(4);
+ uint size;
+ auto rc = tempContents.Read(pv, 4, null);
+ OS.MoveMemory(&size, pv, 4);
+ COM.CoTaskMemFree(pv);
+ if (rc is COM.S_OK && size > 0) {
+
+ // Read the data
+ byte[] buffer = new byte[size];
+ pv = COM.CoTaskMemAlloc(size);
+ rc = tempContents.Read(pv, size, null);
+ OS.MoveMemory(buffer.ptr, pv, size);
+ COM.CoTaskMemFree(pv);
+
+ // open the file and write data into it
+ try {
+ FileOutputStream writer = new FileOutputStream(file);
+ writer.write(buffer); // Note: if file does not exist, this will create the file
+ writer.close();
+
+ success = true;
+ } catch (IOException err) {
+ }
+ }
+ tempContents.Release();
+
+ return success;
+}
+private int SaveObject() {
+
+ updateStorage();
+
+ return COM.S_OK;
+}
+/**
+ * Saves the document to the specified file and includes OLE specific information. This method
+ * must only be used for files that have an OLE Storage format. For example, a word file
+ * edited with Word.Document should be saved using this method because there is formating information
+ * that should be stored in the OLE specific Storage format.
+ *
+ * @param file the file to which the changes are to be saved
+ *
+ * @return true if the save was successful
+ */
+private bool saveToStorageFile(File file) {
+ // The file will be saved using the formating of the current application - this
+ // may not be the format of the application that was originally used to create the file
+ // e.g. if an Excel file is opened in Word, the Word application will save the file in the
+ // Word format
+ // Note: if the file already exists, some applications will not overwrite the file
+ // In these cases, you should delete the file first (probably save the contents of the file in case the
+ // save fails)
+ if (file is null || file.isDirectory()) return false;
+ if (!updateStorage()) return false;
+
+ // get access to the persistent storage mechanism
+ IPersistStorage permStorage;
+ if (objIOleObject.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&permStorage) !is COM.S_OK) return false;
+ try {
+ IStorage storage;
+ wchar* path = StrToWCHARz(file.getAbsolutePath());
+ int mode = COM.STGM_TRANSACTED | COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
+ int result = COM.StgCreateDocfile(path, mode, 0, &storage); //Does an AddRef if successful
+ if (result !is COM.S_OK) return false;
+ try {
+ if (COM.OleSave(permStorage, storage, false) is COM.S_OK) {
+ if (storage.Commit(COM.STGC_DEFAULT) is COM.S_OK) {
+ return true;
+ }
+ }
+ } finally {
+ storage.Release();
+ }
+ } finally {
+ permStorage.Release();
+ }
+ return false;
+}
+/**
+ * Saves the document to the specified file. This method must be used for
+ * files that do not have an OLE Storage format. For example, a bitmap file edited with MSPaint
+ * should be saved using this method because bitmap is a standard format that does not include any
+ * OLE specific data.
+ *
+ * @param file the file to which the changes are to be saved
+ *
+ * @return true if the save was successful
+ */
+private bool saveToTraditionalFile(File file) {
+ // Note: if the file already exists, some applications will not overwrite the file
+ // In these cases, you should delete the file first (probably save the contents of the file in case the
+ // save fails)
+ if (file is null || file.isDirectory())
+ return false;
+ if (!updateStorage())
+ return false;
+
+ IStream stream;
+ // Look for a CONTENTS stream
+ if (tempStorage.OpenStream(("CONTENTS"w).ptr, null, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, &stream) is COM.S_OK) //$NON-NLS-1$
+ return saveFromContents(stream, file);
+
+ // Look for Ole 1.0 object stream
+ if (tempStorage.OpenStream(("\1Ole10Native"w).ptr, null, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, &stream) is COM.S_OK) //$NON-NLS-1$
+ return saveFromOle10Native(stream, file);
+
+ return false;
+}
+private int Scroll(int scrollExtant) {
+ return COM.S_OK;
+}
+void setBorderSpace(RECT* newBorderwidth) {
+ borderWidths = *newBorderwidth;
+ // readjust size and location of client site
+ Rectangle area = frame.getClientArea();
+ setBounds(borderWidths.left, borderWidths.top,
+ area.width - borderWidths.left - borderWidths.right,
+ area.height - borderWidths.top - borderWidths.bottom);
+ setObjectRects();
+}
+private void setExtent(int width, int height){
+ // Resize the width and height of the embedded/linked OLENatives object
+ // to the specified values.
+
+ if (objIOleObject is null || isStatic || inUpdate) return;
+ SIZE* currentExtent = getExtent();
+ if (width is currentExtent.cx && height is currentExtent.cy) return;
+
+ SIZE* newExtent = new SIZE();
+ newExtent.cx = width; newExtent.cy = height;
+ newExtent = xFormPixelsToHimetric(newExtent);
+
+ // Get the server running first, then do a SetExtent, then show it
+ bool alreadyRunning = cast(bool) COM.OleIsRunning(objIOleObject);
+ if (!alreadyRunning)
+ COM.OleRun(objIOleObject);
+
+ if (objIOleObject.SetExtent(aspect, newExtent) is COM.S_OK){
+ inUpdate = true;
+ objIOleObject.Update();
+ inUpdate = false;
+ if (!alreadyRunning)
+ // Close server if it wasn't already running upon entering this method.
+ objIOleObject.Close(COM.OLECLOSE_SAVEIFDIRTY);
+ }
+}
+/**
+ * The indent value is no longer being used by the client site.
+ *
+ * @param newIndent the rectangle representing the indent amount
+ */
+public void setIndent(Rectangle newIndent) {
+ indent.left = newIndent.x;
+ indent.right = newIndent.width;
+ indent.top = newIndent.y;
+ indent.bottom = newIndent.height;
+}
+private void setObjectRects() {
+ if (objIOleInPlaceObject is null) return;
+ // size the object to fill the available space
+ // leave a border
+ RECT* rect = getRect();
+ objIOleInPlaceObject.SetObjectRects(rect, rect);
+}
+
+private int ShowObject() {
+ /* Tells the container to position the object so it is visible to
+ * the user. This method ensures that the container itself is
+ * visible and not minimized.
+ */
+ return COM.S_OK;
+}
+/**
+ * Displays a dialog with the property information for this OLE Object. The OLE Document or
+ * ActiveX Control must support the ISpecifyPropertyPages interface.
+ *
+ * @param title the name that will appear in the titlebar of the dialog
+ */
+public void showProperties(String title) {
+
+ // Get the Property Page information from the OLE Object
+ ISpecifyPropertyPages objISPP;
+ if (objIUnknown.QueryInterface(&COM.IIDISpecifyPropertyPages, cast(void**)&objISPP) !is COM.S_OK) return;
+ CAUUID* caGUID = new CAUUID();
+ auto result = objISPP.GetPages(caGUID);
+ objISPP.Release();
+ if (result !is COM.S_OK) return;
+
+ // create a frame in which to display the pages
+ wchar* chTitle = null;
+ if (title !is null) {
+ chTitle = StrToWCHARz(title);
+ }
+ result = COM.OleCreatePropertyFrame(frame.handle, 10, 10, chTitle, 1, &objIUnknown, caGUID.cElems, caGUID.pElems, COM.LOCALE_USER_DEFAULT, 0, null);
+
+ // free the property page information
+ COM.CoTaskMemFree(caGUID.pElems);
+}
+private bool updateStorage() {
+
+ if (tempStorage is null) return false;
+
+ IPersistStorage iPersistStorage;
+ if (objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&iPersistStorage) !is COM.S_OK) return false;
+
+ auto result = COM.OleSave(iPersistStorage, tempStorage, true);
+
+ if (result !is COM.S_OK){
+ // OleSave will fail for static objects, so do what OleSave does.
+ COM.WriteClassStg(tempStorage, objClsid);
+ result = iPersistStorage.Save(tempStorage, true);
+ }
+
+ tempStorage.Commit(COM.STGC_DEFAULT);
+ result = iPersistStorage.SaveCompleted(null);
+ iPersistStorage.Release();
+
+ return true;
+}
+private SIZE* xFormHimetricToPixels(SIZE* aSize) {
+ // Return a new Size which is the pixel transformation of a
+ // size in HIMETRIC units.
+
+ auto hDC = OS.GetDC(null);
+ int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
+ int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
+ OS.ReleaseDC(null, hDC);
+ int cx = Compatibility.round(aSize.cx * xppi, 2540); // 2540 HIMETRIC units per inch
+ int cy = Compatibility.round(aSize.cy * yppi, 2540);
+ SIZE* size = new SIZE();
+ size.cx = cx;
+ size.cy = cy;
+ return size;
+}
+private SIZE* xFormPixelsToHimetric(SIZE* aSize) {
+ // Return a new size which is the HIMETRIC transformation of a
+ // size in pixel units.
+
+ auto hDC = OS.GetDC(null);
+ int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
+ int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
+ OS.ReleaseDC(null, hDC);
+ int cx = Compatibility.round(aSize.cx * 2540, xppi); // 2540 HIMETRIC units per inch
+ int cy = Compatibility.round(aSize.cy * 2540, yppi);
+ SIZE* size = new SIZE();
+ size.cx = cx;
+ size.cy = cy;
+ return size;
+}
+}
+
+class _IAdviseSinkImpl : IAdviseSink {
+
+ OleClientSite parent;
+ this(OleClientSite p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface of IAdviseSink
+ void OnDataChange(FORMATETC *pFormatetc,STGMEDIUM *pStgmed) {return COM.S_OK; }
+ void OnViewChange(DWORD dwAspect, LONG lindex) {return COM.S_OK; }
+ void OnRename(IMoniker pmk) {return COM.S_OK; }
+ void OnSave() {return COM.S_OK; }
+ void OnClose() {return COM.S_OK; }
+}
+
+class _IOleClientSiteImpl : IOleClientSite {
+
+ OleClientSite parent;
+ this(OleClientSite p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface of IOleClientSite
+ HRESULT SaveObject() { if(parent) parent.updateStorage(); return COM.S_OK; }
+ HRESULT GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker, IMoniker * ppmk ) {return COM.E_NOTIMPL; }
+ HRESULT GetContainer( IOleContainer* ppContainer ) { return parent.GetContainer(ppContainer);}
+ HRESULT ShowObject() {
+ /* Tells the container to position the object so it is visible to
+ * the user. This method ensures that the container itself is
+ * visible and not minimized.
+ */
+ return COM.S_OK;
+ }
+ HRESULT OnShowWindow(BOOL fShow ) {return COM.S_OK; }
+ HRESULT RequestNewObjectLayout() {return COM.E_NOTIMPL; }
+}
+
+class _IOleDocumentSiteImpl : IOleDocumentSite {
+
+ OleClientSite parent;
+ this(OleClientSite p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface of IOleDocumentSite
+ HRESULT ActivateMe(IOleDocumentView pViewToActivate) { return parent.ActivateMe(pViewToActivate);}
+}
+
+class _IOleInPlaceSiteImpl : IOleInPlaceSite {
+ OleClientSite parent;
+ this(OleClientSite p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface of IOleWindow
+ HRESULT GetWindow( HWND* phwnd ) { return parent.GetWindow(phwnd); }
+ HRESULT ContextSensitiveHelp( BOOL fEnterMode ) {return COM.S_OK; }
+
+ // interface of IOleInPlaceSite
+ HRESULT CanInPlaceActivate() { return parent.CanInPlaceActivate();}
+ HRESULT OnInPlaceActivate() { return parent.OnInPlaceActivate(); }
+ HRESULT OnUIActivate() { return parent.OnUIActivate(); }
+ HRESULT GetWindowContext( IOleInPlaceFrame * ppFrame, IOleInPlaceUIWindow * ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo ) {
+ return parent.GetWindowContext(ppFrame, ppDoc, lprcPosRect, lprcClipRect, lpFrameInfo);
+ }
+ HRESULT Scroll( SIZE scrollExtant ) {return COM.S_OK; }
+ HRESULT OnUIDeactivate( BOOL fUndoable ) { return parent.OnUIDeactivate(fUndoable);}
+ HRESULT OnInPlaceDeactivate() { return parent.OnInPlaceDeactivate();}
+ HRESULT DiscardUndoState() {return COM.E_NOTIMPL; }
+ HRESULT DeactivateAndUndo() {return COM.E_NOTIMPL; }
+ HRESULT OnPosRectChange( LPCRECT lprcPosRect) { return parent.OnPosRectChange(lprcPosRect);}
+}
+
+class _IUnknownImpl : IUnknown
+{
+
+ OleClientSite parent;
+ this(OleClientSite p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+}
+
+
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleControlSite.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleControlSite.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,915 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleControlSite;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.COMTYPES;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.ifs;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+
+import org.eclipse.swt.ole.win32.OleClientSite;
+import org.eclipse.swt.ole.win32.OleEventSink;
+import org.eclipse.swt.ole.win32.OlePropertyChangeSink;
+import org.eclipse.swt.ole.win32.OleListener;
+import org.eclipse.swt.ole.win32.OleAutomation;
+import org.eclipse.swt.ole.win32.Variant;
+import org.eclipse.swt.ole.win32.OLE;
+
+import java.lang.all;
+
+/**
+ * OleControlSite provides a site to manage an embedded ActiveX Control within a container.
+ *
+ * In addition to the behaviour provided by OleClientSite, this object provides the following:
+ *
+ * - events from the ActiveX control
+ *
- notification of property changes from the ActiveX control
+ *
- simplified access to well known properties of the ActiveX Control (e.g. font, background color)
+ *
- expose ambient properties of the container to the ActiveX Control
+ *
+ *
+ * This object implements the OLE Interfaces IOleControlSite, IDispatch, and IPropertyNotifySink.
+ *
+ *
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
- BORDER
+ *
- Events
- Dispose, Move, Resize
+ *
+ *
+ * @see OLE and ActiveX snippets
+ * @see SWT Examples: OLEExample, OleWebBrowser
+ */
+public class OleControlSite : OleClientSite
+{
+ // interfaces for this container
+ private _IOleControlSiteImpl iOleControlSite;
+ private _IDispatchImpl iDispatch;
+
+ // supporting Property Change attributes
+ private OlePropertyChangeSink olePropertyChangeSink;
+
+ // supporting Event Sink attributes
+ private OleEventSink[] oleEventSink;
+ private GUID*[] oleEventSinkGUID;
+ private IUnknown[] oleEventSinkIUnknown;
+
+ // supporting information for the Control COM object
+ private CONTROLINFO* currentControlInfo;
+ private int[] sitePropertyIds;
+ private Variant[] sitePropertyValues;
+
+ // work around for IE destroying the caret
+ static int SWT_RESTORECARET;
+
+/**
+ * Create an OleControlSite child widget using style bits
+ * to select a particular look or set of properties.
+ *
+ * @param parent a composite widget; must be an OleFrame
+ * @param style the bitwise OR'ing of widget styles
+ * @param progId the unique program identifier which has been registered for this ActiveX Control;
+ * the value of the ProgID key or the value of the VersionIndependentProgID key specified
+ * in the registry for this Control (for example, the VersionIndependentProgID for
+ * Internet Explorer is Shell.Explorer)
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when the parent is null
+ *
+ * @exception SWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
- ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
+ *
- ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ *
- ERROR_CANNOT_ACCESS_CLASSFACTORY when Class Factory could not be found
+ *
- ERROR_CANNOT_CREATE_LICENSED_OBJECT when failed to create a licensed OLE Object
+ *
+ */
+public this(Composite parent, int style, String progId) {
+ super(parent, style);
+ try {
+
+ // check for licensing
+ appClsid = getClassID(progId);
+ if (appClsid is null) OLE.error(__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID);
+
+ BSTR licinfo = getLicenseInfo(appClsid);
+ if (licinfo is null) {
+
+ // Open a storage object
+ tempStorage = createTempStorage();
+
+ // Create ole object with storage object
+ HRESULT result = COM.OleCreate(appClsid, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
+ if (result !is COM.S_OK)
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+ } else {
+ // Prepare the ClassFactory
+ try {
+ IClassFactory2 classFactory;
+ HRESULT result = COM.CoGetClassObject(appClsid, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, null, &COM.IIDIClassFactory2, cast(void**)&classFactory);
+ if (result !is COM.S_OK) {
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_ACCESS_CLASSFACTORY, result);
+ }
+ // Create Com Object
+ result = classFactory.CreateInstanceLic(null, null, &COM.IIDIUnknown, licinfo, cast(void**)&objIUnknown);
+ classFactory.Release();
+ if (result !is COM.S_OK)
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_LICENSED_OBJECT, result);
+ } finally {
+ COM.SysFreeString(licinfo);
+ }
+
+ // Prepare a storage medium
+ IPersistStorage persist;
+ if (objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&persist) is COM.S_OK) {
+ tempStorage = createTempStorage();
+ persist.InitNew(tempStorage);
+ persist.Release();
+ }
+ }
+
+ // Init sinks
+ addObjectReferences();
+
+ // Init site properties
+ setSiteProperty(COM.DISPID_AMBIENT_USERMODE, new Variant(true));
+ setSiteProperty(COM.DISPID_AMBIENT_UIDEAD, new Variant(false));
+
+ if (COM.OleRun(objIUnknown) is OLE.S_OK) state= STATE_RUNNING;
+
+ } catch (SWTError e) {
+ dispose();
+ disposeCOMInterfaces();
+ throw e;
+ }
+}
+/**
+ * Adds the listener to receive events.
+ *
+ * @param eventID the id of the event
+ *
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addEventListener(int eventID, OleListener listener) {
+ if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ GUID* riid = getDefaultEventSinkGUID(objIUnknown);
+ if (riid !is null) {
+ addEventListener(objIUnknown, riid, eventID, listener);
+ }
+}
+
+
+static GUID* getDefaultEventSinkGUID(IUnknown unknown) {
+ // get Event Sink I/F from IProvideClassInfo2
+ IProvideClassInfo2 pci2;
+ if (unknown.QueryInterface(&COM.IIDIProvideClassInfo2, cast(void**)&pci2) is COM.S_OK) {
+ GUID* riid = new GUID();
+ HRESULT result = pci2.GetGUID(COM.GUIDKIND_DEFAULT_SOURCE_DISP_IID, riid);
+ pci2.Release();
+ if (result is COM.S_OK) return riid;
+ }
+
+ // get Event Sink I/F from IProvideClassInfo
+ IProvideClassInfo pci;
+ if (unknown.QueryInterface(&COM.IIDIProvideClassInfo, cast(void**)&pci) is COM.S_OK) {
+ ITypeInfo classInfo;
+ ITypeInfo eventInfo;
+ HRESULT result = pci.GetClassInfo(&classInfo);
+ pci.Release();
+
+ if (result is COM.S_OK && classInfo !is null) {
+ TYPEATTR* typeAttribute;
+ result = classInfo.GetTypeAttr(&typeAttribute);
+ if (result is COM.S_OK && typeAttribute !is null) {
+ int implMask = COM.IMPLTYPEFLAG_FDEFAULT | COM.IMPLTYPEFLAG_FSOURCE | COM.IMPLTYPEFLAG_FRESTRICTED;
+ int implBits = COM.IMPLTYPEFLAG_FDEFAULT | COM.IMPLTYPEFLAG_FSOURCE;
+
+ for (uint i = 0; i < typeAttribute.cImplTypes; i++) {
+ int pImplTypeFlags;
+ if (classInfo.GetImplTypeFlags(i, &pImplTypeFlags) is COM.S_OK) {
+ if ((pImplTypeFlags & implMask) is implBits) {
+ uint pRefType;
+ if (classInfo.GetRefTypeOfImplType(i, &pRefType) is COM.S_OK) {
+ classInfo.GetRefTypeInfo(pRefType, &eventInfo);
+ }
+ }
+ }
+ }
+ classInfo.ReleaseTypeAttr(typeAttribute);
+ }
+ classInfo.Release();
+
+ if (eventInfo !is null) {
+ TYPEATTR* ppTypeAttr;
+ result = eventInfo.GetTypeAttr(&ppTypeAttr);
+ GUID* riid = null;
+ if (result is COM.S_OK && ppTypeAttr !is null) {
+ riid = new GUID();
+ *riid = ppTypeAttr.guid;
+ eventInfo.ReleaseTypeAttr(ppTypeAttr);
+ }
+ eventInfo.Release();
+ return riid;
+ }
+ }
+ }
+ return null;
+}
+
+/**
+ * Adds the listener to receive events.
+ *
+ * @since 2.0
+ *
+ * @param automation the automation object that provides the event notification
+ * @param eventID the id of the event
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addEventListener(OleAutomation automation, int eventID, OleListener listener) {
+ if (listener is null || automation is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ IUnknown unknown = automation.getAddress();
+ GUID* riid = getDefaultEventSinkGUID(unknown);
+ if (riid !is null) {
+ addEventListener(unknown, riid, eventID, listener);
+ }
+
+}
+/**
+ * Adds the listener to receive events.
+ *
+ * @since 3.2
+ *
+ * @param automation the automation object that provides the event notification
+ * @param eventSinkId the GUID of the event sink
+ * @param eventID the id of the event
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addEventListener(OleAutomation automation, String eventSinkId, int eventID, OleListener listener) {
+ if (listener is null || automation is null || eventSinkId is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ auto address = automation.getAddress();
+ if (address is null) return;
+ wchar[] buffer = StrToWCHARs(0,eventSinkId,true);
+ GUID* guid = new GUID();
+ if (COM.IIDFromString(buffer.ptr, guid) !is COM.S_OK) return;
+ addEventListener(address, guid, eventID, listener);
+}
+
+void addEventListener(IUnknown iunknown, GUID* guid, int eventID, OleListener listener) {
+ if (listener is null || iunknown is null || guid is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ // have we connected to this kind of event sink before?
+ int index = -1;
+ for (int i = 0; i < oleEventSinkGUID.length; i++) {
+ if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
+ if (iunknown is oleEventSinkIUnknown[i]) {
+ index = i;
+ break;
+ }
+ }
+ }
+ if (index !is -1) {
+ oleEventSink[index].addListener(eventID, listener);
+ } else {
+ int oldLength = oleEventSink.length;
+
+ oleEventSink ~= new OleEventSink(this, iunknown, guid);
+ oleEventSinkGUID ~= guid;
+ oleEventSinkIUnknown ~= iunknown;
+
+ oleEventSink[oldLength].AddRef();
+ oleEventSink[oldLength].connect();
+ oleEventSink[oldLength].addListener(eventID, listener);
+
+ }
+}
+protected void addObjectReferences() {
+
+ super.addObjectReferences();
+
+ // Get property change notification from control
+ connectPropertyChangeSink();
+
+ // Get access to the Control object
+ IOleControl objIOleControl;
+ if (objIUnknown.QueryInterface(&COM.IIDIOleControl, cast(void**)&objIOleControl) is COM.S_OK) {
+ // ask the control for its info in case users
+ // need to act on it
+ currentControlInfo = new CONTROLINFO();
+ objIOleControl.GetControlInfo(currentControlInfo);
+ objIOleControl.Release();
+ }
+}
+/**
+ * Adds the listener to receive events.
+ *
+ * @param propertyID the identifier of the property
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addPropertyListener(int propertyID, OleListener listener) {
+ if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ olePropertyChangeSink.addListener(propertyID, listener);
+}
+
+private void connectPropertyChangeSink() {
+ olePropertyChangeSink = new OlePropertyChangeSink(this);
+ olePropertyChangeSink.AddRef();
+ olePropertyChangeSink.connect(objIUnknown);
+}
+protected void createCOMInterfaces () {
+ super.createCOMInterfaces();
+ iOleControlSite = new _IOleControlSiteImpl(this);
+ iDispatch = new _IDispatchImpl(this);
+}
+private void disconnectEventSinks() {
+
+ for (int i = 0; i < oleEventSink.length; i++) {
+ OleEventSink sink = oleEventSink[i];
+ sink.disconnect();
+ sink.Release();
+ }
+ oleEventSink = null;
+ oleEventSinkGUID = null;
+ oleEventSinkIUnknown = null;
+}
+private void disconnectPropertyChangeSink() {
+
+ if (olePropertyChangeSink !is null) {
+ olePropertyChangeSink.disconnect(objIUnknown);
+ olePropertyChangeSink.Release();
+ }
+ olePropertyChangeSink = null;
+}
+protected void disposeCOMInterfaces() {
+ super.disposeCOMInterfaces();
+ iOleControlSite = null;
+ iDispatch = null;
+}
+public Color getBackground () {
+
+ if (objIUnknown !is null) {
+ // !! We are getting the OLE_COLOR - should we change this to the COLORREF value?
+ OleAutomation oleObject= new OleAutomation(this);
+ Variant varBackColor = oleObject.getProperty(COM.DISPID_BACKCOLOR);
+ oleObject.dispose();
+
+ if (varBackColor !is null){
+ COLORREF colorRef;
+ if (COM.OleTranslateColor(varBackColor.getInt(), getDisplay().hPalette, &colorRef) is COM.S_OK)
+ return Color.win32_new(getDisplay(), colorRef);
+ }
+ }
+
+ return super.getBackground();
+}
+public Font getFont () {
+
+ if (objIUnknown !is null) {
+ OleAutomation oleObject= new OleAutomation(this);
+ Variant varDispFont = oleObject.getProperty(COM.DISPID_FONT);
+ oleObject.dispose();
+
+ if (varDispFont !is null){
+ OleAutomation iDispFont = varDispFont.getAutomation();
+ Variant lfFaceName = iDispFont.getProperty(COM.DISPID_FONT_NAME);
+ Variant lfHeight = iDispFont.getProperty(COM.DISPID_FONT_SIZE);
+ Variant lfItalic = iDispFont.getProperty(COM.DISPID_FONT_ITALIC);
+ //Variant lfCharSet = iDispFont.getProperty(COM.DISPID_FONT_CHARSET);
+ Variant lfBold = iDispFont.getProperty(COM.DISPID_FONT_BOLD);
+ iDispFont.dispose();
+
+ if (lfFaceName !is null &&
+ lfHeight !is null &&
+ lfItalic !is null &&
+ lfBold !is null){
+ int style = 3 * lfBold.getInt() + 2 * lfItalic.getInt();
+ Device dev = getShell().getDisplay();
+ Font font = new Font(dev, lfFaceName.getString(), lfHeight.getInt(), style);
+ return font;
+ }
+ }
+ }
+
+ return super.getFont();
+}
+public Color getForeground () {
+
+ if (objIUnknown !is null) {
+ // !! We are getting the OLE_COLOR - should we change this to the COLORREF value?
+ OleAutomation oleObject= new OleAutomation(this);
+ Variant varForeColor = oleObject.getProperty(COM.DISPID_FORECOLOR);
+ oleObject.dispose();
+
+ if (varForeColor !is null){
+ COLORREF colorRef;
+ if (COM.OleTranslateColor(varForeColor.getInt(), getDisplay().hPalette, &colorRef) is COM.S_OK)
+ return Color.win32_new(getDisplay(), colorRef);
+ }
+ }
+
+ return super.getForeground();
+}
+protected BSTR getLicenseInfo(GUID* clsid) {
+ IClassFactory2 classFactory;
+ if (COM.CoGetClassObject(clsid, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, null, &COM.IIDIClassFactory2, cast(void**)&classFactory) !is COM.S_OK) {
+ return null;
+ }
+ LICINFO licinfo;
+ if (classFactory.GetLicInfo(&licinfo) !is COM.S_OK) {
+ classFactory.Release();
+ return null;
+ }
+ BSTR pBstrKey;
+ if (licinfo.fRuntimeKeyAvail) {
+ if (classFactory.RequestLicKey(0, &pBstrKey) is COM.S_OK) {
+ classFactory.Release();
+ return pBstrKey;
+ }
+ }
+ classFactory.Release();
+ return null;
+}
+/**
+ *
+ * Get the control site property specified by the dispIdMember, or
+ * null
if the dispId is not recognised.
+ *
+ * @param dispId the dispId
+ *
+ * @return the property value or null
+ *
+ * @since 2.1
+ */
+public Variant getSiteProperty(int dispId){
+ for (int i = 0; i < sitePropertyIds.length; i++) {
+ if (sitePropertyIds[i] is dispId) {
+ return sitePropertyValues[i];
+ }
+ }
+ return null;
+}
+protected HRESULT GetWindow(HWND* phwnd) {
+
+ if (phwnd is null)
+ return COM.E_INVALIDARG;
+ if (frame is null) {
+ *phwnd = null;
+ return COM.E_NOTIMPL;
+ }
+
+ // Copy the Window's handle into the memory passed in
+ *phwnd = handle;
+ return COM.S_OK;
+}
+
+private HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD dwFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* pArgErr) {
+ int nullv = 0;
+ if (pVarResult is null || dwFlags !is COM.DISPATCH_PROPERTYGET) {
+ if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
+ if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
+ return COM.DISP_E_MEMBERNOTFOUND;
+ }
+ Variant result = getSiteProperty(dispIdMember);
+ if (result !is null) {
+ if (pVarResult !is null) result.getData(pVarResult);
+ return COM.S_OK;
+ }
+ switch (dispIdMember) {
+ // indicate a false result
+ case COM.DISPID_AMBIENT_SUPPORTSMNEMONICS :
+ case COM.DISPID_AMBIENT_SHOWGRABHANDLES :
+ case COM.DISPID_AMBIENT_SHOWHATCHING :
+ if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
+ if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
+ if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
+ return COM.S_FALSE;
+
+ // not implemented
+ case COM.DISPID_AMBIENT_OFFLINEIFNOTCONNECTED :
+ case COM.DISPID_AMBIENT_BACKCOLOR :
+ case COM.DISPID_AMBIENT_FORECOLOR :
+ case COM.DISPID_AMBIENT_FONT :
+ case COM.DISPID_AMBIENT_LOCALEID :
+ case COM.DISPID_AMBIENT_SILENT :
+ case COM.DISPID_AMBIENT_MESSAGEREFLECT :
+ if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
+ if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
+ if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
+ return COM.E_NOTIMPL;
+
+ default :
+ if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
+ if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
+ if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
+ return COM.DISP_E_MEMBERNOTFOUND;
+ }
+}
+private int OnControlInfoChanged() {
+ IOleControl objIOleControl;
+ if (objIUnknown.QueryInterface(&COM.IIDIOleControl, cast(void**)&objIOleControl ) is COM.S_OK) {
+ // ask the control for its info in case users
+ // need to act on it
+ currentControlInfo = new CONTROLINFO();
+ objIOleControl.GetControlInfo(currentControlInfo);
+ objIOleControl.Release();
+ }
+ return COM.S_OK;
+}
+void onFocusIn(Event e) {
+ if (objIOleInPlaceObject is null) return;
+ doVerb(OLE.OLEIVERB_UIACTIVATE);
+ if (isFocusControl()) return;
+ HWND phwnd;
+ objIOleInPlaceObject.GetWindow(&phwnd);
+ if (phwnd is null) return;
+ OS.SetFocus(phwnd);
+}
+void onFocusOut(Event e) {
+ if (objIOleInPlaceObject !is null) {
+ /*
+ * Bug in Windows. When IE7 loses focus and UIDeactivate()
+ * is called, IE destroys the caret even though it is
+ * no longer owned by IE. If focus has moved to a control
+ * that shows a caret then the caret disappears. The fix
+ * is to detect this case and restore the caret.
+ */
+ auto threadId = OS.GetCurrentThreadId();
+ GUITHREADINFO* lpgui1 = new GUITHREADINFO();
+ lpgui1.cbSize = GUITHREADINFO.sizeof;
+ OS.GetGUIThreadInfo(threadId, lpgui1);
+ objIOleInPlaceObject.UIDeactivate();
+ if (lpgui1.hwndCaret !is null) {
+ GUITHREADINFO* lpgui2 = new GUITHREADINFO();
+ lpgui2.cbSize = GUITHREADINFO.sizeof;
+ OS.GetGUIThreadInfo(threadId, lpgui2);
+ if (lpgui2.hwndCaret is null && lpgui1.hwndCaret is OS.GetFocus()) {
+ if (SWT_RESTORECARET is 0) {
+ SWT_RESTORECARET = OS.RegisterWindowMessage (StrToTCHARz (0, "SWT_RESTORECARET"));
+ }
+ /*
+ * If the caret was not restored by SWT, put it back using
+ * the information from GUITHREADINFO. Note that this will
+ * not be correct when the caret has a bitmap. There is no
+ * API to query the bitmap that the caret is using.
+ */
+ if (OS.SendMessage (lpgui1.hwndCaret, SWT_RESTORECARET, 0, 0) is 0) {
+ int width = lpgui1.rcCaret.right - lpgui1.rcCaret.left;
+ int height = lpgui1.rcCaret.bottom - lpgui1.rcCaret.top;
+ OS.CreateCaret (lpgui1.hwndCaret, null, width, height);
+ OS.SetCaretPos (lpgui1.rcCaret.left, lpgui1.rcCaret.top);
+ OS.ShowCaret (lpgui1.hwndCaret);
+ }
+ }
+ }
+ }
+}
+private int OnFocus(int fGotFocus) {
+ return COM.S_OK;
+}
+protected int OnUIDeactivate(int fUndoable) {
+ // controls don't need to do anything for
+ // border space or menubars
+ state = STATE_INPLACEACTIVE;
+ return COM.S_OK;
+}
+override protected HRESULT QueryInterface(REFIID riid, void ** ppvObject) {
+ int nullv = 0;
+ int result = super.QueryInterface(riid, ppvObject);
+ if (result is COM.S_OK)
+ return result;
+ if (riid is null || ppvObject is null)
+ return COM.E_INVALIDARG;
+ GUID oGuid = *riid;
+ GUID* guid = &oGuid;
+ //COM.MoveMemory(&guid, riid, GUID.sizeof);
+ if (COM.IsEqualGUID(guid, &COM.IIDIOleControlSite)) {
+ *ppvObject = cast(void*)cast(IOleControlSite)iOleControlSite;
+ AddRef();
+ return COM.S_OK;
+ }
+ if (COM.IsEqualGUID(guid, &COM.IIDIDispatch)) {
+ *ppvObject = cast(void*)cast(IDispatch)iDispatch;
+ AddRef();
+ return COM.S_OK;
+ }
+ *ppvObject = null;
+ return COM.E_NOINTERFACE;
+}
+protected int Release() {
+ int result = super.Release();
+ if (result is 0) {
+ for (int i = 0; i < sitePropertyIds.length; i++) {
+ sitePropertyValues[i].dispose();
+ }
+ sitePropertyIds = null;
+ sitePropertyValues = null;
+ }
+ return result;
+}
+protected void releaseObjectInterfaces() {
+
+ disconnectEventSinks();
+
+ disconnectPropertyChangeSink();
+
+ super.releaseObjectInterfaces();
+}
+/**
+ * Removes the listener.
+ *
+ * @param eventID the event identifier
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void removeEventListener(int eventID, OleListener listener) {
+ checkWidget();
+ if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+
+ GUID* riid = getDefaultEventSinkGUID(objIUnknown);
+ if (riid !is null) {
+ removeEventListener(objIUnknown, riid, eventID, listener);
+ }
+}
+/**
+ * Removes the listener.
+ *
+ * @since 2.0
+ * @deprecated - use OleControlSite.removeEventListener(OleAutomation, int, OleListener)
+ *
+ * @param automation the automation object that provides the event notification
+ *
+ * @param guid the identifier of the events COM interface
+ *
+ * @param eventID the event identifier
+ *
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void removeEventListener(OleAutomation automation, GUID* guid, int eventID, OleListener listener) {
+ checkWidget();
+ if (automation is null || listener is null || guid is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ removeEventListener(automation.getAddress(), guid, eventID, listener);
+}
+/**
+ * Removes the listener.
+ *
+ * @param automation the automation object that provides the event notification
+ * @param eventID the event identifier
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when listener is null
+ *
+ *
+ * @since 2.0
+ */
+public void removeEventListener(OleAutomation automation, int eventID, OleListener listener) {
+ checkWidget();
+ if (automation is null || listener is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ auto unknown = automation.getAddress();
+ GUID* riid = getDefaultEventSinkGUID(unknown);
+ if (riid !is null) {
+ removeEventListener(unknown, riid, eventID, listener);
+ }
+}
+void removeEventListener(IUnknown iunknown, GUID* guid, int eventID, OleListener listener) {
+ if (listener is null || guid is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ for (int i = 0; i < oleEventSink.length; i++) {
+ if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
+ if (iunknown is oleEventSinkIUnknown[i]) {
+ oleEventSink[i].removeListener(eventID, listener);
+ if (!oleEventSink[i].hasListeners()) {
+ //free resources associated with event sink
+ oleEventSink[i].disconnect();
+ oleEventSink[i].Release();
+ int oldLength = oleEventSink.length;
+ if (oldLength is 1) {
+ oleEventSink = null;
+ oleEventSinkGUID = null;
+ oleEventSinkIUnknown = null;
+ } else {
+ OleEventSink[] newOleEventSink = new OleEventSink[oldLength - 1];
+ System.arraycopy(oleEventSink, 0, newOleEventSink, 0, i);
+ System.arraycopy(oleEventSink, i + 1, newOleEventSink, i, oldLength - i - 1);
+ oleEventSink = newOleEventSink;
+
+ GUID*[] newOleEventSinkGUID = new GUID*[oldLength - 1];
+ SimpleType!(GUID*).arraycopy(oleEventSinkGUID, 0, newOleEventSinkGUID, 0, i);
+ SimpleType!(GUID*).arraycopy(oleEventSinkGUID, i + 1, newOleEventSinkGUID, i, oldLength - i - 1);
+ oleEventSinkGUID = newOleEventSinkGUID;
+
+ IUnknown[] newOleEventSinkIUnknown = new IUnknown[oldLength - 1];
+ SimpleType!(IUnknown).arraycopy(oleEventSinkIUnknown, 0, newOleEventSinkIUnknown, 0, i);
+ SimpleType!(IUnknown).arraycopy(oleEventSinkIUnknown, i + 1, newOleEventSinkIUnknown, i, oldLength - i - 1);
+ oleEventSinkIUnknown = newOleEventSinkIUnknown;
+ }
+ }
+ return;
+ }
+ }
+ }
+}
+/**
+ * Removes the listener.
+ *
+ * @param propertyID the identifier of the property
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void removePropertyListener(int propertyID, OleListener listener) {
+ if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ olePropertyChangeSink.removeListener(propertyID, listener);
+}
+public void setBackground (Color color) {
+
+ super.setBackground(color);
+
+ //set the background of the ActiveX Control
+ if (objIUnknown !is null) {
+ OleAutomation oleObject= new OleAutomation(this);
+ oleObject.setProperty(COM.DISPID_BACKCOLOR, new Variant(cast(int)color.handle));
+ oleObject.dispose();
+ }
+}
+public void setFont (Font font) {
+
+ super.setFont(font);
+
+ //set the font of the ActiveX Control
+ if (objIUnknown !is null) {
+
+ OleAutomation oleObject= new OleAutomation(this);
+ Variant varDispFont = oleObject.getProperty(COM.DISPID_FONT);
+ oleObject.dispose();
+
+ if (varDispFont !is null){
+ OleAutomation iDispFont = varDispFont.getAutomation();
+ FontData[] fdata = font.getFontData();
+ iDispFont.setProperty(COM.DISPID_FONT_NAME, new Variant(fdata[0].getName()));
+ iDispFont.setProperty(COM.DISPID_FONT_SIZE, new Variant(fdata[0].getHeight()));
+ iDispFont.setProperty(COM.DISPID_FONT_ITALIC, new Variant(fdata[0].getStyle() & SWT.ITALIC));
+ //iDispFont.setProperty(COM.DISPID_FONT_CHARSET, new Variant(fdata[0].getCharset));
+ iDispFont.setProperty(COM.DISPID_FONT_BOLD, new Variant((fdata[0].getStyle() & SWT.BOLD)));
+ iDispFont.dispose();
+ }
+ }
+
+ return;
+}
+public void setForeground (Color color) {
+
+ super.setForeground(color);
+
+ //set the foreground of the ActiveX Control
+ if (objIUnknown !is null) {
+ OleAutomation oleObject= new OleAutomation(this);
+ oleObject.setProperty(COM.DISPID_FORECOLOR, new Variant(cast(int)color.handle));
+ oleObject.dispose();
+ }
+}
+/**
+ * Sets the control site property specified by the dispIdMember to a new value.
+ * The value will be disposed by the control site when it is no longer required
+ * using Variant.dispose. Passing a value of null will clear the dispId value.
+ *
+ * @param dispId the ID of the property as specified by the IDL of the ActiveX Control
+ * @param value The new value for the property as expressed in a Variant.
+ *
+ * @since 2.1
+ */
+public void setSiteProperty(int dispId, Variant value){
+ for (int i = 0; i < sitePropertyIds.length; i++) {
+ if (sitePropertyIds[i] is dispId) {
+ if (sitePropertyValues[i] !is null) {
+ sitePropertyValues[i].dispose();
+ }
+ if (value !is null) {
+ sitePropertyValues[i] = value;
+ } else {
+ int oldLength = sitePropertyIds.length;
+ int[] newSitePropertyIds = new int[oldLength - 1];
+ Variant[] newSitePropertyValues = new Variant[oldLength - 1];
+ System.arraycopy(sitePropertyIds, 0, newSitePropertyIds, 0, i);
+ System.arraycopy(sitePropertyIds, i + 1, newSitePropertyIds, i, oldLength - i - 1);
+ System.arraycopy(sitePropertyValues, 0, newSitePropertyValues, 0, i);
+ System.arraycopy(sitePropertyValues, i + 1, newSitePropertyValues, i, oldLength - i - 1);
+ sitePropertyIds = newSitePropertyIds;
+ sitePropertyValues = newSitePropertyValues;
+ }
+ return;
+ }
+ }
+ int oldLength = sitePropertyIds.length;
+ int[] newSitePropertyIds = new int[oldLength + 1];
+ Variant[] newSitePropertyValues = new Variant[oldLength + 1];
+ System.arraycopy(sitePropertyIds, 0, newSitePropertyIds, 0, oldLength);
+ System.arraycopy(sitePropertyValues, 0, newSitePropertyValues, 0, oldLength);
+ newSitePropertyIds[oldLength] = dispId;
+ newSitePropertyValues[oldLength] = value;
+ sitePropertyIds = newSitePropertyIds;
+ sitePropertyValues = newSitePropertyValues;
+}
+}
+
+class _IDispatchImpl : IDispatch {
+
+ OleControlSite parent;
+ this(OleControlSite p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface of IDispatch : IUnknown
+ HRESULT GetTypeInfoCount(UINT * pctinfo) { return COM.E_NOTIMPL; }
+ HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo) { return COM.E_NOTIMPL; }
+ HRESULT GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { return COM.E_NOTIMPL; }
+ // Note : one argument is short !!!
+ HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr) {
+ return parent.Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+ }
+}
+
+class _IOleControlSiteImpl : IOleControlSite {
+
+ OleControlSite parent;
+ this(OleControlSite p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface IOleControlSite : IUnknown
+ HRESULT OnControlInfoChanged() { return parent.OnControlInfoChanged();}
+ HRESULT LockInPlaceActive(BOOL fLock) { return COM.E_NOTIMPL; }
+ HRESULT GetExtendedControl(LPDISPATCH* ppDisp) { return COM.E_NOTIMPL; }
+ HRESULT TransformCoords(
+ POINTL* pPtlHimetric , //Address of POINTL structure
+ POINTF* pPtfContainer , //Address of POINTF structure
+ DWORD dwFlags //Flags indicating the exact conversion
+ ) { return COM.E_NOTIMPL; }
+ HRESULT TranslateAccelerator(
+ LPMSG pMsg , //Pointer to the structure
+ DWORD grfModifiers //Flags describing the state of the keys
+ )
+ { return COM.E_NOTIMPL; }
+ HRESULT OnFocus(
+ BOOL fGotFocus //Indicates whether the control gained focus
+ )
+ { return COM.S_OK; }
+ HRESULT ShowPropertyFrame() { return COM.E_NOTIMPL; }
+}
+
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEvent.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleEvent;
+
+import org.eclipse.swt.ole.win32.Variant;
+
+import org.eclipse.swt.widgets.Widget;
+
+public class OleEvent {
+ public int type;
+ public Widget widget;
+ public int detail;
+ public bool doit = true;
+ public Variant[] arguments;
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEventSink.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEventSink.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleEventSink;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.ole.win32.ifs;
+
+import org.eclipse.swt.ole.win32.OleControlSite;
+import org.eclipse.swt.ole.win32.OleEventTable;
+import org.eclipse.swt.ole.win32.OleListener;
+import org.eclipse.swt.ole.win32.OleEvent;
+import org.eclipse.swt.ole.win32.OLE;
+import org.eclipse.swt.ole.win32.Variant;
+
+final class OleEventSink
+{
+ private OleControlSite widget;
+
+ private _DispatchImpl iDispatch;
+ private int refCount;
+
+ private IUnknown objIUnknown;
+ private int eventCookie;
+ private GUID* eventGuid;
+
+ private OleEventTable eventTable;
+
+this(OleControlSite widget, IUnknown iUnknown, GUID* riid) {
+
+ this.widget = widget;
+ this.eventGuid = riid;
+ this.objIUnknown = iUnknown;
+
+ createCOMInterfaces();
+}
+
+void connect () {
+ IConnectionPointContainer cpc;
+ if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
+ IConnectionPoint cp;
+ if (cpc.FindConnectionPoint(eventGuid, &cp) is COM.S_OK) {
+ uint pCookie;
+ if (cp.Advise(iDispatch, &pCookie) is COM.S_OK)
+ eventCookie = pCookie;
+ cp.Release();
+ }
+ cpc.Release();
+ }
+}
+void addListener(int eventID, OleListener listener) {
+ if (listener is null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable is null) eventTable = new OleEventTable ();
+ eventTable.hook(eventID, listener);
+}
+int AddRef() {
+ refCount++;
+ return refCount;
+}
+private void createCOMInterfaces() {
+ iDispatch = new _DispatchImpl(this);
+}
+void disconnect() {
+ // disconnect event sink
+ if (eventCookie !is 0 && objIUnknown !is null) {
+ IConnectionPointContainer cpc;
+ if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
+ IConnectionPoint cp;
+ if (cpc.FindConnectionPoint(eventGuid, &cp) is COM.S_OK) {
+ if (cp.Unadvise(eventCookie) is COM.S_OK) {
+ eventCookie = 0;
+ }
+ cp.Release();
+ }
+ cpc.Release();
+ }
+ }
+}
+private void disposeCOMInterfaces() {
+ iDispatch = null;
+}
+
+private HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr)
+{
+ if (eventTable is null || !eventTable.hooks(dispIdMember)) return COM.S_OK;
+
+ // Construct an array of the parameters that are passed in
+ // Note: parameters are passed in reverse order - here we will correct the order
+ Variant[] eventInfo = null;
+ if (pDispParams !is null) {
+ DISPPARAMS* dispParams = new DISPPARAMS();
+ COM.MoveMemory(dispParams, pDispParams, DISPPARAMS.sizeof);
+ eventInfo = new Variant[dispParams.cArgs];
+ int size = Variant.sizeof;
+ int offset = (dispParams.cArgs - 1) * size;
+
+ for (int j = 0; j < dispParams.cArgs; j++){
+ eventInfo[j] = new Variant();
+ eventInfo[j].setData(dispParams.rgvarg + offset);
+ offset = offset - size;
+ }
+ }
+
+ OleEvent event = new OleEvent();
+ event.arguments = eventInfo;
+ notifyListener(dispIdMember,event);
+ return COM.S_OK;
+}
+/**
+* Notify listeners of an event.
+*
+* This method notifies all listeners that an event
+* has occurred.
+*
+* @param eventType the desired SWT event
+* @param event the event data
+*
+* @exception IllegalArgumentException
+* - ERROR_NULL_ARGUMENT when handler is null
+*
+* @exception SWTException
+* - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+* - ERROR_WIDGET_DISPOSED when the widget has been disposed
+*
+*/
+private void notifyListener (int eventType, OleEvent event) {
+ if (event is null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable is null) return;
+ event.type = eventType;
+ event.widget = widget;
+ eventTable.sendEvent (event);
+}
+
+private HRESULT QueryInterface(REFIID riid, void ** ppvObject) {
+
+ if (riid is null || ppvObject is null)
+ return COM.E_INVALIDARG;
+
+ if ( COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIDispatch) ||
+ COM.IsEqualGUID(riid, eventGuid)) {
+ *ppvObject = cast(void*)cast(IDispatch)iDispatch;
+ AddRef();
+ return OLE.S_OK;
+ }
+
+ *ppvObject = null;
+ return COM.E_NOINTERFACE;
+}
+int Release() {
+ refCount--;
+ if (refCount is 0) {
+ disposeCOMInterfaces();
+ }
+
+ return refCount;
+}
+void removeListener(int eventID, OleListener listener) {
+ if (listener is null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable is null) return;
+ eventTable.unhook (eventID, listener);
+}
+bool hasListeners() {
+ return eventTable.hasEntries();
+}
+}
+
+private class _DispatchImpl : IDispatch {
+
+ OleEventSink parent;
+ this(OleEventSink sink) { parent = sink;}
+extern (Windows) :
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject){
+ return parent.QueryInterface(riid, ppvObject);
+ }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+ HRESULT GetTypeInfoCount(UINT * pctinfo) { return COM.E_NOTIMPL; }
+ HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo) { return COM.E_NOTIMPL; }
+ HRESULT GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { return COM.E_NOTIMPL; }
+ HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr){
+ return parent.Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+ }
+}
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEventTable.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEventTable.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleEventTable;
+
+import org.eclipse.swt.ole.win32.OleListener;
+import org.eclipse.swt.ole.win32.OleEvent;
+
+import java.lang.all;
+
+/**
+* The OleEventTable class implements a simple
+* look up mechanism that maps an event type
+* to a listener. Multiple listeners for the
+* same event type are supported.
+*
+*/
+
+class OleEventTable {
+ int [] types;
+ OleListener [] handlers;
+void hook (int eventType, OleListener handler) {
+ if (types is null) types = new int [4];
+ if (handlers is null) handlers = new OleListener [4];
+ for (int i=0; i
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleFrame;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OLEIDL;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.ole.win32.OleClientSite;
+import org.eclipse.swt.ole.win32.OLE;
+
+import java.lang.all;
+import java.lang.Runnable;
+import tango.core.Array;
+
+/**
+ *
+ * OleFrame is an OLE Container's top level frame.
+ *
+ * This object implements the OLE Interfaces IUnknown and IOleInPlaceFrame
+ *
+ *
OleFrame allows the container to do the following:
+ * - position and size the ActiveX Control or OLE Document within the application
+ *
- insert menu items from the application into the OLE Document's menu
+ *
- activate and deactivate the OLE Document's menus
+ *
- position the OLE Document's menu in the application
+ *
- translate accelerator keystrokes intended for the container's frame
+ *
+ *
+ * - Styles
- BORDER
+ *
- Events
- Dispose, Move, Resize
+ *
+ *
+ * @see OLE and ActiveX snippets
+ * @see SWT Examples: OLEExample, OleWebBrowser
+ */
+final public class OleFrame : Composite
+{
+ // Interfaces for this Ole Client Container
+ //private COMObject iUnknown;
+ private _IOleInPlaceFrameImpl iOleInPlaceFrame;
+
+ // Access to the embedded/linked Ole Object
+ private IOleInPlaceActiveObject objIOleInPlaceActiveObject;
+
+ private OleClientSite currentdoc;
+
+ private int refCount = 0;
+
+ private MenuItem[] fileMenuItems;
+ private MenuItem[] containerMenuItems;
+ private MenuItem[] windowMenuItems;
+
+ private Listener listener;
+
+ private static String CHECK_FOCUS = "OLE_CHECK_FOCUS"; //$NON-NLS-1$
+ private static String HHOOK = "OLE_HHOOK"; //$NON-NLS-1$
+ private static String HHOOKMSG = "OLE_HHOOK_MSG"; //$NON-NLS-1$
+
+ private static bool ignoreNextKey;
+ private static const short [] ACCENTS = [ cast(short)'~', '`', '\'', '^', '"'];
+
+ private static const String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$NON-NLS-1$
+
+/**
+ * Create an OleFrame child widget using style bits
+ * to select a particular look or set of properties.
+ *
+ * @param parent a composite widget (cannot be null)
+ * @param style the bitwise OR'ing of widget styles
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when the parent is null
+ *
+ * @exception SWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
+ *
+ */
+public this(Composite parent, int style) {
+ super(parent, style);
+
+ createCOMInterfaces();
+
+ // setup cleanup proc
+ listener = new class() Listener {
+ public void handleEvent(Event e) {
+ switch (e.type) {
+ case SWT.Activate : onActivate(e); break;
+ case SWT.Deactivate : onDeactivate(e); break;
+ case SWT.Dispose : onDispose(e); break;
+ case SWT.Resize :
+ case SWT.Move : onResize(e); break;
+ default :
+ OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
+ }
+ }
+ };
+
+
+ addListener(SWT.Activate, listener);
+ addListener(SWT.Deactivate, listener);
+ addListener(SWT.Dispose, listener);
+
+ // inform inplaceactiveobject whenever frame resizes
+ addListener(SWT.Resize, listener);
+
+ // inform inplaceactiveobject whenever frame moves
+ addListener(SWT.Move, listener);
+
+ // Maintain a reference to yourself so that when
+ // ClientSites close, they don't take the frame away
+ // with them.
+ this.AddRef();
+
+ // Check for focus change
+ Display display = getDisplay();
+ initCheckFocus(display);
+ initMsgHook(display);
+}
+private static void initCheckFocus (Display display_) {
+ if (display_.getData(CHECK_FOCUS) !is null) return;
+ display_.setData(CHECK_FOCUS, new ArrayWrapperString(CHECK_FOCUS));
+ static const int time = 50;
+ auto timer = new class(display_) Runnable {
+ Display display;
+ Control[1] lastFocus;
+ this( Display display){ this.display = display; }
+ public void run() {
+ if (( null !is cast(OleClientSite)lastFocus[0] ) && !lastFocus[0].isDisposed()) {
+ // ignore popup menus and dialogs
+ auto hwnd = OS.GetFocus();
+ while (hwnd !is null) {
+ auto ownerHwnd = OS.GetWindow(hwnd, OS.GW_OWNER);
+ if (ownerHwnd !is null) {
+ display.timerExec(time, this);
+ return;
+ }
+ hwnd = OS.GetParent(hwnd);
+ }
+ }
+ if (lastFocus[0] is null || lastFocus[0].isDisposed() || !lastFocus[0].isFocusControl()) {
+ Control currentFocus = display.getFocusControl();
+ if ( auto frame = cast(OleFrame)currentFocus ) {
+ currentFocus = frame.getCurrentDocument();
+ }
+ if (lastFocus[0] !is currentFocus) {
+ Event event = new Event();
+ if (( null !is cast(OleClientSite)lastFocus[0] ) && !lastFocus[0].isDisposed()) {
+ lastFocus[0].notifyListeners (SWT.FocusOut, event);
+ }
+ if (( null !is cast(OleClientSite)currentFocus ) && !currentFocus.isDisposed()) {
+ currentFocus.notifyListeners(SWT.FocusIn, event);
+ }
+ }
+ lastFocus[0] = currentFocus;
+ }
+ display.timerExec(time, this);
+ }
+ };
+ display_.timerExec(time, timer);
+}
+private static void initMsgHook(Display display) {
+ if (display.getData(HHOOK) !is null) return;
+ //final Callback callback = new Callback(OleFrame.class, "getMsgProc", 3); //$NON-NLS-1$
+ //int address = callback.getAddress();
+ //if (address is 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+ int threadId = OS.GetCurrentThreadId();
+ auto hHook_ = OS.SetWindowsHookEx(OS.WH_GETMESSAGE, &getMsgProc, null, threadId);
+ if (hHook_ is null) {
+ //callback.dispose();
+ return;
+ }
+ display.setData(HHOOK, new ValueWrapperT!(void*)(hHook_));
+ display.setData(HHOOKMSG, new ValueWrapperT!(MSG*)(new MSG()));
+ display.disposeExec(new class(hHook_) Runnable {
+ void* hHook;
+ this( void* hHook ){ this.hHook = hHook; }
+ public void run() {
+ if (hHook !is null) OS.UnhookWindowsHookEx(hHook);
+ //if (callback !is null) callback.dispose();
+ }
+ });
+}
+static extern(Windows) int getMsgProc(int code, uint wParam, int lParam) {
+ Display display = Display.getCurrent();
+ if (display is null) return 0;
+ auto hHook = cast(ValueWrapperT!(void*))display.getData(HHOOK);
+ if (hHook is null) return 0;
+ if (code < 0) {
+ return OS.CallNextHookEx(hHook.value, code, wParam, lParam);
+ }
+ MSG* msg = cast(MSG*)(cast(ValueWrapperT!(MSG*))display.getData(HHOOKMSG)).value;
+ OS.MoveMemory(msg, lParam, MSG.sizeof);
+ int message = msg.message;
+ if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) {
+ if (display !is null) {
+ Widget widget = null;
+ auto hwnd = msg.hwnd;
+ while (hwnd !is null) {
+ widget = display.findWidget (hwnd);
+ if (widget !is null) break;
+ hwnd = OS.GetParent (hwnd);
+ }
+ if (widget !is null && (null !is cast(OleClientSite)widget )) {
+ OleClientSite site = cast(OleClientSite)widget;
+ if (site.handle is hwnd) {
+ bool consumed = false;
+ /* Allow activeX control to translate accelerators except when a menu is active. */
+ int thread = OS.GetWindowThreadProcessId(msg.hwnd, null);
+ GUITHREADINFO* lpgui = new GUITHREADINFO();
+ lpgui.cbSize = GUITHREADINFO.sizeof;
+ bool rc = cast(bool) OS.GetGUIThreadInfo(thread, lpgui);
+ int mask = OS.GUI_INMENUMODE | OS.GUI_INMOVESIZE | OS.GUI_POPUPMENUMODE | OS.GUI_SYSTEMMENUMODE;
+ if (!rc || (lpgui.flags & mask) is 0) {
+ OleFrame frame = site.frame;
+ frame.setData(CONSUME_KEY, null);
+ consumed = frame.translateOleAccelerator(msg);
+ if (frame.getData(CONSUME_KEY) !is null) consumed = false;
+ frame.setData(CONSUME_KEY, null);
+ }
+ bool accentKey = false;
+ switch (msg.message) {
+ case OS.WM_KEYDOWN:
+ case OS.WM_SYSKEYDOWN: {
+ static if (!OS.IsWinCE) {
+ switch (msg.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:
+ break;
+ default: {
+ /*
+ * Bug in Windows. The high bit in the result of MapVirtualKey() on
+ * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
+ * They should both be bit 32. The fix is to test the right bit.
+ */
+ int mapKey = OS.MapVirtualKey (msg.wParam, 2);
+ if (mapKey !is 0) {
+ accentKey = (mapKey & (OS.IsWinNT ? 0x80000000 : 0x8000)) !is 0;
+ if (!accentKey) {
+ for (int i=0; i> 8;
+ if ((OS.GetKeyState (OS.VK_SHIFT) < 0) is ((state & 0x1) !is 0) &&
+ (OS.GetKeyState (OS.VK_CONTROL) < 0) is ((state & 0x2) !is 0) &&
+ (OS.GetKeyState (OS.VK_MENU) < 0) is ((state & 0x4) !is 0)) {
+ if ((state & 0x7) !is 0) accentKey = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ }
+ /* Allow OleClientSite to process key events before activeX control */
+ if (!consumed && !accentKey && !ignoreNextKey) {
+ auto hwndOld = msg.hwnd;
+ msg.hwnd = site.handle;
+ consumed = OS.DispatchMessage (msg) is 1;
+ msg.hwnd = hwndOld;
+ }
+ switch (msg.message) {
+ case OS.WM_KEYDOWN:
+ case OS.WM_SYSKEYDOWN: {
+ switch (msg.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:
+ break;
+ default: {
+ ignoreNextKey = accentKey;
+ break;
+ }
+ }
+ }
+ default:
+ }
+
+ if (consumed) {
+ // In order to prevent this message from also being processed
+ // by the application, zero out message, wParam and lParam
+ msg.message = OS.WM_NULL;
+ msg.wParam = msg.lParam = 0;
+ OS.MoveMemory(lParam, msg, MSG.sizeof);
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ return OS.CallNextHookEx( hHook.value, code, wParam, lParam);
+}
+/**
+ * Increment the count of references to this instance
+ *
+ * @return the current reference count
+ */
+int AddRef() {
+ refCount++;
+ return refCount;
+}
+private int ContextSensitiveHelp(int fEnterMode) {
+ return COM.S_OK;
+}
+private void createCOMInterfaces() {
+ iOleInPlaceFrame = new _IOleInPlaceFrameImpl(this);
+}
+private void disposeCOMInterfaces () {
+ iOleInPlaceFrame = null;
+}
+private HRESULT GetBorder(LPRECT lprectBorder) {
+ /*
+ The IOleInPlaceUIWindow::GetBorder function, when called on a document or frame window
+ object, returns the outer rectangle (relative to the window) where the object can put
+ toolbars or similar controls.
+ */
+ if (lprectBorder is null) return COM.E_INVALIDARG;
+ RECT* rectBorder = new RECT();
+ // Coordinates must be relative to the window
+ OS.GetClientRect(handle, lprectBorder);
+ return COM.S_OK;
+}
+/**
+ *
+ * Returns the application menu items that will appear in the Container location when an OLE Document
+ * is in-place activated.
+ *
+ * When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar. The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
+ * menu locations. Note that an application can insert more than one menu into a single location.
+ *
+ * @return the application menu items that will appear in the Container location when an OLE Document
+ * is in-place activated.
+ *
+ */
+public MenuItem[] getContainerMenus(){
+ return containerMenuItems;
+}
+/**
+ *
+ * Returns the application menu items that will appear in the File location when an OLE Document
+ * is in-place activated.
+ *
+ *
When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar. The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
+ * menu locations. Note that an application can insert more than one menu into a single location.
+ *
+ * @return the application menu items that will appear in the File location when an OLE Document
+ * is in-place activated.
+ *
+ */
+public MenuItem[] getFileMenus(){
+ return fileMenuItems;
+}
+IOleInPlaceFrame getIOleInPlaceFrame() {
+ return iOleInPlaceFrame;
+}
+private int getMenuItemID(HMENU hMenu, int index) {
+ int id = 0;
+ MENUITEMINFO lpmii;
+ lpmii.cbSize = OS.MENUITEMINFO_sizeof;
+ lpmii.fMask = OS.MIIM_STATE | OS.MIIM_SUBMENU | OS.MIIM_ID;
+ OS.GetMenuItemInfo(hMenu, index, true, &lpmii);
+ if ((lpmii.fState & OS.MF_POPUP) is OS.MF_POPUP) {
+ id = cast(int)lpmii.hSubMenu;
+ } else {
+ id = lpmii.wID;
+ }
+ return id;
+}
+private int GetWindow(HWND* phwnd) {
+ if (phwnd !is null) {
+ *phwnd = handle;
+ }
+ return COM.S_OK;
+}
+/**
+ *
+ * Returns the application menu items that will appear in the Window location when an OLE Document
+ * is in-place activated.
+ *
+ *
When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar. The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
+ * menu locations. Note that an application can insert more than one menu into a single location.
+ *
+ * @return the application menu items that will appear in the Window location when an OLE Document
+ * is in-place activated.
+ *
+ */
+public MenuItem[] getWindowMenus(){
+ return windowMenuItems;
+}
+private HRESULT InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths ) {
+ // locate menu bar
+ Menu menubar = getShell().getMenuBar();
+ if (menubar is null || menubar.isDisposed()) {
+ int temp = 0;
+ COM.MoveMemory(lpMenuWidths, &temp, 4);
+ return COM.S_OK;
+ }
+ HMENU hMenu = menubar.handle;
+
+ // Create a holder for menu information. This will be passed down to
+ // the OS and the OS will fill in the requested information for each menu.
+ MENUITEMINFO lpmii;
+ auto hHeap = OS.GetProcessHeap();
+ int cch = 128;
+ int byteCount = cch * TCHAR.sizeof;
+ auto pszText = cast(TCHAR*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+ lpmii.cbSize = OS.MENUITEMINFO_sizeof;
+ lpmii.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_SUBMENU | OS.MIIM_DATA;
+ lpmii.dwTypeData = pszText;
+ lpmii.cch = cch;
+
+ // Loop over all "File-like" menus in the menubar and get information about the
+ // item from the OS.
+ int fileMenuCount = 0;
+ int newindex = 0;
+ if (this.fileMenuItems !is null) {
+ for (int i = 0; i < this.fileMenuItems.length; i++) {
+ MenuItem item = this.fileMenuItems[i];
+ if (item !is null) {
+ int index = item.getParent().indexOf(item);
+ lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
+ // exact number of characters in name. Reset it to our max size
+ // before each call.
+ if (OS.GetMenuItemInfo(hMenu, index, true, &lpmii)) {
+ if (OS.InsertMenuItem(hmenuShared, newindex, true, &lpmii)) {
+ // keep track of the number of items
+ fileMenuCount++;
+ newindex++;
+ }
+ }
+ }
+ }
+ }
+
+ // copy the menu item count information to the pointer
+ COM.MoveMemory(lpMenuWidths, &fileMenuCount, 4);
+
+ // Loop over all "Container-like" menus in the menubar and get information about the
+ // item from the OS.
+ int containerMenuCount = 0;
+ if (this.containerMenuItems !is null) {
+ for (int i = 0; i < this.containerMenuItems.length; i++) {
+ MenuItem item = this.containerMenuItems[i];
+ if (item !is null) {
+ int index = item.getParent().indexOf(item);
+ lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
+ // exact number of characters in name. Reset it to a large number
+ // before each call.
+ if (OS.GetMenuItemInfo(hMenu, index, true, &lpmii)) {
+ if (OS.InsertMenuItem(hmenuShared, newindex, true, &lpmii)) {
+ // keep track of the number of items
+ containerMenuCount++;
+ newindex++;
+ }
+ }
+ }
+ }
+ }
+
+ // copy the menu item count information to the pointer
+ COM.MoveMemory((cast(void*)lpMenuWidths) + 8, &containerMenuCount, 4);
+
+ // Loop over all "Window-like" menus in the menubar and get information about the
+ // item from the OS.
+ int windowMenuCount = 0;
+ if (this.windowMenuItems !is null) {
+ for (int i = 0; i < this.windowMenuItems.length; i++) {
+ MenuItem item = this.windowMenuItems[i];
+ if (item !is null) {
+ int index = item.getParent().indexOf(item);
+ lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
+ // exact number of characters in name. Reset it to a large number
+ // before each call.
+ if (OS.GetMenuItemInfo(hMenu, index, true, &lpmii)) {
+ if (OS.InsertMenuItem(hmenuShared, newindex, true, &lpmii)) {
+ // keep track of the number of items
+ windowMenuCount++;
+ newindex++;
+ }
+ }
+ }
+ }
+ }
+
+ // copy the menu item count information to the pointer
+ COM.MoveMemory((cast(void*)lpMenuWidths) + 16, &windowMenuCount, 4);
+
+ // free resources used in querying the OS
+ if (pszText !is null)
+ OS.HeapFree(hHeap, 0, pszText);
+ return COM.S_OK;
+}
+void onActivate(Event e) {
+ if (objIOleInPlaceActiveObject !is null) {
+ objIOleInPlaceActiveObject.OnFrameWindowActivate(true);
+ }
+ if (objIOleInPlaceActiveObject !is null) {
+ objIOleInPlaceActiveObject.OnDocWindowActivate(true);
+ }
+}
+void onDeactivate(Event e) {
+ if (objIOleInPlaceActiveObject !is null) {
+ objIOleInPlaceActiveObject.OnFrameWindowActivate(false);
+ }
+ if (objIOleInPlaceActiveObject !is null) {
+ objIOleInPlaceActiveObject.OnDocWindowActivate(false);
+ }
+}
+private void onDispose(Event e) {
+
+ releaseObjectInterfaces();
+ currentdoc = null;
+
+ this.Release();
+ removeListener(SWT.Activate, listener);
+ removeListener(SWT.Deactivate, listener);
+ removeListener(SWT.Dispose, listener);
+ removeListener(SWT.Resize, listener);
+ removeListener(SWT.Move, listener);
+}
+private void onResize(Event e) {
+ if (objIOleInPlaceActiveObject !is null) {
+ RECT lpRect;
+ OS.GetClientRect(handle, &lpRect);
+ objIOleInPlaceActiveObject.ResizeBorder(&lpRect, iOleInPlaceFrame, true);
+ }
+}
+private HRESULT QueryInterface(REFIID riid, void** ppvObject) {
+// implements IUnknown, IOleInPlaceFrame, IOleContainer, IOleInPlaceUIWindow
+ if (riid is null || ppvObject is null)
+ return COM.E_INVALIDARG;
+
+ if (COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIOleInPlaceFrame) ) {
+ *ppvObject = cast(void*)cast(IOleInPlaceFrame)iOleInPlaceFrame;
+ AddRef();
+ return COM.S_OK;
+ }
+
+ *ppvObject = null;
+ return COM.E_NOINTERFACE;
+}
+/**
+ * Decrement the count of references to this instance
+ *
+ * @return the current reference count
+ */
+int Release() {
+ refCount--;
+ if (refCount is 0){
+ disposeCOMInterfaces();
+ COM.CoFreeUnusedLibraries();
+ }
+ return refCount;
+}
+private void releaseObjectInterfaces() {
+ if (objIOleInPlaceActiveObject !is null) {
+ objIOleInPlaceActiveObject.Release();
+ }
+ objIOleInPlaceActiveObject = null;
+}
+private int RemoveMenus(HMENU hmenuShared) {
+
+ Menu menubar = getShell().getMenuBar();
+ if (menubar is null || menubar.isDisposed()) return COM.S_FALSE;
+
+ auto hMenu = menubar.handle;
+
+ int[] ids;
+ if (this.fileMenuItems !is null) {
+ for (int i = 0; i < this.fileMenuItems.length; i++) {
+ MenuItem item = this.fileMenuItems[i];
+ if (item !is null && !item.isDisposed()) {
+ int index = item.getParent().indexOf(item);
+ // get Id from original menubar
+ int id = getMenuItemID(hMenu, index);
+ ids ~= id;
+ }
+ }
+ }
+ if (this.containerMenuItems !is null) {
+ for (int i = 0; i < this.containerMenuItems.length; i++) {
+ MenuItem item = this.containerMenuItems[i];
+ if (item !is null && !item.isDisposed()) {
+ int index = item.getParent().indexOf(item);
+ int id = getMenuItemID(hMenu, index);
+ ids ~= id;
+ }
+ }
+ }
+ if (this.windowMenuItems !is null) {
+ for (int i = 0; i < this.windowMenuItems.length; i++) {
+ MenuItem item = this.windowMenuItems[i];
+ if (item !is null && !item.isDisposed()) {
+ int index = item.getParent().indexOf(item);
+ int id = getMenuItemID(hMenu, index);
+ ids ~= id;
+ }
+ }
+ }
+ int index = OS.GetMenuItemCount(hmenuShared) - 1;
+ for (int i = index; i >= 0; i--) {
+ int id = getMenuItemID(hmenuShared, i);
+ if ( ids.contains(id)){
+ OS.RemoveMenu(hmenuShared, i, OS.MF_BYPOSITION);
+ }
+ }
+ return COM.S_OK;
+}
+private int RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) {
+ return COM.S_OK;
+}
+HRESULT SetActiveObject( LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR pszObjName ) {
+ if (objIOleInPlaceActiveObject !is null) {
+ objIOleInPlaceActiveObject.Release();
+ objIOleInPlaceActiveObject = null;
+ }
+ if (pActiveObject !is null) {
+ objIOleInPlaceActiveObject = pActiveObject;
+ objIOleInPlaceActiveObject.AddRef();
+ }
+
+ return COM.S_OK;
+}
+
+private HRESULT SetBorderSpace( LPCBORDERWIDTHS pborderwidths ) {
+ // A Control/Document can :
+ // Use its own toolbars, requesting border space of a specific size, or,
+ // Use no toolbars, but force the container to remove its toolbars by passing a
+ // valid BORDERWIDTHS structure containing nothing but zeros in the pborderwidths parameter, or,
+ // Use no toolbars but allow the in-place container to leave its toolbars up by
+ // passing NULL as the pborderwidths parameter.
+ if (objIOleInPlaceActiveObject is null) return COM.S_OK;
+ RECT* borderwidth = new RECT();
+ if (pborderwidths is null || currentdoc is null ) return COM.S_OK;
+
+ COM.MoveMemory(borderwidth, pborderwidths, RECT.sizeof);
+ currentdoc.setBorderSpace(borderwidth);
+
+ return COM.S_OK;
+}
+/**
+ *
+ * Specify the menu items that should appear in the Container location when an OLE Document
+ * is in-place activated.
+ *
+ *
When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar. The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
+ * menu locations. Note that an application can insert more than one menu into a single location.
+ *
+ *
This method must be called before in place activation of the OLE Document. After the Document
+ * is activated, the menu bar will not be modified until a subsequent activation.
+ *
+ * @param containerMenus an array of top level MenuItems to be inserted into the Container location of
+ * the menubar
+ */
+public void setContainerMenus(MenuItem[] containerMenus){
+ containerMenuItems = containerMenus;
+}
+OleClientSite getCurrentDocument() {
+ return currentdoc;
+}
+void setCurrentDocument(OleClientSite doc) {
+ currentdoc = doc;
+
+ if (currentdoc !is null && objIOleInPlaceActiveObject !is null) {
+ RECT lpRect;
+ OS.GetClientRect(handle, &lpRect);
+ objIOleInPlaceActiveObject.ResizeBorder(&lpRect, iOleInPlaceFrame, true);
+ }
+}
+/**
+ *
+ * Specify the menu items that should appear in the File location when an OLE Document
+ * is in-place activated.
+ *
+ *
When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar. The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
+ * menu locations. Note that an application can insert more than one menu into a single location.
+ *
+ *
This method must be called before in place activation of the OLE Document. After the Document
+ * is activated, the menu bar will not be modified until a subsequent activation.
+ *
+ * @param fileMenus an array of top level MenuItems to be inserted into the File location of
+ * the menubar
+ */
+public void setFileMenus(MenuItem[] fileMenus){
+ fileMenuItems = fileMenus;
+}
+HRESULT SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject ) {
+ IOleInPlaceActiveObject inPlaceActiveObject;
+ if (objIOleInPlaceActiveObject !is null)
+ inPlaceActiveObject = objIOleInPlaceActiveObject;
+
+ Menu menubar = getShell().getMenuBar();
+ if (menubar is null || menubar.isDisposed()){
+ return COM.OleSetMenuDescriptor(null, getShell().handle, hwndActiveObject, iOleInPlaceFrame, inPlaceActiveObject);
+ }
+
+ HWND handle = menubar.getShell().handle;
+
+ if (hmenuShared is null && holemenu is null) {
+ // re-instate the original menu - this occurs on deactivation
+ hmenuShared = menubar.handle;
+ }
+ if (hmenuShared is null) return COM.E_FAIL;
+
+ OS.SetMenu(handle, hmenuShared);
+ OS.DrawMenuBar(handle);
+
+ return COM.OleSetMenuDescriptor(holemenu, handle, hwndActiveObject, iOleInPlaceFrame, inPlaceActiveObject);
+}
+
+/**
+ *
+ * Set the menu items that should appear in the Window location when an OLE Document
+ * is in-place activated.
+ *
+ *
When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar. The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help). The OLE Document retains control of the Edit, Object and Help
+ * menu locations. Note that an application can insert more than one menu into a single location.
+ *
+ *
This method must be called before in place activation of the OLE Document. After the Document
+ * is activated, the menu bar will not be modified until a subsequent activation.
+ *
+ * @param windowMenus an array of top level MenuItems to be inserted into the Window location of
+ * the menubar
+ */
+public void setWindowMenus(MenuItem[] windowMenus){
+ windowMenuItems = windowMenus;
+}
+private bool translateOleAccelerator(MSG* msg) {
+ if (objIOleInPlaceActiveObject is null) return false;
+ int result = objIOleInPlaceActiveObject.TranslateAccelerator(msg);
+ return (result != COM.S_FALSE && result != COM.E_NOTIMPL);
+}
+
+HRESULT TranslateAccelerator( LPMSG lpmsg, WORD wID ){
+ Menu menubar = getShell().getMenuBar();
+ if (menubar is null || menubar.isDisposed() || !menubar.isEnabled()) return COM.S_FALSE;
+ if (wID < 0) return COM.S_FALSE;
+
+ Shell shell = menubar.getShell();
+ HWND hwnd = shell.handle;
+ HACCEL hAccel = cast(HACCEL)OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
+ if (hAccel is null) return COM.S_FALSE;
+
+ MSG msg = *lpmsg;
+ int result = OS.TranslateAccelerator(hwnd, hAccel, &msg);
+ return result == 0 ? COM.S_FALSE : COM.S_OK;
+}
+}
+
+// implements IOleInPlaceFrame, IOleInPlaceUIWindow, IOleWindow, IUnknown
+class _IOleInPlaceFrameImpl : IOleInPlaceFrame {
+
+ OleFrame parent;
+ this(OleFrame p) { parent = p; }
+extern (Windows) :
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface IOleWindow
+ HRESULT GetWindow( HWND * phwnd ) { return parent.GetWindow(phwnd); }
+ HRESULT ContextSensitiveHelp( BOOL fEnterMode ){ return COM.S_OK; }
+
+ //interface IOleInPlaceUIWindow
+ HRESULT GetBorder( LPRECT lprectBorder ) { return parent.GetBorder(lprectBorder); }
+ HRESULT RequestBorderSpace( LPCBORDERWIDTHS pborderwidths ){ return COM.S_OK; }
+ HRESULT SetBorderSpace( LPCBORDERWIDTHS pborderwidths ) { return parent.SetBorderSpace(pborderwidths); }
+ HRESULT SetActiveObject( LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR pszObjName ) {
+ return parent.SetActiveObject(pActiveObject, pszObjName);
+ }
+
+ // interface IOleInPlaceFrame : IOleInPlaceUIWindow
+ HRESULT InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths ){
+ return parent.InsertMenus(hmenuShared, lpMenuWidths);
+ }
+ HRESULT SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject ){
+ return parent.SetMenu(hmenuShared, holemenu, hwndActiveObject);
+ }
+ HRESULT RemoveMenus( HMENU hmenuShared ) {
+ return parent.RemoveMenus(hmenuShared);
+ }
+ HRESULT SetStatusText( LPCOLESTR pszStatusText ) { return COM.E_NOTIMPL; }
+ HRESULT EnableModeless( BOOL fEnable ) { return COM.E_NOTIMPL; }
+ HRESULT TranslateAccelerator( LPMSG lpmsg, WORD wID ) {
+ return parent.TranslateAccelerator(lpmsg, wID);
+ }
+
+}
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleFunctionDescription.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleFunctionDescription.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleFunctionDescription;
+
+import org.eclipse.swt.ole.win32.OleParameterDescription;
+import java.lang.all;
+
+public class OleFunctionDescription {
+
+ public int id;
+ public String name;
+ public OleParameterDescription[] args;
+ public int optionalArgCount;
+ public short returnType;
+ public int invokeKind;
+ public int funcKind;
+ public short flags;
+ public int callingConvention;
+ public String documentation;
+ public String helpFile;
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleListener.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleListener;
+
+import org.eclipse.swt.ole.win32.OleEvent;
+
+/**
+ * Implementers of OleListener
provide a simple
+ * handleEvent()
method that is used internally
+ * by SWT to dispatch events.
+ *
+ * After creating an instance of a class that implements this
+ * interface it can be added to an OleControlSite
+ * using the addEventListener()
method and removed
+ * using the removeEventListener()
method. When the
+ * specified event occurs, handleEvent()
will be
+ * sent to the instance.
+ *
+ *
+ * @see OleControlSite
+ */
+public interface OleListener {
+
+/**
+ * Sent when an event that the receiver has registered for occurs.
+ *
+ * @param event the event which occurred
+ */
+public void handleEvent(OleEvent event);
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleParameterDescription.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleParameterDescription.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleParameterDescription;
+import java.lang.all;
+
+
+public class OleParameterDescription {
+ public String name;
+ public short flags;
+ public short type;
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OlePropertyChangeSink.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OlePropertyChangeSink.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OlePropertyChangeSink;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.ifs;
+
+import org.eclipse.swt.ole.win32.OleControlSite;
+import org.eclipse.swt.ole.win32.OleEventTable;
+import org.eclipse.swt.ole.win32.OleListener;
+import org.eclipse.swt.ole.win32.OleEvent;
+import org.eclipse.swt.ole.win32.OleEventTable;
+import org.eclipse.swt.ole.win32.OLE;
+
+final class OlePropertyChangeSink {
+
+ private OleControlSite controlSite;
+ //private IUnknown objIUnknown;
+
+ //private COMObject iUnknown;
+ private _IPropertyNotifySinkImpl iPropertyNotifySink;
+
+ private int refCount;
+
+ private int propertyCookie;
+
+ private OleEventTable eventTable;
+
+this(OleControlSite controlSite) {
+
+ this.controlSite = controlSite;
+
+ createCOMInterfaces();
+}
+void addListener(int propertyID, OleListener listener) {
+ if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable is null) eventTable = new OleEventTable ();
+ eventTable.hook(propertyID, listener);
+}
+int AddRef() {
+ refCount++;
+ return refCount;
+}
+void connect(IUnknown objIUnknown) {
+
+ // Set up property change notification sink
+ IConnectionPointContainer cpc;
+ if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
+ IConnectionPoint cp;
+ if (cpc.FindConnectionPoint(&COM.IIDIPropertyNotifySink, &cp) is COM.S_OK) {
+ uint cookie;
+ if (cp.Advise(iPropertyNotifySink, &cookie) is COM.S_OK) {
+ propertyCookie = cookie;
+ }
+ cp.Release();
+ }
+ cpc.Release();
+ }
+}
+protected void createCOMInterfaces() {
+ // register each of the interfaces that this object implements
+ iPropertyNotifySink = new _IPropertyNotifySinkImpl(this);
+}
+void disconnect(IUnknown objIUnknown) {
+
+ // disconnect property notification sink
+ if (propertyCookie !is 0 && objIUnknown !is null) {
+ IConnectionPointContainer cpc;
+ if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
+ IConnectionPoint cp;
+ if (cpc.FindConnectionPoint(&COM.IIDIPropertyNotifySink, &cp) is COM.S_OK) {
+ if (cp.Unadvise(propertyCookie) is COM.S_OK) {
+ propertyCookie = 0;
+ }
+ cp.Release();
+ }
+ cpc.Release();
+ }
+ }
+}
+private void disposeCOMInterfaces() {
+ iPropertyNotifySink = null;
+}
+/**
+* Notify listeners of an event.
+*
+* This method notifies all listeners that an event
+* has occurred.
+*
+* @param eventType the desired SWT event
+* @param event the event data
+*
+* @exception IllegalArgumentException
+* - ERROR_NULL_ARGUMENT when handler is null
+*
+* @exception SWTException
+* - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+* - ERROR_WIDGET_DISPOSED when the widget has been disposed
+*
+*/
+private void notifyListener (int eventType, OleEvent event) {
+ if (event is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable is null) return;
+ event.type = eventType;
+ event.widget = controlSite;
+ eventTable.sendEvent (event);
+}
+package int OnChanged(int dispID) {
+ if (eventTable is null || !eventTable.hooks(dispID)) return COM.S_OK;
+ OleEvent event = new OleEvent();
+ event.detail = OLE.PROPERTY_CHANGED;
+ notifyListener(dispID,event);
+ return COM.S_OK;
+}
+package int OnRequestEdit(int dispID) {
+ if (eventTable is null || !eventTable.hooks(dispID)) return COM.S_OK;
+ OleEvent event = new OleEvent();
+ event.doit = true;
+ event.detail = OLE.PROPERTY_CHANGING;
+ notifyListener(dispID,event);
+ return (event.doit) ? COM.S_OK : COM.S_FALSE;
+}
+protected HRESULT QueryInterface(REFIID riid, void ** ppvObject) {
+ if (riid is null || ppvObject is null)
+ return COM.E_INVALIDARG;
+
+ if (COM.IsEqualGUID(riid, &COM.IIDIPropertyNotifySink)) {
+ *ppvObject = cast(void*)cast(IPropertyNotifySink)iPropertyNotifySink;
+ AddRef();
+ return COM.S_OK;
+ }
+ *ppvObject = null;
+ return COM.E_NOINTERFACE;
+}
+int Release() {
+ refCount--;
+ if (refCount is 0) {
+ disposeCOMInterfaces();
+ }
+ return refCount;
+}
+void removeListener(int propertyID, OleListener listener) {
+ if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable is null) return;
+ eventTable.unhook (propertyID, listener);
+}
+}
+
+
+private class _IPropertyNotifySinkImpl : IPropertyNotifySink {
+
+ OlePropertyChangeSink parent;
+ this(OlePropertyChangeSink p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface of IPropertyNotifySink
+ int OnChanged(int dispID) { return parent.OnChanged(dispID); }
+ int OnRequestEdit(int dispID) { return parent.OnRequestEdit(dispID); }
+}
+
+
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OlePropertyDescription.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OlePropertyDescription.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OlePropertyDescription;
+import java.lang.all;
+
+
+public class OlePropertyDescription {
+ public int id;
+ public String name;
+ public int type;
+ public int flags;
+ public int kind;
+ public String description;
+ public String helpFile;
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/Variant.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/Variant.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1053 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.Variant;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.COMTYPES;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.ole.win32.OleAutomation;
+import org.eclipse.swt.ole.win32.OLE;
+
+import tango.util.Convert;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ *
+ * A Variant is a generic OLE mechanism for passing data of different types via a common interface.
+ *
+ * It is used within the OleAutomation object for getting a property, setting a property or invoking
+ * a method on an OLE Control or OLE Document.
+ *
+ */
+public final class Variant {
+ /**
+ * The size in bytes of a native VARIANT struct.
+ */
+ /**
+ * A variant always takes up 16 bytes, no matter what you
+ * store in it. Objects, strings, and arrays are not physically
+ * stored in the Variant; in these cases, four bytes of the
+ * Variant are used to hold either an object reference, or a
+ * pointer to the string or array. The actual data are stored elsewhere.
+ */
+ //public static final int sizeof = 16;
+
+
+ private short type; // OLE.VT_* type
+ private bool booleanData;
+ private byte byteData;
+ private short shortData;
+ private wchar charData;
+ private int intData;
+ private long longData;
+ private float floatData;
+ private double doubleData;
+ private String stringData;
+ private void* byRefPtr;
+ private IDispatch dispatchData;
+ private IUnknown unknownData;
+
+/**
+ * Invokes platform specific functionality to copy a variant
+ * into operating system memory.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Variant
. 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 pVarDest destination pointer to a variant
+ * @param varSrc source Variant
+ *
+ * @since 3.3
+ */
+public static void win32_copy (VARIANT* pVarDest, Variant varSrc) {
+ varSrc.getData (pVarDest);
+}
+
+/**
+ * Invokes platform specific functionality to wrap a variant
+ * that was allocated in operating system memory.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Variant
. 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 pVariant pointer to a variant
+ *
+ * @return a new Variant
+ *
+ * @since 3.3
+ */
+public static Variant win32_new (VARIANT* pVariant) {
+ Variant variant = new Variant ();
+ variant.setData (pVariant);
+ return variant;
+}
+
+/**
+ * Create an empty Variant object with type VT_EMPTY.
+ *
+ * @since 2.0
+ */
+public this(){
+ type = COM.VT_EMPTY;
+}
+/**
+ * Create a Variant object which represents a Java float as a VT_R4.
+ *
+ * @param val the Java float value that this Variant represents
+ *
+ */
+public this(float val) {
+ type = COM.VT_R4;
+ floatData = val;
+
+}
+/**
+ * Create a Variant object which represents a Java double as a VT_R8.
+ *
+ * @param val the Java double value that this Variant represents
+ *
+ * @since 3.2
+ */
+public this(double val) {
+ type = COM.VT_R8;
+ doubleData = val;
+}
+/**
+ * Create a Variant object which represents a Java int as a VT_I4.
+ *
+ * @param val the Java int value that this Variant represents
+ *
+ */
+public this(int val) {
+ type = COM.VT_I4;
+ intData = val;
+}
+public this(uint val) {
+ type = COM.VT_I4;
+ intData = val;
+}
+/**
+ * Create a Variant object which contains a reference to the data being transferred.
+ *
+ * When creating a VT_BYREF Variant, you must give the full Variant type
+ * including VT_BYREF such as
+ *
+ *
short byRefType = OLE.VT_BSTR | OLE.VT_BYREF
.
+ *
+ * @param ptr a pointer to the data being transferred.
+ * @param byRefType the type of the data being transferred such as OLE.VT_BSTR | OLE.VT_BYREF
+ *
+ */
+public this(void* ptr, ushort byRefType) {
+ type = byRefType;
+ byRefPtr = ptr;
+}
+/**
+ * Create a Variant object which represents an IDispatch interface as a VT_Dispatch.
+ *
+ * @param automation the OleAutomation object that this Variant represents
+ *
+ */
+public this(OleAutomation automation) {
+ type = COM.VT_DISPATCH;
+ dispatchData = automation.getAddress();
+}
+/**
+ * Create a Variant object which represents an IDispatch interface as a VT_Dispatch.
+ * The caller is expected to have appropriately invoked unknown.AddRef() before creating
+ * this Variant.
+ *
+ * @since 2.0
+ *
+ * @param idispatch the IDispatch object that this Variant represents
+ *
+ */
+public this(IDispatch idispatch) {
+ type = COM.VT_DISPATCH;
+ dispatchData = idispatch;
+}
+/**
+ * Create a Variant object which represents an IUnknown interface as a VT_UNKNOWN.
+ *
+ *
The caller is expected to have appropriately invoked unknown.AddRef() before creating
+ * this Variant.
+ *
+ * @param unknown the IUnknown object that this Variant represents
+ *
+ */
+public this(IUnknown unknown) {
+ type = COM.VT_UNKNOWN;
+ unknownData = unknown;
+}
+/**
+ * Create a Variant object which represents a Java long as a VT_I8.
+ *
+ * @param val the Java long value that this Variant represents
+ *
+ * @since 3.2
+ */
+ public this(long val) {
+ type = COM.VT_I8;
+ longData = val;
+}
+/**
+ * Create a Variant object which represents a Java String as a VT_BSTR.
+ *
+ * @param string the Java String value that this Variant represents
+ *
+ */
+public this(String string) {
+ type = COM.VT_BSTR;
+ stringData = string;
+}
+/**
+ * Create a Variant object which represents a Java short as a VT_I2.
+ *
+ * @param val the Java short value that this Variant represents
+ *
+ */
+public this(short val) {
+ type = COM.VT_I2;
+ shortData = val;
+}
+/**
+ * Create a Variant object which represents a Java bool as a VT_BOOL.
+ *
+ * @param val the Java bool value that this Variant represents
+ *
+ */
+public this(bool val) {
+ type = COM.VT_BOOL;
+ booleanData = val;
+}
+
+/**
+ * Calling dispose will release resources associated with this Variant.
+ * If the resource is an IDispatch or IUnknown interface, Release will be called.
+ * If the resource is a ByRef pointer, nothing is released.
+ *
+ * @since 2.1
+ */
+public void dispose() {
+ if ((type & COM.VT_BYREF) is COM.VT_BYREF) {
+ return;
+ }
+
+ switch (type) {
+ case COM.VT_DISPATCH :
+ dispatchData.Release();
+ break;
+ case COM.VT_UNKNOWN :
+ unknownData.Release();
+ break;
+ default:
+ }
+
+}
+/**
+ * Returns the OleAutomation object represented by this Variant.
+ *
+ *
If this Variant does not contain an OleAutomation object, an attempt is made to
+ * coerce the Variant type into an OleAutomation object. If this fails, an error is
+ * thrown. Note that OleAutomation objects must be disposed when no longer
+ * needed.
+ *
+ * @return the OleAutomation object represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an OleAutomation object
+ *
+ */
+public OleAutomation getAutomation() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_DISPATCH) {
+ return new OleAutomation(dispatchData);
+ }
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_DISPATCH);
+ if (result !is COM.S_OK)
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant autoVar = new Variant();
+ autoVar.setData(&newPtr);
+ return autoVar.getAutomation();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the
+ // OleAutomation object is created as Variant Clear
+ // will result in a Release being performed on the
+ // Dispatch object
+ }
+}
+/**
+ * Returns the IDispatch object represented by this Variant.
+ *
+ * If this Variant does not contain an IDispatch object, an attempt is made to
+ * coerce the Variant type into an IDIspatch object. If this fails, an error is
+ * thrown.
+ *
+ * @since 2.0
+ *
+ * @return the IDispatch object represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an IDispatch object
+ *
+ */
+public IDispatch getDispatch() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+
+ if (type is COM.VT_DISPATCH) {
+ return dispatchData;
+ }
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_DISPATCH);
+ if (result !is COM.S_OK)
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant autoVar = new Variant();
+ autoVar.setData(&newPtr);
+ return autoVar.getDispatch();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the
+ // OleAutomation object is created as Variant Clear
+ // will result in a Release being performed on the
+ // Dispatch object
+ }
+}
+/**
+ * Returns the Java bool represented by this Variant.
+ *
+ * If this Variant does not contain a Java bool, an attempt is made to
+ * coerce the Variant type into a Java bool. If this fails, an error is thrown.
+ *
+ * @return the Java bool represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a bool
+ *
+ *
+ */
+public bool getBoolean() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_BOOL) {
+ return booleanData;
+ }
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_BOOL);
+ if (result !is COM.S_OK)
+ OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant boolVar = new Variant();
+ boolVar.setData(&newPtr);
+ return boolVar.getBoolean();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+}
+/**
+ * Returns a pointer to the referenced data represented by this Variant.
+ *
+ * If this Variant does not contain a reference to data, zero is returned.
+ *
+ * @return a pointer to the referenced data represented by this Variant or 0
+ *
+ */
+public void* getByRef() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if ((type & COM.VT_BYREF)is COM.VT_BYREF) {
+ return byRefPtr;
+ }
+
+ return null;
+}
+/**
+ * Returns the Java byte represented by this Variant.
+ *
+ *
If this Variant does not contain a Java byte, an attempt is made to
+ * coerce the Variant type into a Java byte. If this fails, an error is thrown.
+ *
+ * @return the Java byte represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a byte
+ *
+ *
+ * @since 3.3
+ */
+public byte getByte() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_I1) {
+ return byteData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I1);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant byteVar = new Variant();
+ byteVar.setData(&newPtr);
+ return byteVar.getByte();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+}
+/**
+ * Returns the Java char represented by this Variant.
+ *
+ * If this Variant does not contain a Java char, an attempt is made to
+ * coerce the Variant type into a Java char. If this fails, an error is thrown.
+ *
+ * @return the Java char represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a char
+ *
+ *
+ * @since 3.3
+ */
+public wchar getChar() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_UI2) {
+ return charData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_UI2);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant charVar = new Variant();
+ charVar.setData(&newPtr);
+ return charVar.getChar();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+}
+void getData(VARIANT* pData){
+ if (pData is null) OLE.error(OLE.ERROR_OUT_OF_MEMORY);
+
+ COM.VariantInit(pData);
+
+ // set type
+ pData.vt = type;
+ if ((type & COM.VT_BYREF) is COM.VT_BYREF) {
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ COM.MoveMemory((cast(void*)pData) + 8, &byRefPtr, 4);
+ return;
+ }
+
+ switch (type) {
+ case COM.VT_EMPTY :
+ case COM.VT_NULL :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ break;
+ case COM.VT_BOOL :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ auto v = booleanData ? COM.VARIANT_TRUE : COM.VARIANT_FALSE;
+ COM.MoveMemory((cast(void*)pData) + 8, &v, 2);
+ break;
+ case COM.VT_I1 :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ COM.MoveMemory((cast(void*)pData) + 8, &byteData, 1);
+ break;
+ case COM.VT_I2 :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ COM.MoveMemory((cast(void*)pData) + 8, &shortData, 2);
+ break;
+ case COM.VT_UI2 :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ COM.MoveMemory((cast(void*)pData) + 8, &charData, 2);
+ break;
+ case COM.VT_I4 :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ COM.MoveMemory((cast(void*)pData) + 8, &intData, 4);
+ break;
+ case COM.VT_I8 :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ COM.MoveMemory((cast(void*)pData) + 8, &longData, 8);
+ break;
+ case COM.VT_R4 :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ COM.MoveMemory((cast(void*)pData) + 8, &floatData, 4);
+ break;
+ case COM.VT_R8 :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ COM.MoveMemory((cast(void*)pData) + 8, &doubleData, 8);
+ break;
+ case COM.VT_DISPATCH :
+ dispatchData.AddRef();
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ auto v = cast(void*)dispatchData;
+ COM.MoveMemory((cast(void*)pData) + 8, &v, 4);
+ break;
+ case COM.VT_UNKNOWN :
+ unknownData.AddRef();
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ auto v = cast(void*)dispatchData;
+ COM.MoveMemory((cast(void*)pData) + 8, &v, 4);
+ break;
+ case COM.VT_BSTR :
+ COM.MoveMemory((cast(void*)pData), &type, 2);
+ wchar[] data = StrToWCHARs(stringData);
+ auto ptr = COM.SysAllocString(data.ptr);
+ COM.MoveMemory((cast(void*)pData) + 8, &ptr, 4);
+ break;
+
+ default :
+ OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
+ }
+}
+/**
+ * Returns the Java double represented by this Variant.
+ *
+ * If this Variant does not contain a Java double, an attempt is made to
+ * coerce the Variant type into a Java double. If this fails, an error is thrown.
+ *
+ * @return the Java double represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a double
+ *
+ *
+ * @since 3.2
+ */
+public double getDouble() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_R8) {
+ return doubleData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_R8);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant doubleVar = new Variant();
+ doubleVar.setData(&newPtr);
+ return doubleVar.getDouble();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+}
+
+/**
+ * Returns the Java float represented by this Variant.
+ *
+ * If this Variant does not contain a Java float, an attempt is made to
+ * coerce the Variant type into a Java float. If this fails, an error is thrown.
+ *
+ * @return the Java float represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a float
+ *
+ */
+public float getFloat() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_R4) {
+ return floatData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_R4);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant floatVar = new Variant();
+ floatVar.setData(&newPtr);
+ return floatVar.getFloat();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+
+}
+/**
+ * Returns the Java int represented by this Variant.
+ *
+ * If this Variant does not contain a Java int, an attempt is made to
+ * coerce the Variant type into a Java int. If this fails, an error is thrown.
+ *
+ * @return the Java int represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a int
+ *
+ */
+public int getInt() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_I4) {
+ return intData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I4);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant intVar = new Variant();
+ intVar.setData(&newPtr);
+ return intVar.getInt();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+}
+/**
+ * Returns the Java long represented by this Variant.
+ *
+ * If this Variant does not contain a Java long, an attempt is made to
+ * coerce the Variant type into a Java long. If this fails, an error is thrown.
+ *
+ * @return the Java long represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a long
+ *
+ *
+ * @since 3.2
+ */
+public long getLong() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_I8) {
+ return longData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I8);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant longVar = new Variant();
+ longVar.setData(&newPtr);
+ return longVar.getLong();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+}
+/**
+ * Returns the Java short represented by this Variant.
+ *
+ * If this Variant does not contain a Java short, an attempt is made to
+ * coerce the Variant type into a Java short. If this fails, an error is thrown.
+ *
+ * @return the Java short represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a short
+ *
+ */
+public short getShort() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_I2) {
+ return shortData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I2);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant shortVar = new Variant();
+ shortVar.setData(&newPtr);
+ return shortVar.getShort();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+
+}
+/**
+ * Returns the Java String represented by this Variant.
+ *
+ * If this Variant does not contain a Java String, an attempt is made to
+ * coerce the Variant type into a Java String. If this fails, an error is thrown.
+ *
+ * @return the Java String represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a String
+ *
+ */
+public String getString() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_BSTR) {
+ return stringData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_BSTR);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+
+ Variant stringVar = new Variant();
+ stringVar.setData(&newPtr);
+ return stringVar.getString();
+
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr);
+ }
+}
+/**
+ * Returns the type of the variant type. This will be an OLE.VT_* value or
+ * a bitwise combination of OLE.VT_* values as in the case of
+ * OLE.VT_BSTR | OLE.VT_BYREF.
+ *
+ * @return the type of the variant data
+ *
+ * @since 2.0
+ */
+public short getType() {
+ return type;
+}
+/**
+ * Returns the IUnknown object represented by this Variant.
+ *
+ * If this Variant does not contain an IUnknown object, an attempt is made to
+ * coerce the Variant type into an IUnknown object. If this fails, an error is
+ * thrown.
+ *
+ * @return the IUnknown object represented by this Variant
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into
+ * an IUnknown object
+ *
+ */
+public IUnknown getUnknown() {
+ if (type is COM.VT_EMPTY) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+ }
+ if (type is COM.VT_UNKNOWN) {
+ return unknownData;
+ }
+
+ // try to coerce the value to the desired type
+ VARIANT oldPtr, newPtr;
+ try {
+ getData(&oldPtr);
+ int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_UNKNOWN);
+ if (result !is COM.S_OK)
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+ Variant unknownVar = new Variant();
+ unknownVar.setData(&newPtr);
+ return unknownVar.getUnknown();
+ } finally {
+ COM.VariantClear(&oldPtr);
+ COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the
+ // IUnknown object is created as Variant Clear
+ // will result in a Release being performed on the
+ // Dispatch object
+ }
+}
+/**
+ * Update the by reference value of this variant with a new bool value.
+ *
+ * @param val the new bool value
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not
+ * a (VT_BYREF | VT_BOOL) object
+ *
+ *
+ * @since 2.1
+ */
+public void setByRef(bool val) {
+ if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_BOOL) is 0) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+ }
+ auto v = val ? COM.VARIANT_TRUE : COM.VARIANT_FALSE;
+ COM.MoveMemory(byRefPtr, &v, 2);
+}
+/**
+ * Update the by reference value of this variant with a new float value.
+ *
+ * @param val the new float value
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not
+ * a (VT_BYREF | VT_R4) object
+ *
+ *
+ * @since 2.1
+ */
+public void setByRef(float val) {
+ if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_R4) is 0) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+ }
+ COM.MoveMemory(byRefPtr, &val, 4);
+}
+/**
+ * Update the by reference value of this variant with a new integer value.
+ *
+ * @param val the new integer value
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I4) object
+ *
+ *
+ * @since 2.1
+ */
+public void setByRef(int val) {
+ if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_I4) is 0) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+ }
+ COM.MoveMemory(byRefPtr, &val, 4);
+}
+/**
+ * Update the by reference value of this variant with a new short value.
+ *
+ * @param val the new short value
+ *
+ * @exception SWTException
+ * - ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I2) object
+ *
+ *
+ * @since 2.1
+ */
+public void setByRef(short val) {
+ if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_I2) is 0) {
+ OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+ }
+ COM.MoveMemory(byRefPtr, &val, 2);
+}
+
+void setData(VARIANT* pData){
+ if (pData is null) OLE.error(OLE.ERROR_INVALID_ARGUMENT);
+
+ short[1] dataType ;
+ COM.MoveMemory(dataType.ptr, (cast(void*)pData), 2);
+ type = dataType[0];
+
+ if ((type & COM.VT_BYREF) is COM.VT_BYREF) {
+ void*[1] newByRefPtr;
+ OS.MoveMemory(newByRefPtr.ptr, (cast(void*)pData) + 8, 4);
+ byRefPtr = newByRefPtr[0];
+ return;
+ }
+
+ switch (type) {
+ case COM.VT_EMPTY :
+ case COM.VT_NULL :
+ break;
+ case COM.VT_BOOL :
+ short[1] newBooleanData;
+ COM.MoveMemory(newBooleanData.ptr, (cast(void*)pData) + 8, 2);
+ booleanData = (newBooleanData[0] !is COM.VARIANT_FALSE);
+ break;
+ case COM.VT_I1 :
+ byte[1] newByteData;
+ COM.MoveMemory(newByteData.ptr, (cast(void*)pData) + 8, 1);
+ byteData = newByteData[0];
+ break;
+ case COM.VT_I2 :
+ short[1] newShortData;
+ COM.MoveMemory(newShortData.ptr, (cast(void*)pData) + 8, 2);
+ shortData = newShortData[0];
+ break;
+ case COM.VT_UI2 :
+ wchar[1] newCharData;
+ COM.MoveMemory(newCharData.ptr, (cast(void*)pData) + 8, 2);
+ charData = newCharData[0];
+ break;
+ case COM.VT_I4 :
+ int[1] newIntData;
+ OS.MoveMemory(newIntData.ptr, (cast(void*)pData) + 8, 4);
+ intData = newIntData[0];
+ break;
+ case COM.VT_I8 :
+ long[1] newLongData;
+ OS.MoveMemory(newLongData.ptr, (cast(void*)pData) + 8, 8);
+ longData = newLongData[0];
+ break;
+ case COM.VT_R4 :
+ float[1] newFloatData;
+ COM.MoveMemory(newFloatData.ptr, (cast(void*)pData) + 8, 4);
+ floatData = newFloatData[0];
+ break;
+ case COM.VT_R8 :
+ double[1] newDoubleData;
+ COM.MoveMemory(newDoubleData.ptr, (cast(void*)pData) + 8, 8);
+ doubleData = newDoubleData[0];
+ break;
+ case COM.VT_DISPATCH : {
+ IDispatch[1] ppvObject;
+ OS.MoveMemory(ppvObject.ptr, (cast(void*)pData) + 8, 4);
+ if (ppvObject[0] is null) {
+ type = COM.VT_EMPTY;
+ break;
+ }
+ dispatchData = ppvObject[0];
+ dispatchData.AddRef();
+ break;
+ }
+ case COM.VT_UNKNOWN : {
+ IUnknown[1] ppvObject;
+ OS.MoveMemory(ppvObject.ptr, (cast(void*)pData) + 8, 4);
+ if (ppvObject[0] is null) {
+ type = COM.VT_EMPTY;
+ break;
+ }
+ unknownData = ppvObject[0];
+ unknownData.AddRef();
+ break;
+ }
+ case COM.VT_BSTR :
+ // get the address of the memory in which the string resides
+ wchar*[1] hMem;
+ OS.MoveMemory(hMem.ptr, (cast(void*)pData) + 8, 4);
+ if (hMem[0] is null) {
+ type = COM.VT_EMPTY;
+ break;
+ }
+ // Get the size of the string from the OS - the size is expressed in number
+ // of bytes - each unicode character is 2 bytes.
+ int size = COM.SysStringByteLen(hMem[0]);
+ if (size > 0){
+ // get the unicode character array from the global memory and create a String
+ wchar[] buffer = new wchar[(size + 1) /2]; // add one to avoid rounding errors
+ COM.MoveMemory(buffer.ptr, hMem[0], size);
+ stringData = WCHARsToStr( buffer );
+ } else {
+ stringData = ""; //$NON-NLS-1$
+ }
+ break;
+
+ default :
+ // try coercing it into one of the known forms
+ auto newPData = cast(VARIANT*) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+ if (COM.VariantChangeType(newPData, pData, 0, COM.VT_R4) is COM.S_OK) {
+ setData(newPData);
+ } else if (COM.VariantChangeType(newPData, pData, 0, COM.VT_I4) is COM.S_OK) {
+ setData(newPData);
+ } else if (COM.VariantChangeType(newPData, pData, 0, COM.VT_BSTR) is COM.S_OK) {
+ setData(newPData);
+ }
+ COM.VariantClear(newPData);
+ OS.GlobalFree(newPData);
+ break;
+ }
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the Variant
+ */
+public String toString () {
+ switch (type) {
+ case COM.VT_BOOL :
+ return "VT_BOOL{"~to!(String)(booleanData)~"}";
+ case COM.VT_I1 :
+ return "VT_I1{"~to!(String)(byteData)~"}";
+ case COM.VT_I2 :
+ return "VT_I2{"~to!(String)(shortData)~"}";
+ case COM.VT_UI2 :
+ return "VT_UI2{"~ dcharToString(charData) ~"}";
+ case COM.VT_I4 :
+ return "VT_I4{"~to!(String)(intData)~"}";
+ case COM.VT_I8 :
+ return "VT_I8{"~to!(String)(longData)~"}";
+ case COM.VT_R4 :
+ return "VT_R4{"~to!(String)(floatData)~"}";
+ case COM.VT_R8 :
+ return "VT_R8{"~to!(String)(doubleData)~"}";
+ case COM.VT_BSTR :
+ return "VT_BSTR{"~stringData~"}";
+ case COM.VT_DISPATCH :
+ return Format("VT_DISPATCH{{0x{:X}}", cast(void*) (dispatchData is null ? null : dispatchData));
+ case COM.VT_UNKNOWN :
+ return Format("VT_UNKNOWN{{0x{:X}}", cast(void*) (unknownData is null ? null : unknownData));
+ case COM.VT_EMPTY :
+ return "VT_EMPTY";
+ case COM.VT_NULL :
+ return "VT_NULL";
+ default:
+ }
+ if ((type & COM.VT_BYREF) !is 0) {
+ return Format("VT_BYREF|{}{{{}}",(type & ~COM.VT_BYREF), byRefPtr );
+ }
+ return "Unsupported Type "~to!(String)(type);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/GLCanvas.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/GLCanvas.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D Programming Language:
+ * John Reimer
+ *******************************************************************************/
+module org.eclipse.swt.opengl.GLCanvas;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.opengl.win32.WGL;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.opengl.GLData;
+
+/**
+ * GLCanvas is a widget capable of displaying OpenGL content.
+ *
+ * @see GLData
+ * @see OpenGL snippets
+ * @see Sample code and further information
+ *
+ * @since 3.2
+ */
+
+public class GLCanvas : Canvas {
+ HGLRC context;
+ int pixelFormat;
+
+/**
+ * Create a GLCanvas widget using the attributes described in the GLData
+ * object provided.
+ *
+ * @param parent a composite widget
+ * @param style the bitwise OR'ing of widget styles
+ * @param data the requested attributes of the GLCanvas
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when the data is null
+ *
- ERROR_UNSUPPORTED_DEPTH when the requested attributes cannot be provided
+ *
+ */
+public this (Composite parent, int style, GLData data) {
+ super (parent, style);
+ if (data is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ PIXELFORMATDESCRIPTOR pfd;
+ pfd.nSize = cast(short) PIXELFORMATDESCRIPTOR.sizeof;
+ pfd.nVersion = 1;
+ pfd.dwFlags = WGL.PFD_DRAW_TO_WINDOW | WGL.PFD_SUPPORT_OPENGL;
+ pfd.dwLayerMask = WGL.PFD_MAIN_PLANE;
+ pfd.iPixelType = cast(byte) WGL.PFD_TYPE_RGBA;
+ if (data.doubleBuffer) pfd.dwFlags |= WGL.PFD_DOUBLEBUFFER;
+ if (data.stereo) pfd.dwFlags |= WGL.PFD_STEREO;
+ pfd.cRedBits = cast(byte) data.redSize;
+ pfd.cGreenBits = cast(byte) data.greenSize;
+ pfd.cBlueBits = cast(byte) data.blueSize;
+ pfd.cAlphaBits = cast(byte) data.alphaSize;
+ pfd.cDepthBits = cast(byte) data.depthSize;
+ pfd.cStencilBits = cast(byte) data.stencilSize;
+ pfd.cAccumRedBits = cast(byte) data.accumRedSize;
+ pfd.cAccumGreenBits = cast(byte) data.accumGreenSize;
+ pfd.cAccumBlueBits = cast(byte) data.accumBlueSize;
+ pfd.cAccumAlphaBits = cast(byte) data.accumAlphaSize;
+ pfd.cAccumBits = cast(byte) (pfd.cAccumRedBits + pfd.cAccumGreenBits + pfd.cAccumBlueBits + pfd.cAccumAlphaBits);
+
+ //FIXME - use wglChoosePixelFormatARB
+// if (data.sampleBuffers > 0) {
+// wglAttrib [pos++] = WGL.WGL_SAMPLE_BUFFERS_ARB;
+// wglAttrib [pos++] = data.sampleBuffers;
+// }
+// if (data.samples > 0) {
+// wglAttrib [pos++] = WGL.WGL_SAMPLES_ARB;
+// wglAttrib [pos++] = data.samples;
+// }
+
+ auto hDC = OS.GetDC (handle);
+ pixelFormat = WGL.ChoosePixelFormat (hDC, &pfd);
+ if (pixelFormat is 0 || !WGL.SetPixelFormat (hDC, pixelFormat, &pfd)) {
+ OS.ReleaseDC (handle, hDC);
+ dispose ();
+ SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
+ }
+ context = WGL.wglCreateContext (hDC);
+ if (context is null) {
+ OS.ReleaseDC (handle, hDC);
+ SWT.error (SWT.ERROR_NO_HANDLES);
+ }
+ OS.ReleaseDC (handle, hDC);
+ //FIXME- share lists
+ //if (share !is null) WGL.wglShareLists (context, share.context);
+
+ Listener listener = new class() Listener {
+ public void handleEvent (Event event) {
+ switch (event.type) {
+ case SWT.Dispose:
+ WGL.wglDeleteContext (context);
+ break;
+ default:
+ }
+ }
+ };
+ addListener (SWT.Dispose, listener);
+}
+
+/**
+ * Returns a GLData object describing the created context.
+ *
+ * @return GLData description of the OpenGL context attributes
+ * @exception SWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public GLData getGLData () {
+ checkWidget ();
+ GLData data = new GLData ();
+ PIXELFORMATDESCRIPTOR pfd;
+ pfd.nSize = cast(short) PIXELFORMATDESCRIPTOR.sizeof;
+ auto hDC = OS.GetDC (handle);
+ WGL.DescribePixelFormat (hDC, pixelFormat, PIXELFORMATDESCRIPTOR.sizeof, &pfd);
+ OS.ReleaseDC (handle, hDC);
+ data.doubleBuffer = (pfd.dwFlags & WGL.PFD_DOUBLEBUFFER) !is 0;
+ data.stereo = (pfd.dwFlags & WGL.PFD_STEREO) !is 0;
+ data.redSize = pfd.cRedBits;
+ data.greenSize = pfd.cGreenBits;
+ data.blueSize = pfd.cBlueBits;
+ data.alphaSize = pfd.cAlphaBits;
+ data.depthSize = pfd.cDepthBits;
+ data.stencilSize = pfd.cStencilBits;
+ data.accumRedSize = pfd.cAccumRedBits;
+ data.accumGreenSize = pfd.cAccumGreenBits;
+ data.accumBlueSize = pfd.cAccumBlueBits;
+ data.accumAlphaSize = pfd.cAccumAlphaBits;
+ return data;
+}
+
+/**
+ * Returns a bool indicating whether the receiver's OpenGL context
+ * is the current context.
+ *
+ * @return true if the receiver holds the current OpenGL context,
+ * 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 bool isCurrent () {
+ checkWidget ();
+ return (WGL.wglGetCurrentContext is context);
+}
+
+/**
+ * Sets the OpenGL context associated with this GLCanvas to be the
+ * current GL context.
+ *
+ * @exception SWTException
+ * - 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 setCurrent () {
+ checkWidget ();
+ if (WGL.wglGetCurrentContext is context) return;
+ auto hDC = OS.GetDC (handle);
+ WGL.wglMakeCurrent (hDC, context);
+ OS.ReleaseDC (handle, hDC);
+}
+
+/**
+ * Swaps the front and back color buffers.
+ *
+ * @exception SWTException
+ * - 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 swapBuffers () {
+ checkWidget ();
+ auto hDC = OS.GetDC (handle);
+ WGL.SwapBuffers (hDC);
+ OS.ReleaseDC (handle, hDC);
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/GLData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/GLData.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 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
+ * Port to the D Programming Language:
+ * John Reimer
+ *******************************************************************************/
+module org.eclipse.swt.opengl.GLData;
+
+import tango.text.Util;
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ * The GLData class is a device-independent description
+ * of the pixel format attributes of a GL drawable.
+ *
+ * @see GLCanvas
+ * @see OpenGL snippets
+ * @see Sample code and further information
+ *
+ * @since 3.2
+ */
+
+public class GLData {
+ /**
+ * Specifies a double-buffered surface. During context
+ * creation, only double-buffered formats are considered
+ * when set to true.
+ */
+ public bool doubleBuffer;
+
+ /**
+ * Specifies a stereo surface. During context creation,
+ * only stereo formats are considered when set to true.
+ */
+ public bool 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;
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the data
+ */
+override public String toString() {
+ String string = doubleBuffer ? "doubleBuffer," : "";
+ string ~= stereo ? "stereo," : "";
+ string ~= "r:" ~ to!(String)(redSize) ~ " g:" ~ to!(String)(greenSize) ~
+ " b:" ~ to!(String)(blueSize) ~ " a:" ~ to!(String)(alphaSize) ~ "," ~
+ "depth:" ~ to!(String)(depthSize) ~ ",stencil:" ~ to!(String)(stencilSize) ~
+ ",accum r:" ~ to!(String)(accumRedSize) ~ "g:" ~ to!(String)(accumGreenSize) ~
+ "b:" ~ to!(String)(accumBlueSize) ~ "a:" ~ to!(String)(accumAlphaSize) ~
+ ",sampleBuffers:" ~ to!(String)(sampleBuffers) ~ ",samples:" ~ to!(String)(samples);
+ return string;
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/all.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/all.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,6 @@
+module org.eclipse.swt.opengl.all;
+
+public import org.eclipse.swt.opengl.GLCanvas;
+public import org.eclipse.swt.opengl.GLData;
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/PrintDialog.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/PrintDialog.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,380 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.printing.PrintDialog;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.printing.Printer;
+import org.eclipse.swt.printing.PrinterData;
+
+import java.lang.all;
+
+/**
+ * Instances of this class allow the user to select
+ * a printer and various print-related parameters
+ * prior to starting a print job.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ *
+ * @see Printing snippets
+ * @see SWT Example: ControlExample, Dialog tab
+ * @see Sample code and further information
+ */
+
+public class PrintDialog : Dialog {
+ PrinterData printerData;
+ int scope_ = PrinterData.ALL_PAGES;
+ int startPage = 1, endPage = 1;
+ bool 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 this (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 this (Shell parent, int style) {
+ super (parent, style);
+ checkSubclass ();
+}
+
+/**
+ * Sets the printer data that will be used when the dialog
+ * is opened.
+ *
+ * @param data the data that will be used when the dialog is opened
+ *
+ * @since 3.4
+ */
+public void setPrinterData(PrinterData data) {
+ this.printerData = data;
+}
+
+/**
+ * Returns the printer data that will be used when the dialog
+ * is opened.
+ *
+ * @return the data that will be used when the dialog is opened
+ *
+ * @since 3.4
+ */
+public PrinterData getPrinterData() {
+ return printerData;
+}
+
+/**
+ * Returns the print job scope that the user selected
+ * before pressing OK in the dialog. This will be one
+ * of the following values:
+ *
+ * PrinterData.ALL_PAGES
+ * - Print all pages in the current document
+ * PrinterData.PAGE_RANGE
+ * - Print the range of pages specified by startPage and endPage
+ * PrinterData.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:
+ *
+ * PrinterData.ALL_PAGES
+ * - Print all pages in the current document
+ * PrinterData.PAGE_RANGE
+ * - Print the range of pages specified by startPage and endPage
+ * PrinterData.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.
+ *
+ * This value can be from 1 to the maximum number of pages for the platform.
+ * Note that it is only valid if the scope is PrinterData.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.
+ *
+ * This value can be from 1 to the maximum number of pages for the platform.
+ * Note that it is only valid if the scope is PrinterData.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.
+ *
+ * This value can be from 1 to the maximum number of pages for the platform.
+ * Note that it is only valid if the scope is PrinterData.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.
+ *
+ * This value can be from 1 to the maximum number of pages for the platform.
+ * Note that it is only valid if the scope is PrinterData.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 bool 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(bool printToFile) {
+ this.printToFile = printToFile;
+}
+
+protected void checkSubclass() {
+ String name = this.classinfo.name;
+ String validName = PrintDialog.classinfo.name;
+ if (validName!=/*eq*/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() {
+ PRINTDLG pd;
+ pd.lStructSize = PRINTDLG.sizeof;
+ Control parent = getParent();
+ if (parent !is null) pd.hwndOwner = parent.handle;
+ void* lpInitData;
+ auto hHeap = OS.GetProcessHeap();
+ if (printerData !is null) {
+ byte buffer [] = printerData.otherData;
+ if (buffer !is null && buffer.length !is 0) {
+ /* If user setup info from a previous print dialog was specified, restore the DEVMODE struct. */
+ lpInitData = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, buffer.length);
+ OS.MoveMemory(lpInitData, buffer.ptr, buffer.length);
+ pd.hDevMode = lpInitData;
+ }
+ }
+ 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 = cast(ushort)-1;
+ pd.nFromPage = cast(short) Math.min (0xFFFF, Math.max (1, startPage));
+ pd.nToPage = cast(short) Math.min (0xFFFF, Math.max (1, endPage));
+
+ Display display = parent.getDisplay();
+ Shell [] shells = display.getShells();
+ if ((getStyle() & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+ for (int i=0; i
+ *******************************************************************************/
+module org.eclipse.swt.printing.Printer;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.DeviceData;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.printing.PrinterData;
+
+import java.lang.all;
+
+/**
+ * Instances of this class are used to print to a printer.
+ * Applications create a GC on a printer using new 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
+ * @see Printing snippets
+ * @see Sample code and further information
+ */
+public final class Printer : 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 HANDLE handle;
+
+ /**
+ * the printer data describing this printer
+ */
+ PrinterData data;
+
+ /**
+ * whether or not a GC was created for this printer
+ */
+ bool isGCCreated = false;
+
+ /**
+ * strings used to access the Windows registry
+ */
+ static TCHAR[] profile;
+ static TCHAR[] appName;
+ static TCHAR[] keyName;
+ static this() {
+ profile = StrToTCHARs(0, "PrinterPorts", true); //$NON-NLS-1$
+ appName = StrToTCHARs(0, "windows", true); //$NON-NLS-1$
+ keyName = StrToTCHARs(0, "device", true); //$NON-NLS-1$
+ }
+
+/**
+ * Returns an array of PrinterData
objects
+ * representing all available printers.
+ *
+ * @return the list of available printers
+ */
+public static PrinterData[] getPrinterList() {
+ int length = 1024;
+ /* Use the character encoding for the default locale */
+ String buf = new String(length);
+ int n = OS.GetProfileString( TCHARsToStr(profile), null, null, buf, length);
+ if (n is 0) return null;
+ String[] deviceNames = new String[](5);
+ int nameCount = 0;
+ int index = 0;
+ for (int i = 0; i < n; i++) {
+ if (buf[i] is 0) {
+ if (nameCount is deviceNames.length) {
+ String[] newNames = new String[](deviceNames.length + 5);
+ System.arraycopy(deviceNames, 0, newNames, 0, deviceNames.length);
+ deviceNames = newNames;
+ }
+ deviceNames[nameCount] = buf[index .. i ].dup;
+ nameCount++;
+ index = i + 1;
+ }
+ }
+ PrinterData printerList[] = new PrinterData[nameCount];
+ for (int p = 0; p < nameCount; p++) {
+ String device = deviceNames[p];
+ String driver = ""; //$NON-NLS-1$
+ if (OS.GetProfileString(TCHARsToStr(profile), device, null, buf, length) > 0) {
+ int commaIndex = 0;
+ while (buf[commaIndex] !is ',' && commaIndex < length) commaIndex++;
+ if (commaIndex < length) {
+ driver = buf[0 .. commaIndex].dup;
+ }
+ }
+ printerList[p] = new PrinterData(driver, device);
+ }
+ return printerList;
+}
+
+/**
+ * Returns a PrinterData
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() {
+ String deviceName = null;
+ int length = 1024;
+ /* Use the character encoding for the default locale */
+ String buf = new String(length);
+ int n = OS.GetProfileString(TCHARsToStr(appName), TCHARsToStr(keyName), null, buf, length);
+ if (n is 0) return null;
+ int commaIndex = 0;
+ while(buf[commaIndex] !is ',' && commaIndex < length) commaIndex++;
+ if (commaIndex < length) {
+ deviceName = buf[0 .. commaIndex].dup;
+ }
+ String driver = ""; //$NON-NLS-1$
+ if (OS.GetProfileString(TCHARsToStr(profile), deviceName, null, buf, length) > 0) {
+ commaIndex = 0;
+ while (buf[commaIndex] !is ',' && commaIndex < length) commaIndex++;
+ if (commaIndex < length) {
+ driver = buf[0 .. commaIndex].dup;
+ }
+ }
+ return new PrinterData(driver, deviceName);
+}
+
+static DeviceData checkNull (PrinterData data) {
+ if (data is null) data = new PrinterData();
+ if (data.driver is null || data.name is null) {
+ PrinterData defaultPrinter = getDefaultPrinterData();
+ if (defaultPrinter is 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 this() {
+ 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 this(PrinterData data) {
+ super(checkNull(data));
+}
+
+/**
+ * Creates the printer handle.
+ * This method is called internally by the instance creation
+ * mechanism of the Device
class.
+ * @param deviceData the device data
+ */
+protected void create(DeviceData deviceData) {
+ data = cast(PrinterData)deviceData;
+ /* Use the character encoding for the default locale */
+ TCHAR[] driver = StrToTCHARs(0, data.driver, true);
+ TCHAR[] device = StrToTCHARs(0, data.name, true);
+ DEVMODE* lpInitData;
+ byte buffer [] = data.otherData;
+ auto hHeap = OS.GetProcessHeap();
+ if (buffer !is null && buffer.length !is 0) {
+ /* If user setup info from a print dialog was specified, restore the DEVMODE struct. */
+ lpInitData = cast(DEVMODE*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, buffer.length);
+ OS.MoveMemory(lpInitData, buffer.ptr, buffer.length);
+ }
+ handle = OS.CreateDC(driver.ptr, device.ptr, null, lpInitData);
+ if (lpInitData !is null) OS.HeapFree(hHeap, 0, lpInitData);
+ if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * 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
+ */
+public HDC internal_new_GC(GCData data) {
+ if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+ if (data !is null) {
+ if (isGCCreated) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ if ((data.style & mask) !is 0) {
+ data.layout = (data.style & SWT.RIGHT_TO_LEFT) !is 0 ? OS.LAYOUT_RTL : 0;
+ } else {
+ data.style |= SWT.LEFT_TO_RIGHT;
+ }
+ data.device = this;
+ data.font = Font.win32_new(this, 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
+ */
+public void internal_dispose_GC(HDC hDC, GCData data) {
+ if (data !is null) isGCCreated = false;
+}
+
+/**
+ * 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 bool startJob(String jobName) {
+ checkDevice();
+ DOCINFO di;
+ di.cbSize = DOCINFO.sizeof;
+ auto hHeap = OS.GetProcessHeap();
+ TCHAR* lpszDocName;
+ if (jobName !is null && jobName.length !is 0) {
+ /* Use the character encoding for the default locale */
+ TCHAR[] buffer = StrToTCHARs(0, jobName, true);
+ int byteCount = buffer.length * TCHAR.sizeof;
+ lpszDocName = cast(TCHAR*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+ OS.MoveMemory(lpszDocName, buffer.ptr, byteCount);
+ di.lpszDocName = lpszDocName;
+ }
+ TCHAR* lpszOutput;
+ if (data.printToFile && data.fileName !is null) {
+ /* Use the character encoding for the default locale */
+ TCHAR[] buffer = StrToTCHARs(0, data.fileName, true);
+ int byteCount = buffer.length * TCHAR.sizeof;
+ lpszOutput = cast(TCHAR*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+ OS.MoveMemory(lpszOutput, buffer.ptr, byteCount);
+ di.lpszOutput = lpszOutput;
+ }
+ int rc = OS.StartDoc(handle, &di);
+ if (lpszDocName !is null) OS.HeapFree(hHeap, 0, lpszDocName);
+ if (lpszOutput !is null) 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();
+ OS.EndDoc(handle);
+}
+
+/**
+ * Cancels a print job in progress.
+ *
+ * @exception SWTException
+ * - ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void cancelJob() {
+ checkDevice();
+ 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 bool startPage() {
+ checkDevice();
+ int rc = OS.StartPage(handle);
+ if (rc <= 0) OS.AbortDoc(handle);
+ return rc > 0;
+}
+
+/**
+ * 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();
+ OS.EndPage(handle);
+}
+
+/**
+ * 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
+ *
+ */
+public Point getDPI() {
+ checkDevice();
+ 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 the physical page, in pixels.
+ *
+ *
+ * @return the bounding rectangle
+ *
+ * @exception SWTException
+ * - ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getClientArea
+ * @see #computeTrim
+ */
+public Rectangle getBounds() {
+ checkDevice();
+ int width = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH);
+ int height = OS.GetDeviceCaps(handle, OS.PHYSICALHEIGHT);
+ return new Rectangle(0, 0, width, height);
+}
+
+/**
+ * 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 the page, in pixels.
+ *
+ *
+ * @return the client area
+ *
+ * @exception SWTException
+ * - ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getBounds
+ * @see #computeTrim
+ */
+public Rectangle getClientArea() {
+ checkDevice();
+ int width = OS.GetDeviceCaps(handle, OS.HORZRES);
+ int height = OS.GetDeviceCaps(handle, OS.VERTRES);
+ return new Rectangle(0, 0, width, height);
+}
+
+/**
+ * Given a client area (as described by the arguments),
+ * returns a rectangle, relative to the client area's coordinates,
+ * that is the client area expanded by the printer's trim (or minimum margins).
+ *
+ * Most printers have a minimum margin on each edge of the paper where the
+ * printer device is unable to print. This margin is known as the "trim."
+ * This method can be used to calculate the printer's minimum margins
+ * by passing in a client area of 0, 0, 0, 0 and then using the resulting
+ * x and y coordinates (which will be <= 0) to determine the minimum margins
+ * for the top and left edges of the paper, and the resulting width and height
+ * (offset by the resulting x and y) to determine the minimum margins for the
+ * bottom and right edges of the paper, as follows:
+ *
+ * - The left trim width is -x pixels
+ * - The top trim height is -y pixels
+ * - The right trim width is (x + width) pixels
+ * - The bottom trim height is (y + height) pixels
+ *
+ *
+ *
+ * @param x the x coordinate of the client area
+ * @param y the y coordinate of the client area
+ * @param width the width of the client area
+ * @param height the height of the client area
+ * @return a rectangle, relative to the client area's coordinates, that is
+ * the client area expanded by the printer's trim (or minimum margins)
+ *
+ * @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();
+ int printX = -OS.GetDeviceCaps(handle, OS.PHYSICALOFFSETX);
+ int printY = -OS.GetDeviceCaps(handle, OS.PHYSICALOFFSETY);
+ int printWidth = OS.GetDeviceCaps(handle, OS.HORZRES);
+ int printHeight = OS.GetDeviceCaps(handle, OS.VERTRES);
+ int paperWidth = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH);
+ int paperHeight = OS.GetDeviceCaps(handle, OS.PHYSICALHEIGHT);
+ int hTrim = paperWidth - printWidth;
+ int vTrim = paperHeight - printHeight;
+ return new Rectangle(x + printX, y + printY, width + hTrim, height + vTrim);
+}
+
+/**
+ * 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
+ *
+ */
+protected void checkDevice() {
+ if (handle is 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.
+ */
+protected void release() {
+ super.release();
+ data = null;
+}
+
+/**
+ * Destroys the printer handle.
+ * This method is called internally by the dispose
+ * mechanism of the Device
class.
+ */
+protected void destroy() {
+ if (handle !is null) OS.DeleteDC(handle);
+ handle = null;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/PrinterData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/PrinterData.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.printing.PrinterData;
+
+
+import org.eclipse.swt.graphics.DeviceData;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * 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
+ * @see Printing snippets
+ * @see Sample code and further information
+ */
+
+public final class PrinterData : DeviceData {
+
+ /**
+ * the printer driver
+ * On Windows systems, this is the name of the driver (often "winspool").
+ * On Mac OSX, this is the destination type ("Printer", "Fax", "File", or "Preview").
+ * On X/Window systems, this is the name of a display connection to the
+ * Xprt server (the default is ":1").
+ * On GTK+, this is the backend type name (eg. GtkPrintBackendCups).
+ */
+ // TODO: note that this api is not finalized for GTK+
+ public String driver;
+
+ /**
+ * the name of the printer
+ * On Windows systems, this is the name of the 'device'.
+ * On Mac OSX, X/Window systems, and GTK+, 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.
+ * This value can be from 1 to the maximum number of pages for the platform.
+ */
+ public int startPage = 0;
+
+ /**
+ * the end page of a page range, used when scope is PAGE_RANGE.
+ * This value can be from 1 to the maximum number of pages for the platform.
+ */
+ public int endPage = 0;
+
+ /**
+ * whether or not the print job should go to a file
+ */
+ public bool 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 bool collate = false;
+
+ /**
+ * scope
field value indicating that
+ * all pages should be printed
+ */
+ public static const int ALL_PAGES = 0;
+
+ /**
+ * scope
field value indicating that
+ * the range of pages specified by startPage and endPage
+ * should be printed
+ */
+ public static const int PAGE_RANGE = 1;
+
+ /**
+ * scope
field value indicating that
+ * the current selection should be printed
+ */
+ public static const int SELECTION = 2;
+
+ /**
+ * private, platform-specific data
+ * On Windows, this contains a copy of the DEVMODE struct
+ * returned from the PrintDialog
.
+ * On GTK, this contains a copy of the print_settings and page_setup
+ * returned from the PrintDialog
.
+ * On OS X Carbon, this contains a copy of the PrintSettings and PageFormat
+ * returned from the PrintDialog
.
+ * This field is not currently used on the X/Window System.
+ */
+ byte [] otherData;
+
+ /**
+ * Constructs an instance of this class that can be
+ * used to print to the default printer.
+ *
+ * @see Printer#getDefaultPrinterData
+ */
+ public this() {
+ }
+
+ /**
+ * 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 this(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 Format("PrinterData {{driver = {}, name = {}}", driver, name ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/all.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/all.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,7 @@
+module org.eclipse.swt.printing.all;
+
+public import org.eclipse.swt.printing.PrintDialog;
+public import org.eclipse.swt.printing.Printer;
+public import org.eclipse.swt.printing.PrinterData;
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/Program.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/Program.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,435 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D Programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.program.Program;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.internal.win32.OS;
+
+import java.lang.all;
+static import tango.text.convert.Utf;
+
+/**
+ * Instances of this class represent programs and
+ * their associated file extensions in the operating
+ * system.
+ *
+ * @see Program snippets
+ * @see Sample code and further information
+ */
+public final class Program {
+ String name;
+ String command;
+ String iconName;
+ String extension;
+ static const String[] ARGUMENTS = ["%1"[], "%l", "%L"]; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+static String assocQueryString (int assocStr, TCHAR[] key, bool expand) {
+ TCHAR[] pszOut = NewTCHARs(0, 1024);
+ uint[1] pcchOut;
+ pcchOut[0] = pszOut.length;
+ int flags = OS.ASSOCF_NOTRUNCATE | OS.ASSOCF_INIT_IGNOREUNKNOWN;
+ int result = OS.AssocQueryString (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr);
+ if (result is OS.E_POINTER) {
+ pszOut = NewTCHARs(0, pcchOut [0]);
+ result = OS.AssocQueryString (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr);
+ }
+ if (result is 0) {
+ if (!OS.IsWinCE && expand) {
+ int length_ = OS.ExpandEnvironmentStrings (pszOut.ptr, null, 0);
+ if (length_ !is 0) {
+ TCHAR[] lpDst = NewTCHARs (0, length_);
+ OS.ExpandEnvironmentStrings (pszOut.ptr, lpDst.ptr, length_);
+ return tango.text.convert.Utf.toString( lpDst[ 0 .. Math.max (0, length_ - 1) ] );
+ } else {
+ return "";
+ }
+ } else {
+ return tango.text.convert.Utf.toString( pszOut[ 0 .. Math.max (0, pcchOut [0] - 1)]);
+ }
+ }
+ return null;
+}
+
+/**
+ * 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
+ *
+ */
+public static Program findProgram (String extension) {
+ // SWT extension: allow null string
+ //if (extension is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (extension.length is 0) return null;
+ if (extension.charAt (0) !is '.') extension = "." ~ extension; //$NON-NLS-1$
+ /* Use the character encoding for the default locale */
+ TCHAR[] key = StrToTCHARs (0, extension, true);
+ Program program = null;
+ if (OS.IsWinCE) {
+ void*[1] phkResult;
+ if (OS.RegOpenKeyEx ( cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) {
+ return null;
+ }
+ uint [1] lpcbData;
+ int result = OS.RegQueryValueEx (phkResult [0], null, null, null, null, lpcbData.ptr);
+ if (result is 0) {
+ TCHAR[] lpData = NewTCHARs (0, lpcbData [0] / TCHAR.sizeof);
+ result = OS.RegQueryValueEx (phkResult [0], null, null, null, cast(ubyte*)lpData.ptr, lpcbData.ptr);
+ if (result is 0) program = getProgram ( TCHARzToStr( lpData.ptr ), extension);
+ }
+ OS.RegCloseKey (phkResult [0]);
+ } else {
+ String command = assocQueryString (OS.ASSOCSTR_COMMAND, key, true);
+ if (command !is null) {
+ String name = null;
+ if (name is null) name = assocQueryString (OS.ASSOCSTR_FRIENDLYDOCNAME, key, false);
+ if (name is null) name = assocQueryString (OS.ASSOCSTR_FRIENDLYAPPNAME, key, false);
+ if (name is null) name = "";
+ String iconName = assocQueryString (OS.ASSOCSTR_DEFAULTICON, key, true);
+ if (iconName is null) iconName = "";
+ program = new Program ();
+ program.name = name;
+ program.command = command;
+ program.iconName = iconName;
+ program.extension = extension;
+ }
+ }
+ return program;
+}
+
+/**
+ * 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 () {
+ String [] extensions = new String [1024];
+ /* Use the character encoding for the default locale */
+ TCHAR[] lpName = NewTCHARs (0, 1024);
+ uint [1] lpcName; lpcName[0] = lpName.length;
+ FILETIME ft;
+ int dwIndex = 0, count = 0;
+ while (OS.RegEnumKeyEx ( cast(void*)OS.HKEY_CLASSES_ROOT, dwIndex, lpName.ptr, lpcName.ptr, null, null, null, &ft) !is OS.ERROR_NO_MORE_ITEMS) {
+ String extension = TCHARsToStr( lpName[0 .. lpcName[0] ]);
+ lpcName [0] = lpName.length;
+ if (extension.length > 0 && extension.charAt (0) is '.') {
+ if (count is extensions.length) {
+ String[] newExtensions = new String[]( extensions.length + 1024 );
+ System.arraycopy (extensions, 0, newExtensions, 0, extensions.length);
+ extensions = newExtensions;
+ }
+ extensions [count++] = extension;
+ }
+ dwIndex++;
+ }
+ if (count !is extensions.length) {
+ String[] newExtension = new String[]( count );
+ System.arraycopy (extensions, 0, newExtension, 0, count);
+ extensions = newExtension;
+ }
+ return extensions;
+}
+
+static String getKeyValue (String string, bool expand) {
+ /* Use the character encoding for the default locale */
+ TCHAR[] key = StrToTCHARs (0, string, true);
+ void* [1] phkResult;
+ if (OS.RegOpenKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) {
+ return null;
+ }
+ String result = null;
+ uint [1] lpcbData;
+ if (OS.RegQueryValueEx (phkResult [0], null, null, null, null, lpcbData.ptr) is 0) {
+ result = "";
+ int length_ = lpcbData [0] / TCHAR.sizeof;
+ if (length_ !is 0) {
+ /* Use the character encoding for the default locale */
+ TCHAR[] lpData = NewTCHARs (0, length_);
+ if (OS.RegQueryValueEx (phkResult [0], null, null, null, cast(ubyte*)lpData.ptr, lpcbData.ptr) is 0) {
+ if (!OS.IsWinCE && expand) {
+ length_ = OS.ExpandEnvironmentStrings (lpData.ptr, null, 0);
+ if (length_ !is 0) {
+ TCHAR[] lpDst = NewTCHARs (0, length_);
+ OS.ExpandEnvironmentStrings (lpData.ptr, lpDst.ptr, length_);
+ result = tango.text.convert.Utf.toString ( lpDst[0 .. Math.max (0, length_ - 1) ] );
+ }
+ } else {
+ length_ = Math.max (0, lpData.length - 1);
+ result = tango.text.convert.Utf.toString ( lpData[0 .. length_]);
+ }
+ }
+ }
+ }
+ if (phkResult [0] !is null) OS.RegCloseKey (phkResult [0]);
+ return result;
+}
+
+static Program getProgram (String key, String extension) {
+
+ /* Name */
+ String name = getKeyValue (key, false);
+ if (name is null || name.length is 0) {
+ name = key;
+ }
+
+ /* Command */
+ String DEFAULT_COMMAND = "\\shell"; //$NON-NLS-1$
+ String defaultCommand = getKeyValue (key ~ DEFAULT_COMMAND, true);
+ if (defaultCommand is null || defaultCommand.length is 0) defaultCommand = "open"; //$NON-NLS-1$
+ String COMMAND = "\\shell\\" ~ defaultCommand ~ "\\command"; //$NON-NLS-1$
+ String command = getKeyValue (key ~ COMMAND, true);
+ if (command is null || command.length is 0) return null;
+
+ /* Icon */
+ String DEFAULT_ICON = "\\DefaultIcon"; //$NON-NLS-1$
+ String iconName = getKeyValue (key ~ DEFAULT_ICON, true);
+ if (iconName is null) iconName = ""; //$NON-NLS-1$
+
+ /* Program */
+ Program program = new Program ();
+ program.name = name;
+ program.command = command;
+ program.iconName = iconName;
+ program.extension = extension;
+ return program;
+}
+
+/**
+ * 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 () {
+ Program [] programs = new Program [1024];
+ /* Use the character encoding for the default locale */
+ TCHAR[] lpName = NewTCHARs (0, 1024);
+ uint [1] lpcName; lpcName[0] = lpName.length;
+ FILETIME ft;
+ int dwIndex = 0, count = 0;
+ while (OS.RegEnumKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, dwIndex, lpName.ptr, lpcName.ptr, null, null, null, &ft) !is OS.ERROR_NO_MORE_ITEMS) {
+ String path = tango.text.convert.Utf.toString ( lpName[0 .. lpcName [0]]);
+ lpcName [0] = lpName.length ;
+ Program program = getProgram (path, null);
+ if (program !is null) {
+ if (count is programs.length) {
+ Program [] newPrograms = new Program [programs.length + 1024];
+ System.arraycopy (programs, 0, newPrograms, 0, programs.length);
+ programs = newPrograms;
+ }
+ programs [count++] = program;
+ }
+ dwIndex++;
+ }
+ if (count !is programs.length) {
+ Program [] newPrograms = new Program [count];
+ System.arraycopy (programs, 0, newPrograms, 0, count);
+ programs = newPrograms;
+ }
+ return programs;
+}
+
+/**
+ * Launches the operating system executable associated with the file or
+ * URL (http:// or https://). 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 or URL (http:// or https://)
+ * @return true
if the file is launched, otherwise false
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT when fileName is null
+ *
+ */
+public static bool launch (String fileName) {
+ if (fileName is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+
+ /* Use the character encoding for the default locale */
+ auto hHeap = OS.GetProcessHeap ();
+ TCHAR[] buffer = StrToTCHARs (0, fileName, true);
+ int byteCount = buffer.length * TCHAR.sizeof;
+ auto lpFile = cast(wchar*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+ OS.MoveMemory (lpFile, buffer.ptr, byteCount);
+ SHELLEXECUTEINFO info;
+ info.cbSize = SHELLEXECUTEINFO.sizeof;
+ info.lpFile = lpFile;
+ info.nShow = OS.SW_SHOW;
+ bool result = cast(bool) OS.ShellExecuteEx (&info);
+ if (lpFile !is null) OS.HeapFree (hHeap, 0, lpFile);
+ return result;
+}
+
+/**
+ * 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 bool execute (String fileName) {
+ if (fileName is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ int index = 0;
+ bool append = true;
+ String prefix = command, suffix = ""; //$NON-NLS-1$
+ while (index < ARGUMENTS.length) {
+ int i = command.indexOf (ARGUMENTS [index]);
+ if (i !is -1) {
+ append = false;
+ prefix = command.substring (0, i);
+ suffix = command.substring (i + ARGUMENTS [index].length , command.length );
+ break;
+ }
+ index++;
+ }
+ if (append) fileName = " \"" ~ fileName ~ "\"";
+ String commandLine = prefix ~ fileName ~ suffix;
+ auto hHeap = OS.GetProcessHeap ();
+ /* Use the character encoding for the default locale */
+ TCHAR[] buffer = StrToTCHARs (0, commandLine, true);
+ int byteCount = buffer.length * TCHAR.sizeof;
+ auto lpCommandLine = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+ OS.MoveMemory (lpCommandLine, buffer.ptr, byteCount);
+ STARTUPINFO lpStartupInfo;
+ lpStartupInfo.cb = STARTUPINFO.sizeof;
+ PROCESS_INFORMATION lpProcessInformation;
+ bool success = cast(bool) OS.CreateProcess (null, lpCommandLine, null, null, false, 0, null, null, &lpStartupInfo, &lpProcessInformation);
+ if (lpCommandLine !is null) OS.HeapFree (hHeap, 0, lpCommandLine);
+ if (lpProcessInformation.hProcess !is null) OS.CloseHandle (lpProcessInformation.hProcess);
+ if (lpProcessInformation.hThread !is null) OS.CloseHandle (lpProcessInformation.hThread);
+ return success;
+}
+
+/**
+ * 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 () {
+ if (extension !is null) {
+ SHFILEINFOW shfi;
+ int flags = OS.SHGFI_ICON | OS.SHGFI_SMALLICON | OS.SHGFI_USEFILEATTRIBUTES;
+ TCHAR[] pszPath = StrToTCHARs (0, extension, true);
+ OS.SHGetFileInfo (pszPath.ptr, OS.FILE_ATTRIBUTE_NORMAL, &shfi, SHFILEINFO.sizeof, flags);
+ if (shfi.hIcon !is null) {
+ Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon);
+ ImageData imageData = image.getImageData ();
+ image.dispose ();
+ return imageData;
+ }
+ }
+ int nIconIndex = 0;
+ String fileName = iconName;
+ int index = iconName.indexOf (',');
+ if (index !is -1) {
+ fileName = iconName.substring (0, index);
+ String iconIndex = iconName.substring (index + 1, iconName.length ).trim ();
+ try {
+ nIconIndex = Integer.parseInt (iconIndex);
+ } catch (NumberFormatException e) {}
+ }
+ int length = fileName.length;
+ if (length !is 0 && fileName.charAt (0) is '\"') {
+ if (fileName.charAt (length - 1) is '\"') {
+ fileName = fileName.substring (1, length - 1);
+ }
+ }
+ /* Use the character encoding for the default locale */
+ TCHAR[] lpszFile = StrToTCHARs (0, fileName, true);
+ HICON [1] phiconSmall, phiconLarge;
+ OS.ExtractIconEx (lpszFile.ptr, nIconIndex, phiconLarge.ptr, phiconSmall.ptr, 1);
+ if (phiconSmall [0] is null) 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 override int opEquals(Object other) {
+ if (this is other) return true;
+ if ( auto program = cast(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 override hash_t toHash() {
+ return .toHash(name) ^ .toHash(command) ^ .toHash(iconName);
+}
+
+/**
+ * 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 -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/all.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/all.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,5 @@
+module org.eclipse.swt.program.all;
+
+public import org.eclipse.swt.program.Program;
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/std.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/std.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,13 @@
+module org.eclipse.swt.std;
+
+public import org.eclipse.swt.SWT;
+public import org.eclipse.swt.SWTError;
+public import org.eclipse.swt.SWTException;
+public import java.lang.all;
+
+public import org.eclipse.swt.events.all;
+public import org.eclipse.swt.graphics.all;
+public import org.eclipse.swt.layout.all;
+public import org.eclipse.swt.widgets.all;
+
+
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Button.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Button.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1409 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Button;
+
+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.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TypedListener;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a selectable user interface object that
+ * issues notification when pressed and released.
+ *
+ * - 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.
+ *
+ *
+ * @see Button snippets
+ * @see SWT Example: ControlExample
+ * @see Sample code and further information
+ */
+
+public class Button : Control {
+
+ alias Control.computeSize computeSize;
+ alias Control.windowProc windowProc;
+
+ alias extern(Windows) int function( HWND, uint, uint, int ) TWindowProc;
+ String text = "", message = "";
+ Image image, image2, disabledImage;
+ ImageList imageList;
+ bool ignoreMouse, grayed;
+ static const int MARGIN = 4;
+ private static /+const+/ int CHECK_WIDTH, CHECK_HEIGHT;
+ static const int ICON_WIDTH = 128, ICON_HEIGHT = 128;
+ static const bool COMMAND_LINK = false;
+ private static /+const+/ TWindowProc ButtonProc;
+ static const TCHAR[] ButtonClass = "BUTTON\0";
+
+ private static bool static_this_completed = false;
+ private static void static_this() {
+ if( static_this_completed ){
+ return;
+ }
+ synchronized {
+ if( static_this_completed ){
+ return;
+ }
+ auto hBitmap = OS.LoadBitmap (null, OS.OBM_CHECKBOXES);
+ if (hBitmap is null) {
+ CHECK_WIDTH = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CXSMICON : OS.SM_CXVSCROLL);
+ CHECK_HEIGHT = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CYSMICON : OS.SM_CYVSCROLL);
+ } else {
+ BITMAP bitmap;
+ OS.GetObject (hBitmap, BITMAP.sizeof, &bitmap);
+ OS.DeleteObject (hBitmap);
+ CHECK_WIDTH = bitmap.bmWidth / 4;
+ CHECK_HEIGHT = bitmap.bmHeight / 3;
+ }
+ WNDCLASS lpWndClass;
+ OS.GetClassInfo (null, ButtonClass.ptr, &lpWndClass);
+ ButtonProc = lpWndClass.lpfnWndProc;
+ static_this_completed = true;
+ }
+ }
+
+/**
+ * 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 this (Composite parent, int style) {
+ static_this();
+ super (parent, checkStyle (style));
+}
+
+void _setImage (Image image) {
+ if ((style & SWT.COMMAND) !is 0) return;
+ if (OS.COMCTL32_MAJOR >= 6) {
+ if (imageList !is null) imageList.dispose ();
+ imageList = null;
+ if (image !is null) {
+ imageList = new ImageList (style & SWT.RIGHT_TO_LEFT);
+ if (OS.IsWindowEnabled (handle)) {
+ imageList.add (image);
+ } else {
+ if (disabledImage !is null) disabledImage.dispose ();
+ disabledImage = new Image (display, image, SWT.IMAGE_DISABLE);
+ imageList.add (disabledImage);
+ }
+ BUTTON_IMAGELIST buttonImageList;
+ buttonImageList.himl = imageList.getHandle ();
+ int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+ newBits &= ~(OS.BS_LEFT | OS.BS_CENTER | OS.BS_RIGHT);
+ if ((style & SWT.LEFT) !is 0) newBits |= OS.BS_LEFT;
+ if ((style & SWT.CENTER) !is 0) newBits |= OS.BS_CENTER;
+ if ((style & SWT.RIGHT) !is 0) newBits |= OS.BS_RIGHT;
+ if (text.length is 0) {
+ if ((style & SWT.LEFT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+ if ((style & SWT.CENTER) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+ if ((style & SWT.RIGHT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_RIGHT;
+ } else {
+ buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+ buttonImageList.margin.left = computeLeftMargin ();
+ buttonImageList.margin.right = MARGIN;
+ newBits &= ~(OS.BS_CENTER | OS.BS_RIGHT);
+ newBits |= OS.BS_LEFT;
+ }
+ if (newBits !is oldBits) {
+ OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+ OS.InvalidateRect (handle, null, true);
+ }
+ OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+ } else {
+ OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, 0);
+ }
+ /*
+ * Bug in Windows. Under certain cirumstances yet to be
+ * isolated, BCM_SETIMAGELIST does not redraw the control
+ * when a new image is set. The fix is to force a redraw.
+ */
+ OS.InvalidateRect (handle, null, true);
+ } else {
+ if (image2 !is null) image2.dispose ();
+ image2 = null;
+ HBITMAP hImage;
+ int imageBits = 0, fImageType = 0;
+ if (image !is null) {
+ switch (image.type) {
+ case SWT.BITMAP: {
+ Rectangle rect = image.getBounds ();
+ ImageData data = image.getImageData ();
+ switch (data.getTransparencyType ()) {
+ case SWT.TRANSPARENCY_PIXEL:
+ if (rect.width <= ICON_WIDTH && rect.height <= ICON_HEIGHT) {
+ image2 = new Image (display, data, data.getTransparencyMask ());
+ hImage = image2.handle;
+ imageBits = OS.BS_ICON;
+ fImageType = OS.IMAGE_ICON;
+ break;
+ }
+ //FALL THROUGH
+ case SWT.TRANSPARENCY_ALPHA:
+ image2 = new Image (display, rect.width, rect.height);
+ GC gc = new GC (image2);
+ gc.setBackground (getBackground ());
+ gc.fillRectangle (rect);
+ gc.drawImage (image, 0, 0);
+ gc.dispose ();
+ hImage = image2.handle;
+ imageBits = OS.BS_BITMAP;
+ fImageType = OS.IMAGE_BITMAP;
+ break;
+ case SWT.TRANSPARENCY_NONE:
+ hImage = image.handle;
+ imageBits = OS.BS_BITMAP;
+ fImageType = OS.IMAGE_BITMAP;
+ break;
+ default:
+ }
+ break;
+ }
+ case SWT.ICON: {
+ hImage = image.handle;
+ imageBits = OS.BS_ICON;
+ fImageType = OS.IMAGE_ICON;
+ break;
+ }
+ default:
+ }
+ /*
+ * Feature in Windows. The button control mirrors its image when the
+ * flag WS_EX_LAYOUTRTL is set. This behaviour is not desirable in SWT.
+ * The fix is to set a mirrored version of real image in the button.
+ */
+ if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+ Rectangle rect = image.getBounds ();
+ auto hDC = OS.GetDC (handle);
+ auto dstHdc = OS.CreateCompatibleDC (hDC);
+ auto hBitmap = OS.CreateCompatibleBitmap (hDC, rect.width, rect.height);
+ auto oldBitmap = OS.SelectObject (dstHdc, hBitmap);
+ OS.SetLayout (dstHdc, OS.LAYOUT_RTL);
+ if (fImageType is OS.IMAGE_BITMAP) {
+ auto srcHdc = OS.CreateCompatibleDC (hDC);
+ auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage);
+ OS.SetLayout (dstHdc, 0);
+ OS.BitBlt (dstHdc, 0, 0, rect.width, rect.height, srcHdc, 0, 0, OS.SRCCOPY);
+ OS.SelectObject (srcHdc, oldSrcBitmap);
+ OS.DeleteDC (srcHdc);
+ } else {
+ Control control = findBackgroundControl ();
+ if (control is null) control = this;
+ auto newBrush = OS.CreateSolidBrush (control.getBackgroundPixel ());
+ auto oldBrush = OS.SelectObject (dstHdc, newBrush);
+ OS.PatBlt (dstHdc, 0, 0, rect.width, rect.height, OS.PATCOPY);
+ OS.DrawIconEx (dstHdc, 0, 0, hImage, 0, 0, 0, null, OS.DI_NORMAL);
+ OS.SelectObject (dstHdc, oldBrush);
+ OS.DeleteObject (newBrush);
+ }
+ OS.SelectObject (dstHdc, oldBitmap);
+ OS.DeleteDC (dstHdc);
+ OS.ReleaseDC (handle, hDC);
+ if (image2 !is null) image2.dispose ();
+ image2 = Image.win32_new (display, SWT.BITMAP, hBitmap);
+ imageBits = OS.BS_BITMAP;
+ fImageType = OS.IMAGE_BITMAP;
+ hImage = hBitmap;
+ }
+ }
+ }
+ int newBits = OS.GetWindowLong (handle, OS.GWL_STYLE), oldBits = newBits;
+ newBits &= ~(OS.BS_BITMAP | OS.BS_ICON);
+ newBits |= imageBits;
+ if (newBits !is oldBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+ OS.SendMessage (handle, OS.BM_SETIMAGE, fImageType, hImage);
+ }
+}
+
+void _setText (String text) {
+ int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+ if (OS.COMCTL32_MAJOR >= 6) {
+ newBits &= ~(OS.BS_LEFT | OS.BS_CENTER | OS.BS_RIGHT);
+ if ((style & SWT.LEFT) !is 0) newBits |= OS.BS_LEFT;
+ if ((style & SWT.CENTER) !is 0) newBits |= OS.BS_CENTER;
+ if ((style & SWT.RIGHT) !is 0) newBits |= OS.BS_RIGHT;
+ if (imageList !is null) {
+ BUTTON_IMAGELIST buttonImageList;
+ buttonImageList.himl = imageList.getHandle ();
+ if (text.length is 0) {
+ if ((style & SWT.LEFT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+ if ((style & SWT.CENTER) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+ if ((style & SWT.RIGHT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_RIGHT;
+ } else {
+ buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+ buttonImageList.margin.left = computeLeftMargin ();
+ buttonImageList.margin.right = MARGIN;
+ newBits &= ~(OS.BS_CENTER | OS.BS_RIGHT);
+ newBits |= OS.BS_LEFT;
+ }
+ OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+ }
+ } else {
+ newBits &= ~(OS.BS_BITMAP | OS.BS_ICON);
+ }
+ if (newBits !is oldBits) {
+ OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+ OS.InvalidateRect (handle, null, true);
+ }
+ /*
+ * Bug in Windows. When a Button control is right-to-left and
+ * is disabled, the first pixel of the text is clipped. The
+ * fix is to add a space to both sides of the text.
+ */
+ if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+ if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+ text = OS.IsWindowEnabled (handle) ? text : " " ~ text ~ " ";
+ }
+ }
+ TCHAR* buffer = StrToTCHARz ( text );
+ OS.SetWindowText (handle, buffer);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * widgetSelected
is called when the control is selected by the user.
+ * 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 is null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+ if (handle is null) 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, COMMAND_LINK ? SWT.COMMAND : 0);
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+ return checkBits (style, SWT.CENTER, SWT.LEFT, SWT.RIGHT, 0, 0, 0);
+ }
+ if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) {
+ return checkBits (style, SWT.LEFT, SWT.RIGHT, SWT.CENTER, 0, 0, 0);
+ }
+ if ((style & SWT.ARROW) !is 0) {
+ style |= SWT.NO_FOCUS;
+ return checkBits (style, SWT.UP, SWT.DOWN, SWT.LEFT, SWT.RIGHT, 0, 0);
+ }
+ return style;
+}
+
+void click () {
+ /*
+ * 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;
+}
+
+int computeLeftMargin () {
+ if (OS.COMCTL32_MAJOR < 6) return MARGIN;
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) is 0) return MARGIN;
+ int margin = 0;
+ if (image !is null && text.length !is 0) {
+ Rectangle bounds = image.getBounds ();
+ margin += bounds.width + MARGIN * 2;
+ HFONT oldFont;
+ auto hDC = OS.GetDC (handle);
+ HFONT newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+ if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+ TCHAR* buffer = StrToTCHARz( getCodePage (), text);
+ RECT rect;
+ int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+ OS.DrawText (hDC, buffer, -1, &rect, flags);
+ margin += rect.right - rect.left;
+ if (newFont !is null) OS.SelectObject (hDC, oldFont);
+ OS.ReleaseDC (handle, hDC);
+ OS.GetClientRect (handle, &rect);
+ margin = Math.max (MARGIN, (rect.right - rect.left - margin) / 2);
+ }
+ return margin;
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+ checkWidget ();
+ int width = 0, height = 0, border = getBorderWidth ();
+ if ((style & SWT.ARROW) !is 0) {
+ if ((style & (SWT.UP | SWT.DOWN)) !is 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);
+ }
+ } else {
+ if ((style & SWT.COMMAND) !is 0) {
+ SIZE size;
+ if (wHint !is SWT.DEFAULT) {
+ size.cx = wHint;
+ OS.SendMessage (handle, OS.BCM_GETIDEALSIZE, 0, &size);
+ width = size.cx;
+ height = size.cy;
+ } else {
+ OS.SendMessage (handle, OS.BCM_GETIDEALSIZE, 0, &size);
+ width = size.cy;
+ height = size.cy;
+ size.cy = 0;
+ while (size.cy !is height) {
+ size.cx = width++;
+ size.cy = 0;
+ OS.SendMessage (handle, OS.BCM_GETIDEALSIZE, 0, &size);
+ }
+ }
+ } else {
+ int extra = 0;
+ bool hasImage = image !is null, hasText = true;
+ if (OS.COMCTL32_MAJOR < 6) {
+ if ((style & SWT.PUSH) is 0) {
+ int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+ hasImage = (bits & (OS.BS_BITMAP | OS.BS_ICON)) !is 0;
+ if (hasImage) hasText = false;
+ }
+ }
+ if (hasImage) {
+ if (image !is null) {
+ Rectangle rect = image.getBounds ();
+ width = rect.width;
+ if (hasText && text.length !is 0) {
+ width += MARGIN * 2;
+ }
+ height = rect.height;
+ extra = MARGIN * 2;
+ }
+ }
+ if (hasText) {
+ HFONT oldFont;
+ auto hDC = OS.GetDC (handle);
+ auto newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+ if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+ TEXTMETRIC lptm;
+ OS.GetTextMetrics (hDC, &lptm);
+ int length_ = text.length;
+ if (length_ is 0) {
+ height = Math.max (height, lptm.tmHeight);
+ } else {
+ extra = Math.max (MARGIN * 2, lptm.tmAveCharWidth);
+ TCHAR* buffer = StrToTCHARz( getCodePage (), text);
+ RECT rect;
+ int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+ OS.DrawText (hDC, buffer, -1, &rect, flags);
+ width += rect.right - rect.left;
+ height = Math.max (height, rect.bottom - rect.top);
+ }
+ if (newFont !is null) OS.SelectObject (hDC, oldFont);
+ OS.ReleaseDC (handle, hDC);
+ }
+ if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) {
+ width += CHECK_WIDTH + extra;
+ height = Math.max (height, CHECK_HEIGHT + 3);
+ }
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+ width += 12; height += 10;
+ }
+ }
+ }
+ if (wHint !is SWT.DEFAULT) width = wHint;
+ if (hHint !is SWT.DEFAULT) height = hHint;
+ width += border * 2;
+ height += border * 2;
+ return new Point (width, height);
+}
+
+override void createHandle () {
+ /*
+ * Feature in Windows. When a button is created,
+ * it clears the UI state for all controls in the
+ * shell by sending WM_CHANGEUISTATE with UIS_SET,
+ * UISF_HIDEACCEL and UISF_HIDEFOCUS to the parent.
+ * This is undocumented and unexpected. The fix
+ * is to ignore the WM_CHANGEUISTATE, when sent
+ * from CreateWindowEx().
+ */
+ parent.state |= IGNORE_WM_CHANGEUISTATE;
+ super.createHandle ();
+ parent.state &= ~IGNORE_WM_CHANGEUISTATE;
+
+ /* Set the theme background */
+ if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+ /*
+ * NOTE: On Vista this causes problems when the tab
+ * key is pressed for push buttons so disable the
+ * theme background drawing for these widgets for
+ * now.
+ */
+ if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+ state |= THEME_BACKGROUND;
+ } else {
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) is 0) {
+ state |= THEME_BACKGROUND;
+ }
+ }
+ }
+
+ /*
+ * Bug in Windows. For some reason, the HBRUSH that
+ * is returned from WM_CTRLCOLOR is misaligned when
+ * the button uses it to draw. If the brush is a solid
+ * color, this does not matter. However, if the brush
+ * contains an image, the image is misaligned. The
+ * fix is to draw the background in WM_CTRLCOLOR.
+ *
+ * NOTE: For comctl32.dll 6.0 with themes disabled,
+ * drawing in WM_ERASEBKGND will draw on top of the
+ * text of the control.
+ */
+ if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+ if ((style & SWT.RADIO) !is 0) state |= DRAW_BACKGROUND;
+ }
+
+ /*
+ * Feature in Windows. Push buttons draw border around
+ * the button using the default background color instead
+ * of using the color provided by WM_CTRLCOLOR. The fix
+ * is to draw the background in WM_CTRLCOLOR.
+ *
+ * NOTE: On Vista this causes problems when the tab key
+ * is pressed for push buttons so disable the fix for now.
+ */
+ if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+ if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+ state |= DRAW_BACKGROUND;
+ }
+ }
+ }
+}
+
+override int defaultBackground () {
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+ return OS.GetSysColor (OS.COLOR_BTNFACE);
+ }
+ return super.defaultBackground ();
+}
+
+override int defaultForeground () {
+ return OS.GetSysColor (OS.COLOR_BTNTEXT);
+}
+
+override void enableWidget (bool enabled) {
+ super.enableWidget (enabled);
+ /*
+ * Bug in Windows. When a button control is right-to-left and
+ * is disabled, the first pixel of the text is clipped. The
+ * fix is to add a space to both sides of the text.
+ */
+ if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+ if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+ int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+ bool hasImage = (bits & (OS.BS_BITMAP | OS.BS_ICON)) !is 0;
+ if (!hasImage) {
+ String string = enabled ? text : " " ~ text ~ " ";
+ TCHAR* buffer = StrToTCHARz (getCodePage (), string);
+ OS.SetWindowText (handle, buffer);
+ }
+ }
+ }
+ /*
+ * Bug in Windows. When a button has the style BS_CHECKBOX
+ * or BS_RADIOBUTTON, is checked, and is displaying both an
+ * image and some text, when BCM_SETIMAGELIST is used to
+ * assign an image list for each of the button states, the
+ * button does not draw properly. When the user drags the
+ * mouse in and out of the button, it draws using a blank
+ * image. The fix is to set the complete image list only
+ * when the button is disabled.
+ */
+ if (OS.COMCTL32_MAJOR >= 6) {
+ if (imageList !is null) {
+ BUTTON_IMAGELIST buttonImageList;
+ OS.SendMessage (handle, OS.BCM_GETIMAGELIST, 0, &buttonImageList);
+ if (imageList !is null) imageList.dispose ();
+ imageList = new ImageList (style & SWT.RIGHT_TO_LEFT);
+ if (OS.IsWindowEnabled (handle)) {
+ imageList.add (image);
+ } else {
+ if (disabledImage !is null) disabledImage.dispose ();
+ disabledImage = new Image (display, image, SWT.IMAGE_DISABLE);
+ imageList.add (disabledImage);
+ }
+ buttonImageList.himl = imageList.getHandle ();
+ OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+ /*
+ * Bug in Windows. Under certain cirumstances yet to be
+ * isolated, BCM_SETIMAGELIST does not redraw the control
+ * when an image is set. The fix is to force a redraw.
+ */
+ OS.InvalidateRect (handle, null, true);
+ }
+ }
+}
+
+/**
+ * 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) !is 0) {
+ if ((style & SWT.UP) !is 0) return SWT.UP;
+ if ((style & SWT.DOWN) !is 0) return SWT.DOWN;
+ if ((style & SWT.LEFT) !is 0) return SWT.LEFT;
+ if ((style & SWT.RIGHT) !is 0) return SWT.RIGHT;
+ return SWT.UP;
+ }
+ if ((style & SWT.LEFT) !is 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) !is 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) !is 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+bool getDefault () {
+ if ((style & SWT.PUSH) is 0) return false;
+ int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+ return (bits & OS.BS_DEFPUSHBUTTON) !is 0;
+}
+
+/**
+ * Returns true
if the receiver is grayed,
+ * and false otherwise. When the widget 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
+ *
+ *
+ * @since 3.4
+ */
+public bool getGrayed () {
+ checkWidget();
+ if ((style & SWT.CHECK) is 0) return false;
+ return grayed;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Returns the widget message. When the widget is created
+ * with the style SWT.COMMAND
, the message text
+ * is displayed to provide further information for the user.
+ *
+ * @return the widget 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
+ *
+ *
+ * @since 3.3
+ */
+/*public*/ String getMessage () {
+ checkWidget ();
+ return message;
+}
+
+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 bool getSelection () {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) is 0) return false;
+ int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+ return flags !is OS.BST_UNCHECKED;
+}
+
+/**
+ * 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) !is 0) return "";
+ return text;
+}
+
+override bool isTabItem () {
+ if ((style & SWT.PUSH) !is 0) return isTabGroup ();
+ return super.isTabItem ();
+}
+
+override bool mnemonicHit (wchar 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) is 0) click ();
+ return true;
+}
+
+override bool mnemonicMatch (wchar key) {
+ wchar mnemonic = findMnemonic (getText ());
+ if (mnemonic is '\0') return false;
+ return CharacterToUpper (key) is CharacterToUpper (mnemonic);
+}
+
+void printWidget (HWND hwnd, GC gc) {
+ /*
+ * Bug in Windows. For some reason, PrintWindow() fails
+ * when it is called on a push button. The fix is to
+ * detect the failure and use WM_PRINT instead. Note
+ * that WM_PRINT cannot be used all the time because it
+ * fails for browser controls when the browser has focus.
+ */
+ auto hDC = gc.handle;
+ if (!OS.PrintWindow (hwnd, hDC, 0)) {
+ int flags = OS.PRF_CLIENT | OS.PRF_NONCLIENT | OS.PRF_ERASEBKGND | OS.PRF_CHILDREN;
+ OS.SendMessage (hwnd, OS.WM_PRINT, hDC, flags);
+ }
+}
+
+override void releaseWidget () {
+ super.releaseWidget ();
+ if (imageList !is null) imageList.dispose ();
+ imageList = null;
+ if (disabledImage !is null) disabledImage.dispose ();
+ disabledImage = null;
+ if (image2 !is null) image2.dispose ();
+ image2 = null;
+ text = null;
+ image = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @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 is null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable is 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] !is 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) !is 0) {
+ if ((style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) is 0) return;
+ style &= ~(SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT);
+ style |= alignment & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT);
+ OS.InvalidateRect (handle, null, true);
+ return;
+ }
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) is 0) return;
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+ newBits &= ~(OS.BS_LEFT | OS.BS_CENTER | OS.BS_RIGHT);
+ if ((style & SWT.LEFT) !is 0) newBits |= OS.BS_LEFT;
+ if ((style & SWT.CENTER) !is 0) newBits |= OS.BS_CENTER;
+ if ((style & SWT.RIGHT) !is 0) newBits |= OS.BS_RIGHT;
+ if (OS.COMCTL32_MAJOR >= 6) {
+ if (imageList !is null) {
+ BUTTON_IMAGELIST buttonImageList;
+ buttonImageList.himl = imageList.getHandle ();
+ if (text.length is 0) {
+ if ((style & SWT.LEFT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+ if ((style & SWT.CENTER) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+ if ((style & SWT.RIGHT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_RIGHT;
+ } else {
+ buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+ buttonImageList.margin.left = computeLeftMargin ();
+ buttonImageList.margin.right = MARGIN;
+ newBits &= ~(OS.BS_CENTER | OS.BS_RIGHT);
+ newBits |= OS.BS_LEFT;
+ }
+ OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+ }
+ }
+ if (newBits !is oldBits) {
+ OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+ OS.InvalidateRect (handle, null, true);
+ }
+}
+
+void setDefault (bool value) {
+ if ((style & SWT.PUSH) is 0) return;
+ auto 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);
+}
+
+override bool setFixedFocus () {
+ /*
+ * Feature in Windows. When a radio button gets focus,
+ * it selects the button in WM_SETFOCUS. The fix is to
+ * not assign focus to an unselected radio button.
+ */
+ if ((style & SWT.RADIO) !is 0 && !getSelection ()) return false;
+ return super.setFixedFocus ();
+}
+
+/**
+ * Sets the receiver's image to the argument, which may be
+ * null
indicating that no image should be displayed.
+ *
+ * Note that a Button can display an image and text simultaneously
+ * on Windows (starting with XP), GTK+ and OSX. On other platforms,
+ * a Button that has an image and text set into it will display the
+ * image or text that was set most recently.
+ *
+ * @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 !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if ((style & SWT.ARROW) !is 0) return;
+ this.image = image;
+ /* This code is intentionally commented */
+// if (OS.COMCTL32_MAJOR < 6) {
+// if (image is null || text.length !is 0) {
+// _setText (text);
+// return;
+// }
+// }
+ _setImage (image);
+}
+
+/**
+ * Sets the grayed state of the receiver. This state change
+ * only applies if the control was created with the SWT.CHECK
+ * style.
+ *
+ * @param grayed the new grayed 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.4
+ */
+public void setGrayed (bool grayed) {
+ checkWidget ();
+ if ((style & SWT.CHECK) is 0) return;
+ this.grayed = grayed;
+ int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+ if (grayed) {
+ if (flags is OS.BST_CHECKED) updateSelection (OS.BST_INDETERMINATE);
+ } else {
+ if (flags is OS.BST_INDETERMINATE) updateSelection (OS.BST_CHECKED);
+ }
+}
+
+/**
+ * Sets the widget message. When the widget is created
+ * with the style SWT.COMMAND
, the message text
+ * is displayed to provide further information for the user.
+ *
+ * @param message the new message
+ *
+ * @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.3
+ */
+/*public*/ void setMessage (String message) {
+ checkWidget ();
+ // SWT externsion: allow null string
+ //if (message is null) error (SWT.ERROR_NULL_ARGUMENT);
+ this.message = message;
+ if (OS.COMCTL32_VERSION >= OS.VERSION (6, 1)) {
+ if ((style & SWT.COMMAND) !is 0) {
+ OS.SendMessage (handle, OS.BCM_SETNOTE, 0, StrToTCHARz( message ));
+ }
+ }
+}
+
+override bool setRadioFocus () {
+ if ((style & SWT.RADIO) is 0 || !getSelection ()) return false;
+ return setFocus ();
+}
+
+override bool setRadioSelection (bool value) {
+ if ((style & SWT.RADIO) is 0) return false;
+ if (getSelection () !is value) {
+ setSelection (value);
+ postEvent (SWT.Selection);
+ }
+ return true;
+}
+
+override bool 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
+ * not assign focus to an unselected radio button.
+ */
+ if ((style & SWT.RADIO) !is 0 && !getSelection ()) return false;
+ return super.setSavedFocus ();
+}
+
+/**
+ * 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 (bool selected) {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) is 0) return;
+ int flags = selected ? OS.BST_CHECKED : OS.BST_UNCHECKED;
+ if ((style & SWT.CHECK) !is 0) {
+ if (selected && grayed) flags = OS.BST_INDETERMINATE;
+ }
+ updateSelection (flags);
+}
+
+/**
+ * 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 emphasized in a platform specific
+ * manner. The mnemonic indicator character '&' can be
+ * escaped by doubling it in the string, causing a single
+ * '&' to be displayed.
+ *
+ * Note that a Button can display an image and text simultaneously
+ * on Windows (starting with XP), GTK+ and OSX. On other platforms,
+ * a Button that has an image and text set into it will display the
+ * image or text that was set most recently.
+ *
+ * @param string the new 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 setText (String string) {
+ checkWidget ();
+ // SWT externsion: allow null string
+ //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.ARROW) !is 0) return;
+ text = string;
+ /* This code is intentionally commented */
+// if (OS.COMCTL32_MAJOR < 6) {
+// if (text.length is 0 && image !is null) {
+// _setImage (image);
+// return;
+// }
+// }
+ _setText (string);
+}
+
+void updateSelection (int flags) {
+ if (flags !is OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0)) {
+ /*
+ * Feature in Windows. When BM_SETCHECK is used
+ * to set the checked state of a radio or check
+ * 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 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+ if ((style & SWT.CHECK) !is 0) {
+ if (flags is OS.BST_INDETERMINATE) {
+ bits &= ~OS.BS_CHECKBOX;
+ bits |= OS.BS_3STATE;
+ } else {
+ bits |= OS.BS_CHECKBOX;
+ bits &= ~OS.BS_3STATE;
+ }
+ if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+ OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+ }
+ }
+ OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0);
+ if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+ OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+ }
+ }
+}
+
+override int widgetStyle () {
+ int bits = super.widgetStyle ();
+ if ((style & SWT.FLAT) !is 0) bits |= OS.BS_FLAT;
+ if ((style & SWT.ARROW) !is 0) return bits | OS.BS_OWNERDRAW;
+ if ((style & SWT.LEFT) !is 0) bits |= OS.BS_LEFT;
+ if ((style & SWT.CENTER) !is 0) bits |= OS.BS_CENTER;
+ if ((style & SWT.RIGHT) !is 0) bits |= OS.BS_RIGHT;
+ if ((style & SWT.PUSH) !is 0) return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP;
+ if ((style & SWT.CHECK) !is 0) return bits | OS.BS_CHECKBOX | OS.WS_TABSTOP;
+ if ((style & SWT.RADIO) !is 0) return bits | OS.BS_RADIOBUTTON;
+ if ((style & SWT.TOGGLE) !is 0) return bits | OS.BS_PUSHLIKE | OS.BS_CHECKBOX | OS.WS_TABSTOP;
+ if ((style & SWT.COMMAND) !is 0) return bits | OS.BS_COMMANDLINK | OS.WS_TABSTOP;
+ return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP;
+}
+
+override String windowClass () {
+ return TCHARzToStr( ButtonClass.ptr );
+}
+
+override int windowProc () {
+ return cast(int) ButtonProc;
+}
+
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+ LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+ if (result !is null) return result;
+ /*
+ * Bug in Windows. For some reason, the HBRUSH that
+ * is returned from WM_CTRLCOLOR is misaligned when
+ * the button uses it to draw. If the brush is a solid
+ * color, this does not matter. However, if the brush
+ * contains an image, the image is misaligned. The
+ * fix is to draw the background in WM_ERASEBKGND.
+ */
+ if (OS.COMCTL32_MAJOR < 6) {
+ if ((style & (SWT.RADIO | SWT.CHECK)) !is 0) {
+ if (findImageControl () !is null) {
+ drawBackground (cast(HWND)wParam);
+ return LRESULT.ONE;
+ }
+ }
+ }
+ return result;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+ LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+ if (result !is null) return result;
+ if ((style & SWT.ARROW) !is 0) {
+ return new LRESULT (OS.DLGC_STATIC);
+ }
+ return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+ LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+ if ((style & SWT.PUSH) !is 0 && getDefault ()) {
+ menuShell ().setDefaultButton (null, false);
+ }
+ return result;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+ if (ignoreMouse) return null;
+ return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
+override LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+ if (ignoreMouse) return null;
+ return super.WM_LBUTTONUP (wParam, lParam);
+}
+
+override 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) !is 0) {
+ bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+ }
+ LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+ if ((style & SWT.RADIO) !is 0) {
+ OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+ }
+ if ((style & SWT.PUSH) !is 0) {
+ menuShell ().setDefaultButton (this, false);
+ }
+ return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+ LRESULT result = super.WM_SIZE (wParam, lParam);
+ if (result !is null) return result;
+ if (OS.COMCTL32_MAJOR >= 6) {
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+ if (imageList !is null && text.length !is 0) {
+ BUTTON_IMAGELIST buttonImageList;
+ OS.SendMessage (handle, OS.BCM_GETIMAGELIST, 0, &buttonImageList);
+ buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+ buttonImageList.margin.left = computeLeftMargin ();
+ buttonImageList.margin.right = MARGIN;
+ OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+ }
+ }
+ }
+ return result;
+}
+
+override LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+ LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+ if (result !is null) return result;
+ if (image2 !is null) _setImage (image);
+ return result;
+}
+
+override LRESULT WM_UPDATEUISTATE (int wParam, int lParam) {
+ LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+ if (result !is null) return result;
+ /*
+ * Feature in Windows. When WM_UPDATEUISTATE is sent to
+ * a button, it sends WM_CTLCOLORBTN to get the foreground
+ * and background. If drawing happens in WM_CTLCOLORBTN,
+ * it will overwrite the contents of the control. The
+ * fix is draw the button without drawing the background
+ * and avoid the button window proc.
+ *
+ * NOTE: This only happens for radio, check and toggle
+ * buttons.
+ */
+ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+ if ((style & (SWT.RADIO | SWT.CHECK | SWT.TOGGLE)) !is 0) {
+ bool redraw = findImageControl () !is null;
+ if (!redraw) {
+ if ((state & THEME_BACKGROUND) !is 0) {
+ if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+ redraw = findThemeControl () !is null;
+ }
+ }
+ if (!redraw) redraw = findBackgroundControl () !is null;
+ }
+ if (redraw) {
+ OS.InvalidateRect (handle, null, false);
+ int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+ return new LRESULT (code);
+ }
+ }
+ }
+ return result;
+}
+
+override LRESULT wmCommandChild (int wParam, int lParam) {
+ int code = OS.HIWORD (wParam);
+ switch (code) {
+ case OS.BN_CLICKED:
+ case OS.BN_DOUBLECLICKED:
+ if ((style & (SWT.CHECK | SWT.TOGGLE)) !is 0) {
+ setSelection (!getSelection ());
+ } else {
+ if ((style & SWT.RADIO) !is 0) {
+ if ((parent.getStyle () & SWT.NO_RADIO_GROUP) !is 0) {
+ setSelection (!getSelection ());
+ } else {
+ selectRadio ();
+ }
+ }
+ }
+ postEvent (SWT.Selection);
+ default:
+ }
+ return super.wmCommandChild (wParam, lParam);
+}
+
+override LRESULT wmColorChild (int wParam, int lParam) {
+ /*
+ * Bug in Windows. For some reason, the HBRUSH that
+ * is returned from WM_CTRLCOLOR is misaligned when
+ * the button uses it to draw. If the brush is a solid
+ * color, this does not matter. However, if the brush
+ * contains an image, the image is misaligned. The
+ * fix is to draw the background in WM_ERASEBKGND.
+ */
+ LRESULT result = super.wmColorChild (wParam, lParam);
+ if (OS.COMCTL32_MAJOR < 6) {
+ if ((style & (SWT.RADIO | SWT.CHECK)) !is 0) {
+ if (findImageControl () !is null) {
+ OS.SetBkMode (cast(HANDLE)wParam, OS.TRANSPARENT);
+ return new LRESULT ( cast(int) OS.GetStockObject (OS.NULL_BRUSH));
+ }
+ }
+ }
+ return result;
+}
+
+override LRESULT wmDrawChild (int wParam, int lParam) {
+ if ((style & SWT.ARROW) is 0) return super.wmDrawChild (wParam, lParam);
+ auto struct_ = cast(DRAWITEMSTRUCT*)lParam;
+ //OS.MoveMemory (struct_, lParam, DRAWITEMSTRUCT.sizeof);
+ RECT rect;
+ OS.SetRect (&rect, struct_.rcItem.left, struct_.rcItem.top, struct_.rcItem.right, struct_.rcItem.bottom);
+ if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+ 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;
+ default:
+ }
+ /*
+ * 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) !is 0) iStateId += OS.ABS_UPPRESSED - OS.ABS_UPNORMAL;
+ OS.DrawThemeBackground (display.hScrollBarTheme (), struct_.hDC, OS.SBP_ARROWBTN, iStateId, &rect, null);
+ } 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;
+ default:
+ }
+ if (!getEnabled ()) uState |= OS.DFCS_INACTIVE;
+ if ((style & SWT.FLAT) is SWT.FLAT) uState |= OS.DFCS_FLAT;
+ if ((struct_.itemState & OS.ODS_SELECTED) !is 0) uState |= OS.DFCS_PUSHED;
+ OS.DrawFrameControl (struct_.hDC, &rect, OS.DFC_SCROLL, uState);
+ }
+ return null;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Canvas.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Canvas.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,503 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Canvas;
+
+import org.eclipse.swt.widgets.Composite;
+
+
+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.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Caret;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.IME;
+
+import java.lang.all;
+
+/**
+ * Instances of this class provide a surface for drawing
+ * arbitrary graphics.
+ *
+ * - 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
+ * @see Canvas snippets
+ * @see SWT Example: ControlExample
+ * @see Sample code and further information
+ */
+
+public class Canvas : Composite {
+
+ alias Composite.drawBackground drawBackground;
+ alias Composite.windowProc windowProc;
+
+ Caret caret;
+ IME ime;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+/**
+ * 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 this (Composite parent, int style) {
+ super (parent, style);
+}
+
+void clearArea (int x, int y, int width, int height) {
+ checkWidget ();
+ if (OS.IsWindowVisible (handle)) {
+ RECT rect;
+ OS.SetRect (&rect, x, y, x + width, y + height);
+ auto hDC = OS.GetDCEx (handle, null, OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS);
+ drawBackground (hDC, &rect);
+ OS.ReleaseDC (handle, hDC);
+ }
+}
+
+/**
+ * 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 is null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ RECT rect;
+ OS.SetRect (&rect, x, y, x + width, y + height);
+ auto hDC = gc.handle;
+ int pixel = background is -1 ? gc.getBackground ().handle : -1;
+ drawBackground (hDC, &rect, pixel);
+}
+
+/**
+ * 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 for the receiver, may 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
+ *
+ */
+public Caret getCaret () {
+ checkWidget ();
+ return caret;
+}
+
+/**
+ * Returns the IME.
+ *
+ * @return the IME
+ *
+ * @exception 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.4
+ */
+public IME getIME () {
+ checkWidget ();
+ return ime;
+}
+
+void releaseChildren (bool destroy) {
+ if (caret !is null) {
+ caret.release (false);
+ caret = null;
+ }
+ if (ime !is null) {
+ ime.release (false);
+ ime = null;
+ }
+ super.releaseChildren (destroy);
+}
+
+/**
+ * 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 true
if 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, bool all) {
+ checkWidget ();
+ forceResize ();
+ bool isFocus = caret !is null && caret.isFocusCaret ();
+ if (isFocus) caret.killFocus ();
+ RECT sourceRect;
+ OS.SetRect (&sourceRect, x, y, x + width, y + height);
+ RECT clientRect;
+ OS.GetClientRect (handle, &clientRect);
+ if (OS.IntersectRect (&clientRect, &sourceRect, &clientRect)) {
+ static if (OS.IsWinCE) {
+ OS.UpdateWindow (handle);
+ } else {
+ int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+ OS.RedrawWindow (handle, null, null, flags);
+ }
+ }
+ int deltaX = destX - x, deltaY = destY - y;
+ if (findImageControl () !is null) {
+ static if (OS.IsWinCE) {
+ OS.InvalidateRect (handle, &sourceRect, true);
+ } else {
+ { // scope for flags
+ int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+ if (all) flags |= OS.RDW_ALLCHILDREN;
+ OS.RedrawWindow (handle, &sourceRect, null, flags);
+ }
+ }
+ OS.OffsetRect (&sourceRect, deltaX, deltaY);
+ static if (OS.IsWinCE) {
+ OS.InvalidateRect (handle, &sourceRect, true);
+ } else {
+ int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+ if (all) flags |= OS.RDW_ALLCHILDREN;
+ OS.RedrawWindow (handle, &sourceRect, null, flags);
+ }
+ } else {
+ 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, null, 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 (hasFocus ()) {
+ if (oldCaret !is null) oldCaret.killFocus ();
+ if (newCaret !is null) {
+ if (newCaret.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ newCaret.setFocus ();
+ }
+ }
+}
+
+override public void setFont (Font font) {
+ checkWidget ();
+ if (caret !is null) caret.setFont (font);
+ super.setFont (font);
+}
+
+/**
+ * Sets the receiver's IME.
+ *
+ * @param ime the new IME for the receiver, may be null
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_INVALID_ARGUMENT - if the IME 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.4
+ */
+public void setIME (IME ime) {
+ checkWidget ();
+ if (ime !is null && ime.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ this.ime = ime;
+}
+
+override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
+ if (msg is Display.SWT_RESTORECARET) {
+ if ((state & CANVAS) !is 0) {
+ if (caret !is null) {
+ caret.killFocus ();
+ caret.setFocus ();
+ return 1;
+ }
+ }
+ }
+ return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+override LRESULT WM_CHAR (int wParam, int lParam) {
+ LRESULT result = super.WM_CHAR (wParam, lParam);
+ if (result !is null) return result;
+ if (caret !is null) {
+ switch (wParam) {
+ case SWT.DEL:
+ case SWT.BS:
+ case SWT.ESC:
+ break;
+ default: {
+ if (OS.GetKeyState (OS.VK_CONTROL) >= 0) {
+ int value;
+ if (OS.SystemParametersInfo (OS.SPI_GETMOUSEVANISH, 0, &value, 0)) {
+ if (value !is 0) OS.SetCursor (null);
+ }
+ }
+ }
+ }
+ }
+ return result;
+}
+
+override LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) {
+ if (ime !is null) {
+ LRESULT result = ime.WM_IME_COMPOSITION (wParam, lParam);
+ if (result !is null) return result;
+ }
+
+ /*
+ * Bug in Windows. On Korean Windows XP, the IME window
+ * for the Korean Input System (MS-IME 2002) always opens
+ * in the top left corner of the screen, despite the fact
+ * that ImmSetCompositionWindow() was called to position
+ * the IME when focus is gained. The fix is to position
+ * the IME on every WM_IME_COMPOSITION message.
+ */
+ if (!OS.IsWinCE && OS.WIN32_VERSION is OS.VERSION (5, 1)) {
+ if (OS.IsDBLocale) {
+ short langID = OS.GetSystemDefaultUILanguage ();
+ short primaryLang = OS.PRIMARYLANGID (langID);
+ if (primaryLang is OS.LANG_KOREAN) {
+ if (caret !is null && caret.isFocusCaret ()) {
+ POINT ptCurrentPos;
+ if (OS.GetCaretPos (&ptCurrentPos)) {
+ COMPOSITIONFORM lpCompForm;
+ lpCompForm.dwStyle = OS.CFS_POINT;
+ lpCompForm.ptCurrentPos.x = ptCurrentPos.x;
+ lpCompForm.ptCurrentPos.y = ptCurrentPos.y;
+ auto hIMC = OS.ImmGetContext (handle);
+ OS.ImmSetCompositionWindow (hIMC, &lpCompForm);
+ OS.ImmReleaseContext (handle, hIMC);
+ }
+ }
+ }
+ }
+ }
+ return super.WM_IME_COMPOSITION (wParam, lParam);
+}
+
+override LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) {
+ if (ime !is null) {
+ LRESULT result = ime.WM_IME_COMPOSITION_START (wParam, lParam);
+ if (result !is null) return result;
+ }
+ return super.WM_IME_COMPOSITION_START (wParam, lParam);
+}
+
+override LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) {
+ if (ime !is null) {
+ LRESULT result = ime.WM_IME_ENDCOMPOSITION (wParam, lParam);
+ if (result !is null) return result;
+ }
+ return super.WM_IME_ENDCOMPOSITION (wParam, lParam);
+}
+
+override LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) {
+ LRESULT result = super.WM_INPUTLANGCHANGE (wParam, lParam);
+ if (caret !is null && caret.isFocusCaret ()) {
+ caret.setIMEFont ();
+ caret.resizeIME ();
+ }
+ return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+ if (ime !is null) {
+ LRESULT result = ime.WM_KILLFOCUS (wParam, lParam);
+ if (result !is null) return result;
+ }
+ LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+ if (caret !is null) caret.killFocus ();
+ return result;
+}
+
+override LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+ if (ime !is null) {
+ LRESULT result = ime.WM_LBUTTONDOWN (wParam, lParam);
+ if (result !is null) return result;
+ }
+ return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+ LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+ if (caret !is null) caret.setFocus ();
+ return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+ LRESULT result = super.WM_SIZE (wParam, lParam);
+ if (caret !is null && caret.isFocusCaret ()) caret.resizeIME ();
+ return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) {
+ LRESULT result = super.WM_WINDOWPOSCHANGED (wParam, lParam);
+ //if (result !is 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.
+ */
+ bool isFocus = (style & SWT.RIGHT_TO_LEFT) !is 0 && caret !is null && caret.isFocusCaret ();
+ if (isFocus) caret.setFocus ();
+ return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+ LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+ if (result !is 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.
+ */
+ bool isFocus = (style & SWT.RIGHT_TO_LEFT) !is 0 && caret !is null && caret.isFocusCaret ();
+ if (isFocus) caret.killFocus ();
+ return result;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Caret.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Caret.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,612 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Caret;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.IME;
+
+import java.lang.all;
+
+/**
+ * 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.
+ *
+ *
+ * @see Caret snippets
+ * @see SWT Example: ControlExample, Canvas tab
+ * @see Sample code and further information
+ */
+
+public class Caret : Widget {
+ Canvas parent;
+ int x, y, width, height;
+ bool moved, resized;
+ bool isVisible_;
+ Image image;
+ Font font;
+ LOGFONT* oldFont;
+
+/**
+ * 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 this (Canvas parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ createWidget ();
+}
+
+void createWidget () {
+ isVisible_ = true;
+ if (parent.getCaret () is null) {
+ parent.setCaret (this);
+ }
+}
+
+HFONT defaultFont () {
+ auto hwnd = parent.handle;
+ auto hwndIME = OS.ImmGetDefaultIMEWnd (hwnd);
+ HFONT hFont;
+ if (hwndIME !is null) {
+ hFont = cast(HFONT) OS.SendMessage (hwndIME, OS.WM_GETFONT, 0, 0);
+ }
+ if (hFont is null) {
+ hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+ }
+ if (hFont is null) 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 !is null) {
+ Rectangle rect = image.getBounds ();
+ return new Rectangle (x, y, rect.width, rect.height);
+ } else {
+ if (!OS.IsWinCE && width is 0) {
+ int buffer;
+ if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
+ return new Rectangle (x, y, buffer, 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 is null) {
+ HFONT 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 !is null) {
+ Rectangle rect = image.getBounds ();
+ return new Point (rect.width, rect.height);
+ } else {
+ if (!OS.IsWinCE && width is 0) {
+ int buffer;
+ if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
+ return new Point (buffer, 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 bool getVisible () {
+ checkWidget();
+ return isVisible_;
+}
+
+bool hasFocus () {
+ return parent.handle is OS.GetFocus ();
+}
+
+bool isFocusCaret () {
+ return parent.caret is 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 bool isVisible () {
+ checkWidget();
+ return isVisible_ && parent.isVisible () && hasFocus ();
+}
+
+void killFocus () {
+ OS.DestroyCaret ();
+ restoreIMEFont ();
+}
+
+void move () {
+ moved = false;
+ if (!OS.SetCaretPos (x, y)) return;
+ resizeIME ();
+}
+
+void resizeIME () {
+ if (!OS.IsDBLocale) return;
+ POINT ptCurrentPos;
+ if (!OS.GetCaretPos (&ptCurrentPos)) return;
+ auto hwnd = parent.handle;
+ auto hIMC = OS.ImmGetContext (hwnd);
+ IME ime = parent.getIME ();
+ if (ime !is null && ime.isInlineEnabled ()) {
+ Point size = getSize ();
+ CANDIDATEFORM lpCandidate;
+ lpCandidate.dwStyle = OS.CFS_EXCLUDE;
+ lpCandidate.ptCurrentPos = ptCurrentPos;
+ //lpCandidate.rcArea = new RECT ();
+ OS.SetRect (&lpCandidate.rcArea, ptCurrentPos.x, ptCurrentPos.y, ptCurrentPos.x + size.x, ptCurrentPos.y + size.y);
+ OS.ImmSetCandidateWindow (hIMC, &lpCandidate);
+ } else {
+ RECT rect;
+ OS.GetClientRect (hwnd, &rect);
+ COMPOSITIONFORM lpCompForm;
+ lpCompForm.dwStyle = OS.CFS_RECT;
+ lpCompForm.ptCurrentPos.x = ptCurrentPos.x;
+ lpCompForm.ptCurrentPos.y = ptCurrentPos.y;
+ lpCompForm.rcArea.left = rect.left;
+ lpCompForm.rcArea.right = rect.right;
+ lpCompForm.rcArea.top = rect.top;
+ lpCompForm.rcArea.bottom = rect.bottom;
+ OS.ImmSetCompositionWindow (hIMC, &lpCompForm);
+ }
+ OS.ImmReleaseContext (hwnd, hIMC);
+}
+
+override void releaseParent () {
+ super.releaseParent ();
+ if (this is parent.getCaret ()) parent.setCaret (null);
+}
+
+override void releaseWidget () {
+ super.releaseWidget ();
+ parent = null;
+ image = null;
+ font = null;
+ oldFont = null;
+}
+
+void resize () {
+ resized = false;
+ auto hwnd = parent.handle;
+ OS.DestroyCaret ();
+ auto hBitmap = image !is null ? image.handle : null;
+ int width = this.width;
+ if (!OS.IsWinCE && image is null && width is 0) {
+ int buffer;
+ if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
+ width = buffer;
+ }
+ }
+ OS.CreateCaret (hwnd, hBitmap, width, height);
+ OS.SetCaretPos (x, y);
+ OS.ShowCaret (hwnd);
+ move ();
+}
+
+void restoreIMEFont () {
+ if (!OS.IsDBLocale) return;
+ if (oldFont is null) return;
+ auto hwnd = parent.handle;
+ auto hIMC = OS.ImmGetContext (hwnd);
+ OS.ImmSetCompositionFont (hIMC, oldFont);
+ OS.ImmReleaseContext (hwnd, hIMC);
+ oldFont = null;
+}
+
+/**
+ * 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();
+ bool samePosition = this.x is x && this.y is y;
+ bool sameExtent = this.width is width && this.height is height;
+ if (samePosition && sameExtent) return;
+ 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 ();
+ }
+}
+
+/**
+ * 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 is null) error (SWT.ERROR_NULL_ARGUMENT);
+ setBounds (rect.x, rect.y, rect.width, rect.height);
+}
+
+void setFocus () {
+ auto hwnd = parent.handle;
+ HBITMAP hBitmap;
+ if (image !is null) hBitmap = image.handle;
+ int width = this.width;
+ if (!OS.IsWinCE && image is null && width is 0) {
+ int buffer;
+ if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
+ width = buffer;
+ }
+ }
+ OS.CreateCaret (hwnd, hBitmap, width, height);
+ move ();
+ setIMEFont ();
+ 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) {
+ checkWidget();
+ if (font !is null && font.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.font = font;
+ if (hasFocus ()) setIMEFont ();
+}
+
+/**
+ * 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 !is null && image.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.image = image;
+ if (isVisible_ && hasFocus ()) resize ();
+}
+
+void setIMEFont () {
+ if (!OS.IsDBLocale) return;
+ HFONT hFont;
+ if (font !is null) hFont = font.handle;
+ if (hFont is null) hFont = defaultFont ();
+ auto hwnd = parent.handle;
+ auto hIMC = OS.ImmGetContext (hwnd);
+ /* Save the current IME font */
+ if (oldFont is null) {
+ oldFont = new LOGFONT;
+ if (!OS.ImmGetCompositionFont (hIMC, oldFont)) oldFont = null;
+ }
+ /* Set new IME font */
+ LOGFONT logFont;
+ if (OS.GetObject (hFont, LOGFONT.sizeof, &logFont) !is 0) {
+ 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 is x && this.y is y) return;
+ this.x = x; this.y = y;
+ moved = true;
+ if (isVisible_ && hasFocus ()) move ();
+}
+
+/**
+ * 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 is 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 is width && this.height is 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 is 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 (bool visible) {
+ checkWidget();
+ if (visible is isVisible_) return;
+ isVisible_ = visible;
+ auto hwnd = parent.handle;
+ if (OS.GetFocus () !is hwnd) return;
+ if (!isVisible_) {
+ OS.HideCaret (hwnd);
+ } else {
+ if (resized) {
+ resize ();
+ } else {
+ if (moved) move ();
+ }
+ OS.ShowCaret (hwnd);
+ }
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ColorDialog.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ColorDialog.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ColorDialog;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.win32.OS;
+
+
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Display;
+
+
+/**
+ * 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.
+ *
+ *
+ * @see SWT Example: ControlExample, Dialog tab
+ * @see Sample code and further information
+ */
+
+public class ColorDialog : Dialog {
+ Display display;
+ int width, height;
+ RGB rgb;
+ private static ColorDialog sThis;
+
+/**
+ * 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 this (Shell parent) {
+ this (parent, 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 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 this (Shell parent, int style) {
+ super (parent, checkStyle (parent, style));
+ checkSubclass ();
+}
+
+private static extern(Windows) uint CCHookFunc (HWND hdlg, uint uiMsg, uint lParam, int lpData) {
+ return sThis.CCHookProc( hdlg, uiMsg, lParam );
+}
+
+int CCHookProc (HWND hdlg, uint uiMsg, uint lParam ) {
+ switch (uiMsg) {
+ case OS.WM_INITDIALOG: {
+ RECT rect;
+ OS.GetWindowRect (hdlg, &rect);
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+ if (title !is null && title.length !is 0) {
+ /* Use the character encoding for the default locale */
+ OS.SetWindowText (hdlg, StrToTCHARz(title));
+ }
+ break;
+ }
+ case OS.WM_DESTROY: {
+ RECT rect;
+ OS.GetWindowRect (hdlg, &rect);
+ int newWidth = rect.right - rect.left;
+ int newHeight = rect.bottom - rect.top;
+ if (newWidth < width || newHeight < height) {
+ //display.fullOpen = false;
+ } else {
+ if (newWidth > width || newHeight > height) {
+ //display.fullOpen = true;
+ }
+ }
+ break;
+ }
+ default:
+ }
+ return 0;
+}
+
+/**
+ * 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 () {
+
+ /* Get the owner HWND for the dialog */
+ auto hwndOwner = parent.handle;
+ auto hwndParent = parent.handle;
+
+ /*
+ * Feature in Windows. There is no API to set the orientation of a
+ * color dialog. It is always inherited from the parent. The fix is
+ * to create a hidden parent and set the orientation in the hidden
+ * parent for the dialog to inherit.
+ */
+ bool enabled = false;
+ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+ int dialogOrientation = style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+ int parentOrientation = parent.style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+ if (dialogOrientation !is parentOrientation) {
+ int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+ if (dialogOrientation is SWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
+ hwndOwner = OS.CreateWindowEx (
+ exStyle,
+ Shell.DialogClass.ptr,
+ null,
+ 0,
+ OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+ hwndParent,
+ null,
+ OS.GetModuleHandle (null),
+ null);
+ enabled = OS.IsWindowEnabled (hwndParent) !is 0;
+ if (enabled) OS.EnableWindow (hwndParent, false);
+ }
+ }
+
+ /* Create the CCHookProc */
+ //Callback callback = new Callback (this, "CCHookProc", 4); //$NON-NLS-1$
+ //int lpfnHook = callback.getAddress ();
+ //if (lpfnHook is 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+
+ /* Allocate the Custom Colors */
+ display = parent.display;
+ if (display.lpCustColors is null) {
+ auto hHeap = OS.GetProcessHeap ();
+ display.lpCustColors = cast(uint*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, 16 * 4);
+ }
+
+ /* Open the dialog */
+ CHOOSECOLOR lpcc;
+ lpcc.lCustData = cast(int)cast(void*)this;
+ lpcc.lStructSize = CHOOSECOLOR.sizeof;
+ lpcc.Flags = OS.CC_ANYCOLOR | OS.CC_ENABLEHOOK;
+ //if (display.fullOpen) lpcc.Flags |= OS.CC_FULLOPEN;
+ lpcc.lpfnHook = &CCHookFunc;
+ lpcc.hwndOwner = hwndOwner;
+ lpcc.lpCustColors = display.lpCustColors;
+ if (rgb !is null) {
+ lpcc.Flags |= OS.CC_RGBINIT;
+ int red = rgb.red & 0xFF;
+ int green = (rgb.green << 8) & 0xFF00;
+ int blue = (rgb.blue << 16) & 0xFF0000;
+ lpcc.rgbResult = red | green | blue;
+ }
+
+ /* Make the parent shell be temporary modal */
+ Dialog oldModal = null;
+ if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+ oldModal = display.getModalDialog ();
+ display.setModalDialog (this);
+ }
+
+ /* Open the dialog */
+ bool success;
+ synchronized {
+ sThis = this;
+ success = cast(bool) OS.ChooseColor (&lpcc);
+ sThis = null;
+ }
+
+ /* Clear the temporary dialog modal parent */
+ if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+ display.setModalDialog (oldModal);
+ }
+
+ if (success) {
+ int red = lpcc.rgbResult & 0xFF;
+ int green = (lpcc.rgbResult >> 8) & 0xFF;
+ int blue = (lpcc.rgbResult >> 16) & 0xFF;
+ rgb = new RGB (red, green, blue);
+ }
+
+ /* Free the CCHookProc */
+ //callback.dispose ();
+
+ /* Free the Custom Colors */
+ /*
+ * This code is intentionally commented. Currently,
+ * there is exactly one set of custom colors per display.
+ * The memory associated with these colors is released
+ * when the display is disposed.
+ */
+// if (lpCustColors !is 0) OS.HeapFree (hHeap, 0, lpCustColors);
+
+ /* Destroy the BIDI orientation window */
+ if (hwndParent !is hwndOwner) {
+ if (enabled) OS.EnableWindow (hwndParent, true);
+ OS.SetActiveWindow (hwndParent);
+ OS.DestroyWindow (hwndOwner);
+ }
+
+ /*
+ * 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.
+ */
+// if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner);
+
+ display = null;
+ if (!success) return null;
+ 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 -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Combo.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Combo.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2552 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Combo;
+
+import org.eclipse.swt.widgets.Composite;
+
+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.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Display;
+
+import java.lang.all;
+
+/**
+ * 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, Combo
s 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 Combo
s 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, Verify
+ *
+ *
+ * Note: Only one of the styles DROP_DOWN and SIMPLE may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @see List
+ * @see Combo snippets
+ * @see SWT Example: ControlExample
+ * @see Sample code and further information
+ */
+
+public class Combo : Composite {
+
+ alias Composite.computeSize computeSize;
+ alias Composite.dragDetect dragDetect;
+ alias Composite.sendKeyEvent sendKeyEvent;
+ alias Composite.setBackgroundImage setBackgroundImage;
+ alias Composite.setBounds setBounds;
+ alias Composite.setToolTipText setToolTipText;
+
+ private static Combo pThis;
+ bool noSelection, ignoreDefaultSelection, ignoreCharacter, ignoreModify, ignoreResize;
+ HHOOK cbtHook;
+ int scrollWidth, visibleCount = 5;
+
+ /**
+ * the operating system limit for the number of characters
+ * that the text field in an instance of this class can hold
+ */
+ private static int LIMIT_ = 0;
+
+ /*
+ * These values can be different on different platforms.
+ * Therefore they are not initialized in the declaration
+ * to stop the compiler from inlining.
+ */
+ public static int LIMIT(){
+ if( LIMIT_ is 0 ){
+ synchronized {
+ LIMIT_ = OS.IsWinNT ? 0x7FFFFFFF : 0x7FFF;
+ }
+ }
+ return LIMIT_;
+ }
+ /*
+ * These are the undocumented control id's for the children of
+ * a combo box. Since there are no constants for these values,
+ * they may change with different versions of Windows (but have
+ * been the same since Windows 3.0).
+ */
+ static const int CBID_LIST = 1000;
+ static const int CBID_EDIT = 1001;
+ static /*final*/ WNDPROC EditProc, ListProc;
+
+ static /+const+/ WNDPROC ComboProc;
+ static const TCHAR* ComboClass = "COMBOBOX\0";
+
+ private static bool static_this_completed = false;
+ private static void static_this() {
+ if( static_this_completed ){
+ return;
+ }
+ synchronized {
+ if( static_this_completed ){
+ return;
+ }
+ WNDCLASS lpWndClass;
+ OS.GetClassInfo (null, ComboClass, &lpWndClass);
+ ComboProc = lpWndClass.lpfnWndProc;
+ static_this_completed = true;
+ }
+ }
+
+
+/**
+ * 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 this (Composite parent, int style) {
+ static_this();
+ super (parent, checkStyle (style));
+ /* This code is intentionally commented */
+ //if ((style & SWT.H_SCROLL) !is 0) this.style |= SWT.H_SCROLL;
+ this.style |= SWT.H_SCROLL;
+}
+
+/**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param string the new 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
+ *
+ *
+ * @see #add(String,int)
+ */
+public void add (String string) {
+ checkWidget ();
+ // SWT extension: allow null string
+ //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+ auto buffer = StrToTCHARs( getCodePage(), string, true );
+ int result = OS.SendMessage (handle, OS.CB_ADDSTRING, 0, buffer.ptr );
+ if (result is OS.CB_ERR) error (SWT.ERROR_ITEM_NOT_ADDED);
+ if (result is OS.CB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+ if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
+}
+
+/**
+ * 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_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 ();
+ // SWT extension: allow null string
+ //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+ if (!(0 <= index && index <= count)) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ auto buffer = StrToTCHARs( getCodePage(), string, true );
+ int result = OS.SendMessage (handle, OS.CB_INSERTSTRING, index, buffer.ptr);
+ if (result is OS.CB_ERRSPACE || result is OS.CB_ERR) {
+ error (SWT.ERROR_ITEM_NOT_ADDED);
+ }
+ if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
+}
+
+/**
+ * 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 is 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 user changes the receiver's selection, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * widgetSelected
is called when the user changes the combo's list selection.
+ * 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 is 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 is null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Verify, typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+ if (handle is null) return 0;
+ if (hwnd is handle) {
+ switch (msg) {
+ case OS.WM_SIZE: {
+ ignoreResize = true;
+ int /*long*/ result = OS.CallWindowProc (ComboProc, hwnd, msg, wParam, lParam);
+ ignoreResize = false;
+ return result;
+ default:
+ }
+ }
+ return OS.CallWindowProc( ComboProc, hwnd, msg, wParam, lParam);
+ }
+ auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+ if (hwnd is hwndText) {
+ return OS.CallWindowProc( EditProc, hwnd, msg, wParam, lParam);
+ }
+ auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+ if (hwnd is hwndList) {
+ return OS.CallWindowProc( ListProc, hwnd, msg, wParam, lParam);
+ }
+ return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+private static extern(Windows) int CBTFunc (int nCode, uint wParam, int lParam) {
+ return pThis.CBTProc( nCode, wParam, lParam );
+}
+
+int CBTProc (int nCode, int wParam, int lParam) {
+ if (nCode is OS.HCBT_CREATEWND) {
+ TCHAR[128] buffer = 0;
+ OS.GetClassName (cast(HANDLE)wParam, buffer.ptr, buffer.length );
+ String className = TCHARzToStr(buffer.ptr);
+ if (className=="Edit" || className=="EDIT") { //$NON-NLS-1$ //$NON-NLS-2$
+ int bits = OS.GetWindowLong (cast(HANDLE)wParam, OS.GWL_STYLE);
+ OS.SetWindowLong (cast(HANDLE)wParam, OS.GWL_STYLE, bits & ~OS.ES_NOHIDESEL);
+ }
+ }
+ return OS.CallNextHookEx (cbtHook, nCode, wParam, lParam);
+}
+
+override bool checkHandle (HWND hwnd) {
+ return hwnd is handle || hwnd is OS.GetDlgItem (handle, CBID_EDIT) || hwnd is OS.GetDlgItem (handle, CBID_LIST);
+}
+
+override protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+ /*
+ * Feature in Windows. It is not possible to create
+ * a combo box that has a border using Windows style
+ * bits. All combo boxes draw their own border and
+ * do not use the standard Windows border styles.
+ * Therefore, no matter what style bits are specified,
+ * clear the BORDER bits so that the SWT style will
+ * match the Windows widget.
+ *
+ * The Windows behavior is currently implemented on
+ * all platforms.
+ */
+ style &= ~SWT.BORDER;
+
+ /*
+ * 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) !is 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 ();
+ OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, -1);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+ checkWidget ();
+ int width = 0, height = 0;
+ if (wHint is SWT.DEFAULT) {
+ HFONT newFont, oldFont;
+ auto hDC = OS.GetDC (handle);
+ newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+ if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+ int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+ RECT rect;
+ int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
+ if ((style & SWT.READ_ONLY) is 0) flags |= OS.DT_EDITCONTROL;
+ int length_ = OS.GetWindowTextLength (handle);
+ int cp = getCodePage ();
+ TCHAR[] buffer = new TCHAR[ length_ + 1];
+ buffer[] = 0;
+ OS.GetWindowText (handle, buffer.ptr, length_ + 1);
+ OS.DrawText (hDC, buffer.ptr, length_, &rect, flags);
+ width = Math.max (width, rect.right - rect.left);
+ if ((style & SWT.H_SCROLL) !is 0) {
+ width = Math.max (width, scrollWidth);
+ } else {
+ for (int i=0; i buffer.length ) buffer = new TCHAR[ length_ + 1 ], buffer[] =0;
+ int result = OS.SendMessage (handle, OS.CB_GETLBTEXT, i, buffer.ptr);
+ if (result !is OS.CB_ERR) {
+ OS.DrawText (hDC, buffer.ptr, length_, &rect, flags);
+ width = Math.max (width, rect.right - rect.left);
+ }
+ }
+ }
+ }
+ if (newFont !is null) OS.SelectObject (hDC, oldFont);
+ OS.ReleaseDC (handle, hDC);
+ }
+ if (hHint is SWT.DEFAULT) {
+ if ((style & SWT.SIMPLE) !is 0) {
+ int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+ int itemHeight = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
+ height = count * itemHeight;
+ }
+ }
+ if (width is 0) width = DEFAULT_WIDTH;
+ if (height is 0) height = DEFAULT_HEIGHT;
+ if (wHint !is SWT.DEFAULT) width = wHint;
+ if (hHint !is SWT.DEFAULT) height = hHint;
+ if ((style & SWT.READ_ONLY) !is 0) {
+ width += 8;
+ } else {
+ auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+ if (hwndText !is null) {
+ int /*long*/ margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
+ int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins);
+ width += marginWidth + 3;
+ }
+ }
+ COMBOBOXINFO pcbi;
+ pcbi.cbSize = COMBOBOXINFO.sizeof;
+ if (((style & SWT.SIMPLE) is 0) && !OS.IsWinCE && OS.GetComboBoxInfo (handle, &pcbi)) {
+ width += pcbi.rcItem.left + (pcbi.rcButton.right - pcbi.rcButton.left);
+ height = (pcbi.rcButton.bottom - pcbi.rcButton.top) + pcbi.rcButton.top * 2;
+ } else {
+ int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
+ width += OS.GetSystemMetrics (OS.SM_CXVSCROLL) + border * 2;
+ int textHeight = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, -1, 0);
+ if ((style & SWT.DROP_DOWN) !is 0) {
+ height = textHeight + 6;
+ } else {
+ height += textHeight + 10;
+ }
+ }
+ if ((style & SWT.SIMPLE) !is 0 && (style & SWT.H_SCROLL) !is 0) {
+ height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+ }
+ return new Point (width, 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 ();
+ OS.SendMessage (handle, OS.WM_COPY, 0, 0);
+}
+
+override void createHandle () {
+ /*
+ * Feature in Windows. When the selection changes in a combo box,
+ * Windows draws the selection, even when the combo box does not
+ * have focus. Strictly speaking, this is the correct Windows
+ * behavior because the combo box sets ES_NOHIDESEL on the text
+ * control that it creates. Despite this, it looks strange because
+ * Windows also clears the selection and selects all the text when
+ * the combo box gets focus. The fix is use the CBT hook to clear
+ * the ES_NOHIDESEL style bit when the text control is created.
+ */
+ if (OS.IsWinCE || (style & (SWT.READ_ONLY | SWT.SIMPLE)) !is 0) {
+ super.createHandle ();
+ } else {
+ int threadId = OS.GetCurrentThreadId ();
+ //Callback cbtCallback = new Callback (this, "CBTProc", 3); //$NON-NLS-1$
+ //int cbtProc = cbtCallback.getAddress ();
+ //if (cbtProc is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+ pThis = this;
+ cbtHook = OS.SetWindowsHookEx (OS.WH_CBT, &CBTFunc, null, threadId);
+ super.createHandle ();
+ if (cbtHook !is null) OS.UnhookWindowsHookEx (cbtHook);
+ pThis = null;
+ //cbtHook = 0;
+ //cbtCallback.dispose ();
+ }
+ state &= ~(CANVAS | THEME_BACKGROUND);
+
+ /* Get the text and list window procs */
+ auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+ if (hwndText !is null && EditProc is null) {
+ EditProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndText, OS.GWLP_WNDPROC);
+ }
+ auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+ if (hwndList !is null && ListProc is null) {
+ ListProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndList, OS.GWLP_WNDPROC);
+ }
+
+ /*
+ * Bug in Windows. If the combo box has the CBS_SIMPLE style,
+ * the list portion of the combo box is not drawn correctly the
+ * first time, causing pixel corruption. The fix is to ensure
+ * that the combo box has been resized more than once.
+ */
+ if ((style & SWT.SIMPLE) !is 0) {
+ int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+ SetWindowPos (handle, null, 0, 0, 0x3FFF, 0x3FFF, flags);
+ SetWindowPos (handle, null, 0, 0, 0, 0, flags);
+ }
+}
+
+/**
+ * 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) !is 0) return;
+ OS.SendMessage (handle, OS.WM_CUT, 0, 0);
+}
+
+override int defaultBackground () {
+ return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+override void deregister () {
+ super.deregister ();
+ auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+ if (hwndText !is null) display.removeControl (hwndText);
+ auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+ if (hwndList !is null) display.removeControl (hwndList);
+}
+
+/**
+ * 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 ();
+ int selection = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+ if (index !is selection) return;
+ OS.SendMessage (handle, OS.CB_SETCURSEL, -1, 0);
+ 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 ();
+ OS.SendMessage (handle, OS.CB_SETCURSEL, -1, 0);
+ sendEvent (SWT.Modify);
+ // widget could be disposed at this point
+}
+
+override bool dragDetect (HWND hwnd, int x, int y, bool filter, bool [] detect, bool [] consume) {
+ if (filter && (style & SWT.READ_ONLY) is 0) {
+ auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+ if (hwndText !is null) {
+ int start, end;
+ OS.SendMessage (handle, OS.CB_GETEDITSEL, &start, &end);
+ if (start !is end ) {
+ int /*long*/ lParam = OS.MAKELPARAM (x, y);
+ int position = OS.LOWORD (OS.SendMessage (hwndText, OS.EM_CHARFROMPOS, 0, lParam));
+ if (start <= position && position < end ) {
+ if (super.dragDetect (hwnd, x, y, filter, detect, consume)) {
+ if (consume !is null) consume [0] = true;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+ return super.dragDetect (hwnd, x, y, filter, detect, consume);
+}
+
+/**
+ * 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 length_ = OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, index, 0);
+ if (length_ !is OS.CB_ERR) {
+ TCHAR[] buffer = new TCHAR[ length_ + 1];
+ int result = OS.SendMessage (handle, OS.CB_GETLBTEXT, index, buffer.ptr);
+ if (result !is OS.CB_ERR) return TCHARzToStr( buffer.ptr );
+ }
+ int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+ if (0 <= index && index < count) error (SWT.ERROR_CANNOT_GET_ITEM);
+ 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 ();
+ int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+ if (count is OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_COUNT);
+ return count;
+}
+
+/**
+ * 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 ();
+ int result = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
+ if (result is OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT);
+ return result;
+}
+
+/**
+ * Returns a (possibly empty) array of String
s 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; itrue
if the receiver's list 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 list's visibility state + * + * @exception SWTExceptiontrue
,
+ * 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 SWTExceptionPoint
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 SWTExceptionsetTextLimit()
, it will be the constant
+ * Combo.LIMIT
.
+ *
+ * @return the text limit
+ *
+ * @exception SWTException + * 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+ * The selected text is deleted from the widget + * and new text inserted from the clipboard. + *
+ * + * @exception SWTException+ * @exception SWTException
SWT.RIGHT_TO_LEFT
.
+ * + * + * @param orientation new orientation style + * + * @exception SWTException
+ * 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.
+ *
+ * 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
.
+ *
+ * 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
+ * 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 + * @see Composite snippets + * @see Sample code and further information + */ + +public class Composite : Scrollable { + + alias Scrollable.setBounds setBounds; + alias Scrollable.computeSize computeSize; + alias Scrollable.translateMnemonic translateMnemonic; + + Layout layout_; + WINDOWPOS* [] lpwp; + Control [] tabList; + int layoutCount, backgroundMode; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this () { +} + +/** + * 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.
+ *
INHERIT_NONE
, INHERIT_DEFAULT
,
+ * INHERTIT_FORCE
.
+ *
+ * @return the background mode
+ *
+ * @exception SWTException + * 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 SWTExceptionfalse
otherwise.
+ *
+ * @return the receiver's deferred layout state
+ *
+ * @exception SWTException 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
+ * This is equivalent to calling layout(true)
.
+ *
+ * Note: Layout is different from painting. If a child is + * moved or resized such that an area in the parent is + * exposed, then the parent will paint. If no child is + * affected, the parent will not paint. + *
+ * + * @exception SWTExceptiontrue
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)
).
+ *
+ * Note: Layout is different from painting. If a child is + * moved or resized such that an area in the parent is + * exposed, then the parent will paint. If no child is + * affected, the parent will not paint. + *
+ * + * @param changedtrue
if the layout must flush its caches, and false
otherwise
+ *
+ * @exception SWTException 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)
).
+ *
+ * + * Note: Layout is different from painting. If a child is + * moved or resized such that an area in the parent is + * exposed, then the parent will paint. If no child is + * affected, the parent will not paint. + *
+ * + * @param changedtrue
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 + * Note: Layout is different from painting. If a child is + * moved or resized such that an area in the parent is + * exposed, then the parent will paint. If no child is + * affected, the parent will not paint. + *
+ * + * @param changed a control that has had a state change which requires a recalculation of its size + * + * @exception IllegalArgumentExceptionSWT
:
+ * INHERIT_NONE
, INHERIT_DEFAULT
,
+ * INHERIT_FORCE
.
+ *
+ * @param mode the new background mode
+ *
+ * @exception SWTException 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 + *
+ * 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. + *
+ * + * @see Control snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + */ + +public abstract class Control : Widget, Drawable { + + alias Widget.dragDetect dragDetect; + alias Widget.callWindowProc callWindowProc; + + /** + * 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 HANDLE handle; + Composite parent; + Cursor cursor; + Menu menu; + String toolTipText_; + Object layoutData; + Accessible accessible; + Image backgroundImage; + Region region; + Font font; + int drawCount, foreground, background; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this () { +} + +/** + * 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.
+ *
ControlListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException DragDetectListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException FocusListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException HelpListener
interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException KeyListener
+ * interface.
+ * + * When a key listener is added to a control, the control + * will take part in widget traversal. By default, all + * traversal keys (such as the tab key and so on) are + * delivered to the control. In order for a control to take + * part in traversal, it should listen for traversal events. + * Otherwise, the user can traverse into a control but not + * out. Note that native controls such as table and tree + * implement key traversal in the operating system. It is + * not necessary to add traversal listeners for these controls, + * unless you want to override the default traversal. + *
+ * @param listener the listener which should be notified + * + * @exception IllegalArgumentExceptionMenuDetectListener
interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException MouseListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException MouseTrackListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException MouseMoveListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException MouseWheelListener
interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException PaintListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException TraverseListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ * 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.
+ *
SWT.DEFAULT
)
+ * @param hHint the height hint (can be SWT.DEFAULT
)
+ * @return the preferred size of the control
+ *
+ * @exception SWTException
+ * 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.
+ *
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 By default, a drag is detected when the gesture
+ * occurs anywhere within the client area of a control.
+ * Some controls, such as tables and trees, override this
+ * behavior. In addition to the operating system specific
+ * drag gesture, they require the mouse to be inside an
+ * item. Custom widget writers can use setDragDetect
+ * to disable the default detection, listen for mouse down,
+ * and then call dragDetect()
from within the
+ * listener to conditionally detect a drag.
+ *
true
if the gesture occurred, and false
otherwise.
+ *
+ * @exception IllegalArgumentException By default, a drag is detected when the gesture
+ * occurs anywhere within the client area of a control.
+ * Some controls, such as tables and trees, override this
+ * behavior. In addition to the operating system specific
+ * drag gesture, they require the mouse to be inside an
+ * item. Custom widget writers can use setDragDetect
+ * to disable the default detection, listen for mouse down,
+ * and then call dragDetect()
from within the
+ * listener to conditionally detect a drag.
+ *
true
if the gesture occurred, and false
otherwise.
+ *
+ * @exception IllegalArgumentException true
if the control got focus, and false
if it was unable to.
+ *
+ * @exception SWTException + * When the mouse pointer passes over a control its appearance + * is changed to match the control's cursor. + *
+ * + * @return the receiver's cursor ornull
+ *
+ * @exception SWTException true
if the receiver is detecting
+ * drag gestures, and false
otherwise.
+ *
+ * @return the receiver's drag detect state
+ *
+ * @exception SWTException 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 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 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
+ * 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.
+ *
+ * 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.
+ *
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 true
if the receiver has the user-interface
+ * focus, and false
otherwise.
+ *
+ * @return the receiver's focus state
+ *
+ * @exception SWTException true
if the underlying operating
+ * system supports this reparenting, otherwise false
+ *
+ * @return true
if the widget can be reparented, otherwise false
+ *
+ * @exception SWTException false
is returned.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ * 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.
+ *
true
if the operation was successful and false
otherwise
+ *
+ * @exception IllegalArgumentException 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 + * Note: This operation is a hint and may be overridden by the platform. + * For example, on Windows the background of a Button cannot be changed. + *
+ * @param color the new color (or null) + * + * @exception IllegalArgumentException+ * Note: This operation is a hint and may be overridden by the platform. + * For example, on Windows the background of a Button cannot be changed. + *
+ * @param image the new image (or null) + * + * @exception IllegalArgumentExceptionx
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 SWTExceptionx
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 SWTExceptiontrue
, causes the receiver to have
+ * all mouse events delivered to it until the method is called with
+ * false
as the argument. Note that on some platforms,
+ * a mouse button must currently be down for capture to be assigned.
+ *
+ * @param capture true
to capture the mouse, and false
to release it
+ *
+ * @exception SWTException + * 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 IllegalArgumentExceptiontrue
, the receiver will detect drag gestures,
+ * otherwise these gestures will be ignored.
+ *
+ * @param dragDetect the new drag detect state
+ *
+ * @exception SWTException 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 true
if the control got focus, and false
if it was unable to.
+ *
+ * @exception SWTException + * Note: This operation is a hint and may be overridden by the platform. + *
+ * @param color the new color (or null) + * + * @exception IllegalArgumentException+ * 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 IllegalArgumentExceptionfalse
, 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+ * 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+ * 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 IllegalArgumentExceptiontrue
,
+ * 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+ * @param x the x coordinate to be translated + * @param y the y coordinate to be translated + * @return the translated coordinates + * + * @exception SWTException
+ * @param point the point to be translated (must not be null) + * @return the translated coordinates + * + * @exception IllegalArgumentException
+ * @param x the x coordinate to be translated + * @param y the y coordinate to be translated + * @return the translated coordinates + * + * @exception SWTException
+ * @param point the point to be translated (must not be null) + * @return the translated coordinates + * + * @exception IllegalArgumentException
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 + * Note: This method does not cause a redraw. + *
+ * + * @exception SWTExceptiontrue
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 null
+ * 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.
+ *
+ *
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see CoolBar snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + */ + +public class CoolBar : Composite { + + alias Composite.computeSize computeSize; + alias Composite.windowProc windowProc; + + CoolItem [] items; + CoolItem [] originalItems; + bool locked; + bool ignoreResize; + private static /+const+/ WNDPROC ReBarProc; + static const TCHAR* ReBarClass = OS.REBARCLASSNAME.ptr; + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + INITCOMMONCONTROLSEX icex; + icex.dwSize = INITCOMMONCONTROLSEX.sizeof; + icex.dwICC = OS.ICC_COOL_CLASSES; + OS.InitCommonControlsEx (&icex); + WNDCLASS lpWndClass; + OS.GetClassInfo (null, ReBarClass, &lpWndClass); + ReBarProc = lpWndClass.lpfnWndProc; + static_this_completed = true; + } + } + + static const int SEPARATOR_WIDTH = 2; + static const int MAX_WIDTH = 0x7FFF; + static const int DEFAULT_COOLBAR_WIDTH = 0; + static const int DEFAULT_COOLBAR_HEIGHT = 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.
+ *
+ * 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+ * 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+ * 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 SWTExceptionCoolBar
.
+ * + * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see Sample code and further information + */ + +public class CoolItem : Item { + CoolBar parent; + Control control; + int id; + bool ideal, minimum; + +/** + * Constructs a new instance of this class given its parent + * (which must be aCoolBar
) 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.
+ *
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.
+ *
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.
+ *
+ * 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.
+ *
SWT.DEFAULT
)
+ * @param hHint the height hint (can be SWT.DEFAULT
)
+ * @return the preferred size
+ *
+ * @exception SWTException CoolBar
.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException + * 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+ * 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
+ * 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.
+ *
+ * Note: Only one of the styles DATE, TIME, or CALENDAR may be specified, + * and only one of the styles SHORT, MEDIUM, or LONG may be specified. + *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see DateTime snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + * + * @since 3.3 + */ + +public class DateTime : Composite { + + alias Composite.computeSize computeSize; + alias Composite.windowProc windowProc; + + bool ignoreSelection; + SYSTEMTIME* lastSystemTime; + SYSTEMTIME time; // only used in calendar mode + static /+const+/ WNDPROC DateTimeProc; + static const TCHAR[] DateTimeClass = OS.DATETIMEPICK_CLASS; + static /+const+/ WNDPROC CalendarProc; + static const TCHAR[] CalendarClass = OS.MONTHCAL_CLASS; + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + INITCOMMONCONTROLSEX icex; + icex.dwSize = INITCOMMONCONTROLSEX.sizeof; + icex.dwICC = OS.ICC_DATE_CLASSES; + OS.InitCommonControlsEx (&icex); + WNDCLASS lpWndClass; + OS.GetClassInfo (null, DateTimeClass.ptr, &lpWndClass); + DateTimeProc = lpWndClass.lpfnWndProc; + /* + * Feature in Windows. The date time window class + * does not include CS_DBLCLKS. This means that these + * controls will not get double click messages such as + * WM_LBUTTONDBLCLK. The fix is to register a new + * window class with CS_DBLCLKS. + * + * NOTE: Screen readers look for the exact class name + * of the control in order to provide the correct kind + * of assistance. Therefore, it is critical that the + * new window class have the same name. It is possible + * to register a local window class with the same name + * as a global class. Since bits that affect the class + * are being changed, it is possible that other native + * code, other than SWT, could create a control with + * this class name, and fail unexpectedly. + */ + auto hInstance = OS.GetModuleHandle (null); + auto hHeap = OS.GetProcessHeap (); + lpWndClass.hInstance = hInstance; + lpWndClass.style &= ~OS.CS_GLOBALCLASS; + lpWndClass.style |= OS.CS_DBLCLKS; + int byteCount = DateTimeClass.length * TCHAR.sizeof; + auto lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + OS.MoveMemory (lpszClassName, DateTimeClass.ptr, byteCount); + lpWndClass.lpszClassName = lpszClassName; + OS.RegisterClass (&lpWndClass); + OS.HeapFree (hHeap, 0, lpszClassName); + OS.GetClassInfo (null, CalendarClass.ptr, &lpWndClass); + CalendarProc = lpWndClass.lpfnWndProc; + /* + * Feature in Windows. The date time window class + * does not include CS_DBLCLKS. This means that these + * controls will not get double click messages such as + * WM_LBUTTONDBLCLK. The fix is to register a new + * window class with CS_DBLCLKS. + * + * NOTE: Screen readers look for the exact class name + * of the control in order to provide the correct kind + * of assistance. Therefore, it is critical that the + * new window class have the same name. It is possible + * to register a local window class with the same name + * as a global class. Since bits that affect the class + * are being changed, it is possible that other native + * code, other than SWT, could create a control with + * this class name, and fail unexpectedly. + */ + hInstance = OS.GetModuleHandle (null); + hHeap = OS.GetProcessHeap (); + lpWndClass.hInstance = hInstance; + lpWndClass.style &= ~OS.CS_GLOBALCLASS; + lpWndClass.style |= OS.CS_DBLCLKS; + byteCount = CalendarClass.length * TCHAR.sizeof; + lpszClassName = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + OS.MoveMemory (lpszClassName, CalendarClass.ptr, byteCount); + lpWndClass.lpszClassName = lpszClassName; + OS.RegisterClass (&lpWndClass); + OS.HeapFree (hHeap, 0, lpszClassName); + static_this_completed = true; + } + } + + static const int MARGIN = 4; + static const int MAX_DIGIT = 9; + static const int MAX_DAY = 31; + static const int MAX_12HOUR = 12; + static const int MAX_24HOUR = 24; + static const int MAX_MINUTE = 60; + static const int MONTH_DAY_YEAR = 0; + static const int DAY_MONTH_YEAR = 1; + static const int YEAR_MONTH_DAY = 2; + static const char SINGLE_QUOTE = '\''; //$NON-NLS-1$ short date format may include quoted text + static const char DAY_FORMAT_CONSTANT = 'd'; //$NON-NLS-1$ 1-4 lowercase 'd's represent day + static const char MONTH_FORMAT_CONSTANT = 'M'; //$NON-NLS-1$ 1-4 uppercase 'M's represent month + static const char YEAR_FORMAT_CONSTANT = 'y'; //$NON-NLS-1$ 1-5 lowercase 'y's represent year + static const char HOURS_FORMAT_CONSTANT = 'h'; //$NON-NLS-1$ 1-2 upper or lowercase 'h's represent hours + static const char MINUTES_FORMAT_CONSTANT = 'm'; //$NON-NLS-1$ 1-2 lowercase 'm's represent minutes + static const char SECONDS_FORMAT_CONSTANT = 's'; //$NON-NLS-1$ 1-2 lowercase 's's represent seconds + static const char AMPM_FORMAT_CONSTANT = 't'; //$NON-NLS-1$ 1-2 lowercase 't's represent am/pm + static const int[] MONTH_NAMES = [OS.LOCALE_SMONTHNAME1, OS.LOCALE_SMONTHNAME2, OS.LOCALE_SMONTHNAME3, OS.LOCALE_SMONTHNAME4, OS.LOCALE_SMONTHNAME5, OS.LOCALE_SMONTHNAME6, OS.LOCALE_SMONTHNAME7, OS.LOCALE_SMONTHNAME8, OS.LOCALE_SMONTHNAME9, OS.LOCALE_SMONTHNAME10, OS.LOCALE_SMONTHNAME11, OS.LOCALE_SMONTHNAME12]; + + +/** + * 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.
+ *
SelectionListener
+ * interface.
+ *
+ * widgetSelected
is called when the user changes the control's value.
+ * widgetDefaultSelected
is not called.
+ *
+ * The first day of the month is 1, and the last day depends on the month and year. + *
+ * + * @return a positive integer beginning with 1 + * + * @exception SWTException+ * Hours is an integer between 0 and 23. + *
+ * + * @return an integer between 0 and 23 + * + * @exception SWTException+ * Minutes is an integer between 0 and 59. + *
+ * + * @return an integer between 0 and 59 + * + * @exception SWTException+ * The first month of the year is 0, and the last month is 11. + *
+ * + * @return an integer between 0 and 11 + * + * @exception SWTException+ * Seconds is an integer between 0 and 59. + *
+ * + * @return an integer between 0 and 59 + * + * @exception SWTException+ * The first year is 1752 and the last year is 9999. + *
+ * + * @return an integer between 1752 and 9999 + * + * @exception SWTException+ * This is the recommended way to set the date, because setting the year, + * month, and day separately may result in invalid intermediate dates. + *
+ * + * @param year an integer between 1752 and 9999 + * @param month an integer between 0 and 11 + * @param day a positive integer beginning with 1 + * + * @exception SWTException+ * The first day of the month is 1, and the last day depends on the month and year. + *
+ * + * @param day a positive integer beginning with 1 + * + * @exception SWTException+ * Hours is an integer between 0 and 23. + *
+ * + * @param hours an integer between 0 and 23 + * + * @exception SWTException+ * Minutes is an integer between 0 and 59. + *
+ * + * @param minutes an integer between 0 and 59 + * + * @exception SWTException+ * The first month of the year is 0, and the last month is 11. + *
+ * + * @param month an integer between 0 and 11 + * + * @exception SWTException+ * Seconds is an integer between 0 and 59. + *
+ * + * @param seconds an integer between 0 and 59 + * + * @exception SWTException+ * The first year is 1752 and the last year is 9999. + *
+ * + * @param year an integer between 1752 and 9999 + * + * @exception SWTExceptionShells
, 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: + *
RESIZE
) until it is
+ * no longer maximized.
+ * SWT
provides two "convenience constants"
+ * for the most commonly required style combinations:
+ * SHELL_TRIM
CLOSE | TITLE | MIN | MAX | RESIZE
)
+ * DIALOG_TRIM
TITLE | CLOSE | BORDER
)
+ * + * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *
+ * + * @see #getMinimized + * @see #getMaximized + * @see Shell + * @see SWT + * @see Sample code and further information + */ + +public class Decorations : Canvas { + + alias Canvas.setBounds setBounds; + alias Canvas.setParent setParent; + alias Canvas.setSavedFocus setSavedFocus; + alias Canvas.sort sort; + alias Canvas.windowProc windowProc; + + Image image, smallImage, largeImage; + Image [] images; + Menu menuBar; + Menu [] menus; + Control savedFocus; + Button defaultButton, saveDefault; + int swFlags; + HACCEL hAccel; + int nAccel; + bool moved, resized, 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. + */ +this () { +} + +/** + * 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.
+ *
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.
+ *
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.
+ *
true
if the receiver is currently
+ * maximized, and false otherwise.
+ * + * + * @return the maximized state + * + * @exception SWTException
true
if the receiver is currently
+ * minimized, and false otherwise.
+ * + * + * @return the minimized state + * + * @exception SWTException
+ * 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 IllegalArgumentExceptiontrue
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.
+ *
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.
+ *
Dialog
typically contains other widgets
+ * that are not accessible. A Dialog
is not
+ * a Widget
.
+ * + * This class can also be used as the abstract superclass + * for user-designed dialogs. Such dialogs usually consist + * of a Shell with child widgets. The basic template for a + * user-defined dialog typically looks something like this: + *
+ * public class MyDialog extends Dialog {
+ * Object result;
+ *
+ * public MyDialog (Shell parent, int style) {
+ * super (parent, style);
+ * }
+ * public MyDialog (Shell parent) {
+ * this (parent, 0); // your default style bits go here (not the Shell's style bits)
+ * }
+ * public Object open () {
+ * Shell parent = getParent();
+ * Shell shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ * shell.setText(getText());
+ * // Your code goes here (widget creation, set result, etc).
+ * shell.open();
+ * Display display = parent.getDisplay();
+ * while (!shell.isDisposed()) {
+ * if (!display.readAndDispatch()) display.sleep();
+ * }
+ * return result;
+ * }
+ * }
+ *
+ *
+ * Note: The modality styles supported by this class
+ * are treated as HINTs, because not all are supported
+ * by every subclass on every platform. 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 by a particular dialog, it would be upgraded to
+ * APPLICATION_MODAL
. In addition, as is the case
+ * for shells, the window manager for the desktop on which the
+ * instance is visible has ultimate control over the appearance
+ * and behavior of the instance, including its modality.
+ *
+ * Note: Only one of the styles APPLICATION_MODAL, PRIMARY_MODAL, + * and SYSTEM_MODAL may be specified. + *
+ * + * @see Shell + * @see SWT Example: ControlExample + * @see Sample code and further information + */ + +public abstract class Dialog { + int style; + Shell parent; + String title; + +/** + * 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
+ * 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
+ * IMPORTANT: See the comment in Widget.checkSubclass()
.
+ *
SWTError.error
to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWT#error(int)
+ */
+void error (int code) {
+ SWT.error(code);
+}
+
+/**
+ * Returns the receiver's parent, which must be a Shell
+ * or null.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException + * 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. + *
+ * + * @return the style bits + * + * @exception SWTException+ * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *
+ * + * @see DirectoryDialog snippets + * @see SWT Example: ControlExample, Dialog tab + * @see Sample code and further information + */ + +public class DirectoryDialog : Dialog { + static String message = ""; + static String filterPath = ""; //$NON-NLS-1$//$NON-NLS-2$ + static 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
+ * 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.
+ *
+ * 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.
+ *
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.)
+ * Display
s 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.)
+ *
+ * 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.
+ *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * @see #syncExec + * @see #asyncExec + * @see #wake + * @see #readAndDispatch + * @see #sleep + * @see Device#dispose + * @see Display snippets + * @see Sample code and further information + */ + +public class Display : Device { + + /** + * the handle to the OS message queue + * (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 MSG* msg; + + /* Windows and Events */ + Event [] eventQueue; + //Callback windowCallback; + //int windowProc_; + int threadId; + TCHAR[] windowClass_, windowShadowClass; + static int WindowClassCount; + static const String WindowName = "SWT_Window"; //$NON-NLS-1$ + static const String WindowShadowName = "SWT_WindowShadow"; //$NON-NLS-1$ + EventTable eventTable, filterTable; + + /* Widget Table */ + int freeSlot; + int [] indexTable; + Control lastControl, lastGetControl; + HANDLE lastHwnd; + HWND lastGetHwnd; + Control [] controlTable; + static const int GROW_SIZE = 1024; + private static /+const+/ int SWT_OBJECT_INDEX; + static const bool USE_PROPERTY = !OS.IsWinCE; + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + static if (USE_PROPERTY) { + SWT_OBJECT_INDEX = OS.GlobalAddAtom (StrToTCHARz("SWT_OBJECT_INDEX")); //$NON-NLS-1$ + } else { + SWT_OBJECT_INDEX = 0; + } + static_this_StartupInfo (); + static_this_DeviceFinder (); + static_this_completed = true; + } + } + + /* Startup info */ + private static STARTUPINFO* lpStartupInfo; + private static void static_this_StartupInfo (){ + static if (!OS.IsWinCE) { + lpStartupInfo = new STARTUPINFO (); + lpStartupInfo.cb = STARTUPINFO.sizeof; + OS.GetStartupInfo (lpStartupInfo); + } + } + /* XP Themes */ + HTHEME hButtonTheme_, hEditTheme_, hExplorerBarTheme_, hScrollBarTheme_, hTabTheme_; + static const wchar [] BUTTON = "BUTTON\0"w; + static const wchar [] EDIT = "EDIT\0"w; + static const wchar [] EXPLORER = "EXPLORER\0"w; + static const wchar [] EXPLORERBAR = "EXPLORERBAR\0"w; + static const wchar [] SCROLLBAR = "SCROLLBAR\0"w; + static const wchar [] LISTVIEW = "LISTVIEW\0"w; + static const wchar [] TAB = "TAB\0"w; + static const wchar [] TREEVIEW = "TREEVIEW\0"w; + + /* Focus */ + int focusEvent; + Control focusControl; + + /* Menus */ + Menu [] bars, popups; + MenuItem [] items; + + /* + * The start value for WM_COMMAND id's. + * Windows reserves the values 0..100. + * + * The SmartPhone SWT resource file reserves + * the values 101..107. + */ + static const int ID_START = 108; + + /* Filter Hook */ + //Callback msgFilterCallback; + //int msgFilterProc_, + HHOOK filterHook; + bool runDragDrop = true, dragCancelled = false; + MSG* hookMsg; + + /* Idle Hook */ + //Callback foregroundIdleCallback; + //int foregroundIdleProc_; + HHOOK idleHook; + + /* Message Hook and Embedding */ + bool ignoreNextKey; + //Callback getMsgCallback, embeddedCallback; + int getMsgProc_; + HHOOK msgHook; + HWND embeddedHwnd; + int embeddedProc_; + static const String AWT_WINDOW_CLASS = "SunAwtWindow"; + static const short [] ACCENTS = [ cast(short) '~', '`', '\'', '^', '"']; + + /* Sync/Async Widget Communication */ + Synchronizer synchronizer; + bool runMessages = true, runMessagesInIdle = false, runMessagesInMessageProc = true; + static const String RUN_MESSAGES_IN_IDLE_KEY = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$ + static final String RUN_MESSAGES_IN_MESSAGE_PROC_KEY = "org.eclipse.swt.internal.win32.runMessagesInMessageProc"; //$NON-NLS-1$ + Thread thread; + + /* Display Shutdown */ + Runnable [] disposeList; + + /* System Tray */ + Tray tray; + int nextTrayId; + + /* Timers */ + int /*long*/ [] timerIds; + Runnable [] timerList; + int /*long*/ nextTimerId = SETTINGS_ID + 1; + static const int SETTINGS_ID = 100; + static const int SETTINGS_DELAY = 2000; + + /* Keyboard and Mouse */ + RECT* clickRect; + int clickCount, lastTime, lastButton; + HWND lastClickHwnd; + int scrollRemainder; + int lastKey, lastAscii, lastMouse; + bool lastVirtual, lastNull, lastDead; + ubyte [256] keyboard; + bool accelKeyHit, mnemonicKeyHit; + bool lockActiveWindow, captureChanged, xMouse; + + /* Tool Tips */ + int nextToolTipId; + + /* MDI */ + bool ignoreRestoreFocus; + Control lastHittestControl; + int lastHittest; + + /* Message Only Window */ + HWND hwndMessage; + + /* System Resources */ + LOGFONT* lfSystemFont; + Font systemFont; + Image errorImage, infoImage, questionImage, warningIcon; + Cursor [] cursors; + Resource [] resources; + static const int RESOURCE_SIZE = 1 + 4 + SWT.CURSOR_HAND + 1; + + /* ImageList Cache */ + ImageList[] imageList, toolImageList, toolHotImageList, toolDisabledImageList; + + /* Custom Colors for ChooseColor */ + COLORREF* lpCustColors; + + /* Sort Indicators */ + Image upArrow, downArrow; + + /* Table */ + char [] tableBuffer; + NMHDR* hdr; + NMLVDISPINFO* plvfi; + HWND hwndParent; + int columnCount; + bool [] columnVisible; + + /* Resize and move recursion */ + int resizeCount; + static final int RESIZE_LIMIT = 4; + + /* Display Data */ + Object data; + String [] keys; + Object [] values; + + /* Key Mappings */ + static const int [] [] KeyTable = [ + + /* Keyboard and Mouse Masks */ + [OS.VK_MENU, SWT.ALT], + [OS.VK_SHIFT, SWT.SHIFT], + [OS.VK_CONTROL, SWT.CONTROL], +// [OS.VK_????, SWT.COMMAND], + + /* NOT CURRENTLY USED */ +// [OS.VK_LBUTTON, SWT.BUTTON1], +// [OS.VK_MBUTTON, SWT.BUTTON3], +// [OS.VK_RBUTTON, SWT.BUTTON2], + + /* Non-Numeric Keypad Keys */ + [OS.VK_UP, SWT.ARROW_UP], + [OS.VK_DOWN, SWT.ARROW_DOWN], + [OS.VK_LEFT, SWT.ARROW_LEFT], + [OS.VK_RIGHT, SWT.ARROW_RIGHT], + [OS.VK_PRIOR, SWT.PAGE_UP], + [OS.VK_NEXT, SWT.PAGE_DOWN], + [OS.VK_HOME, SWT.HOME], + [OS.VK_END, SWT.END], + [OS.VK_INSERT, SWT.INSERT], + + /* Virtual and Ascii Keys */ + [OS.VK_BACK, SWT.BS], + [OS.VK_RETURN, SWT.CR], + [OS.VK_DELETE, SWT.DEL], + [OS.VK_ESCAPE, SWT.ESC], + [OS.VK_RETURN, SWT.LF], + [OS.VK_TAB, SWT.TAB], + + /* Functions Keys */ + [OS.VK_F1, SWT.F1], + [OS.VK_F2, SWT.F2], + [OS.VK_F3, SWT.F3], + [OS.VK_F4, SWT.F4], + [OS.VK_F5, SWT.F5], + [OS.VK_F6, SWT.F6], + [OS.VK_F7, SWT.F7], + [OS.VK_F8, SWT.F8], + [OS.VK_F9, SWT.F9], + [OS.VK_F10, SWT.F10], + [OS.VK_F11, SWT.F11], + [OS.VK_F12, SWT.F12], + [OS.VK_F13, SWT.F13], + [OS.VK_F14, SWT.F14], + [OS.VK_F15, SWT.F15], + + /* Numeric Keypad Keys */ + [OS.VK_MULTIPLY, SWT.KEYPAD_MULTIPLY], + [OS.VK_ADD, SWT.KEYPAD_ADD], + [OS.VK_RETURN, SWT.KEYPAD_CR], + [OS.VK_SUBTRACT, SWT.KEYPAD_SUBTRACT], + [OS.VK_DECIMAL, SWT.KEYPAD_DECIMAL], + [OS.VK_DIVIDE, SWT.KEYPAD_DIVIDE], + [OS.VK_NUMPAD0, SWT.KEYPAD_0], + [OS.VK_NUMPAD1, SWT.KEYPAD_1], + [OS.VK_NUMPAD2, SWT.KEYPAD_2], + [OS.VK_NUMPAD3, SWT.KEYPAD_3], + [OS.VK_NUMPAD4, SWT.KEYPAD_4], + [OS.VK_NUMPAD5, SWT.KEYPAD_5], + [OS.VK_NUMPAD6, SWT.KEYPAD_6], + [OS.VK_NUMPAD7, SWT.KEYPAD_7], + [OS.VK_NUMPAD8, SWT.KEYPAD_8], + [OS.VK_NUMPAD9, SWT.KEYPAD_9], +// [OS.VK_????, SWT.KEYPAD_EQUAL], + + /* Other keys */ + [OS.VK_CAPITAL, SWT.CAPS_LOCK], + [OS.VK_NUMLOCK, SWT.NUM_LOCK], + [OS.VK_SCROLL, SWT.SCROLL_LOCK], + [OS.VK_PAUSE, SWT.PAUSE], + [OS.VK_CANCEL, SWT.BREAK], + [OS.VK_SNAPSHOT, SWT.PRINT_SCREEN], +// [OS.VK_????, SWT.HELP], + + ]; + + /* Multiple Displays */ + static Display Default; + static Display [] Displays; + + /* Multiple Monitors */ + org.eclipse.swt.widgets.Monitor.Monitor[] monitors = null; + int monitorCount = 0; + + /* Modality */ + Shell [] modalShells; + Dialog modalDialog; + static bool TrimEnabled = false; + + /* Private SWT Window Messages */ + static const int SWT_GETACCELCOUNT = OS.WM_APP; + static const int SWT_GETACCEL = OS.WM_APP + 1; + static const int SWT_KEYMSG = OS.WM_APP + 2; + static const int SWT_DESTROY = OS.WM_APP + 3; + static const int SWT_TRAYICONMSG = OS.WM_APP + 4; + static const int SWT_NULL = OS.WM_APP + 5; + static const int SWT_RUNASYNC = OS.WM_APP + 6; + static int SWT_TASKBARCREATED; + static int SWT_RESTORECARET; + static int DI_GETDRAGIMAGE; + + /* Workaround for Adobe Reader 7.0 */ + int hitCount; + + /* Package Name */ + static const String PACKAGE_PREFIX = "org.eclipse.swt.widgets."; //$NON-NLS-1$ + /* + * This code is intentionally commented. In order + * to support CLDC, .class cannot be used because + * it does not compile on some Java compilers when + * they are targeted for CLDC. + */ +// static { +// String name = Display.class.getName (); +// int index = name.lastIndexOf ('.'); +// PACKAGE_PREFIX = name.substring (0, index + 1); +// } + + /* + * TEMPORARY CODE. Install the runnable that + * gets the current display. This code will + * be removed in the future. + */ + private static void static_this_DeviceFinder () { + DeviceFinder = new class() Runnable { + public void run () { + Device device = getCurrent (); + if (device is null) { + device = getDefault (); + } + setDevice (device); + } + }; + } + +/* +* TEMPORARY CODE. +*/ +static void setDevice (Device device) { + static_this(); + 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 SWTExceptionhandleEvent()
+ * 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.
+ *
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 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 ornull
+ *
+ * @exception SWTException
+ * IMPORTANT: See the comment in Widget.checkSubclass()
.
+ *
+ * This method is called before init
.
+ *
release
.
+ *
+ * @see Device#dispose
+ * @see #release
+ */
+override protected void destroy () {
+ if (this is Default) Default = null;
+ deregister (this);
+ destroyDisplay ();
+}
+
+void destroyDisplay () {
+}
+
+/**
+ * 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 Widget
subclass which
+ * represents it in the currently running application, if
+ * such exists, or null if no matching widget can be found.
+ * + * IMPORTANT: This method should not be called from + * application code. The arguments are platform-specific. + *
+ * + * @param handle the handle for the widget + * @return the SWT widget that the handle represents + * + * @exception SWTExceptionWidget
subclass which represents
+ * the handle/id pair in the currently running application,
+ * if such exists, or null if no matching widget can be found.
+ * + * IMPORTANT: This method should not be called from + * application code. The arguments are platform-specific. + *
+ * + * @param handle the handle for the widget + * @param id the id for the subwidget (usually an item) + * @return the SWT widget that the handle/id pair represents + * + * @exception SWTExceptionWidget
subclass which represents
+ * the widget/id pair in the currently running application,
+ * if such exists, or null if no matching widget can be found.
+ *
+ * @param widget the widget
+ * @param id the id for the subwidget (usually an item)
+ * @return the SWT subwidget (usually an item) that the widget/id pair represents
+ *
+ * @exception SWTException 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 Display findDisplay (Thread thread) {
+ static_this();
+ synchronized (Device.classinfo) {
+ for (int i=0; i
+ * 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.
+ *
+ * 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.
+ *
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 + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept. + *
+ * + * @return the high contrast mode + * + * @exception SWTExceptionsyncExec
+ * 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 SWTExceptionSWT
. 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 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 + * 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 SWTExceptionSWT
. 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 null
+ *
+ * @exception SWTException
+ * 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.
+ *
+ * This method is called after create
.
+ *
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 hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+override public void internal_dispose_GC (HDC hDC, GCData data) {
+ OS.ReleaseDC (null, hDC);
+}
+
+bool isXMouseActive () {
+ /*
+ * NOTE: X-Mouse is active when bit 1 of the UserPreferencesMask is set.
+ */
+ bool xMouseActive = false;
+ TCHAR* key = StrToTCHARz( "Control Panel\\Desktop" ); //$NON-NLS-1$
+ void* phKey;
+ int result = OS.RegOpenKeyEx (cast(void*)OS.HKEY_CURRENT_USER, key, 0, OS.KEY_READ, &phKey);
+ if (result is 0) {
+ TCHAR* lpValueName = StrToTCHARz ( "UserPreferencesMask" ); //$NON-NLS-1$
+ uint[4] lpcbData;
+ uint lpData;
+ result = OS.RegQueryValueEx (phKey, lpValueName, null, null, cast(ubyte*)&lpData, lpcbData.ptr);
+ if (result is 0) xMouseActive = (lpData & 0x01) !is 0;
+ OS.RegCloseKey (phKey);
+ }
+ return xMouseActive;
+}
+
+bool isValidThread () {
+ return thread is Thread.getThis ();
+}
+
+/**
+ * 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 sourceControl
or null
+ * @param to the destination Control
or null
+ * @param point to be mapped
+ * @return point with mapped coordinates
+ *
+ * @exception IllegalArgumentException + * 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 sourceControl
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 + * 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 sourceControl
or null
+ * @param to the destination Control
or null
+ * @param rectangle to be mapped
+ * @return rectangle with mapped coordinates
+ *
+ * @exception IllegalArgumentException + * 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 sourceControl
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 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:
+ *
Either one of: + *
SWT
MouseDown, MouseUp
+ *The following fields in the Event
apply:
+ *
MouseMove
+ *The following fields in the Event
apply:
+ *
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.
+ *
false
if the caller can sleep upon return from this method
+ *
+ * @exception SWTException 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
.
+ *
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
+ *
+ * @exception IllegalArgumentException
+ * 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.
+ *
+ * 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.
+ *
null
for the name clears it.
+ *
+ * @param name the new app name or null
+ */
+public static void setAppName (String name) {
+ /* Do nothing */
+}
+
+void setModalDialog (Dialog modalDailog) {
+ this.modalDialog = modalDailog;
+ Shell [] shells = getShells ();
+ for (int i=0; itrue
if an event requiring dispatching was placed on the queue.
+ *
+ * @exception SWTException 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 ornull
+ *
+ * @exception SWTException 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+ * Note: For a given event, only the fields which are appropriate + * will be filled in. The contents of the fields which are not used + * by the event are unspecified. + *
+ * + * @see Listener + * @see org.eclipse.swt.events.TypedEvent + * @see SWT Example: ControlExample, Listeners + * @see Sample code and further information + */ + +public class Event { + + /** + * the display where the event occurred + * + * @since 2.0 + */ + public Display display; + + /** + * the widget that issued the event + */ + public Widget widget; + + /** + * the type of event, as defined by the event type constants + * in classSWT
+ *
+ * @see org.eclipse.swt.SWT
+ */
+ public int type;
+
+ /**
+ * the event specific detail field, as defined by the detail constants
+ * in class SWT
+ *
+ * @see org.eclipse.swt.SWT
+ */
+ public int detail;
+
+ /**
+ * the item that the event occurred in (can be null)
+ */
+ public Widget item;
+
+ /**
+ * the index of the item where the event occurred
+ *
+ * @since 3.2
+ */
+ public int index;
+
+ /**
+ * the graphics context to use when painting
+ * that is configured to use the colors, font and
+ * damaged region of the control. It is valid
+ * only during the paint and must not be disposed
+ */
+ public GC gc;
+
+ /**
+ * depending on the event type, the x offset of the bounding
+ * rectangle of the region that requires painting or the
+ * widget-relative, x coordinate of the pointer at the
+ * time the mouse button was pressed or released
+ */
+ public int x;
+
+ /**
+ * depending on the event type, the y offset of the bounding
+ * rectangle of the region that requires painting or the
+ * widget-relative, y coordinate of the pointer at the
+ * time the mouse button was pressed or released
+ */
+ public int y;
+
+ /**
+ * the width of the bounding rectangle of the
+ * region that requires painting
+ */
+ public int width;
+
+ /**
+ * the height of the bounding rectangle of the
+ * region that requires painting
+ */
+ public int height;
+
+ /**
+ * depending on the event type, the number of following
+ * paint events which are pending which may always be zero
+ * on some platforms or the number of lines or pages to
+ * scroll using the mouse wheel
+ */
+ public int count;
+
+ /**
+ * the time that the event occurred.
+ *
+ * NOTE: This field is an unsigned integer and should
+ * be AND'ed with 0xFFFFFFFFL so that it can be treated
+ * as a signed long.
+ */
+ public int time;
+
+ /**
+ * the button that was pressed or released; 1 for the
+ * first button, 2 for the second button, and 3 for the
+ * third button, etc.
+ */
+ public int button;
+
+ /**
+ * depending on the event, the character represented by the key
+ * that was typed. This is the final character that results
+ * after all modifiers have been applied. For example, when the
+ * user types Ctrl+A, the character value is 0x01 (ASCII SOH).
+ * It is important that applications do not attempt to modify the
+ * character value based on a stateMask (such as SWT.CTRL) or the
+ * resulting character will not be correct.
+ */
+ public wchar character = '\0';
+
+ /**
+ * depending on the event, the key code of the key that was typed,
+ * as defined by the key code constants in class SWT
.
+ * When the character field of the event is ambiguous, this field
+ * contains the unaffected value of the original character. For
+ * example, typing Ctrl+M or Enter both result in the character '\r'
+ * but the keyCode field will also contain '\r' when Enter was typed
+ * and 'm' when Ctrl+M was typed.
+ *
+ * @see org.eclipse.swt.SWT
+ */
+ public int keyCode;
+
+ /**
+ * depending on the event, the state of the keyboard modifier
+ * keys and mouse masks at the time the event was generated.
+ *
+ * @see org.eclipse.swt.SWT
+ */
+ public int stateMask;
+
+ /**
+ * depending on the event, the range of text being modified.
+ * Setting these fields only has effect during ImeComposition
+ * events.
+ */
+ public int start, end;
+
+ /**
+ * depending on the event, the new text that will be inserted.
+ * Setting this field will change the text that is about to
+ * be inserted or deleted.
+ */
+ public String text;
+
+ /**
+ * depending on the event, a flag indicating whether the operation
+ * should be allowed. Setting this field to false will cancel the
+ * operation.
+ */
+ public bool doit = true;
+
+ /**
+ * a field for application use
+ */
+ public Object data;
+
+/**
+ * Gets the bounds.
+ *
+ * @return a rectangle that is the bounds.
+ */
+public Rectangle getBounds () {
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Sets the bounds.
+ *
+ * @param rect the new rectangle
+ */
+public void setBounds (Rectangle rect) {
+ this.x = rect.x;
+ this.y = rect.y;
+ this.width = rect.width;
+ this.height = rect.height;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+override public String toString () {
+ return Format( "Event {{type={} {} time={} data={} x={} y={} width={} height={} detail={}}",
+ type, widget, time, data, x, y, width, height, detail ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+}
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/EventTable.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/EventTable.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit
+ * The item children that may be added to instances of this class
+ * must be of type ExpandItem
.
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see ExpandItem + * @see ExpandEvent + * @see ExpandListener + * @see ExpandAdapter + * @see ExpandBar snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + * + * @since 3.2 + */ +public class ExpandBar : Composite { + + alias Composite.computeSize computeSize; + alias Composite.windowProc windowProc; + + ExpandItem[] items; + int itemCount; + ExpandItem focusItem; + int spacing = 4; + int yCurrentScroll; + HFONT hFont; + + +/** + * 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.
+ *
ExpandListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException ExpandItem
s 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+ *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see ExpandBar + * @see Sample code and further information + * + * @since 3.2 + */ +public class ExpandItem : Item { + ExpandBar parent; + Control control; + bool expanded, hover; + int x, y, width, height; + int imageHeight, imageWidth; + static const int TEXT_INSET = 6; + static const int BORDER = 1; + static const int CHEVRON_SIZE = 24; + +/** + * 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.
+ *
+ * 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.
+ *
null
.
+ *
+ * @return the control
+ *
+ * @exception SWTException true
if the receiver is expanded,
+ * and false otherwise.
+ *
+ * @return the expanded state
+ *
+ * @exception SWTException ExpandBar
.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException + * 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. + *
+ * + * @see FileDialog snippets + * @see SWT Example: ControlExample, Dialog tab + * @see Sample code and further information + */ +public class FileDialog : Dialog { + String [] filterNames; + String [] filterExtensions; + String [] fileNames; + String filterPath = "", fileName = ""; + int filterIndex = 0; + bool overwrite = false; + static const String FILTER = "*.*"; + static int BUFFER_SIZE = 1024 * 32; + static bool USE_HOOK = true; + static this() { + /* + * Feature in Vista. When OFN_ENABLEHOOK is set in the + * save or open file dialog, Vista uses the old XP look + * and feel. OFN_ENABLEHOOK is used to grow the file + * name buffer in a multi-select file dialog. The fix + * is to only use OFN_ENABLEHOOK when the buffer has + * overrun. + */ + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + USE_HOOK = false; + } + } + +/** + * 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
+ * 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.
+ *
+ * This is an index into the FilterExtensions array and + * the FilterNames array. + *
+ * + * @return index the file extension filter index + * + * @see #getFilterExtensions + * @see #getFilterNames + * + * @since 3.4 + */ +public int getFilterIndex () { + return filterIndex; +} + +/** + * 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; +} + +/** + * Returns the flag that the dialog will use to + * determine whether to prompt the user for file + * overwrite if the selected file already exists. + * + * @return true if the dialog will prompt for file overwrite, false otherwise + * + * @since 3.4 + */ +public bool getOverwrite () { + return overwrite; +} + +private static extern(Windows) uint OFNHookProc (HWND hdlg, uint uiMsg, uint wParam, int lParam) { + switch (uiMsg) { + case OS.WM_NOTIFY: + OFNOTIFY* ofn = cast(OFNOTIFY*)lParam; + //OS.MoveMemory (ofn, lParam, OFNOTIFY.sizeof); + if (ofn.hdr.code is OS.CDN_SELCHANGE) { + int lResult = OS.SendMessage (ofn.hdr.hwndFrom, OS.CDM_GETSPEC, 0, 0); + if (lResult > 0) { + lResult += OS.MAX_PATH; + OPENFILENAME* lpofn = ofn.lpOFN; + //OS.MoveMemory (lpofn, ofn.lpOFN, OS.OPENFILENAME_sizeof); + if (lpofn.nMaxFile < lResult) { + auto hHeap = OS.GetProcessHeap (); + auto lpstrFile = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, lResult * TCHAR.sizeof); + if (lpstrFile !is null) { + if (lpofn.lpstrFile !is null) OS.HeapFree (hHeap, 0, lpofn.lpstrFile); + lpofn.lpstrFile = lpstrFile; + lpofn.nMaxFile = lResult; + //OS.MoveMemory (ofn.lpOFN, lpofn, OS.OPENFILENAME_sizeof); + } + } + } + } + break; + default: + } + return 0; +} + +/** + * 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+ * The strings are platform specific. For example, on + * some platforms, an extension filter string is typically + * of the form "*.extension", where "*.*" matches all files. + * For filters with multiple extensions, use semicolon as + * a separator, e.g. "*.jpg;*.png". + *
+ * + * @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; +} + +/** + * Set the 0-based index of the file extension filter + * which the dialog will use initially to filter the files + * it shows to the argument. + *+ * This is an index into the FilterExtensions array and + * the FilterNames array. + *
+ * + * @param index the file extension filter index + * + * @see #setFilterExtensions + * @see #setFilterNames + * + * @since 3.4 + */ +public void setFilterIndex (int index) { + filterIndex = index; +} + +/** + * Sets 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.
+ *
+ * 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; +} + +/** + * Sets the flag that the dialog will use to + * determine whether to prompt the user for file + * overwrite if the selected file already exists. + * + * @param overwrite true if the dialog will prompt for file overwrite, false otherwise + * + * @since 3.4 + */ +public void setOverwrite (bool overwrite) { + this.overwrite = overwrite; +} +} + diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/FontDialog.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/FontDialog.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,336 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank Benoit+ * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *
+ * + * @see SWT Example: ControlExample, Dialog tab + * @see Sample code and further information + */ +public class FontDialog : 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
+ * 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.
+ *
+ * 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. + *
+ * Note: Only one of the above styles may be specified. + *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see SWT Example: ControlExample + * @see Sample code and further information + */ + +public class Group : Composite { + + alias Composite.computeSize computeSize; + alias Composite.windowProc windowProc; + + String text = ""; + static const int CLIENT_INSET = 3; + private static /+const+/ WNDPROC GroupProc; + static if( OS.IsWinCE ){ + static const TCHAR[] GroupClass = "BUTTON\0"; + } + else{ + static const TCHAR[] GroupClass = "SWT_GROUP\0"; + } + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + /* + * 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 control. + * + * 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; + static if (OS.IsWinCE) { + OS.GetClassInfo (null, GroupClass.ptr, &lpWndClass); + GroupProc = lpWndClass.lpfnWndProc; + } else { + TCHAR[] WC_BUTTON = "BUTTON\0"; + OS.GetClassInfo (null, WC_BUTTON.ptr, &lpWndClass); + GroupProc = lpWndClass.lpfnWndProc; + auto hInstance = OS.GetModuleHandle (null); + if (!OS.GetClassInfo (hInstance, GroupClass.ptr, &lpWndClass)) { + auto hHeap = OS.GetProcessHeap (); + lpWndClass.hInstance = hInstance; + lpWndClass.style &= ~(OS.CS_HREDRAW | OS.CS_VREDRAW); + int byteCount = GroupClass.length * TCHAR.sizeof; + auto lpszClassName = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + OS.MoveMemory (lpszClassName, GroupClass.ptr, byteCount); + lpWndClass.lpszClassName = lpszClassName; + OS.RegisterClass (&lpWndClass); + OS.HeapFree (hHeap, 0, lpszClassName); + } + } + static_this_completed = true; + } + } + +/** + * 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.
+ *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see Sample code and further information + * + * @since 3.4 + */ +public class IME : Widget { + Canvas parent; + int caretOffset; + int startOffset; + int commitCount; + String text; + int [] ranges; + TextStyle [] styles; + + static const int WM_MSIME_MOUSE; + + static byte [16] IID_ITfInputProcessorProfiles; + static byte [16] IID_ITfDisplayAttributeProvider; + static byte [16] CLSID_TF_InputProcessorProfiles; + static byte [16] GUID_TFCAT_TIP_KEYBOARD; + static this() { + WM_MSIME_MOUSE = OS.RegisterWindowMessage (StrToTCHARz ("MSIMEMouseOperation")); + + OS.IIDFromString ("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}\0"w.ptr, IID_ITfInputProcessorProfiles.ptr); + OS.IIDFromString ("{fee47777-163c-4769-996a-6e9c50ad8f54}\0"w.ptr, IID_ITfDisplayAttributeProvider.ptr); + OS.IIDFromString ("{33C53A50-F456-4884-B049-85FD643ECFED}\0"w.ptr, CLSID_TF_InputProcessorProfiles.ptr); + OS.IIDFromString ("{34745C63-B2F0-4784-8B67-5E12C8701A31}\0"w.ptr, GUID_TFCAT_TIP_KEYBOARD.ptr); + } + + /* TextLayout has a copy of these constants */ + static const int UNDERLINE_IME_DOT = 1 << 16; + static const int UNDERLINE_IME_DASH = 2 << 16; + static const int UNDERLINE_IME_THICK = 3 << 16; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this () { +} + +/** + * 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.
+ *
+ * The ranges array contains start and end pairs. Each pair refers to
+ * the corresponding style in the styles array. For example, the pair
+ * that starts at ranges[n] and ends at ranges[n+1] uses the style
+ * at styles[n/2] returned by getStyles()
.
+ *
+ * The ranges array contains start and end pairs. Each pair refers to + * the corresponding style in the styles array. For example, the pair + * that starts at ranges[n] and ends at ranges[n+1] uses the style + * at styles[n/2]. + *
+ * + * @return the ranges for the styles + * + * @exception SWTException+ * The text for an IME is the characters in the widget that + * are in the current composition. When the commit count is + * equal to the length of the composition text, then the + * in-line edit operation is complete. + *
+ * + * @return the widget text + * + * @exception SWTExceptiontrue
if the caret should be wide, and
+ * false
otherwise. In some languages, for example
+ * Korean, the caret is typically widened to the width of the
+ * current character in the in-line edit session.
+ *
+ * @return the wide caret state
+ *
+ * @exception SWTException
+ * 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.
+ *
+ * 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.
+ *
+ * Shadow styles are hints and may not be honoured + * by the platform. To create a separator label + * with the default shadow style for the platform, + * do not specify a shadow style. + *
+ *+ * 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. + *
+ * + * @see Label snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + */ +public class Label : Control { + + alias Control.computeSize computeSize; + alias Control.windowProc windowProc; + + String text = ""; + Image image; + static const int MARGIN = 4; + static const bool IMAGE_AND_TEXT = false; + private static /+const+/ WNDPROC LabelProc; + static const TCHAR[] LabelClass = "STATIC\0"; + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + WNDCLASS lpWndClass; + OS.GetClassInfo (null, LabelClass.ptr, &lpWndClass); + LabelProc = lpWndClass.lpfnWndProc; + static_this_completed = true; + } + } + + +/** + * 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.
+ *
LEFT
, RIGHT
or CENTER
+ * unless the receiver is a SEPARATOR
label, in
+ * which case, NONE
is returned.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException SEPARATOR
label.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException 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 + * 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 SWTException+ * This method computes the size that the client area + * of the composite must be in order to position all + * children at their preferred size inside the + * composite according to the layout algorithm + * encoded by this layout. + *
+ *+ * When a width or height hint is supplied, it is + * used to constrain the result. For example, if a + * width hint is provided that is less than the + * width of the client area, the layout may choose + * to wrap and increase height, clip, overlap, or + * otherwise constrain the children. + *
+ * + * @param composite a composite widget using this layout + * @param wHint width (SWT.DEFAULT
for preferred size)
+ * @param hHint height (SWT.DEFAULT
for preferred size)
+ * @param flushCache true
means flush cached layout values
+ * @return a point containing the computed size (width, height)
+ *
+ * @see #layout
+ * @see Control#getBorderWidth
+ * @see Control#getBounds
+ * @see Control#getSize
+ * @see Control#pack(boolean)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+abstract Point computeSize (Composite composite, int wHint, int hHint, bool flushCache);
+
+/**
+ * Instruct the layout to flush any cached values
+ * associated with the control specified in the argument
+ * control
.
+ *
+ * @param control a control managed by this layout
+ * @return true if the Layout has flushed all cached information associated with control
+ *
+ * @since 3.1
+ */
+bool flushCache (Control control) {
+ return false;
+}
+
+/**
+ * Lays out the children of the specified composite
+ * according to this layout.
+ * + * This method positions and sizes the children of a + * composite using the layout algorithm encoded by this + * layout. Children of the composite are positioned in + * the client area of the composite. The position of + * the composite is not altered by this method. + *
+ *+ * When the flush cache hint is true, the layout is + * instructed to flush any cached values associated + * with the children. Typically, a layout will cache + * the preferred sizes of the children to avoid the + * expense of computing these values each time the + * widget is laid out. + *
+ *+ * When layout is triggered explicitly by the programmer + * the flush cache hint is true. When layout is triggered + * by a resize, either caused by the programmer or by the + * user, the hint is false. + *
+ * + * @param composite a composite widget using this layout + * @param flushCachetrue
means flush cached layout values
+ */
+abstract void layout (Composite composite, bool flushCache);
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Link.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Link.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1073 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit + *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see Link snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + * + * @since 3.1 + */ +public class Link : Control { + + alias Control.computeSize computeSize; + alias Control.windowProc windowProc; + + String text; + TextLayout layout; + Color linkColor, disabledColor; + Point [] offsets; + Point selection; + String [] ids; + int [] mnemonics; + int focusIndex, mouseDownIndex; + HFONT font; + static /+const+/ RGB LINK_FOREGROUND; + static /+const+/ WNDPROC LinkProc; + static const TCHAR[] LinkClass = OS.WC_LINK; + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + LINK_FOREGROUND = new RGB (0, 51, 153); + if (OS.COMCTL32_MAJOR >= 6) { + WNDCLASS lpWndClass; + OS.GetClassInfo (null, LinkClass.ptr, &lpWndClass); + LinkProc = lpWndClass.lpfnWndProc; + /* + * Feature in Windows. The SysLink window class + * does not include CS_DBLCLKS. This means that these + * controls will not get double click messages such as + * WM_LBUTTONDBLCLK. The fix is to register a new + * window class with CS_DBLCLKS. + * + * NOTE: Screen readers look for the exact class name + * of the control in order to provide the correct kind + * of assistance. Therefore, it is critical that the + * new window class have the same name. It is possible + * to register a local window class with the same name + * as a global class. Since bits that affect the class + * are being changed, it is possible that other native + * code, other than SWT, could create a control with + * this class name, and fail unexpectedly. + */ + auto hInstance = OS.GetModuleHandle (null); + auto hHeap = OS.GetProcessHeap (); + lpWndClass.hInstance = hInstance; + lpWndClass.style &= ~OS.CS_GLOBALCLASS; + lpWndClass.style |= OS.CS_DBLCLKS; + int byteCount = LinkClass.length * TCHAR.sizeof; + auto lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + OS.MoveMemory (lpszClassName, LinkClass.ptr, byteCount); + lpWndClass.lpszClassName = lpszClassName; + OS.RegisterClass (&lpWndClass); + OS.HeapFree (hHeap, 0, lpszClassName); + } else { + LinkProc = null; + } + static_this_completed = true; + } + } + +/** + * 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.
+ *
SelectionListener
+ * interface.
+ *
+ * widgetSelected
is called when the control is selected by the user.
+ * widgetDefaultSelected
is not called.
+ *
+ * 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 SWTException+ *
+ * Note: Only one of SINGLE and MULTI may be specified. + *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see List snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + */ + +public class List : Scrollable { + + alias Scrollable.computeSize computeSize; + alias Scrollable.windowProc windowProc; + + static const int INSET = 3; + private static /+const+/ WNDPROC ListProc; + static const TCHAR[] ListClass = "LISTBOX"; + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + WNDCLASS lpWndClass; + OS.GetClassInfo (null, ListClass.ptr, &lpWndClass); + ListProc = lpWndClass.lpfnWndProc; + static_this_completed = true; + } + } + +/** + * 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: To add an item at the end of the list, use the
+ * result of calling getItemCount()
as the
+ * index or use add(String)
.
+ *
SelectionListener
+ * interface.
+ *
+ * widgetSelected
is called when the selection changes.
+ * widgetDefaultSelected
is typically called when an item is double-clicked.
+ *
String
s 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+ * 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+ * 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+ * 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 SWTException
false
otherwise. Indices out of
+ * range are ignored.
+ *
+ * @param index the index of the item
+ * @return the selection state of the item at the index
+ *
+ * @exception SWTException + * @exception SWTException
+ * 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 SWTException
+ * 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
+ * If the receiver is single-select, do nothing. + * + * @exception SWTException
+ * 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 SWTException
+ * 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
Listener
provide a simple
+ * handleEvent()
method that is used internally
+ * by SWT to dispatch events.
+ *
+ * After creating an instance of a class that implements this interface
+ * it can be added to a widget using the
+ * addListener(int eventType, Listener handler)
method and
+ * removed using the
+ * removeListener (int eventType, Listener handler)
method.
+ * When the specified event occurs, handleEvent(...)
will
+ * be sent to the instance.
+ *
+ * Classes which implement this interface are described within SWT as
+ * providing the untyped listener API. Typically, widgets will
+ * also provide a higher-level typed listener API, that is based
+ * on the standard java.util.EventListener
pattern.
+ *
+ * Note that, since all internal SWT event dispatching is based on untyped + * listeners, it is simple to build subsets of SWT for use on memory + * constrained, small footprint devices, by removing the classes and + * methods which implement the typed listener API. + *
+ * + * @see Widget#addListener + * @see java.util.EventListener + * @see org.eclipse.swt.events + */ +public interface Listener { + +/** + * Sent when an event that the receiver has registered for occurs. + * + * @param event the event which occurred + */ +void handleEvent (Event event); +} + + +/// Helper class for the dgListener template function +private class _DgListenerT(Dg,T...) : Listener { + + alias ParameterTupleOf!(Dg) DgArgs; + static assert( is(DgArgs == Tuple!(Event,T)), + "Delegate args not correct: delegate args: ("~DgArgs.stringof~") vs. passed args: ("~Tuple!(Event,T).stringof~")" ); + + Dg dg; + T t; + + private this( Dg dg, T t ){ + this.dg = dg; + static if( T.length > 0 ){ + this.t = t; + } + } + + void handleEvent( Event e ){ + dg(e,t); + } +} + +/++ + + dgListener creates a class implementing the Listener interface and delegating the call to + + handleEvent to the users delegate. This template function will store also additional parameters. + + + + Examle of usage: + + --- + + void handleTextEvent (Event e, int inset ) { + + // ... + + } + + text.addListener (SWT.FocusOut, dgListener( &handleTextEvent, inset )); + + --- + +/ +Listener dgListener( Dg, T... )( Dg dg, T args ){ + return new _DgListenerT!( Dg, T )( dg, args ); +} + + + diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Menu.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Menu.d Mon Mar 02 14:44:16 2009 +0100 @@ -0,0 +1,1584 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Port to the D programming language: + * Frank Benoit+ * 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. + *
+ * + * @see Menu snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + */ + +public class Menu : 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 HMENU handle; + + int x, y; + HBRUSH hBrush; + HWND hwndCB; + int id0, id1; + int foreground = -1, background = -1; + Image backgroundImage; + bool hasLocation; + MenuItem cascade; + Decorations parent; + ImageList imageList; + + /* Resource ID for SHMENUBARINFO */ + static const int ID_PPC = 100; + + /* SmartPhone SoftKeyBar resource ids */ + static const int ID_SPMM = 102; + static const int ID_SPBM = 103; + static const int ID_SPMB = 104; + static const int ID_SPBB = 105; + static const int ID_SPSOFTKEY0 = 106; + static const 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. + *
+ * After constructing a menu, it can be set into its parent
+ * using parent.setMenu(menu)
. In this case, the parent may
+ * be any control in the same widget tree as the parent.
+ *
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.
+ *
+ * After constructing a menu or menuBar, it can be set into its parent
+ * using parent.setMenu(menu)
or parent.setMenuBar(menuBar)
.
+ *
Menu
) and sets the style
+ * for the instance so that the instance will be a drop-down
+ * menu on the given parent's parent.
+ *
+ * After constructing a drop-down menu, it can be set into its parentMenu
+ * using parentMenu.setMenu(menu)
.
+ *
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.
+ *
+ * After constructing a drop-down menu, it can be set into its parentItem
+ * using parentItem.setMenu(menu)
.
+ *
HelpListener
interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException MenuListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException + * 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 SWTExceptiontrue
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 MenuItem
s 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 SWTExceptionMenuItem
or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException Menu
or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException 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 SWTExceptiontrue
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 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 null
.
+ *
+ * @param item the default menu item or null
+ *
+ * @exception IllegalArgumentException 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 + * 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+ * 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 IllegalArgumentExceptiontrue
,
+ * 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+ * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR + * may be specified. + *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @see Sample code and further information + */ + +public class MenuItem : Item { + Menu parent, menu; + HBITMAP hBitmap; + int id, accelerator; + /* + * Feature in Windows. On Windows 98, it is necessary + * to add 4 pixels to the width of the image or the image + * and text are too close. On other Windows platforms, + * this causes the text of the longest item to touch the + * accelerator text. The fix is to use smaller margins + * everywhere but on Windows 98. + */ + private static int MARGIN_WIDTH_; + public static int MARGIN_WIDTH(){ + assert( static_this_completed ); + return MARGIN_WIDTH_; + } + private static int MARGIN_HEIGHT_; + public static int MARGIN_HEIGHT(){ + assert( static_this_completed ); + return MARGIN_HEIGHT_; + } + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + MARGIN_WIDTH_ = OS.IsWin95 ? 2 : 1; + MARGIN_HEIGHT_ = OS.IsWin95 ? 2 : 1; + static_this_completed = true; + } + } + +/** + * Constructs a new instance of this class given its parent + * (which must be aMenu
) 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.
+ *
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.
+ *
ArmListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException HelpListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException SelectionListener
+ * interface.
+ *
+ * When widgetSelected
is called, the stateMask field of the event object is valid.
+ * widgetDefaultSelected
is not called.
+ *
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 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 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 Menu
.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException 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
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 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 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 + * 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 SWTExceptionCASCADE
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 IllegalArgumentExceptionCASCADE
+ * When the receiver is of type CHECK
or RADIO
,
+ * it is selected when it is checked.
+ *
+ * @param selected the new selection state
+ *
+ * @exception SWTException
+ * 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 SWTException+ * 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. + *
+ * + * @see SWT Example: ControlExample, Dialog tab + * @see Sample code and further information + */ +public class MessageBox : Dialog { + + alias Dialog.checkStyle checkStyle; + + String message = ""; + private bool allowNullParent = false; + +/** + * 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
+ * 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
true
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals (Object object) {
+ if (object is this) return true;
+ if ( auto mon = cast(org.eclipse.swt.widgets.Monitor.Monitor)object ){
+ return handle is mon.handle;
+ }
+ return false;
+}
+
+/**
+ * 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 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 override hash_t toHash() {
+ return cast(hash_t)handle;
+}
+
+}
diff -r 000000000000 -r 6dd524f61e62 org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ProgressBar.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ProgressBar.d Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,483 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ * Frank Benoit + * 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. + *
+ * + * @see ProgressBar snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + */ +public class ProgressBar : Control { + + alias Control.computeSize computeSize; + alias Control.windowProc windowProc; + + static const int DELAY = 100; + static const int TIMER_ID = 100; + static const int MINIMUM_WIDTH = 100; + private static /+const+/ WNDPROC ProgressBarProc; + static const TCHAR[] ProgressBarClass = OS.PROGRESS_CLASS; + + private static bool static_this_completed = false; + private static void static_this() { + if( static_this_completed ){ + return; + } + synchronized { + if( static_this_completed ){ + return; + } + WNDCLASS lpWndClass; + OS.GetClassInfo (null, ProgressBarClass.ptr, &lpWndClass); + ProgressBarProc = lpWndClass.lpfnWndProc; + /* + * Feature in Windows. The progress bar window class + * does not include CS_DBLCLKS. This means that these + * controls will not get double click messages such as + * WM_LBUTTONDBLCLK. The fix is to register a new + * window class with CS_DBLCLKS. + * + * NOTE: Screen readers look for the exact class name + * of the control in order to provide the correct kind + * of assistance. Therefore, it is critical that the + * new window class have the same name. It is possible + * to register a local window class with the same name + * as a global class. Since bits that affect the class + * are being changed, it is possible that other native + * code, other than SWT, could create a control with + * this class name, and fail unexpectedly. + */ + auto hInstance = OS.GetModuleHandle (null); + auto hHeap = OS.GetProcessHeap (); + lpWndClass.hInstance = hInstance; + lpWndClass.style &= ~OS.CS_GLOBALCLASS; + lpWndClass.style |= OS.CS_DBLCLKS; + int byteCount = (ProgressBarClass.length+1) * TCHAR.sizeof; + TCHAR* lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + OS.MoveMemory (lpszClassName, ProgressBarClass.ptr, byteCount); + lpWndClass.lpszClassName = lpszClassName; + OS.RegisterClass (&lpWndClass); + OS.HeapFree (hHeap, 0, lpszClassName); + static_this_completed = true; + } + } + +/** + * 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: Only one of the styles HORIZONTAL and VERTICAL may be specified. + *
+ * IMPORTANT: This class is intended to be subclassed only + * within the SWT implementation. + *
+ * + * @see Sash snippets + * @see SWT Example: ControlExample + * @see Sample code and further information + */ +public class Sash : Control { + + alias Control.computeSize computeSize; + alias Control.windowProc windowProc; + + bool dragging; + int startX, startY, lastX, lastY; + const static int INCREMENT = 1; + const 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.
+ *
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.
+ *