# HG changeset patch
# User Jacob Carlborg
+ * By defining constants like UP and DOWN in a single class, DWT
+ * 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 DWT.Paint event is not sent. When it gets bigger, an DWT.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 final char BS = '\b';
+
+ /**
+ * ASCII character convenience constant for the carriage return character
+ * (value is the char
'\r').
+ */
+ public static final char CR = '\r';
+
+ /**
+ * ASCII character convenience constant for the delete character
+ * (value is the char
with value 127).
+ */
+ public static final char DEL = 0x7F;
+
+ /**
+ * ASCII character convenience constant for the escape character
+ * (value is the char
with value 27).
+ */
+ public static final char ESC = 0x1B;
+
+ /**
+ * ASCII character convenience constant for the line feed character
+ * (value is the char
'\n').
+ */
+ public static final char LF = '\n';
+
+ /**
+ * ASCII character convenience constant for the tab character
+ * (value is the char
'\t').
+ *
+ * @since 2.1
+ */
+ public static final 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 & DWT.MODIFIER_MASK) !is 0
.
+ *
+ * @since 2.1
+ */
+ public static const int MODIFIER_MASK;
+
+ /**
+ * 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 & DWT.BUTTON_MASK) !is 0
.
+ *
+ * @since 2.1
+ */
+ public static const int BUTTON_MASK;
+
+ /**
+ * 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;
+
+ /**
+ * 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;
+
+ /**
+ * 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;
+
+ /**
+ * 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;
+
+ /**
+ * Constants to indicate line scrolling (value is 1).
+ * Used By:
Control
Used By:
Control
((DWT.MOD1 | DWT.MOD2 | 'T') & DWT.KEYCODE_BIT) !is 0
.
+ *
+ * The following expression is true:
+ *
+ * ((DWT.MOD3 | DWT.F2) & DWT.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 DWT.Help.
+ *
+ * @since 3.0
+ *
+ * @see DWT#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 dwt.widgets.Widget#checkSubclass
+ */
+ public static const int ERROR_INVALID_SUBCLASS = 43;
+
+ /**
+ * DWT error constant indicating that an attempt was made to
+ * invoke an DWT operation using a graphics object which had
+ * already been disposed
+ * (value is 44).
+ */
+ public static const int ERROR_GRAPHIC_DISPOSED = 44;
+
+ /**
+ * DWT error constant indicating that an attempt was made to
+ * invoke an DWT operation using a device which had already
+ * been disposed
+ * (value is 45).
+ */
+ public static const int ERROR_DEVICE_DISPOSED = 45;
+
+ /**
+ * DWT error constant indicating that an exception happened
+ * when executing a runnable
+ * (value is 46).
+ */
+ public static const int ERROR_FAILED_EXEC = 46;
+
+ /**
+ * DWT 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;
+
+ /**
+ * DWT 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 DWT to throw an exception.
+ * + * In DWT, errors are reported by throwing one of three exceptions: + *
throwable
argument should be either null, or the
+ * throwable which caused DWT to throw an exception.
+ * + * In DWT, 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)).
+ * + * DWTErrors are thrown when something fails internally which + * either leaves DWT in an unknown state (eg. the o/s call to + * remove an item from a list returns an error code) or when DWT + * is left in a known-to-be-unrecoverable state (eg. it runs out + * of callback resources). DWTErrors should not occur in typical + * programs, although "high reliability" applications should + * still catch them. + *
+ * This class also provides support methods used by DWT to match + * error codes to the appropriate exception class (DWTError, + * DWTException, or IllegalArgumentException) and to provide + * human readable Strings for DWT error codes. + *
+ * + * @see DWTException + * @see DWT#error(int) + */ + +public class DWTError : PlatformException { + /** + * The DWT error code, one of DWT.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(DWT.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(DWT.ERROR_UNSPECIFIED, message);
+ }
+
+ /**
+ * Constructs a new instance of this class with its
+ * stack trace and error code filled in.
+ *
+ * @param code the DWT error code
+ */
+ public this (int code) {
+ this(code, DWT.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 DWT 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 DWTError object. + *+ * It is combined with the message String of the Throwable + * which caused this DWTError (if this information is available). + *
+ * @return the error message String of this DWTError object + */ + public String getMessage () { + if (throwable is null) + return super.getMessage(); + return super.getMessage() + " (" + 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 () { + super.printStackTrace(); + if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0) && throwable !is null) { + System.err.println("*** Stack trace of contained error ***"); //$NON-NLS-1$ + throwable.printStackTrace(); + } + } + +} diff -r 000000000000 -r 380af2bdd8e5 dwt/DWTException.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/DWTException.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,152 @@ +/******************************************************************************* + * 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: + * Jacob Carlborgthrowable
field which holds the underlying
+ * exception that caused the problem (if this information is
+ * available (i.e. it may be null)).
+ * + * DWTExceptions are thrown when something fails internally, + * but DWT 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 DWTError + */ + +public class DWTException : Exception { + /** + * The DWT error code, one of DWT.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(DWT.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(DWT.ERROR_UNSPECIFIED, message);
+ }
+
+ /**
+ * Constructs a new instance of this class with its
+ * stack trace and error code filled in.
+ *
+ * @param code the DWT error code
+ */
+ public this (int code) {
+ this(code, DWT.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 DWT 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 DWTException object. + *+ * It is combined with the message String of the Throwable + * which caused this DWTException (if this information is available). + *
+ * @return the error message String of this DWTException object + */ + public String getMessage () { + if (throwable is null) + return super.getMessage(); + return super.getMessage() + " (" + 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 () { + super.printStackTrace(); + if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0) && throwable !is null) { + System.err.println("*** Stack trace of contained exception ***"); //$NON-NLS-1$ + throwable.printStackTrace(); + } + } + +} diff -r 000000000000 -r 380af2bdd8e5 dwt/accessibility/ACC.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/accessibility/ACC.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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: + * Jacob CarlborggetAccessible
, and then add an accessible listener
+ * to override simple items like the name and help string, or they
+ * can add an accessible control listener to override complex items.
+ * As a rule of thumb, an application would only want to use the
+ * accessible control listener to implement accessibility for a
+ * custom control.
+ *
+ * @see Control#getAccessible
+ * @see AccessibleListener
+ * @see AccessibleEvent
+ * @see AccessibleControlListener
+ * @see AccessibleControlEvent
+ *
+ * @since 2.0
+ */
+public class Accessible {
+ Control control;
+
+ this (Control control) {
+ this.control = control;
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an accessible client asks for certain strings,
+ * such as name, description, help, or keyboard shortcut. The
+ * listener is notified by sending it one of the messages defined
+ * in the AccessibleListener
interface.
+ *
+ * @param listener the listener that should be notified when the receiver
+ * is asked for a name, description, help, or keyboard shortcut string
+ *
+ * @exception IllegalArgumentException 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 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 DWTException
+ * 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 DWT. 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 DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
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 + * + * @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 + * + * @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 + * + * @since 2.0 + */ +public class AccessibleControlEvent : DWTEventObject { + 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 "AccessibleControlEvent {childID=" + childID + //$NON-NLS-1$ + " accessible=" + accessible + //$NON-NLS-1$ + " x=" + x + //$NON-NLS-1$ + " y=" + y + //$NON-NLS-1$ + " width=" + width + //$NON-NLS-1$ + " height=" + height + //$NON-NLS-1$ + " detail=" + detail + //$NON-NLS-1$ + " result=" + result + //$NON-NLS-1$ + "}"; //$NON-NLS-1$ + } +} diff -r 000000000000 -r 380af2bdd8e5 dwt/accessibility/AccessibleControlListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/accessibility/AccessibleControlListener.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,237 @@ +/******************************************************************************* + * 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: + * Jacob Carlborg
+ * 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 : DWTEventListener { + + /** + * 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 + * + * @since 2.0 + */ +public class AccessibleEvent : DWTEventObject { + /** + * 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 + */ + public String toString () { + return "AccessibleEvent {childID=" + childID + " result=" + result + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } +} diff -r 000000000000 -r 380af2bdd8e5 dwt/accessibility/AccessibleListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/accessibility/AccessibleListener.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,130 @@ +/******************************************************************************* + * 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: + * Jacob Carlborg
+ * 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 : DWTEventListener { + + /** + * 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 + * + * @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 + * + * @since 3.0 + */ +public class AccessibleTextEvent : DWTEventObject { + 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 + */ + public String toString () { + return "AccessibleTextEvent {childID=" ~ childID + //$NON-NLS-1$ + " offset=" + offset + //$NON-NLS-1$ + " length=" + length + //$NON-NLS-1$ + "}"; //$NON-NLS-1$ + } +} diff -r 000000000000 -r 380af2bdd8e5 dwt/accessibility/AccessibleTextListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/accessibility/AccessibleTextListener.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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: + * Jacob Carlborg
+ * 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 : DWTEventListener { + + /** + * 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.
+ *
+ * Note that although this class is a subclass of Composite
,
+ * it does not make sense to set a layout on it.
+ *
+ * IMPORTANT: This class is not intended to be subclassed. + *
+ * + * @since 3.0 + */ + +public class Browser : Composite { + WebBrowser webBrowser; + int userStyle; + + static final String PACKAGE_PREFIX = "dwt.browser."; //$NON-NLS-1$ + static final String NO_INPUT_METHOD = "dwt.internal.gtk.noInputMethod"; //$NON-NLS-1$ + + /** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *
+ * The style value is either one of the style constants defined in
+ * class DWT
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 DWT
style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ * This notification occurs when a javascript command such as
+ * window.close
gets executed by a Browser
.
+ *
+ * This notification typically occurs when the application navigates + * to a new location with {@link #setUrl(String)} or when the user + * activates a hyperlink. + *
+ * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
+ * This notification occurs when a javascript command such as
+ * window.open
gets executed by a Browser
.
+ *
+ * The status text is typically displayed in the status bar of + * a browser application. + *
+ * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentExceptiontrue
if the operation was successful and false
otherwise
+ *
+ * @exception DWTException
+ * Execute a script containing javascript commands in the context of the current document.
+ *
+ * @param script the script with javascript commands
+ *
+ * @return true
if the operation was successful and false
otherwise
+ *
+ * @exception IllegalArgumentException
true
if the operation was successful and false
otherwise
+ *
+ * @exception DWTException String
+ * if this is empty
+ *
+ * @exception DWTException String
if there is no current URL
+ *
+ * @exception DWTException nsIWebBrowser
for the receiver, or null
+ * if it is not available. In order for an nsIWebBrowser
to be returned all
+ * of the following must be true: DWT.MOZILLA
nsIWebBrowser
or null
+ *
+ * @since 3.3
+ */
+ public Object getWebBrowser () {
+ checkWidget();
+ return webBrowser.getWebBrowser();
+ }
+
+ /**
+ * Returns true
if the receiver can navigate to the
+ * previous session history item, and false
otherwise.
+ *
+ * @return the receiver's back command enabled state
+ *
+ * @exception DWTException true
if the receiver can navigate to the
+ * next session history item, and false
otherwise.
+ *
+ * @return the receiver's forward command enabled state
+ *
+ * @exception DWTException
+ * The html parameter is Unicode encoded since it is a java String
.
+ * As a result, the HTML meta tag charset should not be set. The charset is implied
+ * by the String
itself.
+ *
+ * @param html the HTML content to be rendered
+ *
+ * @return true if the operation was successful and false otherwise.
+ *
+ * @exception IllegalArgumentException
Browser
. The Browser
is disposed after this
+ * notification.
+ *
+ * The following fields in the WindowEvent
apply:
+ *
Browser
that is going to be disposed
+ * WindowEvent
that specifies the Browser
+ * that is going to be disposed
+ *
+ * @see dwt.widgets.Shell#close()
+ *
+ * @since 3.0
+ */
+ public void close (WindowEvent event);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/Download.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/Download.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,386 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.Download;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.Compatibility;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDownload;
+import dwt.internal.mozilla.nsIHelperAppLauncher;
+import dwt.internal.mozilla.nsILocalFile;
+import dwt.internal.mozilla.nsIProgressDialog;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIWebProgressListener;
+import dwt.layout.GridData;
+import dwt.layout.GridLayout;
+import dwt.widgets.Button;
+import dwt.widgets.Event;
+import dwt.widgets.Label;
+import dwt.widgets.Listener;
+import dwt.widgets.Shell;
+
+class Download {
+ XPCOMObject supports;
+ XPCOMObject download;
+ XPCOMObject progressDialog;
+ XPCOMObject webProgressListener;
+ nsIHelperAppLauncher helperAppLauncher;
+ int refCount = 0;
+
+ Shell shell;
+ Label status;
+ Button cancel;
+
+Download () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ download = new XPCOMObject (new int[] {2, 0, 0, 7, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return Init (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return GetSource (args[0]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return GetTarget (args[0]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return GetPersist (args[0]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return GetPercentComplete (args[0]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return GetDisplayName (args[0]);}
+ public int /*long*/ method9 (int /*long*/[] args) {return SetDisplayName (args[0]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return GetStartTime (args[0]);}
+ public int /*long*/ method11 (int /*long*/[] args) {return GetMIMEInfo (args[0]);}
+ public int /*long*/ method12 (int /*long*/[] args) {return GetListener (args[0]);}
+ public int /*long*/ method13 (int /*long*/[] args) {return SetListener (args[0]);}
+ public int /*long*/ method14 (int /*long*/[] args) {return GetObserver (args[0]);}
+ public int /*long*/ method15 (int /*long*/[] args) {return SetObserver (args[0]);}
+ };
+
+ progressDialog = new XPCOMObject (new int[] {2, 0, 0, 7, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return Init (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return GetSource (args[0]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return GetTarget (args[0]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return GetPersist (args[0]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return GetPercentComplete (args[0]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return GetDisplayName (args[0]);}
+ public int /*long*/ method9 (int /*long*/[] args) {return SetDisplayName (args[0]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return GetStartTime (args[0]);}
+ public int /*long*/ method11 (int /*long*/[] args) {return GetMIMEInfo (args[0]);}
+ public int /*long*/ method12 (int /*long*/[] args) {return GetListener (args[0]);}
+ public int /*long*/ method13 (int /*long*/[] args) {return SetListener (args[0]);}
+ public int /*long*/ method14 (int /*long*/[] args) {return GetObserver (args[0]);}
+ public int /*long*/ method15 (int /*long*/[] args) {return SetObserver (args[0]);}
+ public int /*long*/ method16 (int /*long*/[] args) {return Open (args[0]);}
+ public int /*long*/ method17 (int /*long*/[] args) {return GetCancelDownloadOnClose (args[0]);}
+ public int /*long*/ method18 (int /*long*/[] args) {return SetCancelDownloadOnClose ((int)/*64*/args[0]);}
+ public int /*long*/ method19 (int /*long*/[] args) {return GetDialog (args[0]);}
+ public int /*long*/ method20 (int /*long*/[] args) {return SetDialog (args[0]);}
+ };
+
+ webProgressListener = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (download !is null) {
+ download.dispose ();
+ download = null;
+ }
+ if (progressDialog !is null) {
+ progressDialog.dispose ();
+ progressDialog = null;
+ }
+ if (webProgressListener !is null) {
+ webProgressListener.dispose ();
+ webProgressListener = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return progressDialog.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIDownload.NS_IDOWNLOAD_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {download.getAddress ()}, C.PTR_SIZEOF);
+ AddRef();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIProgressDialog.NS_IPROGRESSDIALOG_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {progressDialog.getAddress ()}, C.PTR_SIZEOF);
+ AddRef();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {webProgressListener.getAddress ()}, C.PTR_SIZEOF);
+ AddRef();
+ return XPCOM.NS_OK;
+ }
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIDownload */
+
+/* Note. The argument startTime is defined as a PRInt64. This translates into two java ints. */
+int Init (int /*long*/ aSource, int /*long*/ aTarget, int /*long*/ aDisplayName, int /*long*/ aMIMEInfo, int /*long*/ startTime1, int /*long*/ startTime2, int /*long*/ aPersist) {
+ nsIURI source = new nsIURI (aSource);
+ int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+ int rc = source.GetHost (aSpec);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ int length = XPCOM.nsEmbedCString_Length (aSpec);
+ int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+ byte[] dest = new byte[length];
+ XPCOM.memmove (dest, buffer, length);
+ XPCOM.nsEmbedCString_delete (aSpec);
+ String url = new String (dest);
+
+ /*
+ * As of mozilla 1.7 the second argument of the nsIDownload interface's
+ * Init function changed from nsILocalFile to nsIURI. Detect which of
+ * these interfaces the second argument implements and act accordingly.
+ */
+ String filename = null;
+ nsISupports supports = new nsISupports (aTarget);
+ int /*long*/[] result = new int /*long*/[1];
+ rc = supports.QueryInterface (nsIURI.NS_IURI_IID, result);
+ if (rc is 0) { /* >= 1.7 */
+ nsIURI target = new nsIURI (result[0]);
+ result[0] = 0;
+ int /*long*/ aPath = XPCOM.nsEmbedCString_new ();
+ rc = target.GetPath (aPath);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ length = XPCOM.nsEmbedCString_Length (aPath);
+ buffer = XPCOM.nsEmbedCString_get (aPath);
+ dest = new byte[length];
+ XPCOM.memmove (dest, buffer, length);
+ XPCOM.nsEmbedCString_delete (aPath);
+ filename = new String (dest);
+ int separator = filename.lastIndexOf (System.getProperty ("file.separator")); //$NON-NLS-1$
+ filename = filename.substring (separator + 1);
+ target.Release ();
+ } else { /* < 1.7 */
+ nsILocalFile target = new nsILocalFile (aTarget);
+ int /*long*/ aNativeTarget = XPCOM.nsEmbedCString_new ();
+ rc = target.GetNativeLeafName (aNativeTarget);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ length = XPCOM.nsEmbedCString_Length (aNativeTarget);
+ buffer = XPCOM.nsEmbedCString_get (aNativeTarget);
+ dest = new byte[length];
+ XPCOM.memmove (dest, buffer, length);
+ XPCOM.nsEmbedCString_delete (aNativeTarget);
+ filename = new String (dest);
+ }
+
+ Listener listener = new Listener () {
+ public void handleEvent (Event event) {
+ if (event.widget is cancel) {
+ shell.close ();
+ }
+ if (helperAppLauncher !is null) {
+ helperAppLauncher.Cancel ();
+ helperAppLauncher.Release ();
+ }
+ shell = null;
+ helperAppLauncher = null;
+ }
+ };
+ shell = new Shell (DWT.DIALOG_TRIM);
+ String msg = Compatibility.getMessage ("SWT_Download_File", new Object[] {filename}); //$NON-NLS-1$
+ shell.setText (msg);
+ GridLayout gridLayout = new GridLayout ();
+ gridLayout.marginHeight = 15;
+ gridLayout.marginWidth = 15;
+ gridLayout.verticalSpacing = 20;
+ shell.setLayout(gridLayout);
+ msg = Compatibility.getMessage ("SWT_Download_Location", new Object[] {filename, url}); //$NON-NLS-1$
+ new Label (shell, DWT.SIMPLE).setText (msg);
+ status = new Label (shell, DWT.SIMPLE);
+ msg = Compatibility.getMessage ("SWT_Download_Started"); //$NON-NLS-1$
+ status.setText (msg);
+ GridData data = new GridData ();
+ data.grabExcessHorizontalSpace = true;
+ data.grabExcessVerticalSpace = true;
+ status.setLayoutData (data);
+
+ cancel = new Button (shell, DWT.PUSH);
+ cancel.setText (DWT.getMessage ("SWT_Cancel")); //$NON-NLS-1$
+ data = new GridData ();
+ data.horizontalAlignment = GridData.CENTER;
+ cancel.setLayoutData (data);
+ cancel.addListener (DWT.Selection, listener);
+ shell.addListener (DWT.Close, listener);
+ shell.pack ();
+ shell.open ();
+ return XPCOM.NS_OK;
+}
+
+int GetSource (int /*long*/ aSource) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetTarget (int /*long*/ aTarget) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetPersist (int /*long*/ aPersist) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetPercentComplete (int /*long*/ aPercentComplete) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDisplayName (int /*long*/ aDisplayName) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetDisplayName (int /*long*/ aDisplayName) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetStartTime (int /*long*/ aStartTime) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetMIMEInfo (int /*long*/ aMIMEInfo) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetListener (int /*long*/ aListener) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetListener (int /*long*/ aListener) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetObserver (int /*long*/ aObserver) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetObserver (int /*long*/ aObserver) {
+ if (aObserver !is 0) {
+ nsISupports supports = new nsISupports (aObserver);
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = supports.QueryInterface (nsIHelperAppLauncher.NS_IHELPERAPPLAUNCHER_IID, result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+ helperAppLauncher = new nsIHelperAppLauncher (result[0]);
+ }
+ return XPCOM.NS_OK;
+}
+
+/* nsIProgressDialog */
+int Open (int /*long*/ aParent) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetCancelDownloadOnClose (int /*long*/ aCancelDownloadOnClose) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetCancelDownloadOnClose (int aCancelDownloadOnClose) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDialog (int /*long*/ aDialog) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetDialog (int /*long*/ aDialog) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIWebProgressListener */
+
+int OnStateChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStateFlags, int aStatus) {
+ if ((aStateFlags & nsIWebProgressListener.STATE_STOP) !is 0) {
+ if (helperAppLauncher !is null) helperAppLauncher.Release ();
+ helperAppLauncher = null;
+ if (shell !is null && !shell.isDisposed ()) shell.dispose ();
+ shell = null;
+ }
+ return XPCOM.NS_OK;
+}
+
+int OnProgressChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aCurSelfProgress, int aMaxSelfProgress, int aCurTotalProgress, int aMaxTotalProgress) {
+ int currentKBytes = aCurTotalProgress / 1024;
+ int totalKBytes = aMaxTotalProgress / 1024;
+ if (shell !is null && !shell.isDisposed ()) {
+ Object[] arguments = {new Integer (currentKBytes), new Integer (totalKBytes)};
+ String statusMsg = Compatibility.getMessage ("SWT_Download_Status", arguments); //$NON-NLS-1$
+ status.setText (statusMsg);
+ shell.layout (true);
+ shell.getDisplay ().update ();
+ }
+ return XPCOM.NS_OK;
+}
+
+int OnLocationChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aLocation) {
+ return XPCOM.NS_OK;
+}
+
+int OnStatusChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStatus, int /*long*/ aMessage) {
+ return XPCOM.NS_OK;
+}
+
+int OnSecurityChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int state) {
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/DownloadFactory.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/DownloadFactory.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.DownloadFactory;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class DownloadFactory {
+ XPCOMObject supports;
+ XPCOMObject factory;
+ int refCount = 0;
+
+DownloadFactory () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (factory !is null) {
+ factory.dispose ();
+ factory = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return factory.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIFactory.NS_IFACTORY_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {factory.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+ Download download = new Download ();
+ download.AddRef ();
+ XPCOM.memmove (result, new int /*long*/[] {download.getAddress ()}, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+int LockFactory (int lock) {
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/DownloadFactory_1_8.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/DownloadFactory_1_8.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.DownloadFactory_1_8;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class DownloadFactory_1_8 {
+ XPCOMObject supports;
+ XPCOMObject factory;
+ int refCount = 0;
+
+DownloadFactory_1_8 () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (factory !is null) {
+ factory.dispose ();
+ factory = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return factory.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIFactory.NS_IFACTORY_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {factory.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+ Download_1_8 download = new Download_1_8 ();
+ download.AddRef ();
+ XPCOM.memmove (result, new int /*long*/[] {download.getAddress ()}, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+int LockFactory (int lock) {
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/Download_1_8.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/Download_1_8.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,407 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.Download_1_8;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.Compatibility;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsICancelable;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDownload_1_8;
+import dwt.internal.mozilla.nsIProgressDialog_1_8;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIWebProgressListener;
+import dwt.layout.GridData;
+import dwt.layout.GridLayout;
+import dwt.widgets.Button;
+import dwt.widgets.Event;
+import dwt.widgets.Label;
+import dwt.widgets.Listener;
+import dwt.widgets.Shell;
+
+class Download_1_8 {
+ XPCOMObject supports;
+ XPCOMObject download;
+ XPCOMObject progressDialog;
+ XPCOMObject webProgressListener;
+ nsICancelable cancelable;
+ int refCount = 0;
+
+ Shell shell;
+ Label status;
+ Button cancel;
+
+ static final bool is32 = C.PTR_SIZEOF is 4;
+
+Download_1_8 () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ download = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3, is32 ? 10 : 6, is32 ? 8 : 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+ public int /*long*/ method8 (int /*long*/[] args) {
+ if (args.length is 10) {
+ return OnProgressChange64_32 (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
+ } else {
+ return OnProgressChange64 (args[0], args[1], args[2], args[3], args[4], args[5]);
+ }
+ }
+ public int /*long*/ method9 (int /*long*/[] args) {
+ if (args.length is 8) {
+ return Init_32 (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+ } else {
+ return Init (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ }
+ }
+ public int /*long*/ method10 (int /*long*/[] args) {return GetTargetFile (args[0]);}
+ public int /*long*/ method11 (int /*long*/[] args) {return GetPercentComplete (args[0]);}
+ public int /*long*/ method12 (int /*long*/[] args) {return GetAmountTransferred (args[0]);}
+ public int /*long*/ method13 (int /*long*/[] args) {return GetSize (args[0]);}
+ public int /*long*/ method14 (int /*long*/[] args) {return GetSource (args[0]);}
+ public int /*long*/ method15 (int /*long*/[] args) {return GetTarget (args[0]);}
+ public int /*long*/ method16 (int /*long*/[] args) {return GetCancelable (args[0]);}
+ public int /*long*/ method17 (int /*long*/[] args) {return GetDisplayName (args[0]);}
+ public int /*long*/ method18 (int /*long*/[] args) {return GetStartTime (args[0]);}
+ public int /*long*/ method19 (int /*long*/[] args) {return GetMIMEInfo (args[0]);}
+ };
+
+ progressDialog = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3, is32 ? 10 : 6, is32 ? 8 : 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+ public int /*long*/ method8 (int /*long*/[] args) {
+ if (args.length is 10) {
+ return OnProgressChange64_32 (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
+ } else {
+ return OnProgressChange64 (args[0], args[1], args[2], args[3], args[4], args[5]);
+ }
+ }
+ public int /*long*/ method9 (int /*long*/[] args) {
+ if (args.length is 8) {
+ return Init_32 (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+ } else {
+ return Init (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ }
+ }
+ public int /*long*/ method10 (int /*long*/[] args) {return GetTargetFile (args[0]);}
+ public int /*long*/ method11 (int /*long*/[] args) {return GetPercentComplete (args[0]);}
+ public int /*long*/ method12 (int /*long*/[] args) {return GetAmountTransferred (args[0]);}
+ public int /*long*/ method13 (int /*long*/[] args) {return GetSize (args[0]);}
+ public int /*long*/ method14 (int /*long*/[] args) {return GetSource (args[0]);}
+ public int /*long*/ method15 (int /*long*/[] args) {return GetTarget (args[0]);}
+ public int /*long*/ method16 (int /*long*/[] args) {return GetCancelable (args[0]);}
+ public int /*long*/ method17 (int /*long*/[] args) {return GetDisplayName (args[0]);}
+ public int /*long*/ method18 (int /*long*/[] args) {return GetStartTime (args[0]);}
+ public int /*long*/ method19 (int /*long*/[] args) {return GetMIMEInfo (args[0]);}
+ public int /*long*/ method20 (int /*long*/[] args) {return Open (args[0]);}
+ public int /*long*/ method21 (int /*long*/[] args) {return GetCancelDownloadOnClose (args[0]);}
+ public int /*long*/ method22 (int /*long*/[] args) {return SetCancelDownloadOnClose ((int)/*64*/args[0]);}
+ public int /*long*/ method23 (int /*long*/[] args) {return GetObserver (args[0]);}
+ public int /*long*/ method24 (int /*long*/[] args) {return SetObserver (args[0]);}
+ public int /*long*/ method25 (int /*long*/[] args) {return GetDialog (args[0]);}
+ public int /*long*/ method26 (int /*long*/[] args) {return SetDialog (args[0]);}
+ };
+
+ webProgressListener = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+ };
+}
+
+void disposeCOMInterfaces() {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (download !is null) {
+ download.dispose ();
+ download = null;
+ }
+ if (progressDialog !is null) {
+ progressDialog.dispose ();
+ progressDialog = null;
+ }
+ if (webProgressListener !is null) {
+ webProgressListener.dispose ();
+ webProgressListener = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return progressDialog.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIDownload_1_8.NS_IDOWNLOAD_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {download.getAddress ()}, C.PTR_SIZEOF);
+ AddRef();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIProgressDialog_1_8.NS_IPROGRESSDIALOG_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {progressDialog.getAddress ()}, C.PTR_SIZEOF);
+ AddRef();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {webProgressListener.getAddress ()}, C.PTR_SIZEOF);
+ AddRef();
+ return XPCOM.NS_OK;
+ }
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIDownload */
+
+/* Note. The argument startTime is defined as a PRInt64. This translates into two java ints. */
+int Init_32 (int /*long*/ aSource, int /*long*/ aTarget, int /*long*/ aDisplayName, int /*long*/ aMIMEInfo, int /*long*/ startTime1, int /*long*/ startTime2, int /*long*/ aTempFile, int /*long*/ aCancelable) {
+ long startTime = (startTime2 << 32) + startTime1;
+ return Init (aSource, aTarget, aDisplayName, aMIMEInfo, startTime, aTempFile, aCancelable);
+}
+
+int Init (int /*long*/ aSource, int /*long*/ aTarget, int /*long*/ aDisplayName, int /*long*/ aMIMEInfo, long startTime, int /*long*/ aTempFile, int /*long*/ aCancelable) {
+ cancelable = new nsICancelable (aCancelable);
+ nsIURI source = new nsIURI (aSource);
+ int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+ int rc = source.GetHost (aSpec);
+ if (rc !is XPCOM.NS_OK) Mozilla.error(rc);
+ int length = XPCOM.nsEmbedCString_Length (aSpec);
+ int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+ byte[] dest = new byte[length];
+ XPCOM.memmove (dest, buffer, length);
+ XPCOM.nsEmbedCString_delete (aSpec);
+ String url = new String (dest);
+
+ nsIURI target = new nsIURI (aTarget);
+ int /*long*/ aPath = XPCOM.nsEmbedCString_new ();
+ rc = target.GetPath (aPath);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ length = XPCOM.nsEmbedCString_Length (aPath);
+ buffer = XPCOM.nsEmbedCString_get (aPath);
+ dest = new byte[length];
+ XPCOM.memmove (dest, buffer, length);
+ XPCOM.nsEmbedCString_delete (aPath);
+ String filename = new String (dest);
+ int separator = filename.lastIndexOf (System.getProperty ("file.separator")); //$NON-NLS-1$
+ filename = filename.substring (separator + 1);
+
+ Listener listener = new Listener() {
+ public void handleEvent (Event event) {
+ if (event.widget is cancel) {
+ shell.close ();
+ }
+ if (cancelable !is null) {
+ int rc = cancelable.Cancel (XPCOM.NS_BINDING_ABORTED);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ }
+ shell = null;
+ cancelable = null;
+ }
+ };
+ shell = new Shell (DWT.DIALOG_TRIM);
+ String msg = Compatibility.getMessage ("SWT_Download_File", new Object[] {filename}); //$NON-NLS-1$
+ shell.setText (msg);
+ GridLayout gridLayout = new GridLayout ();
+ gridLayout.marginHeight = 15;
+ gridLayout.marginWidth = 15;
+ gridLayout.verticalSpacing = 20;
+ shell.setLayout (gridLayout);
+ msg = Compatibility.getMessage ("SWT_Download_Location", new Object[] {filename, url}); //$NON-NLS-1$
+ new Label (shell, DWT.SIMPLE).setText (msg);
+ status = new Label (shell, DWT.SIMPLE);
+ msg = Compatibility.getMessage ("SWT_Download_Started"); //$NON-NLS-1$
+ status.setText (msg);
+ GridData data = new GridData ();
+ data.grabExcessHorizontalSpace = true;
+ data.grabExcessVerticalSpace = true;
+ status.setLayoutData (data);
+
+ cancel = new Button (shell, DWT.PUSH);
+ cancel.setText (DWT.getMessage ("SWT_Cancel")); //$NON-NLS-1$
+ data = new GridData ();
+ data.horizontalAlignment = GridData.CENTER;
+ cancel.setLayoutData (data);
+ cancel.addListener (DWT.Selection, listener);
+ shell.addListener (DWT.Close, listener);
+ shell.pack ();
+ shell.open ();
+ return XPCOM.NS_OK;
+}
+
+int GetAmountTransferred (int /*long*/ arg0) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetCancelable (int /*long*/ arg0) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDisplayName (int /*long*/ aDisplayName) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetMIMEInfo (int /*long*/ aMIMEInfo) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetPercentComplete (int /*long*/ aPercentComplete) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetSize (int /*long*/ arg0) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetSource (int /*long*/ aSource) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetStartTime (int /*long*/ aStartTime) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetTarget (int /*long*/ aTarget) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetTargetFile (int /*long*/ arg0) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIProgressDialog */
+int GetCancelDownloadOnClose (int /*long*/ aCancelDownloadOnClose) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDialog (int /*long*/ aDialog) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetObserver (int /*long*/ aObserver) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int Open (int /*long*/ aParent) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetCancelDownloadOnClose (int aCancelDownloadOnClose) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetDialog (int /*long*/ aDialog) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetObserver (int /*long*/ aObserver) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIWebProgressListener */
+
+int OnLocationChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aLocation) {
+ return XPCOM.NS_OK;
+}
+
+int OnProgressChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aCurSelfProgress, int aMaxSelfProgress, int aCurTotalProgress, int aMaxTotalProgress) {
+ return OnProgressChange64 (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
+}
+
+/* Note. The last 4 args in the original interface are defined as PRInt64. These each translate into two java ints. */
+int OnProgressChange64_32 (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aCurSelfProgress1, int /*long*/ aCurSelfProgress2, int /*long*/ aMaxSelfProgress1, int /*long*/ aMaxSelfProgress2, int /*long*/ aCurTotalProgress1, int /*long*/ aCurTotalProgress2, int /*long*/ aMaxTotalProgress1, int /*long*/ aMaxTotalProgress2) {
+ long aCurSelfProgress = (aCurSelfProgress2 << 32) + aCurSelfProgress1;
+ long aMaxSelfProgress = (aMaxSelfProgress2 << 32) + aMaxSelfProgress1;
+ long aCurTotalProgress = (aCurTotalProgress2 << 32) + aCurTotalProgress1;
+ long aMaxTotalProgress = (aMaxTotalProgress2 << 32) + aMaxTotalProgress1;
+ return OnProgressChange64 (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
+}
+
+int OnProgressChange64 (int /*long*/ aWebProgress, int /*long*/ aRequest, long aCurSelfProgress, long aMaxSelfProgress, long aCurTotalProgress, long aMaxTotalProgress) {
+ long currentKBytes = aCurTotalProgress / 1024;
+ long totalKBytes = aMaxTotalProgress / 1024;
+ if (shell !is null && !shell.isDisposed ()) {
+ Object[] arguments = {new Long (currentKBytes), new Long (totalKBytes)};
+ String statusMsg = Compatibility.getMessage ("SWT_Download_Status", arguments); //$NON-NLS-1$
+ status.setText (statusMsg);
+ shell.layout (true);
+ shell.getDisplay ().update ();
+ }
+ return XPCOM.NS_OK;
+}
+
+int OnSecurityChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int state) {
+ return XPCOM.NS_OK;
+}
+
+int OnStateChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStateFlags, int aStatus) {
+ if ((aStateFlags & nsIWebProgressListener.STATE_STOP) !is 0) {
+ cancelable = null;
+ if (shell !is null && !shell.isDisposed ()) shell.dispose ();
+ shell = null;
+ }
+ return XPCOM.NS_OK;
+}
+
+int OnStatusChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStatus, int /*long*/ aMessage) {
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/FilePicker.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/FilePicker.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.FilePicker;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFilePicker;
+import dwt.internal.mozilla.nsIFilePicker_1_8;
+import dwt.internal.mozilla.nsILocalFile;
+import dwt.internal.mozilla.nsISupports;
+import dwt.widgets.DirectoryDialog;
+import dwt.widgets.Display;
+import dwt.widgets.FileDialog;
+import dwt.widgets.Shell;
+
+class FilePicker {
+ XPCOMObject supports;
+ XPCOMObject filePicker;
+
+ int refCount = 0;
+ short mode;
+ int /*long*/ parentHandle;
+ String[] files, masks;
+ String defaultFilename, directory, title;
+
+ static final String SEPARATOR = System.getProperty ("file.separator"); //$NON-NLS-1$
+
+FilePicker () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ filePicker = new XPCOMObject (new int[] {2, 0, 0, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return Init (args[0], args[1], (short)args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return AppendFilters ((int)/*64*/args[0]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return AppendFilter (args[0], args[1]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return GetDefaultString (args[0]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return SetDefaultString (args[0]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return GetDefaultExtension (args[0]);}
+ public int /*long*/ method9 (int /*long*/[] args) {return SetDefaultExtension (args[0]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return GetFilterIndex (args[0]);}
+ public int /*long*/ method11 (int /*long*/[] args) {return SetFilterIndex ((int)/*64*/args[0]);}
+ public int /*long*/ method12 (int /*long*/[] args) {return GetDisplayDirectory (args[0]);}
+ public int /*long*/ method13 (int /*long*/[] args) {return SetDisplayDirectory (args[0]);}
+ public int /*long*/ method14 (int /*long*/[] args) {return GetFile (args[0]);}
+ public int /*long*/ method15 (int /*long*/[] args) {return GetFileURL (args[0]);}
+ public int /*long*/ method16 (int /*long*/[] args) {return GetFiles (args[0]);}
+ public int /*long*/ method17 (int /*long*/[] args) {return Show (args[0]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (filePicker !is null) {
+ filePicker.dispose ();
+ filePicker = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return filePicker.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIFilePicker.NS_IFILEPICKER_IID)) {
+ XPCOM.memmove(ppvObject, new int /*long*/[] {filePicker.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIFilePicker_1_8.NS_IFILEPICKER_IID)) {
+ XPCOM.memmove(ppvObject, new int /*long*/[] {filePicker.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/*
+ * As of Mozilla 1.8 some of nsIFilePicker's string arguments changed type. This method
+ * answers a java string based on the type of string that is appropriate for the Mozilla
+ * version being used.
+ */
+String parseAString (int /*long*/ string) {
+ return null;
+}
+
+/* nsIFilePicker */
+
+int Init (int /*long*/ parent, int /*long*/ title, short mode) {
+ parentHandle = parent;
+ this.mode = mode;
+ this.title = parseAString (title);
+ return XPCOM.NS_OK;
+}
+
+int Show (int /*long*/ _retval) {
+ if (mode is nsIFilePicker.modeGetFolder) {
+ /* picking a directory */
+ int result = showDirectoryPicker ();
+ XPCOM.memmove (_retval, new short[] {(short)result}, 2); /* PRInt16 */
+ return XPCOM.NS_OK;
+ }
+
+ /* picking a file */
+ int style = mode is nsIFilePicker.modeSave ? DWT.SAVE : DWT.OPEN;
+ if (mode is nsIFilePicker.modeOpenMultiple) style |= DWT.MULTI;
+ Display display = Display.getCurrent ();
+ Shell parent = null; // TODO compute parent
+ if (parent is null) {
+ parent = new Shell (display);
+ }
+ FileDialog dialog = new FileDialog (parent, style);
+ if (title !is null) dialog.setText (title);
+ if (directory !is null) dialog.setFilterPath (directory);
+ if (masks !is null) dialog.setFilterExtensions (masks);
+ if (defaultFilename !is null) dialog.setFileName (defaultFilename);
+ String filename = dialog.open ();
+ files = dialog.getFileNames ();
+ directory = dialog.getFilterPath ();
+ title = defaultFilename = null;
+ masks = null;
+ int result = filename is null ? nsIFilePicker.returnCancel : nsIFilePicker.returnOK;
+ XPCOM.memmove (_retval, new short[] {(short)result}, 2); /* PRInt16 */
+ return XPCOM.NS_OK;
+}
+
+int showDirectoryPicker () {
+ Display display = Display.getCurrent ();
+ Shell parent = null; // TODO compute parent
+ if (parent is null) {
+ parent = new Shell (display);
+ }
+ DirectoryDialog dialog = new DirectoryDialog (parent, DWT.NONE);
+ if (title !is null) dialog.setText (title);
+ if (directory !is null) dialog.setFilterPath (directory);
+ directory = dialog.open ();
+ title = defaultFilename = null;
+ files = masks = null;
+ return directory is null ? nsIFilePicker.returnCancel : nsIFilePicker.returnOK;
+}
+
+int GetFiles (int /*long*/ aFiles) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetFileURL (int /*long*/ aFileURL) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetFile (int /*long*/ aFile) {
+ String filename = ""; //$NON-NLS-1$
+ if (directory !is null) filename += directory + SEPARATOR;
+ if (files !is null && files.length > 0) filename += files[0];
+ nsEmbedString path = new nsEmbedString (filename);
+ int /*long*/[] file = new int /*long*/[1];
+ int rc = XPCOM.NS_NewLocalFile (path.getAddress (), 1, file);
+ path.dispose ();
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (file[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+ XPCOM.memmove (aFile, file, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+int SetDisplayDirectory (int /*long*/ aDisplayDirectory) {
+ if (aDisplayDirectory is 0) return XPCOM.NS_OK;
+ nsILocalFile file = new nsILocalFile (aDisplayDirectory);
+ int /*long*/ pathname = XPCOM.nsEmbedCString_new ();
+ file.GetNativePath (pathname);
+ int length = XPCOM.nsEmbedCString_Length (pathname);
+ int /*long*/ buffer = XPCOM.nsEmbedCString_get (pathname);
+ byte[] bytes = new byte[length];
+ XPCOM.memmove (bytes, buffer, length);
+ XPCOM.nsEmbedCString_delete (pathname);
+ char[] chars = MozillaDelegate.mbcsToWcs (null, bytes);
+ directory = new String (chars);
+ return XPCOM.NS_OK;
+}
+
+int GetDisplayDirectory (int /*long*/ aDisplayDirectory) {
+ String directoryName = directory !is null ? directory : ""; //$NON-NLS-1$
+ nsEmbedString path = new nsEmbedString (directoryName);
+ int /*long*/[] file = new int /*long*/[1];
+ int rc = XPCOM.NS_NewLocalFile (path.getAddress (), 1, file);
+ path.dispose ();
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (file[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+ XPCOM.memmove (aDisplayDirectory, file, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+int SetFilterIndex (int aFilterIndex) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetFilterIndex (int /*long*/ aFilterIndex) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetDefaultExtension (int /*long*/ aDefaultExtension) {
+ /* note that the type of argument 1 changed as of Mozilla 1.8 */
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int GetDefaultExtension (int /*long*/ aDefaultExtension) {
+ /* note that the type of argument 1 changed as of Mozilla 1.8 */
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int SetDefaultString (int /*long*/ aDefaultString) {
+ defaultFilename = parseAString (aDefaultString);
+ return XPCOM.NS_OK;
+}
+
+int GetDefaultString (int /*long*/ aDefaultString) {
+ /* note that the type of argument 1 changed as of Mozilla 1.8 */
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int AppendFilter (int /*long*/ title, int /*long*/ filter) {
+ /* note that the type of arguments 1 and 2 changed as of Mozilla 1.8 */
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int AppendFilters (int filterMask) {
+ String[] addFilters = null;
+ switch (filterMask) {
+ case nsIFilePicker.filterAll:
+ case nsIFilePicker.filterApps:
+ masks = null; /* this is equivalent to no filter */
+ break;
+ case nsIFilePicker.filterHTML:
+ addFilters = new String[] {"*.htm;*.html"}; //$NON-NLS-1$
+ break;
+ case nsIFilePicker.filterImages:
+ addFilters = new String[] {"*.gif;*.jpeg;*.jpg;*.png"}; //$NON-NLS-1$
+ break;
+ case nsIFilePicker.filterText:
+ addFilters = new String[] {"*.txt"}; //$NON-NLS-1$
+ break;
+ case nsIFilePicker.filterXML:
+ addFilters = new String[] {"*.xml"}; //$NON-NLS-1$
+ break;
+ case nsIFilePicker.filterXUL:
+ addFilters = new String[] {"*.xul"}; //$NON-NLS-1$
+ break;
+ }
+ if (masks is null) {
+ masks = addFilters;
+ } else {
+ if (addFilters !is null) {
+ String[] newFilters = new String[masks.length + addFilters.length];
+ System.arraycopy (masks, 0, newFilters, 0, masks.length);
+ System.arraycopy (addFilters, 0, newFilters, masks.length, addFilters.length);
+ masks = newFilters;
+ }
+ }
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/FilePickerFactory.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/FilePickerFactory.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.FilePickerFactory;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class FilePickerFactory {
+ XPCOMObject supports;
+ XPCOMObject factory;
+ int refCount = 0;
+
+FilePickerFactory () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (factory !is null) {
+ factory.dispose ();
+ factory = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return factory.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIFactory.NS_IFACTORY_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {factory.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+ FilePicker picker = new FilePicker ();
+ picker.AddRef ();
+ XPCOM.memmove (result, new int /*long*/[] {picker.getAddress ()}, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+int LockFactory (int lock) {
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/FilePickerFactory_1_8.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/FilePickerFactory_1_8.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.FilePickerFactory_1_8;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+
+class FilePickerFactory_1_8 extends FilePickerFactory {
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+ };
+}
+
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+ FilePicker_1_8 picker = new FilePicker_1_8 ();
+ picker.AddRef ();
+ XPCOM.memmove (result, new int /*long*/[] {picker.getAddress ()}, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/FilePicker_1_8.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/FilePicker_1_8.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.FilePicker_1_8;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+
+class FilePicker_1_8 extends FilePicker {
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ filePicker = new XPCOMObject (new int[] {2, 0, 0, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return Init (args[0], args[1], (short)args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return AppendFilters ((int)/*64*/args[0]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return AppendFilter (args[0], args[1]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return GetDefaultString (args[0]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return SetDefaultString (args[0]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return GetDefaultExtension (args[0]);}
+ public int /*long*/ method9 (int /*long*/[] args) {return SetDefaultExtension (args[0]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return GetFilterIndex (args[0]);}
+ public int /*long*/ method11 (int /*long*/[] args) {return SetFilterIndex ((int)/*64*/args[0]);}
+ public int /*long*/ method12 (int /*long*/[] args) {return GetDisplayDirectory (args[0]);}
+ public int /*long*/ method13 (int /*long*/[] args) {return SetDisplayDirectory (args[0]);}
+ public int /*long*/ method14 (int /*long*/[] args) {return GetFile (args[0]);}
+ public int /*long*/ method15 (int /*long*/[] args) {return GetFileURL (args[0]);}
+ public int /*long*/ method16 (int /*long*/[] args) {return GetFiles (args[0]);}
+ public int /*long*/ method17 (int /*long*/[] args) {return Show (args[0]);}
+ };
+}
+
+/*
+ * As of Mozilla 1.8 some of nsIFilePicker's string arguments changed type. This method
+ * answers a java string based on the type of string that is appropriate for the Mozilla
+ * version being used.
+ */
+String parseAString (int /*long*/ string) {
+ if (string is 0) return null;
+ int length = XPCOM.nsEmbedString_Length (string);
+ int /*long*/ buffer = XPCOM.nsEmbedString_get (string);
+ char[] chars = new char[length];
+ XPCOM.memmove (chars, buffer, length * 2);
+ return new String (chars);
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/HelperAppLauncherDialog.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/HelperAppLauncherDialog.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.HelperAppLauncherDialog;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIHelperAppLauncher;
+import dwt.internal.mozilla.nsIHelperAppLauncherDialog;
+import dwt.internal.mozilla.nsIHelperAppLauncher_1_8;
+import dwt.internal.mozilla.nsIHelperAppLauncher_1_9;
+import dwt.internal.mozilla.nsISupports;
+import dwt.widgets.FileDialog;
+import dwt.widgets.Shell;
+
+class HelperAppLauncherDialog {
+ XPCOMObject supports;
+ XPCOMObject helperAppLauncherDialog;
+ int refCount = 0;
+
+HelperAppLauncherDialog () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ helperAppLauncherDialog = new XPCOMObject (new int[] {2, 0, 0, 3, 5}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return Show (args[0], args[1], (int)/*64*/args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return PromptForSaveToFile (args[0], args[1], args[2], args[3], args[4]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (helperAppLauncherDialog !is null) {
+ helperAppLauncherDialog.dispose ();
+ helperAppLauncherDialog = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return helperAppLauncherDialog.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIHelperAppLauncherDialog.NS_IHELPERAPPLAUNCHERDIALOG_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {helperAppLauncherDialog.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ /*
+ * Note. This instance lives as long as the download it is binded to.
+ * Its reference count is expected to go down to 0 when the download
+ * has completed or when it has been cancelled. E.g. when the user
+ * cancels the File Dialog, cancels or closes the Download Dialog
+ * and when the Download Dialog goes away after the download is completed.
+ */
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIHelperAppLauncherDialog */
+
+int Show (int /*long*/ aLauncher, int /*long*/ aContext, int aReason) {
+ /*
+ * The interface for nsIHelperAppLauncher changed in GRE versions 1.8 and 1.9. Query for
+ * each of these interfaces in turn until one is found.
+ */
+ nsISupports supports = new nsISupports (aLauncher);
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = supports.QueryInterface (nsIHelperAppLauncher_1_9.NS_IHELPERAPPLAUNCHER_IID, result);
+ if (rc is 0) {
+ nsIHelperAppLauncher_1_9 helperAppLauncher = new nsIHelperAppLauncher_1_9 (aLauncher);
+ rc = helperAppLauncher.SaveToDisk (0, 0);
+ helperAppLauncher.Release ();
+ return rc;
+ }
+
+ result[0] = 0;
+ rc = supports.QueryInterface (nsIHelperAppLauncher_1_8.NS_IHELPERAPPLAUNCHER_IID, result);
+ if (rc is 0) {
+ nsIHelperAppLauncher_1_8 helperAppLauncher = new nsIHelperAppLauncher_1_8 (aLauncher);
+ rc = helperAppLauncher.SaveToDisk (0, 0);
+ helperAppLauncher.Release ();
+ return rc;
+ }
+
+ nsIHelperAppLauncher helperAppLauncher = new nsIHelperAppLauncher (aLauncher); /* < 1.8 */
+ return helperAppLauncher.SaveToDisk (0, 0);
+}
+
+int PromptForSaveToFile (int /*long*/ arg0, int /*long*/ arg1, int /*long*/ arg2, int /*long*/ arg3, int /*long*/ arg4) {
+ int /*long*/ aDefaultFile, aSuggestedFileExtension, _retval;
+ bool hasLauncher = false;
+
+ /*
+ * The interface for nsIHelperAppLauncherDialog changed as of mozilla 1.5 when an
+ * extra argument was added to the PromptForSaveToFile method (this resulted in all
+ * subsequent arguments shifting right). The workaround is to provide an XPCOMObject
+ * that fits the newer API, and to use the first argument's type to infer whether
+ * the old or new nsIHelperAppLauncherDialog interface is being used (and by extension
+ * the ordering of the arguments). In mozilla >= 1.5 the first argument is an
+ * nsIHelperAppLauncher.
+ */
+ /*
+ * The interface for nsIHelperAppLauncher changed as of mozilla 1.8, so the first
+ * argument must be queried for both the old and new nsIHelperAppLauncher interfaces.
+ */
+ bool using_1_8 = false, using_1_9 = false;
+ nsISupports support = new nsISupports (arg0);
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = support.QueryInterface (nsIHelperAppLauncher_1_8.NS_IHELPERAPPLAUNCHER_IID, result);
+ if (rc is 0) {
+ using_1_8 = true;
+ hasLauncher = true;
+ new nsISupports (result[0]).Release ();
+ } else {
+ result[0] = 0;
+ rc = support.QueryInterface (nsIHelperAppLauncher_1_9.NS_IHELPERAPPLAUNCHER_IID, result);
+ if (rc is 0) {
+ using_1_9 = true;
+ hasLauncher = true;
+ new nsISupports (result[0]).Release ();
+ } else {
+ result[0] = 0;
+ rc = support.QueryInterface (nsIHelperAppLauncher.NS_IHELPERAPPLAUNCHER_IID, result);
+ if (rc is 0) {
+ hasLauncher = true;
+ new nsISupports (result[0]).Release ();
+ }
+ }
+ }
+ result[0] = 0;
+
+ if (hasLauncher) { /* >= 1.5 */
+ aDefaultFile = arg2;
+ aSuggestedFileExtension = arg3;
+ _retval = arg4;
+ } else { /* 1.4 */
+ aDefaultFile = arg1;
+ aSuggestedFileExtension = arg2;
+ _retval = arg3;
+ }
+
+ int length = XPCOM.strlen_PRUnichar (aDefaultFile);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, aDefaultFile, length * 2);
+ String defaultFile = new String (dest);
+
+ length = XPCOM.strlen_PRUnichar (aSuggestedFileExtension);
+ dest = new char[length];
+ XPCOM.memmove (dest, aSuggestedFileExtension, length * 2);
+ String suggestedFileExtension = new String (dest);
+
+ Shell shell = new Shell ();
+ FileDialog fileDialog = new FileDialog (shell, DWT.SAVE);
+ fileDialog.setFileName (defaultFile);
+ fileDialog.setFilterExtensions (new String[] {suggestedFileExtension});
+ String name = fileDialog.open ();
+ shell.close ();
+ if (name is null) {
+ if (hasLauncher) {
+ if (using_1_8) {
+ nsIHelperAppLauncher_1_8 launcher = new nsIHelperAppLauncher_1_8 (arg0);
+ rc = launcher.Cancel (XPCOM.NS_BINDING_ABORTED);
+ } else if (using_1_9) {
+ nsIHelperAppLauncher_1_9 launcher = new nsIHelperAppLauncher_1_9 (arg0);
+ rc = launcher.Cancel (XPCOM.NS_BINDING_ABORTED);
+ } else {
+ nsIHelperAppLauncher launcher = new nsIHelperAppLauncher (arg0);
+ rc = launcher.Cancel ();
+ }
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ return XPCOM.NS_OK;
+ }
+ return XPCOM.NS_ERROR_FAILURE;
+ }
+ nsEmbedString path = new nsEmbedString (name);
+ rc = XPCOM.NS_NewLocalFile (path.getAddress (), 1, result);
+ path.dispose ();
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+ /* Our own nsIDownload has been registered during the Browser initialization. It will be invoked by Mozilla. */
+ XPCOM.memmove (_retval, result, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/HelperAppLauncherDialogFactory.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/HelperAppLauncherDialogFactory.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.HelperAppLauncherDialogFactory;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class HelperAppLauncherDialogFactory {
+ XPCOMObject supports;
+ XPCOMObject factory;
+ int refCount = 0;
+
+HelperAppLauncherDialogFactory () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (factory !is null) {
+ factory.dispose ();
+ factory = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return factory.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIFactory.NS_IFACTORY_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {factory.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+ HelperAppLauncherDialog helperAppLauncherDialog = new HelperAppLauncherDialog ();
+ helperAppLauncherDialog.AddRef ();
+ XPCOM.memmove (result, new int /*long*/[] {helperAppLauncherDialog.getAddress ()}, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+int LockFactory (int lock) {
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/InputStream.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/InputStream.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.InputStream;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIInputStream;
+import dwt.internal.mozilla.nsISupports;
+
+class InputStream {
+ XPCOMObject inputStream;
+ int refCount = 0;
+
+ byte[] buffer;
+ int index = 0;
+
+InputStream (byte[] buffer) {
+ this.buffer = buffer;
+ index = 0;
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ inputStream = new XPCOMObject (new int[] {2, 0, 0, 0, 1, 3, 4, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return Close ();}
+ public int /*long*/ method4 (int /*long*/[] args) {return Available (args[0]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return Read (args[0], (int)/*64*/args[1], args[2]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return ReadSegments (args[0], args[1], (int)/*64*/args[2], args[3]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return IsNonBlocking (args[0]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (inputStream !is null) {
+ inputStream.dispose ();
+ inputStream = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return inputStream.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {inputStream.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIInputStream.NS_IINPUTSTREAM_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {inputStream.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIInputStream implementation */
+
+int Close () {
+ buffer = null;
+ index = 0;
+ return XPCOM.NS_OK;
+}
+
+int Available (int /*long*/ _retval) {
+ int available = buffer is null ? 0 : buffer.length - index;
+ XPCOM.memmove (_retval, new int[] {available}, 4);
+ return XPCOM.NS_OK;
+}
+
+int Read(int /*long*/ aBuf, int aCount, int /*long*/ _retval) {
+ int max = Math.min (aCount, buffer is null ? 0 : buffer.length - index);
+ if (max > 0) {
+ byte[] src = new byte[max];
+ System.arraycopy (buffer, index, src, 0, max);
+ XPCOM.memmove (aBuf, src, max);
+ index += max;
+ }
+ XPCOM.memmove(_retval, new int[] {max}, 4);
+ return XPCOM.NS_OK;
+}
+
+int ReadSegments (int /*long*/ aWriter, int /*long*/ aClosure, int aCount, int /*long*/ _retval) {
+ int max = Math.min (aCount, buffer is null ? 0 : buffer.length - index);
+ int cnt = max;
+ while (cnt > 0) {
+ int[] aWriteCount = new int[1];
+ int /*long*/ rc = XPCOM.Call (aWriter, getAddress (), aClosure, buffer, index, cnt, aWriteCount);
+ if (rc !is XPCOM.NS_OK) break;
+ index += aWriteCount[0];
+ cnt -= aWriteCount[0];
+ }
+ XPCOM.memmove (_retval, new int[] {max - cnt}, 4);
+ return XPCOM.NS_OK;
+}
+
+int IsNonBlocking (int /*long*/ _retval) {
+ /* blocking */
+ XPCOM.memmove (_retval, new int[] {0}, 4);
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/LocationAdapter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/LocationAdapter.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg + * Classes that wish to deal with {@link LocationEvent}'s can + * extend this class and override only the methods which they are + * interested in. + *
+ * + * @since 3.0 + */ +public abstract class LocationAdapter : LocationListener { + + public void changing (LocationEvent event) { + } + + public void changed (LocationEvent event) { + } +} diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/LocationEvent.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/browser/LocationEvent.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2003, 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: + * Jacob CarlborgLocationEvent
is sent by a {@link Browser} to
+ * {@link LocationListener}'s when the Browser
+ * navigates to a different URL. This notification typically
+ * occurs when the application navigates to a new location with
+ * {@link Browser#setUrl(String)} or when the user activates a
+ * hyperlink.
+ *
+ * @since 3.0
+ */
+public class LocationEvent : TypedEvent {
+ /** current location */
+ public String location;
+
+ /**
+ * A flag indicating whether the location opens in the top frame
+ * or not.
+ */
+ public bool top;
+
+ /**
+ * A flag indicating whether the location loading should be allowed.
+ * Setting this field to false
will cancel the operation.
+ */
+ public bool doit;
+
+ static final long serialVersionUID = 3906644198244299574L;
+
+ 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 String toString () {
+ String String = super.toString();
+ return String.substring(0, String.length() - 1) // remove trailing '}'
+ + " location=" + location + " top=" + top + " doit=" + doit + "}";
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/LocationListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/LocationListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg + * + *
The following fields in the LocationEvent
apply:
+ *
Browser
whose location is changing
+ * false
to prevent the location
+ * from being loaded
+ * LocationEvent
that specifies the location
+ * to be loaded by a Browser
+ *
+ * @since 3.0
+ */
+ public void changing (LocationEvent event);
+
+ /**
+ * This method is called when the current location is changed.
+ * + * + *
The following fields in the LocationEvent
apply:
+ *
true
if the location opens in the top frame or
+ * false
otherwise
+ * Browser
whose location has changed
+ * LocationEvent
that specifies the new
+ * location of a Browser
+ *
+ * @since 3.0
+ */
+ public void changed (LocationEvent event);
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/Mozilla.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/Mozilla.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,3254 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.Mozilla;
+
+import dwt.dwthelper.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Vector;
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.graphics.Device;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.internal.C;
+import dwt.internal.Compatibility;
+import dwt.internal.LONG;
+import dwt.internal.Library;
+import dwt.internal.mozilla.GREVersionRange;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMInit;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsIAppShell;
+import dwt.internal.mozilla.nsIBaseWindow;
+import dwt.internal.mozilla.nsICategoryManager;
+import dwt.internal.mozilla.nsIComponentManager;
+import dwt.internal.mozilla.nsIComponentRegistrar;
+import dwt.internal.mozilla.nsIContextMenuListener;
+import dwt.internal.mozilla.nsICookie;
+import dwt.internal.mozilla.nsICookieManager;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDOMEvent;
+import dwt.internal.mozilla.nsIDOMEventTarget;
+import dwt.internal.mozilla.nsIDOMKeyEvent;
+import dwt.internal.mozilla.nsIDOMMouseEvent;
+import dwt.internal.mozilla.nsIDOMSerializer;
+import dwt.internal.mozilla.nsIDOMSerializer_1_7;
+import dwt.internal.mozilla.nsIDOMWindow;
+import dwt.internal.mozilla.nsIDOMWindowCollection;
+import dwt.internal.mozilla.nsIDirectoryService;
+import dwt.internal.mozilla.nsIDocShell;
+import dwt.internal.mozilla.nsIDocShell_1_8;
+import dwt.internal.mozilla.nsIDocShell_1_9;
+import dwt.internal.mozilla.nsIEmbeddingSiteWindow;
+import dwt.internal.mozilla.nsIFile;
+import dwt.internal.mozilla.nsIIOService;
+import dwt.internal.mozilla.nsIInterfaceRequestor;
+import dwt.internal.mozilla.nsIJSContextStack;
+import dwt.internal.mozilla.nsILocalFile;
+import dwt.internal.mozilla.nsIObserverService;
+import dwt.internal.mozilla.nsIPrefBranch;
+import dwt.internal.mozilla.nsIPrefLocalizedString;
+import dwt.internal.mozilla.nsIPrefService;
+import dwt.internal.mozilla.nsIProperties;
+import dwt.internal.mozilla.nsIServiceManager;
+import dwt.internal.mozilla.nsISimpleEnumerator;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsISupportsWeakReference;
+import dwt.internal.mozilla.nsITooltipListener;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIURIContentListener;
+import dwt.internal.mozilla.nsIWeakReference;
+import dwt.internal.mozilla.nsIWebBrowser;
+import dwt.internal.mozilla.nsIWebBrowserChrome;
+import dwt.internal.mozilla.nsIWebBrowserChromeFocus;
+import dwt.internal.mozilla.nsIWebBrowserFocus;
+import dwt.internal.mozilla.nsIWebNavigation;
+import dwt.internal.mozilla.nsIWebNavigationInfo;
+import dwt.internal.mozilla.nsIWebProgress;
+import dwt.internal.mozilla.nsIWebProgressListener;
+import dwt.internal.mozilla.nsIWindowWatcher;
+import dwt.layout.FillLayout;
+import dwt.widgets.Composite;
+import dwt.widgets.Display;
+import dwt.widgets.Event;
+import dwt.widgets.Label;
+import dwt.widgets.Listener;
+import dwt.widgets.Menu;
+import dwt.widgets.Shell;
+
+class Mozilla extends WebBrowser {
+ int /*long*/ embedHandle;
+ nsIWebBrowser webBrowser;
+ Object webBrowserObject;
+ MozillaDelegate delegate;
+
+ /* Interfaces for this Mozilla embedding notification */
+ XPCOMObject supports;
+ XPCOMObject weakReference;
+ XPCOMObject webProgressListener;
+ XPCOMObject webBrowserChrome;
+ XPCOMObject webBrowserChromeFocus;
+ XPCOMObject embeddingSiteWindow;
+ XPCOMObject interfaceRequestor;
+ XPCOMObject supportsWeakReference;
+ XPCOMObject contextMenuListener;
+ XPCOMObject uriContentListener;
+ XPCOMObject tooltipListener;
+ XPCOMObject domEventListener;
+ int chromeFlags = nsIWebBrowserChrome.CHROME_DEFAULT;
+ int refCount, lastKeyCode, lastCharCode;
+ int /*long*/ request;
+ Point location, size;
+ bool visible, isChild, ignoreDispose, awaitingNavigate;
+ Shell tip = null;
+ Listener listener;
+ Vector unhookedDOMWindows = new Vector ();
+
+ static nsIAppShell AppShell;
+ static AppFileLocProvider LocationProvider;
+ static WindowCreator2 WindowCreator;
+ static int BrowserCount;
+ static bool Initialized, IsPre_1_8, PerformedVersionCheck, XPCOMWasGlued, XPCOMInitWasGlued;
+
+ /* XULRunner detect constants */
+ static final String GRERANGE_LOWER = "1.8.1.2"; //$NON-NLS-1$
+ static final String GRERANGE_LOWER_FALLBACK = "1.8"; //$NON-NLS-1$
+ static final bool LowerRangeInclusive = true;
+ static final String GRERANGE_UPPER = "1.9.*"; //$NON-NLS-1$
+ static final bool UpperRangeInclusive = true;
+
+ static final int MAX_PORT = 65535;
+ static final String SEPARATOR_OS = System.getProperty ("file.separator"); //$NON-NLS-1$
+ static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
+ static final String DISPOSE_LISTENER_HOOKED = "dwt.browser.Mozilla.disposeListenerHooked"; //$NON-NLS-1$
+ static final String PREFIX_JAVASCRIPT = "javascript:"; //$NON-NLS-1$
+ static final String PREFERENCE_CHARSET = "intl.charset.default"; //$NON-NLS-1$
+ static final String PREFERENCE_DISABLEOPENDURINGLOAD = "dom.disable_open_during_load"; //$NON-NLS-1$
+ static final String PREFERENCE_DISABLEWINDOWSTATUSCHANGE = "dom.disable_window_status_change"; //$NON-NLS-1$
+ static final String PREFERENCE_LANGUAGES = "intl.accept_languages"; //$NON-NLS-1$
+ static final String PREFERENCE_PROXYHOST_FTP = "network.proxy.ftp"; //$NON-NLS-1$
+ static final String PREFERENCE_PROXYPORT_FTP = "network.proxy.ftp_port"; //$NON-NLS-1$
+ static final String PREFERENCE_PROXYHOST_HTTP = "network.proxy.http"; //$NON-NLS-1$
+ static final String PREFERENCE_PROXYPORT_HTTP = "network.proxy.http_port"; //$NON-NLS-1$
+ static final String PREFERENCE_PROXYHOST_SSL = "network.proxy.ssl"; //$NON-NLS-1$
+ static final String PREFERENCE_PROXYPORT_SSL = "network.proxy.ssl_port"; //$NON-NLS-1$
+ static final String PREFERENCE_PROXYTYPE = "network.proxy.type"; //$NON-NLS-1$
+ static final String PROFILE_AFTER_CHANGE = "profile-after-change"; //$NON-NLS-1$
+ static final String PROFILE_BEFORE_CHANGE = "profile-before-change"; //$NON-NLS-1$
+ static final String PROFILE_DIR = SEPARATOR_OS + "eclipse" + SEPARATOR_OS; //$NON-NLS-1$
+ static final String PROFILE_DO_CHANGE = "profile-do-change"; //$NON-NLS-1$
+ static final String PROPERTY_PROXYPORT = "network.proxy_port"; //$NON-NLS-1$
+ static final String PROPERTY_PROXYHOST = "network.proxy_host"; //$NON-NLS-1$
+ static final String SEPARATOR_LOCALE = "-"; //$NON-NLS-1$
+ static final String SHUTDOWN_PERSIST = "shutdown-persist"; //$NON-NLS-1$
+ static final String STARTUP = "startup"; //$NON-NLS-1$
+ static final String TOKENIZER_LOCALE = ","; //$NON-NLS-1$
+ static final String URI_FROMMEMORY = "file:///"; //$NON-NLS-1$
+ static final String XULRUNNER_PATH = "dwt.browser.XULRunnerPath"; //$NON-NLS-1$
+
+ // TEMPORARY CODE
+ static final String GRE_INITIALIZED = "dwt.browser.XULRunnerInitialized"; //$NON-NLS-1$
+
+ static {
+ MozillaClearSessions = new Runnable () {
+ public void run () {
+ if (!Initialized) return;
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = XPCOM.NS_GetServiceManager (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+ result[0] = 0;
+ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_COOKIEMANAGER_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (aContractID, nsICookieManager.NS_ICOOKIEMANAGER_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ serviceManager.Release ();
+
+ nsICookieManager manager = new nsICookieManager (result[0]);
+ result[0] = 0;
+ rc = manager.GetEnumerator (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ manager.Release ();
+
+ nsISimpleEnumerator enumerator = new nsISimpleEnumerator (result[0]);
+ int[] moreElements = new int[1]; /* PRBool */
+ rc = enumerator.HasMoreElements (moreElements);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ while (moreElements[0] !is 0) {
+ result[0] = 0;
+ rc = enumerator.GetNext (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ nsICookie cookie = new nsICookie (result[0]);
+ long[] expires = new long[1];
+ rc = cookie.GetExpires (expires);
+ if (expires[0] is 0) {
+ /* indicates a session cookie */
+ int /*long*/ domain = XPCOM.nsEmbedCString_new ();
+ int /*long*/ name = XPCOM.nsEmbedCString_new ();
+ int /*long*/ path = XPCOM.nsEmbedCString_new ();
+ cookie.GetHost (domain);
+ cookie.GetName (name);
+ cookie.GetPath (path);
+ rc = manager.Remove (domain, name, path, 0);
+ XPCOM.nsEmbedCString_delete (domain);
+ XPCOM.nsEmbedCString_delete (name);
+ XPCOM.nsEmbedCString_delete (path);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ }
+ cookie.Release ();
+ rc = enumerator.HasMoreElements (moreElements);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ }
+ enumerator.Release ();
+ }
+ };
+ }
+
+public void create (Composite parent, int style) {
+ delegate = new MozillaDelegate (browser);
+ Display display = parent.getDisplay ();
+
+ int /*long*/[] result = new int /*long*/[1];
+ if (!Initialized) {
+ bool initLoaded = false;
+ bool IsXULRunner = false;
+
+ String greInitialized = System.getProperty (GRE_INITIALIZED);
+ if ("true".equals (greInitialized)) { //$NON-NLS-1$
+ /*
+ * Another browser has already initialized xulrunner in this process,
+ * so just bind to it instead of trying to initialize a new one.
+ */
+ Initialized = true;
+ }
+
+ String mozillaPath = System.getProperty (XULRUNNER_PATH);
+ /*
+ * Browser clients that ship XULRunner in a plug-in must have an opportunity
+ * to set the dwt.browser.XULRunnerPath system property to point
+ * at their XULRunner before the first Mozilla-based Browser is created. To
+ * facilitate this, reflection is used to reference non-existent class
+ * dwt.browser.XULRunnerInitializer the first time a Mozilla-
+ * based Browser is created. A client wishing to use this hook can do so
+ * by creating a fragment of dwt that implements this class and
+ * sets the system property in its static initializer.
+ */
+ if (mozillaPath is null) {
+ try {
+ Class.forName ("dwt.browser.XULRunnerInitializer"); //$NON-NLS-1$
+ mozillaPath = System.getProperty (XULRUNNER_PATH);
+ } catch (ClassNotFoundException e) {
+ /* no fragment is providing this class, which is the typical case */
+ }
+ }
+
+ if (mozillaPath is null) {
+ try {
+ String libName = delegate.getSWTInitLibraryName ();
+ Library.loadLibrary (libName);
+ initLoaded = true;
+ } catch (UnsatisfiedLinkError e) {
+ /*
+ * If this library failed to load then do not attempt to detect a
+ * xulrunner to use. The Browser may still be usable if MOZILLA_FIVE_HOME
+ * points at a GRE.
+ */
+ }
+ } else {
+ mozillaPath += SEPARATOR_OS + delegate.getLibraryName ();
+ IsXULRunner = true;
+ }
+
+ if (initLoaded) {
+ /* attempt to discover a XULRunner to use as the GRE */
+ GREVersionRange range = new GREVersionRange ();
+ byte[] bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_LOWER, true);
+ int /*long*/ lower = C.malloc (bytes.length);
+ C.memmove (lower, bytes, bytes.length);
+ range.lower = lower;
+ range.lowerInclusive = LowerRangeInclusive;
+
+ bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_UPPER, true);
+ int /*long*/ upper = C.malloc (bytes.length);
+ C.memmove (upper, bytes, bytes.length);
+ range.upper = upper;
+ range.upperInclusive = UpperRangeInclusive;
+
+ int length = XPCOMInit.PATH_MAX;
+ int /*long*/ greBuffer = C.malloc (length);
+ int /*long*/ propertiesPtr = C.malloc (2 * C.PTR_SIZEOF);
+ int rc = XPCOMInit.GRE_GetGREPathWithProperties (range, 1, propertiesPtr, 0, greBuffer, length);
+
+ /*
+ * A XULRunner was not found that supports wrapping of XPCOM handles as JavaXPCOM objects.
+ * Drop the lower version bound and try to detect an earlier XULRunner installation.
+ */
+ if (rc !is XPCOM.NS_OK) {
+ C.free (lower);
+ bytes = MozillaDelegate.wcsToMbcs (null, GRERANGE_LOWER_FALLBACK, true);
+ lower = C.malloc (bytes.length);
+ C.memmove (lower, bytes, bytes.length);
+ range.lower = lower;
+ rc = XPCOMInit.GRE_GetGREPathWithProperties (range, 1, propertiesPtr, 0, greBuffer, length);
+ }
+
+ C.free (lower);
+ C.free (upper);
+ C.free (propertiesPtr);
+ if (rc is XPCOM.NS_OK) {
+ /* indicates that a XULRunner was found */
+ length = C.strlen (greBuffer);
+ bytes = new byte[length];
+ C.memmove (bytes, greBuffer, length);
+ mozillaPath = new String (MozillaDelegate.mbcsToWcs (null, bytes));
+ IsXULRunner = mozillaPath.length () > 0;
+
+ /*
+ * Test whether the detected XULRunner can be used as the GRE before loading swt's
+ * XULRunner library. If it cannot be used then fall back to attempting to use
+ * the GRE pointed to by MOZILLA_FIVE_HOME.
+ *
+ * One case where this will fail is attempting to use a 64-bit xulrunner while swt
+ * is running in 32-bit mode, or vice versa.
+ */
+ if (IsXULRunner) {
+ byte[] path = MozillaDelegate.wcsToMbcs (null, mozillaPath, true);
+ rc = XPCOMInit.XPCOMGlueStartup (path);
+ if (rc !is XPCOM.NS_OK) {
+ IsXULRunner = false; /* failed */
+ mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS));
+ if (Device.DEBUG) System.out.println ("cannot use detected XULRunner: " + mozillaPath); //$NON-NLS-1$
+ } else {
+ XPCOMInitWasGlued = true;
+ }
+ }
+ }
+ C.free (greBuffer);
+ }
+
+ if (IsXULRunner) {
+ if (Device.DEBUG) System.out.println ("XULRunner path: " + mozillaPath); //$NON-NLS-1$
+ try {
+ Library.loadLibrary ("swt-xulrunner"); //$NON-NLS-1$
+ } catch (UnsatisfiedLinkError e) {
+ DWT.error (DWT.ERROR_NO_HANDLES, e);
+ }
+ byte[] path = MozillaDelegate.wcsToMbcs (null, mozillaPath, true);
+ int rc = XPCOM.XPCOMGlueStartup (path);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ XPCOMWasGlued = true;
+
+ /*
+ * Remove the trailing xpcom lib name from mozillaPath because the
+ * Mozilla.initialize and NS_InitXPCOM2 invocations require a directory name only.
+ */
+ mozillaPath = mozillaPath.substring (0, mozillaPath.lastIndexOf (SEPARATOR_OS));
+ } else {
+ if ((style & DWT.MOZILLA) !is 0) {
+ browser.dispose ();
+ String errorString = (mozillaPath !is null && mozillaPath.length () > 0) ?
+ " [Failed to use detected XULRunner: " + mozillaPath + "]" :
+ " [Could not detect registered XULRunner to use]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ DWT.error (DWT.ERROR_NO_HANDLES, null, errorString);
+ }
+
+ /* attempt to use the GRE pointed at by MOZILLA_FIVE_HOME */
+ int /*long*/ ptr = C.getenv (MozillaDelegate.wcsToMbcs (null, XPCOM.MOZILLA_FIVE_HOME, true));
+ if (ptr !is 0) {
+ int length = C.strlen (ptr);
+ byte[] buffer = new byte[length];
+ C.memmove (buffer, ptr, length);
+ mozillaPath = new String (MozillaDelegate.mbcsToWcs (null, buffer));
+ } else {
+ browser.dispose ();
+ DWT.error (DWT.ERROR_NO_HANDLES, null, " [Unknown Mozilla path (MOZILLA_FIVE_HOME not set)]"); //$NON-NLS-1$
+ }
+ if (Device.DEBUG) System.out.println ("Mozilla path: " + mozillaPath); //$NON-NLS-1$
+
+ /*
+ * Note. Embedding a Mozilla GTK1.2 causes a crash. The workaround
+ * is to check the version of GTK used by Mozilla by looking for
+ * the libwidget_gtk.so library used by Mozilla GTK1.2. Mozilla GTK2
+ * uses the libwidget_gtk2.so library.
+ */
+ if (Compatibility.fileExists (mozillaPath, "components/libwidget_gtk.so")) { //$NON-NLS-1$
+ browser.dispose ();
+ DWT.error (DWT.ERROR_NO_HANDLES, null, " [Mozilla GTK2 required (GTK1.2 detected)]"); //$NON-NLS-1$
+ }
+
+ try {
+ Library.loadLibrary ("swt-mozilla"); //$NON-NLS-1$
+ } catch (UnsatisfiedLinkError e) {
+ try {
+ /*
+ * The initial loadLibrary attempt may have failed as a result of the user's
+ * system not having libstdc++.so.6 installed, so try to load the alternate
+ * swt mozilla library that depends on libswtc++.so.5 instead.
+ */
+ Library.loadLibrary ("swt-mozilla-gcc3"); //$NON-NLS-1$
+ } catch (UnsatisfiedLinkError ex) {
+ browser.dispose ();
+ /*
+ * Print the error from the first failed attempt since at this point it's
+ * known that the failure was not due to the libstdc++.so.6 dependency.
+ */
+ DWT.error (DWT.ERROR_NO_HANDLES, e, " [MOZILLA_FIVE_HOME='" + mozillaPath + "']"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+
+ if (!Initialized) {
+ int /*long*/[] retVal = new int /*long*/[1];
+ nsEmbedString pathString = new nsEmbedString (mozillaPath);
+ int rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, retVal);
+ pathString.dispose ();
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (retVal[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_ERROR_NULL_POINTER);
+ }
+
+ LocationProvider = new AppFileLocProvider (mozillaPath);
+ LocationProvider.AddRef ();
+
+ nsIFile localFile = new nsILocalFile (retVal[0]);
+ rc = XPCOM.NS_InitXPCOM2 (0, localFile.getAddress(), LocationProvider.getAddress ());
+ localFile.Release ();
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ DWT.error (DWT.ERROR_NO_HANDLES, null, " [MOZILLA_FIVE_HOME may not point at an embeddable GRE] [NS_InitEmbedding " + mozillaPath + " error " + rc + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ System.setProperty (GRE_INITIALIZED, "true"); //$NON-NLS-1$
+ if (IsXULRunner) {
+ System.setProperty (XULRUNNER_PATH, mozillaPath);
+ }
+ }
+
+ /* If JavaXPCOM is detected then attempt to initialize it with the XULRunner being used */
+ if (IsXULRunner) {
+ try {
+ Class clazz = Class.forName ("org.mozilla.xpcom.Mozilla"); //$NON-NLS-1$
+ Method method = clazz.getMethod ("getInstance", new Class[0]); //$NON-NLS-1$
+ Object mozilla = method.invoke (null, new Object[0]);
+ method = clazz.getMethod ("getComponentManager", new Class[0]); //$NON-NLS-1$
+ try {
+ method.invoke (mozilla, new Object[0]);
+ } catch (InvocationTargetException e) {
+ /* indicates that JavaXPCOM has not been initialized yet */
+ Class fileClass = Class.forName ("java.io.File"); //$NON-NLS-1$
+ method = clazz.getMethod ("initialize", new Class[] {fileClass}); //$NON-NLS-1$
+ Constructor constructor = fileClass.getDeclaredConstructor (new Class[] {String.class});
+ Object argument = constructor.newInstance (new Object[] {mozillaPath});
+ method.invoke (mozilla, new Object[] {argument});
+ }
+ } catch (ClassNotFoundException e) {
+ /* JavaXPCOM is not on the classpath */
+ } catch (NoSuchMethodException e) {
+ /* the JavaXPCOM on the classpath does not implement initialize() */
+ } catch (IllegalArgumentException e) {
+ } catch (IllegalAccessException e) {
+ } catch (InvocationTargetException e) {
+ } catch (InstantiationException e) {
+ }
+ }
+
+ int rc = XPCOM.NS_GetComponentManager (result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIComponentManager componentManager = new nsIComponentManager (result[0]);
+ result[0] = 0;
+ if (delegate.needsSpinup ()) {
+ /* nsIAppShell is discontinued as of xulrunner 1.9, so do not fail if it is not found */
+ rc = componentManager.CreateInstance (XPCOM.NS_APPSHELL_CID, 0, nsIAppShell.NS_IAPPSHELL_IID, result);
+ if (rc !is XPCOM.NS_ERROR_NO_INTERFACE) {
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ AppShell = new nsIAppShell (result[0]);
+ rc = AppShell.Create (0, null);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ rc = AppShell.Spinup ();
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ }
+ result[0] = 0;
+ }
+
+ WindowCreator = new WindowCreator2 ();
+ WindowCreator.AddRef ();
+
+ rc = XPCOM.NS_GetServiceManager (result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+ result[0] = 0;
+ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WINDOWWATCHER_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (aContractID, nsIWindowWatcher.NS_IWINDOWWATCHER_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIWindowWatcher windowWatcher = new nsIWindowWatcher (result[0]);
+ result[0] = 0;
+ rc = windowWatcher.SetWindowCreator (WindowCreator.getAddress());
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ windowWatcher.Release ();
+
+ /* compute the profile directory and set it on the AppFileLocProvider */
+ if (LocationProvider !is null) {
+ byte[] buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DIRECTORYSERVICE_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (buffer, nsIDirectoryService.NS_IDIRECTORYSERVICE_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIDirectoryService directoryService = new nsIDirectoryService (result[0]);
+ result[0] = 0;
+ rc = directoryService.QueryInterface (nsIProperties.NS_IPROPERTIES_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+ directoryService.Release ();
+
+ nsIProperties properties = new nsIProperties (result[0]);
+ result[0] = 0;
+ buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_APP_APPLICATION_REGISTRY_DIR, true);
+ rc = properties.Get (buffer, nsIFile.NS_IFILE_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+ properties.Release ();
+
+ nsIFile profileDir = new nsIFile (result[0]);
+ result[0] = 0;
+ int /*long*/ path = XPCOM.nsEmbedCString_new ();
+ rc = profileDir.GetNativePath (path);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ int length = XPCOM.nsEmbedCString_Length (path);
+ int /*long*/ ptr = XPCOM.nsEmbedCString_get (path);
+ buffer = new byte [length];
+ XPCOM.memmove (buffer, ptr, length);
+ String profilePath = new String (MozillaDelegate.mbcsToWcs (null, buffer)) + PROFILE_DIR;
+ LocationProvider.setProfilePath (profilePath);
+ LocationProvider.isXULRunner = IsXULRunner;
+ XPCOM.nsEmbedCString_delete (path);
+ profileDir.Release ();
+
+ /* notify observers of a new profile directory being used */
+ buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_OBSERVER_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (buffer, nsIObserverService.NS_IOBSERVERSERVICE_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIObserverService observerService = new nsIObserverService (result[0]);
+ result[0] = 0;
+ buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_DO_CHANGE, true);
+ length = STARTUP.length ();
+ char[] chars = new char [length + 1];
+ STARTUP.getChars (0, length, chars, 0);
+ rc = observerService.NotifyObservers (0, buffer, chars);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_AFTER_CHANGE, true);
+ rc = observerService.NotifyObservers (0, buffer, chars);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ observerService.Release ();
+ }
+
+ /*
+ * As a result of using a common profile the user cannot change their locale
+ * and charset. The fix for this is to set mozilla's locale and charset
+ * preference values according to the user's current locale and charset.
+ */
+ aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFSERVICE_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (aContractID, nsIPrefService.NS_IPREFSERVICE_IID, result);
+ serviceManager.Release ();
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIPrefService prefService = new nsIPrefService (result[0]);
+ result[0] = 0;
+ byte[] buffer = new byte[1];
+ rc = prefService.GetBranch (buffer, result); /* empty buffer denotes root preference level */
+ prefService.Release ();
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIPrefBranch prefBranch = new nsIPrefBranch (result[0]);
+ result[0] = 0;
+
+ /* get Mozilla's current locale preference value */
+ String prefLocales = null;
+ nsIPrefLocalizedString localizedString = null;
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_LANGUAGES, true);
+ rc = prefBranch.GetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+ /*
+ * Feature of Debian. For some reason attempting to query for the current locale
+ * preference fails on Debian. The workaround for this is to assume a value of
+ * "en-us,en" since this is typically the default value when mozilla is used without
+ * a profile.
+ */
+ if (rc !is XPCOM.NS_OK) {
+ prefLocales = "en-us,en" + TOKENIZER_LOCALE; //$NON-NLS-1$
+ } else {
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+ localizedString = new nsIPrefLocalizedString (result[0]);
+ result[0] = 0;
+ rc = localizedString.ToString (result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+ int length = XPCOM.strlen_PRUnichar (result[0]);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, result[0], length * 2);
+ prefLocales = new String (dest) + TOKENIZER_LOCALE;
+ }
+ result[0] = 0;
+
+ /*
+ * construct the new locale preference value by prepending the
+ * user's current locale and language to the original value
+ */
+ Locale locale = Locale.getDefault ();
+ String language = locale.getLanguage ();
+ String country = locale.getCountry ();
+ StringBuffer stringBuffer = new StringBuffer (language);
+ stringBuffer.append (SEPARATOR_LOCALE);
+ stringBuffer.append (country.toLowerCase ());
+ stringBuffer.append (TOKENIZER_LOCALE);
+ stringBuffer.append (language);
+ stringBuffer.append (TOKENIZER_LOCALE);
+ String newLocales = stringBuffer.toString ();
+
+ int start, end = -1;
+ do {
+ start = end + 1;
+ end = prefLocales.indexOf (TOKENIZER_LOCALE, start);
+ String token;
+ if (end is -1) {
+ token = prefLocales.substring (start);
+ } else {
+ token = prefLocales.substring (start, end);
+ }
+ if (token.length () > 0) {
+ token = (token + TOKENIZER_LOCALE).trim ();
+ /* ensure that duplicate locale values are not added */
+ if (newLocales.indexOf (token) is -1) {
+ stringBuffer.append (token);
+ }
+ }
+ } while (end !is -1);
+ newLocales = stringBuffer.toString ();
+ if (!newLocales.equals (prefLocales)) {
+ /* write the new locale value */
+ newLocales = newLocales.substring (0, newLocales.length () - TOKENIZER_LOCALE.length ()); /* remove trailing tokenizer */
+ int length = newLocales.length ();
+ char[] charBuffer = new char[length + 1];
+ newLocales.getChars (0, length, charBuffer, 0);
+ if (localizedString is null) {
+ byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
+ rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+ localizedString = new nsIPrefLocalizedString (result[0]);
+ result[0] = 0;
+ }
+ localizedString.SetDataWithLength (length, charBuffer);
+ rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress());
+ }
+ if (localizedString !is null) {
+ localizedString.Release ();
+ localizedString = null;
+ }
+
+ /* get Mozilla's current charset preference value */
+ String prefCharset = null;
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_CHARSET, true);
+ rc = prefBranch.GetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+ /*
+ * Feature of Debian. For some reason attempting to query for the current charset
+ * preference fails on Debian. The workaround for this is to assume a value of
+ * "ISO-8859-1" since this is typically the default value when mozilla is used
+ * without a profile.
+ */
+ if (rc !is XPCOM.NS_OK) {
+ prefCharset = "ISO-8859-1"; //$NON_NLS-1$
+ } else {
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+ localizedString = new nsIPrefLocalizedString (result[0]);
+ result[0] = 0;
+ rc = localizedString.ToString (result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+ int length = XPCOM.strlen_PRUnichar (result[0]);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, result[0], length * 2);
+ prefCharset = new String (dest);
+ }
+ result[0] = 0;
+
+ String newCharset = System.getProperty ("file.encoding"); // $NON-NLS-1$
+ if (!newCharset.equals (prefCharset)) {
+ /* write the new charset value */
+ int length = newCharset.length ();
+ char[] charBuffer = new char[length + 1];
+ newCharset.getChars (0, length, charBuffer, 0);
+ if (localizedString is null) {
+ byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
+ rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+ localizedString = new nsIPrefLocalizedString (result[0]);
+ result[0] = 0;
+ }
+ localizedString.SetDataWithLength (length, charBuffer);
+ rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
+ }
+ if (localizedString !is null) localizedString.Release ();
+
+ /*
+ * Check for proxy values set as documented java properties and update mozilla's
+ * preferences with these values if needed.
+ */
+ String proxyHost = System.getProperty (PROPERTY_PROXYHOST);
+ String proxyPortString = System.getProperty (PROPERTY_PROXYPORT);
+
+ int port = -1;
+ if (proxyPortString !is null) {
+ try {
+ int value = Integer.valueOf (proxyPortString).intValue ();
+ if (0 <= value && value <= MAX_PORT) port = value;
+ } catch (NumberFormatException e) {
+ /* do nothing, java property has non-integer value */
+ }
+ }
+
+ if (proxyHost !is null) {
+ byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFLOCALIZEDSTRING_CONTRACTID, true);
+ rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ localizedString = new nsIPrefLocalizedString (result[0]);
+ result[0] = 0;
+ int length = proxyHost.length ();
+ char[] charBuffer = new char[length + 1];
+ proxyHost.getChars (0, length, charBuffer, 0);
+ rc = localizedString.SetDataWithLength (length, charBuffer);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_FTP, true);
+ rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
+ if (rc !is XPCOM.NS_OK) error (rc);
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_HTTP, true);
+ rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
+ if (rc !is XPCOM.NS_OK) error (rc);
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYHOST_SSL, true);
+ rc = prefBranch.SetComplexValue (buffer, nsIPrefLocalizedString.NS_IPREFLOCALIZEDSTRING_IID, localizedString.getAddress ());
+ if (rc !is XPCOM.NS_OK) error (rc);
+ localizedString.Release ();
+ }
+
+ if (port !is -1) {
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_FTP, true);
+ rc = prefBranch.SetIntPref (buffer, port);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_HTTP, true);
+ rc = prefBranch.SetIntPref (buffer, port);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYPORT_SSL, true);
+ rc = prefBranch.SetIntPref (buffer, port);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ }
+
+ if (proxyHost !is null || port !is -1) {
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_PROXYTYPE, true);
+ rc = prefBranch.SetIntPref (buffer, 1);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ }
+
+ /*
+ * Ensure that windows that are shown during page loads are not blocked. Firefox may
+ * try to block these by default since such windows are often unwelcome, but this
+ * assumption should not be made in the Browser's context. Since the Browser client
+ * is responsible for creating the new Browser and Shell in an OpenWindowListener,
+ * they should decide whether the new window is unwelcome or not and act accordingly.
+ */
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_DISABLEOPENDURINGLOAD, true);
+ rc = prefBranch.SetBoolPref (buffer, 0);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+
+ /* Ensure that the status text can be set through means like javascript */
+ buffer = MozillaDelegate.wcsToMbcs (null, PREFERENCE_DISABLEWINDOWSTATUSCHANGE, true);
+ rc = prefBranch.SetBoolPref (buffer, 0);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+
+ prefBranch.Release ();
+
+ PromptService2Factory factory = new PromptService2Factory ();
+ factory.AddRef ();
+
+ rc = componentManager.QueryInterface (nsIComponentRegistrar.NS_ICOMPONENTREGISTRAR_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIComponentRegistrar componentRegistrar = new nsIComponentRegistrar (result[0]);
+ result[0] = 0;
+ aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PROMPTSERVICE_CONTRACTID, true);
+ byte[] aClassName = MozillaDelegate.wcsToMbcs (null, "Prompt Service", true); //$NON-NLS-1$
+ rc = componentRegistrar.RegisterFactory (XPCOM.NS_PROMPTSERVICE_CID, aClassName, aContractID, factory.getAddress ());
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ factory.Release ();
+
+ HelperAppLauncherDialogFactory dialogFactory = new HelperAppLauncherDialogFactory ();
+ dialogFactory.AddRef ();
+ aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CONTRACTID, true);
+ aClassName = MozillaDelegate.wcsToMbcs (null, "Helper App Launcher Dialog", true); //$NON-NLS-1$
+ rc = componentRegistrar.RegisterFactory (XPCOM.NS_HELPERAPPLAUNCHERDIALOG_CID, aClassName, aContractID, dialogFactory.getAddress ());
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ dialogFactory.Release ();
+
+ /*
+ * This Download factory will be used if the GRE version is < 1.8.
+ * If the GRE version is 1.8.x then the Download factory that is registered later for
+ * contract "Transfer" will be used.
+ * If the GRE version is >= 1.9 then no Download factory is registered because this
+ * functionality is provided by the GRE.
+ */
+ DownloadFactory downloadFactory = new DownloadFactory ();
+ downloadFactory.AddRef ();
+ aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOWNLOAD_CONTRACTID, true);
+ aClassName = MozillaDelegate.wcsToMbcs (null, "Download", true); //$NON-NLS-1$
+ rc = componentRegistrar.RegisterFactory (XPCOM.NS_DOWNLOAD_CID, aClassName, aContractID, downloadFactory.getAddress ());
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ downloadFactory.Release ();
+
+ FilePickerFactory pickerFactory = IsXULRunner ? new FilePickerFactory_1_8 () : new FilePickerFactory ();
+ pickerFactory.AddRef ();
+ aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_FILEPICKER_CONTRACTID, true);
+ aClassName = MozillaDelegate.wcsToMbcs (null, "FilePicker", true); //$NON-NLS-1$
+ rc = componentRegistrar.RegisterFactory (XPCOM.NS_FILEPICKER_CID, aClassName, aContractID, pickerFactory.getAddress ());
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ pickerFactory.Release ();
+
+ componentRegistrar.Release ();
+ componentManager.Release ();
+
+ Initialized = true;
+ }
+
+ if (display.getData (DISPOSE_LISTENER_HOOKED) is null) {
+ display.setData (DISPOSE_LISTENER_HOOKED, DISPOSE_LISTENER_HOOKED);
+ display.addListener (DWT.Dispose, new Listener () {
+ public void handleEvent (Event event) {
+ if (BrowserCount > 0) return; /* another display is still active */
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = XPCOM.NS_GetServiceManager (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+ result[0] = 0;
+ byte[] buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_OBSERVER_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (buffer, nsIObserverService.NS_IOBSERVERSERVICE_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIObserverService observerService = new nsIObserverService (result[0]);
+ result[0] = 0;
+ buffer = MozillaDelegate.wcsToMbcs (null, PROFILE_BEFORE_CHANGE, true);
+ int length = SHUTDOWN_PERSIST.length ();
+ char[] chars = new char [length + 1];
+ SHUTDOWN_PERSIST.getChars (0, length, chars, 0);
+ rc = observerService.NotifyObservers (0, buffer, chars);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ observerService.Release ();
+
+ if (LocationProvider !is null) {
+ String prefsLocation = LocationProvider.profilePath + AppFileLocProvider.PREFERENCES_FILE;
+ nsEmbedString pathString = new nsEmbedString (prefsLocation);
+ rc = XPCOM.NS_NewLocalFile (pathString.getAddress (), 1, result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
+ pathString.dispose ();
+
+ nsILocalFile localFile = new nsILocalFile (result [0]);
+ result[0] = 0;
+ rc = localFile.QueryInterface (nsIFile.NS_IFILE_IID, result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
+ localFile.Release ();
+
+ nsIFile prefFile = new nsIFile (result[0]);
+ result[0] = 0;
+
+ buffer = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_PREFSERVICE_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (buffer, nsIPrefService.NS_IPREFSERVICE_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIPrefService prefService = new nsIPrefService (result[0]);
+ result[0] = 0;
+ rc = prefService.SavePrefFile(prefFile.getAddress ());
+ prefService.Release ();
+ prefFile.Release ();
+ }
+ serviceManager.Release ();
+
+ if (XPCOMWasGlued) {
+ XPCOM.XPCOMGlueShutdown ();
+ XPCOMWasGlued = false;
+ }
+ if (XPCOMInitWasGlued) {
+ XPCOMInit.XPCOMGlueShutdown ();
+ XPCOMInitWasGlued = false;
+ }
+ Initialized = false;
+ }
+ });
+ }
+
+ BrowserCount++;
+ int rc = XPCOM.NS_GetComponentManager (result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIComponentManager componentManager = new nsIComponentManager (result[0]);
+ result[0] = 0;
+ nsID NS_IWEBBROWSER_CID = new nsID ("F1EAC761-87E9-11d3-AF80-00A024FFC08C"); //$NON-NLS-1$
+ rc = componentManager.CreateInstance (NS_IWEBBROWSER_CID, 0, nsIWebBrowser.NS_IWEBBROWSER_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ webBrowser = new nsIWebBrowser (result[0]);
+ result[0] = 0;
+
+ createCOMInterfaces ();
+ AddRef ();
+
+ rc = webBrowser.SetContainerWindow (webBrowserChrome.getAddress());
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+
+ rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_ERROR_NO_INTERFACE);
+ }
+
+ nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+ result[0] = 0;
+ Rectangle rect = browser.getClientArea ();
+ if (rect.isEmpty ()) {
+ rect.width = 1;
+ rect.height = 1;
+ }
+
+ embedHandle = delegate.getHandle ();
+
+ rc = baseWindow.InitWindow (embedHandle, 0, 0, 0, rect.width, rect.height);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (XPCOM.NS_ERROR_FAILURE);
+ }
+ rc = baseWindow.Create ();
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (XPCOM.NS_ERROR_FAILURE);
+ }
+ rc = baseWindow.SetVisibility (1);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (XPCOM.NS_ERROR_FAILURE);
+ }
+ baseWindow.Release ();
+
+ if (!PerformedVersionCheck) {
+ PerformedVersionCheck = true;
+
+ /*
+ * Check for the availability of the pre-1.8 implementation of nsIDocShell
+ * to determine if the GRE's version is < 1.8.
+ */
+ rc = webBrowser.QueryInterface (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (XPCOM.NS_ERROR_FAILURE);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_ERROR_NO_INTERFACE);
+ }
+ nsIInterfaceRequestor interfaceRequestor = new nsIInterfaceRequestor (result[0]);
+ result[0] = 0;
+
+ rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result);
+ if (rc is XPCOM.NS_OK && result[0] !is 0) {
+ IsPre_1_8 = true;
+ new nsISupports (result[0]).Release ();
+ }
+ result[0] = 0;
+
+ /*
+ * A Download factory for contract "Transfer" must be registered iff the GRE's version is 1.8.x.
+ * Check for the availability of the 1.8 implementation of nsIDocShell to determine if the
+ * GRE's version is 1.8.x.
+ * If the GRE version is < 1.8 then the previously-registered Download factory for contract
+ * "Download" will be used.
+ * If the GRE version is >= 1.9 then no Download factory is registered because this
+ * functionality is provided by the GRE.
+ */
+ if (!IsPre_1_8) {
+ rc = interfaceRequestor.GetInterface (nsIDocShell_1_8.NS_IDOCSHELL_IID, result);
+ if (rc is XPCOM.NS_OK && result[0] !is 0) { /* 1.8 */
+ new nsISupports (result[0]).Release ();
+ result[0] = 0;
+ rc = componentManager.QueryInterface (nsIComponentRegistrar.NS_ICOMPONENTREGISTRAR_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_NOINTERFACE);
+ }
+
+ nsIComponentRegistrar componentRegistrar = new nsIComponentRegistrar (result[0]);
+ DownloadFactory_1_8 downloadFactory_1_8 = new DownloadFactory_1_8 ();
+ downloadFactory_1_8.AddRef ();
+ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_TRANSFER_CONTRACTID, true);
+ byte[] aClassName = MozillaDelegate.wcsToMbcs (null, "Transfer", true); //$NON-NLS-1$
+ rc = componentRegistrar.RegisterFactory (XPCOM.NS_DOWNLOAD_CID, aClassName, aContractID, downloadFactory_1_8.getAddress ());
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ downloadFactory_1_8.Release ();
+ componentRegistrar.Release ();
+ } else { /* >= 1.9 */
+ /*
+ * Bug in XULRunner 1.9. Mozilla no longer clears its background before initial content has
+ * been set. As a result embedders appear broken if they do not immediately navigate to a url.
+ * The workaround for this is to navigate to about:blank immediately so that the background is
+ * cleared, but do not fire any corresponding events or allow Browser API calls to reveal this.
+ * Once the client does a proper navigate with either setUrl() or setText() then resume as
+ * normal. The Mozilla bug for this is https://bugzilla.mozilla.org/show_bug.cgi?id=415789.
+ */
+ awaitingNavigate = true;
+ rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+ if (result[0] is 0) {
+ browser.dispose ();
+ error (XPCOM.NS_ERROR_NO_INTERFACE);
+ }
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ char[] uri = new char[ABOUT_BLANK.length () + 1];
+ ABOUT_BLANK.getChars (0, ABOUT_BLANK.length (), uri, 0);
+ rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
+ webNavigation.Release ();
+ }
+ }
+ result[0] = 0;
+ interfaceRequestor.Release ();
+ }
+ componentManager.Release ();
+
+ rc = webBrowser.AddWebBrowserListener (weakReference.getAddress (), nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID);
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+
+ rc = webBrowser.SetParentURIContentListener (uriContentListener.getAddress ());
+ if (rc !is XPCOM.NS_OK) {
+ browser.dispose ();
+ error (rc);
+ }
+
+ delegate.init ();
+
+ listener = new Listener () {
+ public void handleEvent (Event event) {
+ switch (event.type) {
+ case DWT.Dispose: {
+ /* make this handler run after other dispose listeners */
+ if (ignoreDispose) {
+ ignoreDispose = false;
+ break;
+ }
+ ignoreDispose = true;
+ browser.notifyListeners (event.type, event);
+ event.type = DWT.NONE;
+ onDispose (event.display);
+ break;
+ }
+ case DWT.Resize: onResize (); break;
+ case DWT.FocusIn: Activate (); break;
+ case DWT.Activate: Activate (); break;
+ case DWT.Deactivate: {
+ Display display = event.display;
+ if (Mozilla.this.browser is display.getFocusControl ()) Deactivate ();
+ break;
+ }
+ case DWT.Show: {
+ /*
+ * Feature in GTK Mozilla. Mozilla does not show up when
+ * its container (a GTK fixed handle) is made visible
+ * after having been hidden. The workaround is to reset
+ * its size after the container has been made visible.
+ */
+ Display display = event.display;
+ display.asyncExec(new Runnable () {
+ public void run() {
+ if (browser.isDisposed ()) return;
+ onResize ();
+ }
+ });
+ break;
+ }
+ }
+ }
+ };
+ int[] folderEvents = new int[] {
+ DWT.Dispose,
+ DWT.Resize,
+ DWT.FocusIn,
+ DWT.Activate,
+ DWT.Deactivate,
+ DWT.Show,
+ DWT.KeyDown // needed to make browser traversable
+ };
+ for (int i = 0; i < folderEvents.length; i++) {
+ browser.addListener (folderEvents[i], listener);
+ }
+}
+
+public bool back () {
+ if (awaitingNavigate) return false;
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ rc = webNavigation.GoBack ();
+ webNavigation.Release ();
+ return rc is XPCOM.NS_OK;
+}
+
+void createCOMInterfaces () {
+ // Create each of the interfaces that this object implements
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ weakReference = new XPCOMObject (new int[] {2, 0, 0, 2}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return QueryReferent (args[0], args[1]);}
+ };
+
+ webProgressListener = new XPCOMObject (new int[] {2, 0, 0, 4, 6, 3, 4, 3}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return OnStateChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return OnProgressChange (args[0], args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4], (int)/*64*/args[5]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return OnLocationChange (args[0], args[1], args[2]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return OnStatusChange (args[0], args[1], (int)/*64*/args[2], args[3]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return OnSecurityChange (args[0], args[1], (int)/*64*/args[2]);}
+ };
+
+ webBrowserChrome = new XPCOMObject (new int[] {2, 0, 0, 2, 1, 1, 1, 1, 0, 2, 0, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return SetStatus ((int)/*64*/args[0], args[1]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return GetWebBrowser (args[0]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return SetWebBrowser (args[0]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return GetChromeFlags (args[0]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return SetChromeFlags ((int)/*64*/args[0]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return DestroyBrowserWindow ();}
+ public int /*long*/ method9 (int /*long*/[] args) {return SizeBrowserTo ((int)/*64*/args[0], (int)/*64*/args[1]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return ShowAsModal ();}
+ public int /*long*/ method11 (int /*long*/[] args) {return IsWindowModal (args[0]);}
+ public int /*long*/ method12 (int /*long*/[] args) {return ExitModalEventLoop ((int)/*64*/args[0]);}
+ };
+
+ webBrowserChromeFocus = new XPCOMObject (new int[] {2, 0, 0, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return FocusNextElement ();}
+ public int /*long*/ method4 (int /*long*/[] args) {return FocusPrevElement ();}
+ };
+
+ embeddingSiteWindow = new XPCOMObject (new int[] {2, 0, 0, 5, 5, 0, 1, 1, 1, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return SetDimensions ((int)/*64*/args[0], (int)/*64*/args[1], (int)/*64*/args[2], (int)/*64*/args[3], (int)/*64*/args[4]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return GetDimensions ((int)/*64*/args[0], args[1], args[2], args[3], args[4]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return SetFocus ();}
+ public int /*long*/ method6 (int /*long*/[] args) {return GetVisibility (args[0]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return SetVisibility ((int)/*64*/args[0]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return GetTitle (args[0]);}
+ public int /*long*/ method9 (int /*long*/[] args) {return SetTitle (args[0]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return GetSiteWindow (args[0]);}
+ };
+
+ interfaceRequestor = new XPCOMObject (new int[] {2, 0, 0, 2} ){
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return GetInterface (args[0], args[1]);}
+ };
+
+ supportsWeakReference = new XPCOMObject (new int[] {2, 0, 0, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return GetWeakReference (args[0]);}
+ };
+
+ contextMenuListener = new XPCOMObject (new int[] {2, 0, 0, 3}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return OnShowContextMenu ((int)/*64*/args[0], args[1], args[2]);}
+ };
+
+ uriContentListener = new XPCOMObject (new int[] {2, 0, 0, 2, 5, 3, 4, 1, 1, 1, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return OnStartURIOpen (args[0], args[1]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return DoContent (args[0], (int)/*64*/args[1], args[2], args[3], args[4]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return IsPreferred (args[0], args[1], args[2]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return CanHandleContent (args[0], (int)/*64*/args[1], args[2], args[3]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return GetLoadCookie (args[0]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return SetLoadCookie (args[0]);}
+ public int /*long*/ method9 (int /*long*/[] args) {return GetParentContentListener (args[0]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return SetParentContentListener (args[0]);}
+ };
+
+ tooltipListener = new XPCOMObject (new int[] {2, 0, 0, 3, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return OnShowTooltip ((int)/*64*/args[0], (int)/*64*/args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return OnHideTooltip ();}
+ };
+
+ domEventListener = new XPCOMObject (new int[] {2, 0, 0, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return HandleEvent (args[0]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (weakReference !is null) {
+ weakReference.dispose ();
+ weakReference = null;
+ }
+ if (webProgressListener !is null) {
+ webProgressListener.dispose ();
+ webProgressListener = null;
+ }
+ if (webBrowserChrome !is null) {
+ webBrowserChrome.dispose ();
+ webBrowserChrome = null;
+ }
+ if (webBrowserChromeFocus !is null) {
+ webBrowserChromeFocus.dispose ();
+ webBrowserChromeFocus = null;
+ }
+ if (embeddingSiteWindow !is null) {
+ embeddingSiteWindow.dispose ();
+ embeddingSiteWindow = null;
+ }
+ if (interfaceRequestor !is null) {
+ interfaceRequestor.dispose ();
+ interfaceRequestor = null;
+ }
+ if (supportsWeakReference !is null) {
+ supportsWeakReference.dispose ();
+ supportsWeakReference = null;
+ }
+ if (contextMenuListener !is null) {
+ contextMenuListener.dispose ();
+ contextMenuListener = null;
+ }
+ if (uriContentListener !is null) {
+ uriContentListener.dispose ();
+ uriContentListener = null;
+ }
+ if (tooltipListener !is null) {
+ tooltipListener.dispose ();
+ tooltipListener = null;
+ }
+ if (domEventListener !is null) {
+ domEventListener.dispose ();
+ domEventListener = null;
+ }
+}
+
+public bool execute (String script) {
+ if (awaitingNavigate) return false;
+
+ String url = PREFIX_JAVASCRIPT + script + ";void(0);"; //$NON-NLS-1$
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ char[] arg = url.toCharArray ();
+ char[] c = new char[arg.length+1];
+ System.arraycopy (arg, 0, c, 0, arg.length);
+ rc = webNavigation.LoadURI (c, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
+ webNavigation.Release ();
+ return rc is XPCOM.NS_OK;
+}
+
+static Browser findBrowser (int /*long*/ handle) {
+ return MozillaDelegate.findBrowser (handle);
+}
+
+public bool forward () {
+ if (awaitingNavigate) return false;
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ rc = webNavigation.GoForward ();
+ webNavigation.Release ();
+
+ return rc is XPCOM.NS_OK;
+}
+
+public String getText () {
+ if (awaitingNavigate) return ""; //$NON-NLS-1$
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.GetContentDOMWindow (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIDOMWindow window = new nsIDOMWindow (result[0]);
+ result[0] = 0;
+ rc = window.GetDocument (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ window.Release ();
+
+ int /*long*/ document = result[0];
+ result[0] = 0;
+ rc = XPCOM.NS_GetComponentManager (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIComponentManager componentManager = new nsIComponentManager (result[0]);
+ result[0] = 0;
+ byte[] contractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_DOMSERIALIZER_CONTRACTID, true);
+ char[] chars = null;
+
+ rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIDOMSerializer_1_7.NS_IDOMSERIALIZER_IID, result);
+ if (rc is XPCOM.NS_OK) { /* mozilla >= 1.7 */
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIDOMSerializer_1_7 serializer = new nsIDOMSerializer_1_7 (result[0]);
+ result[0] = 0;
+ int /*long*/ string = XPCOM.nsEmbedString_new ();
+ rc = serializer.SerializeToString (document, string);
+ serializer.Release ();
+
+ int length = XPCOM.nsEmbedString_Length (string);
+ int /*long*/ buffer = XPCOM.nsEmbedString_get (string);
+ chars = new char[length];
+ XPCOM.memmove (chars, buffer, length * 2);
+ XPCOM.nsEmbedString_delete (string);
+ } else { /* mozilla < 1.7 */
+ rc = componentManager.CreateInstanceByContractID (contractID, 0, nsIDOMSerializer.NS_IDOMSERIALIZER_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIDOMSerializer serializer = new nsIDOMSerializer (result[0]);
+ result[0] = 0;
+ rc = serializer.SerializeToString (document, result);
+ serializer.Release ();
+
+ int length = XPCOM.strlen_PRUnichar (result[0]);
+ chars = new char[length];
+ XPCOM.memmove (chars, result[0], length * 2);
+ }
+
+ componentManager.Release ();
+ new nsISupports (document).Release ();
+ return new String (chars);
+}
+
+public String getUrl () {
+ if (awaitingNavigate) return ""; //$NON-NLS-1$
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ int /*long*/[] aCurrentURI = new int /*long*/[1];
+ rc = webNavigation.GetCurrentURI (aCurrentURI);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ webNavigation.Release ();
+
+ byte[] dest = null;
+ if (aCurrentURI[0] !is 0) {
+ nsIURI uri = new nsIURI (aCurrentURI[0]);
+ int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+ rc = uri.GetSpec (aSpec);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ int length = XPCOM.nsEmbedCString_Length (aSpec);
+ int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+ dest = new byte[length];
+ XPCOM.memmove (dest, buffer, length);
+ XPCOM.nsEmbedCString_delete (aSpec);
+ uri.Release ();
+ }
+ if (dest is null) return ""; //$NON-NLS-1$
+
+ String location = new String (dest);
+ /*
+ * If the URI indicates that the page is being rendered from memory
+ * (via setText()) then set it to about:blank to be consistent with IE.
+ */
+ if (location.equals (URI_FROMMEMORY)) location = ABOUT_BLANK;
+ return location;
+}
+
+public Object getWebBrowser () {
+ if ((browser.getStyle () & DWT.MOZILLA) is 0) return null;
+ if (webBrowserObject !is null) return webBrowserObject;
+
+ try {
+ Class clazz = Class.forName ("org.mozilla.xpcom.Mozilla"); //$NON-NLS-1$
+ Method method = clazz.getMethod ("getInstance", new Class[0]); //$NON-NLS-1$
+ Object mozilla = method.invoke (null, new Object[0]);
+ method = clazz.getMethod ("wrapXPCOMObject", new Class[] {Long.TYPE, String.class}); //$NON-NLS-1$
+ webBrowserObject = method.invoke (mozilla, new Object[] {new Long (webBrowser.getAddress ()), nsIWebBrowser.NS_IWEBBROWSER_IID_STR});
+ /*
+ * The following AddRef() is needed to offset the automatic Release() that
+ * will be performed by JavaXPCOM when webBrowserObject is finalized.
+ */
+ webBrowser.AddRef ();
+ return webBrowserObject;
+ } catch (ClassNotFoundException e) {
+ } catch (NoSuchMethodException e) {
+ } catch (IllegalArgumentException e) {
+ } catch (IllegalAccessException e) {
+ } catch (InvocationTargetException e) {
+ }
+ return null;
+}
+
+public bool isBackEnabled () {
+ if (awaitingNavigate) return false;
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ int[] aCanGoBack = new int[1]; /* PRBool */
+ rc = webNavigation.GetCanGoBack (aCanGoBack);
+ webNavigation.Release ();
+ return aCanGoBack[0] !is 0;
+}
+
+public bool isForwardEnabled () {
+ if (awaitingNavigate) return false;
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ int[] aCanGoForward = new int[1]; /* PRBool */
+ rc = webNavigation.GetCanGoForward (aCanGoForward);
+ webNavigation.Release ();
+ return aCanGoForward[0] !is 0;
+}
+
+static String error (int code) {
+ throw new DWTError ("XPCOM error " + code); //$NON-NLS-1$
+}
+
+void onDispose (Display display) {
+ int rc = webBrowser.RemoveWebBrowserListener (weakReference.getAddress (), nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID);
+ if (rc !is XPCOM.NS_OK) error (rc);
+
+ rc = webBrowser.SetParentURIContentListener (0);
+ if (rc !is XPCOM.NS_OK) error (rc);
+
+ unhookDOMListeners ();
+ if (listener !is null) {
+ int[] folderEvents = new int[] {
+ DWT.Dispose,
+ DWT.Resize,
+ DWT.FocusIn,
+ DWT.Activate,
+ DWT.Deactivate,
+ DWT.Show,
+ DWT.KeyDown,
+ };
+ for (int i = 0; i < folderEvents.length; i++) {
+ browser.removeListener (folderEvents[i], listener);
+ }
+ listener = null;
+ }
+
+ int /*long*/[] result = new int /*long*/[1];
+ rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+ rc = baseWindow.Destroy ();
+ if (rc !is XPCOM.NS_OK) error (rc);
+ baseWindow.Release ();
+
+ Release ();
+ webBrowser.Release ();
+ webBrowser = null;
+ webBrowserObject = null;
+
+ if (tip !is null && !tip.isDisposed ()) tip.dispose ();
+ tip = null;
+ location = size = null;
+
+ Enumeration elements = unhookedDOMWindows.elements ();
+ while (elements.hasMoreElements ()) {
+ LONG ptrObject = (LONG)elements.nextElement ();
+ new nsISupports (ptrObject.value).Release ();
+ }
+ unhookedDOMWindows = null;
+
+ delegate.onDispose (embedHandle);
+ delegate = null;
+
+ embedHandle = 0;
+ BrowserCount--;
+}
+
+void Activate () {
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebBrowserFocus.NS_IWEBBROWSERFOCUS_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]);
+ rc = webBrowserFocus.Activate ();
+ if (rc !is XPCOM.NS_OK) error (rc);
+ webBrowserFocus.Release ();
+}
+
+void Deactivate () {
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebBrowserFocus.NS_IWEBBROWSERFOCUS_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebBrowserFocus webBrowserFocus = new nsIWebBrowserFocus (result[0]);
+ rc = webBrowserFocus.Deactivate ();
+ if (rc !is XPCOM.NS_OK) error (rc);
+ webBrowserFocus.Release ();
+}
+
+void onResize () {
+ Rectangle rect = browser.getClientArea ();
+ int width = Math.max (1, rect.width);
+ int height = Math.max (1, rect.height);
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ delegate.setSize (embedHandle, width, height);
+ nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+ rc = baseWindow.SetPositionAndSize (0, 0, width, height, 1);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ baseWindow.Release ();
+}
+
+public void refresh () {
+ if (awaitingNavigate) return;
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error(rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ rc = webNavigation.Reload (nsIWebNavigation.LOAD_FLAGS_NONE);
+ webNavigation.Release ();
+ if (rc is XPCOM.NS_OK) return;
+ /*
+ * Feature in Mozilla. Reload returns an error code NS_ERROR_INVALID_POINTER
+ * when it is called immediately after a request to load a new document using
+ * LoadURI. The workaround is to ignore this error code.
+ *
+ * Feature in Mozilla. Attempting to reload a file that no longer exists
+ * returns an error code of NS_ERROR_FILE_NOT_FOUND. This is equivalent to
+ * attempting to load a non-existent local url, which is not a Browser error,
+ * so this error code should be ignored.
+ */
+ if (rc !is XPCOM.NS_ERROR_INVALID_POINTER && rc !is XPCOM.NS_ERROR_FILE_NOT_FOUND) error (rc);
+}
+
+public bool setText (String html) {
+ /*
+ * Feature in Mozilla. The focus memory of Mozilla must be
+ * properly managed through the nsIWebBrowserFocus interface.
+ * In particular, nsIWebBrowserFocus.deactivate must be called
+ * when the focus moves from the browser (or one of its children
+ * managed by Mozilla to another widget. We currently do not
+ * get notified when a widget takes focus away from the Browser.
+ * As a result, deactivate is not properly called. This causes
+ * Mozilla to retake focus the next time a document is loaded.
+ * This breaks the case where the HTML loaded in the Browser
+ * varies while the user enters characters in a text widget. The text
+ * widget loses focus every time new content is loaded.
+ * The current workaround is to call deactivate everytime if
+ * the browser currently does not have focus. A better workaround
+ * would be to have a way to call deactivate when the Browser
+ * or one of its children loses focus.
+ */
+ if (browser !is browser.getDisplay ().getFocusControl ()) Deactivate ();
+
+ /* convert the String containing HTML to an array of bytes with UTF-8 data */
+ byte[] data = null;
+ try {
+ data = html.getBytes ("UTF-8"); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException e) {
+ return false;
+ }
+
+ awaitingNavigate = false;
+
+ byte[] contentTypeBuffer = MozillaDelegate.wcsToMbcs (null, "text/html", true); // $NON-NLS-1$
+ int /*long*/ aContentType = XPCOM.nsEmbedCString_new (contentTypeBuffer, contentTypeBuffer.length);
+ byte[] contentCharsetBuffer = MozillaDelegate.wcsToMbcs (null, "UTF-8", true); //$NON-NLS-1$
+ int /*long*/ aContentCharset = XPCOM.nsEmbedCString_new (contentCharsetBuffer, contentCharsetBuffer.length);
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = XPCOM.NS_GetServiceManager (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+ result[0] = 0;
+ rc = serviceManager.GetService (XPCOM.NS_IOSERVICE_CID, nsIIOService.NS_IIOSERVICE_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ serviceManager.Release ();
+
+ nsIIOService ioService = new nsIIOService (result[0]);
+ result[0] = 0;
+ /*
+ * Note. Mozilla ignores LINK tags used to load CSS stylesheets
+ * when the URI protocol for the nsInputStreamChannel
+ * is about:blank. The fix is to specify the file protocol.
+ */
+ byte[] aString = MozillaDelegate.wcsToMbcs (null, URI_FROMMEMORY, false);
+ int /*long*/ aSpec = XPCOM.nsEmbedCString_new (aString, aString.length);
+ rc = ioService.NewURI (aSpec, null, 0, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ XPCOM.nsEmbedCString_delete (aSpec);
+ ioService.Release ();
+
+ nsIURI uri = new nsIURI (result[0]);
+ result[0] = 0;
+
+ rc = webBrowser.QueryInterface (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ nsIInterfaceRequestor interfaceRequestor = new nsIInterfaceRequestor (result[0]);
+ result[0] = 0;
+
+ /*
+ * Feature in Mozilla. LoadStream invokes the nsIInputStream argument
+ * through a different thread. The callback mechanism must attach
+ * a non java thread to the JVM otherwise the nsIInputStream Read and
+ * Close methods never get called.
+ */
+ InputStream inputStream = new InputStream (data);
+ inputStream.AddRef ();
+
+ rc = interfaceRequestor.GetInterface (nsIDocShell_1_9.NS_IDOCSHELL_IID, result);
+ if (rc is XPCOM.NS_OK) {
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ nsIDocShell_1_9 docShell = new nsIDocShell_1_9 (result[0]);
+ rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0);
+ docShell.Release ();
+ } else {
+ result[0] = 0;
+ rc = interfaceRequestor.GetInterface (nsIDocShell_1_8.NS_IDOCSHELL_IID, result);
+ if (rc is XPCOM.NS_OK) {
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ nsIDocShell_1_8 docShell = new nsIDocShell_1_8 (result[0]);
+ rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0);
+ docShell.Release ();
+ } else {
+ result[0] = 0;
+ rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ nsIDocShell docShell = new nsIDocShell (result[0]);
+ rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0);
+ docShell.Release ();
+ }
+ }
+ if (rc !is XPCOM.NS_OK) error (rc);
+ result[0] = 0;
+
+ inputStream.Release ();
+ interfaceRequestor.Release ();
+ uri.Release ();
+ XPCOM.nsEmbedCString_delete (aContentCharset);
+ XPCOM.nsEmbedCString_delete (aContentType);
+ return true;
+}
+
+public bool setUrl (String url) {
+ awaitingNavigate = false;
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ char[] uri = new char[url.length () + 1];
+ url.getChars (0, url.length (), uri, 0);
+ rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0);
+ webNavigation.Release ();
+ return rc is XPCOM.NS_OK;
+}
+
+public void stop () {
+ if (awaitingNavigate) return;
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]);
+ rc = webNavigation.Stop (nsIWebNavigation.STOP_ALL);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ webNavigation.Release ();
+}
+
+void hookDOMListeners (nsIDOMEventTarget target, bool isTop) {
+ nsEmbedString string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+
+ /*
+ * Only hook mouseover and mouseout if the target is a top-level frame, so that mouse moves
+ * between frames will not generate events.
+ */
+ if (isTop && delegate.hookEnterExit ()) {
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ }
+
+ string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP);
+ target.AddEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+}
+
+void unhookDOMListeners () {
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.GetContentDOMWindow (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIDOMWindow window = new nsIDOMWindow (result[0]);
+ result[0] = 0;
+ rc = window.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
+ result[0] = 0;
+ unhookDOMListeners (target);
+ target.Release ();
+
+ /* Listeners must be unhooked in pages contained in frames */
+ rc = window.GetFrames (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ nsIDOMWindowCollection frames = new nsIDOMWindowCollection (result[0]);
+ result[0] = 0;
+ int[] frameCount = new int[1];
+ rc = frames.GetLength (frameCount); /* PRUint32 */
+ if (rc !is XPCOM.NS_OK) error (rc);
+ int count = frameCount[0];
+
+ if (count > 0) {
+ for (int i = 0; i < count; i++) {
+ rc = frames.Item (i, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIDOMWindow frame = new nsIDOMWindow (result[0]);
+ result[0] = 0;
+ rc = frame.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ target = new nsIDOMEventTarget (result[0]);
+ result[0] = 0;
+ unhookDOMListeners (target);
+ target.Release ();
+ frame.Release ();
+ }
+ }
+ frames.Release ();
+ window.Release ();
+}
+
+void unhookDOMListeners (nsIDOMEventTarget target) {
+ nsEmbedString string = new nsEmbedString (XPCOM.DOMEVENT_FOCUS);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_UNLOAD);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDOWN);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEUP);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEMOVE);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEWHEEL);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEDRAG);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOVER);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_MOUSEOUT);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_KEYDOWN);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_KEYPRESS);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+ string = new nsEmbedString (XPCOM.DOMEVENT_KEYUP);
+ target.RemoveEventListener (string.getAddress (), domEventListener.getAddress (), 0);
+ string.dispose ();
+}
+
+/* nsISupports */
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIWeakReference.NS_IWEAKREFERENCE_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {weakReference.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {webProgressListener.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIWebBrowserChrome.NS_IWEBBROWSERCHROME_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {webBrowserChrome.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIWebBrowserChromeFocus.NS_IWEBBROWSERCHROMEFOCUS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {webBrowserChromeFocus.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIEmbeddingSiteWindow.NS_IEMBEDDINGSITEWINDOW_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {embeddingSiteWindow.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {interfaceRequestor.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsISupportsWeakReference.NS_ISUPPORTSWEAKREFERENCE_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supportsWeakReference.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIContextMenuListener.NS_ICONTEXTMENULISTENER_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {contextMenuListener.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIURIContentListener.NS_IURICONTENTLISTENER_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {uriContentListener.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsITooltipListener.NS_ITOOLTIPLISTENER_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {tooltipListener.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIWeakReference */
+
+int QueryReferent (int /*long*/ riid, int /*long*/ ppvObject) {
+ return QueryInterface (riid, ppvObject);
+}
+
+/* nsIInterfaceRequestor */
+
+int GetInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+ if (guid.Equals (nsIDOMWindow.NS_IDOMWINDOW_IID)) {
+ int /*long*/[] aContentDOMWindow = new int /*long*/[1];
+ int rc = webBrowser.GetContentDOMWindow (aContentDOMWindow);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (aContentDOMWindow[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ XPCOM.memmove (ppvObject, aContentDOMWindow, C.PTR_SIZEOF);
+ return rc;
+ }
+ return QueryInterface (riid, ppvObject);
+}
+
+int GetWeakReference (int /*long*/ ppvObject) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {weakReference.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+}
+
+/* nsIWebProgressListener */
+
+int OnStateChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStateFlags, int aStatus) {
+ if ((aStateFlags & nsIWebProgressListener.STATE_IS_DOCUMENT) is 0) return XPCOM.NS_OK;
+ if ((aStateFlags & nsIWebProgressListener.STATE_START) !is 0) {
+ if (request is 0) request = aRequest;
+
+ if (!awaitingNavigate) {
+ /*
+ * Add the page's nsIDOMWindow to the collection of windows that will
+ * have DOM listeners added to them later on in the page loading
+ * process. These listeners cannot be added yet because the
+ * nsIDOMWindow is not ready to take them at this stage.
+ */
+ int /*long*/[] result = new int /*long*/[1];
+ nsIWebProgress progress = new nsIWebProgress (aWebProgress);
+ int rc = progress.GetDOMWindow (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ unhookedDOMWindows.addElement (new LONG (result[0]));
+ }
+ } else if ((aStateFlags & nsIWebProgressListener.STATE_REDIRECTING) !is 0) {
+ if (request is aRequest) request = 0;
+ } else if ((aStateFlags & nsIWebProgressListener.STATE_STOP) !is 0) {
+ /*
+ * If this page's nsIDOMWindow handle is still in unhookedDOMWindows then
+ * add its DOM listeners now. It's possible for this to happen since
+ * there is no guarantee that a STATE_TRANSFERRING state change will be
+ * received for every window in a page, which is when these listeners
+ * are typically added.
+ */
+ int /*long*/[] result = new int /*long*/[1];
+ nsIWebProgress progress = new nsIWebProgress (aWebProgress);
+ int rc = progress.GetDOMWindow (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ nsIDOMWindow domWindow = new nsIDOMWindow (result[0]);
+
+ LONG ptrObject = new LONG (result[0]);
+ result[0] = 0;
+ int index = unhookedDOMWindows.indexOf (ptrObject);
+ if (index !is -1) {
+ rc = webBrowser.GetContentDOMWindow (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ bool isTop = result[0] is domWindow.getAddress ();
+ new nsISupports (result[0]).Release ();
+ result[0] = 0;
+
+ rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
+ result[0] = 0;
+ hookDOMListeners (target, isTop);
+ target.Release ();
+
+ /*
+ * Remove and unreference the nsIDOMWindow from the collection of windows
+ * that are waiting to have DOM listeners hooked on them.
+ */
+ unhookedDOMWindows.remove (ptrObject);
+ new nsISupports (ptrObject.value).Release ();
+ }
+ domWindow.Release ();
+
+ /*
+ * Feature in Mozilla. When a request is redirected (STATE_REDIRECTING),
+ * it never reaches the state STATE_STOP and it is replaced with a new request.
+ * The new request is received when it is in the state STATE_STOP.
+ * To handle this case, the variable request is set to 0 when the corresponding
+ * request is redirected. The following request received with the state STATE_STOP
+ * - the new request resulting from the redirection - is used to send
+ * the ProgressListener.completed event.
+ */
+ if (request is aRequest || request is 0) {
+ request = 0;
+ if (!awaitingNavigate) {
+ StatusTextEvent event = new StatusTextEvent (browser);
+ event.display = browser.getDisplay ();
+ event.widget = browser;
+ event.text = ""; //$NON-NLS-1$
+ for (int i = 0; i < statusTextListeners.length; i++) {
+ statusTextListeners[i].changed (event);
+ }
+ ProgressEvent event2 = new ProgressEvent (browser);
+ event2.display = browser.getDisplay ();
+ event2.widget = browser;
+ for (int i = 0; i < progressListeners.length; i++) {
+ progressListeners[i].completed (event2);
+ }
+ }
+ }
+ } else if ((aStateFlags & nsIWebProgressListener.STATE_TRANSFERRING) !is 0) {
+ /*
+ * Hook DOM listeners to the page's nsIDOMWindow here because this is
+ * the earliest opportunity to do so.
+ */
+ int /*long*/[] result = new int /*long*/[1];
+ nsIWebProgress progress = new nsIWebProgress (aWebProgress);
+ int rc = progress.GetDOMWindow (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ nsIDOMWindow domWindow = new nsIDOMWindow (result[0]);
+
+ LONG ptrObject = new LONG (result[0]);
+ result[0] = 0;
+ int index = unhookedDOMWindows.indexOf (ptrObject);
+ if (index !is -1) {
+ rc = webBrowser.GetContentDOMWindow (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ bool isTop = result[0] is domWindow.getAddress ();
+ new nsISupports (result[0]).Release ();
+ result[0] = 0;
+
+ rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]);
+ result[0] = 0;
+ hookDOMListeners (target, isTop);
+ target.Release ();
+
+ /*
+ * Remove and unreference the nsIDOMWindow from the collection of windows
+ * that are waiting to have DOM listeners hooked on them.
+ */
+ unhookedDOMWindows.remove (ptrObject);
+ new nsISupports (ptrObject.value).Release ();
+ }
+ domWindow.Release ();
+ }
+ return XPCOM.NS_OK;
+}
+
+int OnProgressChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aCurSelfProgress, int aMaxSelfProgress, int aCurTotalProgress, int aMaxTotalProgress) {
+ if (awaitingNavigate || progressListeners.length is 0) return XPCOM.NS_OK;
+ ProgressEvent event = new ProgressEvent (browser);
+ event.display = browser.getDisplay ();
+ event.widget = browser;
+ event.current = aCurTotalProgress;
+ event.total = aMaxTotalProgress;
+ for (int i = 0; i < progressListeners.length; i++) {
+ progressListeners[i].changed (event);
+ }
+ return XPCOM.NS_OK;
+}
+
+int OnLocationChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int /*long*/ aLocation) {
+ /*
+ * Feature in Mozilla. When a page is loaded via setText before a previous
+ * setText page load has completed, the expected OnStateChange STATE_STOP for the
+ * original setText never arrives because it gets replaced by the OnStateChange
+ * STATE_STOP for the new request. This results in the request field never being
+ * cleared because the original request's OnStateChange STATE_STOP is still expected
+ * (but never arrives). To handle this case, the request field is updated to the new
+ * overriding request since its OnStateChange STATE_STOP will be received next.
+ */
+ if (request !is 0 && request !is aRequest) request = aRequest;
+
+ if (awaitingNavigate || locationListeners.length is 0) return XPCOM.NS_OK;
+
+ nsIWebProgress webProgress = new nsIWebProgress (aWebProgress);
+ int /*long*/[] aDOMWindow = new int /*long*/[1];
+ int rc = webProgress.GetDOMWindow (aDOMWindow);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (aDOMWindow[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIDOMWindow domWindow = new nsIDOMWindow (aDOMWindow[0]);
+ int /*long*/[] aTop = new int /*long*/[1];
+ rc = domWindow.GetTop (aTop);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (aTop[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+ domWindow.Release ();
+
+ nsIDOMWindow topWindow = new nsIDOMWindow (aTop[0]);
+ topWindow.Release ();
+
+ nsIURI location = new nsIURI (aLocation);
+ int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+ location.GetSpec (aSpec);
+ int length = XPCOM.nsEmbedCString_Length (aSpec);
+ int /*long*/ buffer = XPCOM.nsEmbedCString_get (aSpec);
+ byte[] dest = new byte[length];
+ XPCOM.memmove (dest, buffer, length);
+ XPCOM.nsEmbedCString_delete (aSpec);
+ String url = new String (dest);
+
+ /*
+ * As of Mozilla 1.8, the first time that a page is displayed, regardless of
+ * whether it's via Browser.setURL() or Browser.setText(), the GRE navigates
+ * to about:blank and fires the corresponding navigation events. Do not send
+ * this event on to the user since it is not expected.
+ */
+ if (!IsPre_1_8 && aRequest is 0 && url.startsWith (ABOUT_BLANK)) return XPCOM.NS_OK;
+
+ LocationEvent event = new LocationEvent (browser);
+ event.display = browser.getDisplay ();
+ event.widget = browser;
+ event.location = url;
+ /*
+ * If the URI indicates that the page is being rendered from memory
+ * (via setText()) then set it to about:blank to be consistent with IE.
+ */
+ if (event.location.equals (URI_FROMMEMORY)) event.location = ABOUT_BLANK;
+ event.top = aTop[0] is aDOMWindow[0];
+ for (int i = 0; i < locationListeners.length; i++) {
+ locationListeners[i].changed (event);
+ }
+ return XPCOM.NS_OK;
+}
+
+int OnStatusChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int aStatus, int /*long*/ aMessage) {
+ if (awaitingNavigate || statusTextListeners.length is 0) return XPCOM.NS_OK;
+ StatusTextEvent event = new StatusTextEvent (browser);
+ event.display = browser.getDisplay ();
+ event.widget = browser;
+ int length = XPCOM.strlen_PRUnichar (aMessage);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, aMessage, length * 2);
+ event.text = new String (dest);
+ for (int i = 0; i < statusTextListeners.length; i++) {
+ statusTextListeners[i].changed (event);
+ }
+ return XPCOM.NS_OK;
+}
+
+int OnSecurityChange (int /*long*/ aWebProgress, int /*long*/ aRequest, int state) {
+ return XPCOM.NS_OK;
+}
+
+/* nsIWebBrowserChrome */
+
+int SetStatus (int statusType, int /*long*/ status) {
+ if (awaitingNavigate || statusTextListeners.length is 0) return XPCOM.NS_OK;
+ StatusTextEvent event = new StatusTextEvent (browser);
+ event.display = browser.getDisplay ();
+ event.widget = browser;
+ int length = XPCOM.strlen_PRUnichar (status);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, status, length * 2);
+ String string = new String (dest);
+ event.text = string;
+ for (int i = 0; i < statusTextListeners.length; i++) {
+ statusTextListeners[i].changed (event);
+ }
+ return XPCOM.NS_OK;
+}
+
+int GetWebBrowser (int /*long*/ aWebBrowser) {
+ int /*long*/[] ret = new int /*long*/[1];
+ if (webBrowser !is null) {
+ webBrowser.AddRef ();
+ ret[0] = webBrowser.getAddress ();
+ }
+ XPCOM.memmove (aWebBrowser, ret, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+int SetWebBrowser (int /*long*/ aWebBrowser) {
+ if (webBrowser !is null) webBrowser.Release ();
+ webBrowser = aWebBrowser !is 0 ? new nsIWebBrowser (aWebBrowser) : null;
+ return XPCOM.NS_OK;
+}
+
+int GetChromeFlags (int /*long*/ aChromeFlags) {
+ int[] ret = new int[1];
+ ret[0] = chromeFlags;
+ XPCOM.memmove (aChromeFlags, ret, 4); /* PRUint32 */
+ return XPCOM.NS_OK;
+}
+
+int SetChromeFlags (int aChromeFlags) {
+ chromeFlags = aChromeFlags;
+ return XPCOM.NS_OK;
+}
+
+int DestroyBrowserWindow () {
+ WindowEvent newEvent = new WindowEvent (browser);
+ newEvent.display = browser.getDisplay ();
+ newEvent.widget = browser;
+ for (int i = 0; i < closeWindowListeners.length; i++) {
+ closeWindowListeners[i].close (newEvent);
+ }
+ /*
+ * Note on Mozilla. The DestroyBrowserWindow notification cannot be cancelled.
+ * The browser widget cannot be used after this notification has been received.
+ * The application is advised to close the window hosting the browser widget.
+ * The browser widget must be disposed in all cases.
+ */
+ browser.dispose ();
+ return XPCOM.NS_OK;
+}
+
+int SizeBrowserTo (int aCX, int aCY) {
+ size = new Point (aCX, aCY);
+ bool isChrome = (chromeFlags & nsIWebBrowserChrome.CHROME_OPENAS_CHROME) !is 0;
+ if (isChrome) {
+ Shell shell = browser.getShell ();
+ shell.setSize (shell.computeSize (size.x, size.y));
+ }
+ return XPCOM.NS_OK;
+}
+
+int ShowAsModal () {
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = XPCOM.NS_GetServiceManager (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+
+ nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+ result[0] = 0;
+ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_CONTEXTSTACK_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (aContractID, nsIJSContextStack.NS_IJSCONTEXTSTACK_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_NOINTERFACE);
+ serviceManager.Release ();
+
+ nsIJSContextStack stack = new nsIJSContextStack (result[0]);
+ result[0] = 0;
+ rc = stack.Push (0);
+ if (rc !is XPCOM.NS_OK) error (rc);
+
+ Shell shell = browser.getShell ();
+ Display display = browser.getDisplay ();
+ while (!shell.isDisposed ()) {
+ if (!display.readAndDispatch ()) display.sleep ();
+ }
+
+ rc = stack.Pop (result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ stack.Release ();
+ return XPCOM.NS_OK;
+}
+
+int IsWindowModal (int /*long*/ retval) {
+ int result = (chromeFlags & nsIWebBrowserChrome.CHROME_MODAL) !is 0 ? 1 : 0;
+ XPCOM.memmove (retval, new int[] {result}, 4); /* PRBool */
+ return XPCOM.NS_OK;
+}
+
+int ExitModalEventLoop (int aStatus) {
+ return XPCOM.NS_OK;
+}
+
+/* nsIEmbeddingSiteWindow */
+
+int SetDimensions (int flags, int x, int y, int cx, int cy) {
+ if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) {
+ location = new Point (x, y);
+ browser.getShell ().setLocation (x, y);
+ }
+ if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) {
+ browser.setSize (cx, cy);
+ }
+ if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) {
+ browser.getShell ().setSize (cx, cy);
+ }
+ return XPCOM.NS_OK;
+}
+
+int GetDimensions (int flags, int /*long*/ x, int /*long*/ y, int /*long*/ cx, int /*long*/ cy) {
+ if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_POSITION) !is 0) {
+ Point location = browser.getShell ().getLocation ();
+ if (x !is 0) C.memmove (x, new int[] {location.x}, 4); /* PRInt32 */
+ if (y !is 0) C.memmove (y, new int[] {location.y}, 4); /* PRInt32 */
+ }
+ if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_INNER) !is 0) {
+ Point size = browser.getSize ();
+ if (cx !is 0) C.memmove (cx, new int[] {size.x}, 4); /* PRInt32 */
+ if (cy !is 0) C.memmove (cy, new int[] {size.y}, 4); /* PRInt32 */
+ }
+ if ((flags & nsIEmbeddingSiteWindow.DIM_FLAGS_SIZE_OUTER) !is 0) {
+ Point size = browser.getShell().getSize ();
+ if (cx !is 0) C.memmove (cx, new int[] {size.x}, 4); /* PRInt32 */
+ if (cy !is 0) C.memmove (cy, new int[] {size.y}, 4); /* PRInt32 */
+ }
+ return XPCOM.NS_OK;
+}
+
+int SetFocus () {
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = webBrowser.QueryInterface (nsIBaseWindow.NS_IBASEWINDOW_IID, result);
+ if (rc !is XPCOM.NS_OK) error (rc);
+ if (result[0] is 0) error (XPCOM.NS_ERROR_NO_INTERFACE);
+
+ nsIBaseWindow baseWindow = new nsIBaseWindow (result[0]);
+ rc = baseWindow.SetFocus ();
+ if (rc !is XPCOM.NS_OK) error (rc);
+ baseWindow.Release ();
+
+ /*
+ * Note. Mozilla notifies here that one of the children took
+ * focus. This could or should be used to fire an DWT.FOCUS_IN
+ * event on Browser focus listeners.
+ */
+ return XPCOM.NS_OK;
+}
+
+int GetVisibility (int /*long*/ aVisibility) {
+ bool visible = browser.isVisible () && !browser.getShell ().getMinimized ();
+ XPCOM.memmove (aVisibility, new int[] {visible ? 1 : 0}, 4); /* PRBool */
+ return XPCOM.NS_OK;
+}
+
+int SetVisibility (int aVisibility) {
+ if (isChild) {
+ WindowEvent event = new WindowEvent (browser);
+ event.display = browser.getDisplay ();
+ event.widget = browser;
+ if (aVisibility !is 0) {
+ /*
+ * Bug in Mozilla. When the JavaScript window.open is executed, Mozilla
+ * fires multiple SetVisibility 1 notifications. The workaround is
+ * to ignore subsequent notifications.
+ */
+ if (!visible) {
+ visible = true;
+ event.location = location;
+ event.size = size;
+ event.addressBar = (chromeFlags & nsIWebBrowserChrome.CHROME_LOCATIONBAR) !is 0;
+ event.menuBar = (chromeFlags & nsIWebBrowserChrome.CHROME_MENUBAR) !is 0;
+ event.statusBar = (chromeFlags & nsIWebBrowserChrome.CHROME_STATUSBAR) !is 0;
+ event.toolBar = (chromeFlags & nsIWebBrowserChrome.CHROME_TOOLBAR) !is 0;
+ for (int i = 0; i < visibilityWindowListeners.length; i++) {
+ visibilityWindowListeners[i].show (event);
+ }
+ location = null;
+ size = null;
+ }
+ } else {
+ visible = false;
+ for (int i = 0; i < visibilityWindowListeners.length; i++) {
+ visibilityWindowListeners[i].hide (event);
+ }
+ }
+ } else {
+ visible = aVisibility !is 0;
+ }
+ return XPCOM.NS_OK;
+}
+
+int GetTitle (int /*long*/ aTitle) {
+ return XPCOM.NS_OK;
+}
+
+int SetTitle (int /*long*/ aTitle) {
+ if (awaitingNavigate || titleListeners.length is 0) return XPCOM.NS_OK;
+ TitleEvent event = new TitleEvent (browser);
+ event.display = browser.getDisplay ();
+ event.widget = browser;
+ /*
+ * To be consistent with other platforms the title event should
+ * contain the page's url if the page does not contain a
+ * A particular Browser
can be passed to the event.browser
+ * field to host the content of a new window.
+ *
+ * A standalone system browser is used to host the new window
+ * if the event.required field value is false and if the event.browser
+ * field is left null
. The event.required field
+ * is true on platforms that don't support a standalone system browser for
+ * new window requests.
+ *
+ * The navigation is cancelled if the event.required field is set to
+ * true and the event.browser field is left null
.
+ *
+ *
The following fields in the WindowEvent
apply:
+ *
Browser
to handle the new window or false otherwise.
+ * Browser
that will host the
+ * content of the new window.
+ * Browser
that is requesting to open a
+ * new window
+ * WindowEvent
that needs to be passed a new
+ * Browser
to handle the new window request
+ *
+ * @since 3.0
+ */
+ public void open (WindowEvent event);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/ProgressAdapter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/ProgressAdapter.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg + * Classes that wish to deal with {@link ProgressEvent}'s can + * extend this class and override only the methods which they are + * interested in. + *
+ * + * @since 3.0 + */ +public abstract class ProgressAdapter : ProgressListener { + + public void changed (ProgressEvent event) { + } + + public void completed (ProgressEvent event) { + } +} diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/ProgressEvent.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/browser/ProgressEvent.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2003, 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: + * Jacob CarlborgProgressEvent
is sent by a {@link Browser} to
+ * {@link ProgressListener}'s when a progress is made during the
+ * loading of the current URL or when the loading of the current
+ * URL has been completed.
+ *
+ * @since 3.0
+ */
+public class ProgressEvent : TypedEvent {
+ /** current value */
+ public int current;
+
+ /** total value */
+ public int total;
+
+ static const long serialVersionUID = 3977018427045393972L;
+
+ 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 String toString () {
+ String str = super.toString();
+ return str.substring(0, String.length() - 1) // remove trailing '}'
+ + " current=" + current + " total=" + total + "}";
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/ProgressListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/ProgressListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg + * + *
The following fields in the ProgressEvent
apply:
+ *
Browser
whose current URL is being loaded
+ * ProgressEvent
related to the loading of the
+ * current location of a Browser
+ *
+ * @since 3.0
+ */
+ public void changed (ProgressEvent event);
+
+ /**
+ * This method is called when the current location has been completely loaded.
+ * + * + *
The following fields in the ProgressEvent
apply:
+ *
Browser
whose current URL has been loaded
+ * ProgressEvent
related to the Browser
+ * that has loaded its current URL.
+ *
+ * @since 3.0
+ */
+ public void completed (ProgressEvent event);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/PromptDialog.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/PromptDialog.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ *******************************************************************************/
+module dwt.browser.PromptDialog;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.layout.GridData;
+import dwt.layout.GridLayout;
+import dwt.widgets.Button;
+import dwt.widgets.Composite;
+import dwt.widgets.Dialog;
+import dwt.widgets.Display;
+import dwt.widgets.Event;
+import dwt.widgets.Label;
+import dwt.widgets.Listener;
+import dwt.widgets.Monitor;
+import dwt.widgets.Shell;
+import dwt.widgets.Text;
+import dwt.widgets.Widget;
+
+class PromptDialog extends Dialog {
+
+ PromptDialog(Shell parent, int style) {
+ super(parent, style);
+ }
+
+ PromptDialog(Shell parent) {
+ this(parent, 0);
+ }
+
+ void alertCheck(String title, String text, String check, final int[] checkValue) {
+ Shell parent = getParent();
+ final Shell shell = new Shell(parent, DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);
+ if (title !is null) shell.setText(title);
+ GridLayout gridLayout = new GridLayout();
+ shell.setLayout(gridLayout);
+ Label label = new Label(shell, DWT.WRAP);
+ label.setText(text);
+ GridData data = new GridData();
+ Monitor monitor = parent.getMonitor();
+ int maxWidth = monitor.getBounds().width * 2 / 3;
+ int width = label.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+ data.widthHint = Math.min(width, maxWidth);
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ label.setLayoutData (data);
+
+ final Button checkButton = check !is null ? new Button(shell, DWT.CHECK) : null;
+ if (checkButton !is null) {
+ checkButton.setText(check);
+ checkButton.setSelection(checkValue[0] !is 0);
+ data = new GridData ();
+ data.horizontalAlignment = GridData.BEGINNING;
+ checkButton.setLayoutData (data);
+ }
+ Button okButton = new Button(shell, DWT.PUSH);
+ okButton.setText(DWT.getMessage("SWT_OK")); //$NON-NLS-1$
+ data = new GridData ();
+ data.horizontalAlignment = GridData.CENTER;
+ okButton.setLayoutData (data);
+ okButton.addListener(DWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ if (checkButton !is null) checkValue[0] = checkButton.getSelection() ? 1 : 0;
+ shell.close();
+ }
+ });
+
+ shell.pack();
+ shell.open();
+ Display display = parent.getDisplay();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) display.sleep();
+ }
+ }
+
+ void confirmEx(String title, String text, String check, String button0, String button1, String button2, int defaultIndex, final int[] checkValue, final int[] result) {
+ Shell parent = getParent();
+ final Shell shell = new Shell(parent, DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);
+ shell.setText(title);
+ GridLayout gridLayout = new GridLayout();
+ shell.setLayout(gridLayout);
+ Label label = new Label(shell, DWT.WRAP);
+ label.setText(text);
+ GridData data = new GridData();
+ Monitor monitor = parent.getMonitor();
+ int maxWidth = monitor.getBounds().width * 2 / 3;
+ int width = label.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+ data.widthHint = Math.min(width, maxWidth);
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ label.setLayoutData (data);
+
+ final Button[] buttons = new Button[4];
+ Listener listener = new Listener() {
+ public void handleEvent(Event event) {
+ if (buttons[0] !is null) checkValue[0] = buttons[0].getSelection() ? 1 : 0;
+ Widget widget = event.widget;
+ for (int i = 1; i < buttons.length; i++) {
+ if (widget is buttons[i]) {
+ result[0] = i - 1;
+ break;
+ }
+ }
+ shell.close();
+ }
+ };
+ if (check !is null) {
+ buttons[0] = new Button(shell, DWT.CHECK);
+ buttons[0].setText(check);
+ buttons[0].setSelection(checkValue[0] !is 0);
+ data = new GridData ();
+ data.horizontalAlignment = GridData.BEGINNING;
+ buttons[0].setLayoutData (data);
+ }
+ Composite composite = new Composite(shell, DWT.NONE);
+ data = new GridData();
+ data.horizontalAlignment = GridData.CENTER;
+ composite.setLayoutData (data);
+ GridLayout layout = new GridLayout();
+ layout.makeColumnsEqualWidth = true;
+ composite.setLayout(layout);
+ int buttonCount = 0;
+ if (button0 !is null) {
+ buttons[1] = new Button(composite, DWT.PUSH);
+ buttons[1].setText(button0);
+ buttons[1].addListener(DWT.Selection, listener);
+ buttons[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ buttonCount++;
+ }
+ if (button1 !is null) {
+ buttons[2] = new Button(composite, DWT.PUSH);
+ buttons[2].setText(button1);
+ buttons[2].addListener(DWT.Selection, listener);
+ buttons[2].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ buttonCount++;
+ }
+ if (button2 !is null) {
+ buttons[3] = new Button(composite, DWT.PUSH);
+ buttons[3].setText(button2);
+ buttons[3].addListener(DWT.Selection, listener);
+ buttons[3].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ buttonCount++;
+ }
+ layout.numColumns = buttonCount;
+ Button defaultButton = buttons [defaultIndex + 1];
+ if (defaultButton !is null) shell.setDefaultButton (defaultButton);
+
+ shell.pack();
+ shell.open();
+ Display display = parent.getDisplay();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) display.sleep();
+ }
+ }
+
+ void prompt(String title, String text, String check, final String[] value, final int[] checkValue, final int[] result) {
+ Shell parent = getParent();
+ final Shell shell = new Shell(parent, DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);
+ if (title !is null) shell.setText(title);
+ GridLayout gridLayout = new GridLayout();
+ shell.setLayout(gridLayout);
+ Label label = new Label(shell, DWT.WRAP);
+ label.setText(text);
+ GridData data = new GridData();
+ Monitor monitor = parent.getMonitor();
+ int maxWidth = monitor.getBounds().width * 2 / 3;
+ int width = label.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+ data.widthHint = Math.min(width, maxWidth);
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ label.setLayoutData (data);
+
+ final Text valueText = new Text(shell, DWT.BORDER);
+ if (value[0] !is null) valueText.setText(value[0]);
+ data = new GridData();
+ width = valueText.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+ if (width > maxWidth) data.widthHint = maxWidth;
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ valueText.setLayoutData(data);
+
+ final Button[] buttons = new Button[3];
+ Listener listener = new Listener() {
+ public void handleEvent(Event event) {
+ if (buttons[0] !is null) checkValue[0] = buttons[0].getSelection() ? 1 : 0;
+ value[0] = valueText.getText();
+ result[0] = event.widget is buttons[1] ? 1 : 0;
+ shell.close();
+ }
+ };
+ if (check !is null) {
+ buttons[0] = new Button(shell, DWT.CHECK);
+ buttons[0].setText(check);
+ buttons[0].setSelection(checkValue[0] !is 0);
+ data = new GridData ();
+ data.horizontalAlignment = GridData.BEGINNING;
+ buttons[0].setLayoutData (data);
+ }
+ Composite composite = new Composite(shell, DWT.NONE);
+ data = new GridData();
+ data.horizontalAlignment = GridData.CENTER;
+ composite.setLayoutData (data);
+ composite.setLayout(new GridLayout(2, true));
+ buttons[1] = new Button(composite, DWT.PUSH);
+ buttons[1].setText(DWT.getMessage("SWT_OK")); //$NON-NLS-1$
+ buttons[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ buttons[1].addListener(DWT.Selection, listener);
+ buttons[2] = new Button(composite, DWT.PUSH);
+ buttons[2].setText(DWT.getMessage("SWT_Cancel")); //$NON-NLS-1$
+ buttons[2].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ buttons[2].addListener(DWT.Selection, listener);
+
+ shell.pack();
+ shell.open();
+ Display display = parent.getDisplay();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) display.sleep();
+ }
+ }
+
+ void promptUsernameAndPassword(String title, String text, String check, final String[] user, final String[] pass, final int[] checkValue, final int[] result) {
+ Shell parent = getParent();
+ final Shell shell = new Shell(parent, DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);
+ shell.setText(title);
+ GridLayout gridLayout = new GridLayout();
+ shell.setLayout(gridLayout);
+ Label label = new Label(shell, DWT.WRAP);
+ label.setText(text);
+ GridData data = new GridData();
+ Monitor monitor = parent.getMonitor();
+ int maxWidth = monitor.getBounds().width * 2 / 3;
+ int width = label.computeSize(DWT.DEFAULT, DWT.DEFAULT).x;
+ data.widthHint = Math.min(width, maxWidth);
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ label.setLayoutData (data);
+
+ Label userLabel = new Label(shell, DWT.NONE);
+ userLabel.setText(DWT.getMessage("SWT_Username")); //$NON-NLS-1$
+
+ final Text userText = new Text(shell, DWT.BORDER);
+ if (user[0] !is null) userText.setText(user[0]);
+ data = new GridData();
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ userText.setLayoutData(data);
+
+ Label passwordLabel = new Label(shell, DWT.NONE);
+ passwordLabel.setText(DWT.getMessage("SWT_Password")); //$NON-NLS-1$
+
+ final Text passwordText = new Text(shell, DWT.PASSWORD | DWT.BORDER);
+ if (pass[0] !is null) passwordText.setText(pass[0]);
+ data = new GridData();
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ passwordText.setLayoutData(data);
+
+ final Button[] buttons = new Button[3];
+ Listener listener = new Listener() {
+ public void handleEvent(Event event) {
+ if (buttons[0] !is null) checkValue[0] = buttons[0].getSelection() ? 1 : 0;
+ user[0] = userText.getText();
+ pass[0] = passwordText.getText();
+ result[0] = event.widget is buttons[1] ? 1 : 0;
+ shell.close();
+ }
+ };
+ if (check !is null) {
+ buttons[0] = new Button(shell, DWT.CHECK);
+ buttons[0].setText(check);
+ buttons[0].setSelection(checkValue[0] !is 0);
+ data = new GridData ();
+ data.horizontalAlignment = GridData.BEGINNING;
+ buttons[0].setLayoutData (data);
+ }
+ Composite composite = new Composite(shell, DWT.NONE);
+ data = new GridData();
+ data.horizontalAlignment = GridData.CENTER;
+ composite.setLayoutData (data);
+ composite.setLayout(new GridLayout(2, true));
+ buttons[1] = new Button(composite, DWT.PUSH);
+ buttons[1].setText(DWT.getMessage("SWT_OK")); //$NON-NLS-1$
+ buttons[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ buttons[1].addListener(DWT.Selection, listener);
+ buttons[2] = new Button(composite, DWT.PUSH);
+ buttons[2].setText(DWT.getMessage("SWT_Cancel")); //$NON-NLS-1$
+ buttons[2].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ buttons[2].addListener(DWT.Selection, listener);
+
+ shell.setDefaultButton(buttons[1]);
+ shell.pack();
+ shell.open();
+ Display display = parent.getDisplay();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) display.sleep();
+ }
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/PromptService2.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/PromptService2.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,649 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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 dwt.browser.PromptService2;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.C;
+import dwt.internal.Compatibility;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsEmbedString;
+import dwt.internal.mozilla.nsIAuthInformation;
+import dwt.internal.mozilla.nsIChannel;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIDOMWindow;
+import dwt.internal.mozilla.nsIEmbeddingSiteWindow;
+import dwt.internal.mozilla.nsIMemory;
+import dwt.internal.mozilla.nsIPromptService;
+import dwt.internal.mozilla.nsIPromptService2;
+import dwt.internal.mozilla.nsIServiceManager;
+import dwt.internal.mozilla.nsISupports;
+import dwt.internal.mozilla.nsIURI;
+import dwt.internal.mozilla.nsIWebBrowserChrome;
+import dwt.internal.mozilla.nsIWindowWatcher;
+import dwt.widgets.MessageBox;
+import dwt.widgets.Shell;
+
+class PromptService2 {
+ XPCOMObject supports;
+ XPCOMObject promptService;
+ XPCOMObject promptService2;
+ int refCount = 0;
+
+PromptService2 () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ promptService = new XPCOMObject (new int[] {2, 0, 0, 3, 5, 4, 6, 10, 7, 8, 7, 7}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return Alert (args[0], args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return AlertCheck (args[0], args[1], args[2], args[3], args[4]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return Confirm (args[0], args[1], args[2], args[3]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return ConfirmCheck (args[0], args[1], args[2], args[3], args[4], args[5]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return ConfirmEx (args[0], args[1], args[2], (int)/*64*/args[3], args[4], args[5], args[6], args[7], args[8], args[9]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return Prompt (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+ public int /*long*/ method9 (int /*long*/[] args) {return PromptUsernameAndPassword (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return PromptPassword (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+ public int /*long*/ method11 (int /*long*/[] args) {return Select (args[0], args[1], args[2], (int)/*64*/args[3], args[4], args[5], args[6]);}
+ };
+
+ promptService2 = new XPCOMObject (new int[] {2, 0, 0, 3, 5, 4, 6, 10, 7, 8, 7, 7, 7, 9}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return Alert (args[0], args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return AlertCheck (args[0], args[1], args[2], args[3], args[4]);}
+ public int /*long*/ method5 (int /*long*/[] args) {return Confirm (args[0], args[1], args[2], args[3]);}
+ public int /*long*/ method6 (int /*long*/[] args) {return ConfirmCheck (args[0], args[1], args[2], args[3], args[4], args[5]);}
+ public int /*long*/ method7 (int /*long*/[] args) {return ConfirmEx (args[0], args[1], args[2], (int)/*64*/args[3], args[4], args[5], args[6], args[7], args[8], args[9]);}
+ public int /*long*/ method8 (int /*long*/[] args) {return Prompt (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+ public int /*long*/ method9 (int /*long*/[] args) {return PromptUsernameAndPassword (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);}
+ public int /*long*/ method10 (int /*long*/[] args) {return PromptPassword (args[0], args[1], args[2], args[3], args[4], args[5], args[6]);}
+ public int /*long*/ method11 (int /*long*/[] args) {return Select (args[0], args[1], args[2], (int)/*64*/args[3], args[4], args[5], args[6]);}
+ public int /*long*/ method12 (int /*long*/[] args) {return PromptAuth (args[0], args[1], (int)/*64*/args[2], args[3], args[4], args[5], args[6]);}
+ public int /*long*/ method13 (int /*long*/[] args) {return AsyncPromptAuth (args[0], args[1], args[2], args[3], (int)/*64*/args[4], args[5], args[6], args[7], args[8]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (promptService !is null) {
+ promptService.dispose ();
+ promptService = null;
+ }
+ if (promptService2 !is null) {
+ promptService2.dispose ();
+ promptService2 = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return promptService2.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIPromptService.NS_IPROMPTSERVICE_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {promptService.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIPromptService2.NS_IPROMPTSERVICE2_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {promptService2.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+Browser getBrowser (int /*long*/ aDOMWindow) {
+ if (aDOMWindow is 0) return null;
+
+ int /*long*/[] result = new int /*long*/[1];
+ int rc = XPCOM.NS_GetServiceManager (result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+
+ nsIServiceManager serviceManager = new nsIServiceManager (result[0]);
+ result[0] = 0;
+ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_WINDOWWATCHER_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (aContractID, nsIWindowWatcher.NS_IWINDOWWATCHER_IID, result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error(rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+ serviceManager.Release ();
+
+ nsIWindowWatcher windowWatcher = new nsIWindowWatcher (result[0]);
+ result[0] = 0;
+ /* the chrome will only be answered for the top-level nsIDOMWindow */
+ nsIDOMWindow window = new nsIDOMWindow (aDOMWindow);
+ rc = window.GetTop (result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+ aDOMWindow = result[0];
+ result[0] = 0;
+ rc = windowWatcher.GetChromeForWindow (aDOMWindow, result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+ windowWatcher.Release ();
+
+ nsIWebBrowserChrome webBrowserChrome = new nsIWebBrowserChrome (result[0]);
+ result[0] = 0;
+ rc = webBrowserChrome.QueryInterface (nsIEmbeddingSiteWindow.NS_IEMBEDDINGSITEWINDOW_IID, result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+ webBrowserChrome.Release ();
+
+ nsIEmbeddingSiteWindow embeddingSiteWindow = new nsIEmbeddingSiteWindow (result[0]);
+ result[0] = 0;
+ rc = embeddingSiteWindow.GetSiteWindow (result);
+ if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
+ if (result[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+ embeddingSiteWindow.Release ();
+
+ return Mozilla.findBrowser (result[0]);
+}
+
+String getLabel (int buttonFlag, int index, int /*long*/ buttonTitle) {
+ String label = null;
+ int flag = (buttonFlag & (0xff * index)) / index;
+ switch (flag) {
+ case nsIPromptService.BUTTON_TITLE_CANCEL : label = DWT.getMessage ("SWT_Cancel"); break; //$NON-NLS-1$
+ case nsIPromptService.BUTTON_TITLE_NO : label = DWT.getMessage ("SWT_No"); break; //$NON-NLS-1$
+ case nsIPromptService.BUTTON_TITLE_OK : label = DWT.getMessage ("SWT_OK"); break; //$NON-NLS-1$
+ case nsIPromptService.BUTTON_TITLE_SAVE : label = DWT.getMessage ("SWT_Save"); break; //$NON-NLS-1$
+ case nsIPromptService.BUTTON_TITLE_YES : label = DWT.getMessage ("SWT_Yes"); break; //$NON-NLS-1$
+ case nsIPromptService.BUTTON_TITLE_IS_STRING : {
+ int length = XPCOM.strlen_PRUnichar (buttonTitle);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, buttonTitle, length * 2);
+ label = new String (dest);
+ }
+ }
+ return label;
+}
+
+/* nsIPromptService */
+
+int Alert (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText) {
+ Browser browser = getBrowser (aParent);
+
+ int length = XPCOM.strlen_PRUnichar (aDialogTitle);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, aDialogTitle, length * 2);
+ String titleLabel = new String (dest);
+
+ length = XPCOM.strlen_PRUnichar (aText);
+ dest = new char[length];
+ XPCOM.memmove (dest, aText, length * 2);
+ String textLabel = new String (dest);
+
+ Shell shell = browser is null ? new Shell () : browser.getShell ();
+ MessageBox messageBox = new MessageBox (shell, DWT.OK | DWT.ICON_WARNING);
+ messageBox.setText (titleLabel);
+ messageBox.setMessage (textLabel);
+ messageBox.open ();
+ return XPCOM.NS_OK;
+}
+
+int AlertCheck (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aCheckMsg, int /*long*/ aCheckState) {
+ Browser browser = getBrowser (aParent);
+
+ int length = XPCOM.strlen_PRUnichar (aDialogTitle);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, aDialogTitle, length * 2);
+ String titleLabel = new String (dest);
+
+ length = XPCOM.strlen_PRUnichar (aText);
+ dest = new char[length];
+ XPCOM.memmove (dest, aText, length * 2);
+ String textLabel = new String (dest);
+
+ length = XPCOM.strlen_PRUnichar (aCheckMsg);
+ dest = new char[length];
+ XPCOM.memmove (dest, aCheckMsg, length * 2);
+ String checkLabel = new String (dest);
+
+ Shell shell = browser is null ? new Shell () : browser.getShell ();
+ PromptDialog dialog = new PromptDialog (shell);
+ int[] check = new int[1];
+ if (aCheckState !is 0) XPCOM.memmove (check, aCheckState, 4); /* PRBool */
+ dialog.alertCheck (titleLabel, textLabel, checkLabel, check);
+ if (aCheckState !is 0) XPCOM.memmove (aCheckState, check, 4); /* PRBool */
+ return XPCOM.NS_OK;
+}
+
+int AsyncPromptAuth(int /*long*/ aParent, int /*long*/ aChannel, int /*long*/ aCallback, int /*long*/ aContext, int level, int /*long*/ authInfo, int /*long*/ checkboxLabel, int /*long*/ checkValue, int /*long*/ _retval) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int Confirm (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ _retval) {
+ Browser browser = getBrowser (aParent);
+
+ int length = XPCOM.strlen_PRUnichar (aDialogTitle);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, aDialogTitle, length * 2);
+ String titleLabel = new String (dest);
+
+ length = XPCOM.strlen_PRUnichar (aText);
+ dest = new char[length];
+ XPCOM.memmove (dest, aText, length * 2);
+ String textLabel = new String (dest);
+
+ Shell shell = browser is null ? new Shell () : browser.getShell ();
+ MessageBox messageBox = new MessageBox (shell, DWT.OK | DWT.CANCEL | DWT.ICON_QUESTION);
+ messageBox.setText (titleLabel);
+ messageBox.setMessage (textLabel);
+ int id = messageBox.open ();
+ int[] result = {id is DWT.OK ? 1 : 0};
+ XPCOM.memmove (_retval, result, 4);
+ return XPCOM.NS_OK;
+}
+
+int ConfirmCheck (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int ConfirmEx (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int aButtonFlags, int /*long*/ aButton0Title, int /*long*/ aButton1Title, int /*long*/ aButton2Title, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+ Browser browser = getBrowser (aParent);
+
+ int length = XPCOM.strlen_PRUnichar (aDialogTitle);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, aDialogTitle, length * 2);
+ String titleLabel = new String (dest);
+
+ length = XPCOM.strlen_PRUnichar (aText);
+ dest = new char[length];
+ XPCOM.memmove (dest, aText, length * 2);
+ String textLabel = new String (dest);
+
+ String checkLabel = null;
+ if (aCheckMsg !is 0) {
+ length = XPCOM.strlen_PRUnichar (aCheckMsg);
+ dest = new char[length];
+ XPCOM.memmove (dest, aCheckMsg, length * 2);
+ checkLabel = new String (dest);
+ }
+
+ String button0Label = getLabel (aButtonFlags, nsIPromptService.BUTTON_POS_0, aButton0Title);
+ String button1Label = getLabel (aButtonFlags, nsIPromptService.BUTTON_POS_1, aButton1Title);
+ String button2Label = getLabel (aButtonFlags, nsIPromptService.BUTTON_POS_2, aButton2Title);
+
+ int defaultIndex = 0;
+ if ((aButtonFlags & nsIPromptService.BUTTON_POS_1_DEFAULT) !is 0) {
+ defaultIndex = 1;
+ } else if ((aButtonFlags & nsIPromptService.BUTTON_POS_2_DEFAULT) !is 0) {
+ defaultIndex = 2;
+ }
+
+ Shell shell = browser is null ? new Shell () : browser.getShell ();
+ PromptDialog dialog = new PromptDialog (shell);
+ int[] check = new int[1], result = new int[1];
+ if (aCheckState !is 0) XPCOM.memmove (check, aCheckState, 4);
+ dialog.confirmEx (titleLabel, textLabel, checkLabel, button0Label, button1Label, button2Label, defaultIndex, check, result);
+ if (aCheckState !is 0) XPCOM.memmove (aCheckState, check, 4);
+ XPCOM.memmove (_retval, result, 4);
+ return XPCOM.NS_OK;
+}
+
+int Prompt (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aValue, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+ Browser browser = getBrowser (aParent);
+ String titleLabel = null, textLabel, checkLabel = null;
+ String[] valueLabel = new String[1];
+ char[] dest;
+ int length;
+ if (aDialogTitle !is 0) {
+ length = XPCOM.strlen_PRUnichar (aDialogTitle);
+ dest = new char[length];
+ XPCOM.memmove (dest, aDialogTitle, length * 2);
+ titleLabel = new String (dest);
+ }
+
+ length = XPCOM.strlen_PRUnichar (aText);
+ dest = new char[length];
+ XPCOM.memmove (dest, aText, length * 2);
+ textLabel = new String (dest);
+
+ int /*long*/[] valueAddr = new int /*long*/[1];
+ XPCOM.memmove (valueAddr, aValue, C.PTR_SIZEOF);
+ if (valueAddr[0] !is 0) {
+ length = XPCOM.strlen_PRUnichar (valueAddr[0]);
+ dest = new char[length];
+ XPCOM.memmove (dest, valueAddr[0], length * 2);
+ valueLabel[0] = new String (dest);
+ }
+
+ if (aCheckMsg !is 0) {
+ length = XPCOM.strlen_PRUnichar (aCheckMsg);
+ if (length > 0) {
+ dest = new char[length];
+ XPCOM.memmove (dest, aCheckMsg, length * 2);
+ checkLabel = new String (dest);
+ }
+ }
+
+ Shell shell = browser is null ? new Shell () : browser.getShell ();
+ PromptDialog dialog = new PromptDialog (shell);
+ int[] check = new int[1], result = new int[1];
+ if (aCheckState !is 0) XPCOM.memmove (check, aCheckState, 4);
+ dialog.prompt (titleLabel, textLabel, checkLabel, valueLabel, check, result);
+
+ XPCOM.memmove (_retval, result, 4);
+ if (result[0] is 1) {
+ /*
+ * User selected OK. User name and password are returned as PRUnichar values. Any default
+ * value that we override must be freed using the nsIMemory service.
+ */
+ int cnt, size;
+ int /*long*/ ptr;
+ char[] buffer;
+ int /*long*/[] result2 = new int /*long*/[1];
+ if (valueLabel[0] !is null) {
+ cnt = valueLabel[0].length ();
+ buffer = new char[cnt + 1];
+ valueLabel[0].getChars (0, cnt, buffer, 0);
+ size = buffer.length * 2;
+ ptr = C.malloc (size);
+ XPCOM.memmove (ptr, buffer, size);
+ XPCOM.memmove (aValue, new int /*long*/[] {ptr}, C.PTR_SIZEOF);
+
+ if (valueAddr[0] !is 0) {
+ int rc = XPCOM.NS_GetServiceManager (result2);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+
+ nsIServiceManager serviceManager = new nsIServiceManager (result2[0]);
+ result2[0] = 0;
+ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_MEMORY_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (aContractID, nsIMemory.NS_IMEMORY_IID, result2);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+ serviceManager.Release ();
+
+ nsIMemory memory = new nsIMemory (result2[0]);
+ result2[0] = 0;
+ memory.Free (valueAddr[0]);
+ memory.Release ();
+ }
+ }
+ }
+ if (aCheckState !is 0) XPCOM.memmove (aCheckState, check, 4);
+ return XPCOM.NS_OK;
+}
+
+int PromptAuth(int /*long*/ aParent, int /*long*/ aChannel, int level, int /*long*/ authInfo, int /*long*/ checkboxLabel, int /*long*/ checkboxValue, int /*long*/ _retval) {
+ Browser browser = getBrowser (aParent);
+ String checkLabel = null;
+ int[] checkValue = new int[1];
+ String[] userLabel = new String[1], passLabel = new String[1];
+
+ String title = DWT.getMessage ("SWT_Authentication_Required"); //$NON-NLS-1$
+
+ if (checkboxLabel !is 0 && checkboxValue !is 0) {
+ int length = XPCOM.strlen_PRUnichar (checkboxLabel);
+ char[] dest = new char[length];
+ XPCOM.memmove (dest, checkboxLabel, length * 2);
+ checkLabel = new String (dest);
+ XPCOM.memmove (checkValue, checkboxValue, 4); /* PRBool */
+ }
+
+ /* get initial username and password values */
+
+ nsIAuthInformation auth = new nsIAuthInformation (authInfo);
+
+ int /*long*/ ptr = XPCOM.nsEmbedString_new ();
+ int rc = auth.GetUsername (ptr);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ int length = XPCOM.nsEmbedString_Length (ptr);
+ int /*long*/ buffer = XPCOM.nsEmbedString_get (ptr);
+ char[] chars = new char[length];
+ XPCOM.memmove (chars, buffer, length * 2);
+ userLabel[0] = new String (chars);
+ XPCOM.nsEmbedString_delete (ptr);
+
+ ptr = XPCOM.nsEmbedString_new ();
+ rc = auth.GetPassword (ptr);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ length = XPCOM.nsEmbedString_Length (ptr);
+ buffer = XPCOM.nsEmbedString_get (ptr);
+ chars = new char[length];
+ XPCOM.memmove (chars, buffer, length * 2);
+ passLabel[0] = new String (chars);
+ XPCOM.nsEmbedString_delete (ptr);
+
+ /* compute the message text */
+
+ ptr = XPCOM.nsEmbedString_new ();
+ rc = auth.GetRealm (ptr);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ length = XPCOM.nsEmbedString_Length (ptr);
+ buffer = XPCOM.nsEmbedString_get (ptr);
+ chars = new char[length];
+ XPCOM.memmove (chars, buffer, length * 2);
+ String realm = new String (chars);
+ XPCOM.nsEmbedString_delete (ptr);
+
+ nsIChannel channel = new nsIChannel (aChannel);
+ int /*long*/[] uri = new int /*long*/[1];
+ rc = channel.GetURI (uri);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ if (uri[0] is 0) Mozilla.error (XPCOM.NS_NOINTERFACE);
+
+ nsIURI nsURI = new nsIURI (uri[0]);
+ int /*long*/ aSpec = XPCOM.nsEmbedCString_new ();
+ rc = nsURI.GetHost (aSpec);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ length = XPCOM.nsEmbedCString_Length (aSpec);
+ buffer = XPCOM.nsEmbedCString_get (aSpec);
+ byte[] bytes = new byte[length];
+ XPCOM.memmove (bytes, buffer, length);
+ XPCOM.nsEmbedCString_delete (aSpec);
+ String host = new String (bytes);
+ nsURI.Release ();
+
+ String message;
+ if (realm.length () > 0 && host.length () > 0) {
+ message = Compatibility.getMessage ("SWT_Enter_Username_and_Password", new String[] {realm, host}); //$NON-NLS-1$
+ } else {
+ message = ""; //$NON-NLS-1$
+ }
+
+ /* open the prompter */
+ Shell shell = browser is null ? new Shell () : browser.getShell ();
+ PromptDialog dialog = new PromptDialog (shell);
+ int[] result = new int[1];
+ dialog.promptUsernameAndPassword (title, message, checkLabel, userLabel, passLabel, checkValue, result);
+
+ XPCOM.memmove (_retval, result, 4); /* PRBool */
+ if (result[0] is 1) { /* User selected OK */
+ nsEmbedString string = new nsEmbedString (userLabel[0]);
+ rc = auth.SetUsername(string.getAddress ());
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ string.dispose ();
+
+ string = new nsEmbedString (passLabel[0]);
+ rc = auth.SetPassword(string.getAddress ());
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ string.dispose ();
+ }
+
+ if (checkboxValue !is 0) XPCOM.memmove (checkboxValue, checkValue, 4); /* PRBool */
+ return XPCOM.NS_OK;
+}
+
+int PromptUsernameAndPassword (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aUsername, int /*long*/ aPassword, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+ Browser browser = getBrowser (aParent);
+ String titleLabel, textLabel, checkLabel = null;
+ String[] userLabel = new String[1], passLabel = new String[1];
+ char[] dest;
+ int length;
+ if (aDialogTitle !is 0) {
+ length = XPCOM.strlen_PRUnichar (aDialogTitle);
+ dest = new char[length];
+ XPCOM.memmove (dest, aDialogTitle, length * 2);
+ titleLabel = new String (dest);
+ } else {
+ titleLabel = DWT.getMessage ("SWT_Authentication_Required"); //$NON-NLS-1$
+ }
+
+ length = XPCOM.strlen_PRUnichar (aText);
+ dest = new char[length];
+ XPCOM.memmove (dest, aText, length * 2);
+ textLabel = new String (dest);
+
+ int /*long*/[] userAddr = new int /*long*/[1];
+ XPCOM.memmove (userAddr, aUsername, C.PTR_SIZEOF);
+ if (userAddr[0] !is 0) {
+ length = XPCOM.strlen_PRUnichar (userAddr[0]);
+ dest = new char[length];
+ XPCOM.memmove (dest, userAddr[0], length * 2);
+ userLabel[0] = new String (dest);
+ }
+
+ int /*long*/[] passAddr = new int /*long*/[1];
+ XPCOM.memmove (passAddr, aPassword, C.PTR_SIZEOF);
+ if (passAddr[0] !is 0) {
+ length = XPCOM.strlen_PRUnichar (passAddr[0]);
+ dest = new char[length];
+ XPCOM.memmove (dest, passAddr[0], length * 2);
+ passLabel[0] = new String (dest);
+ }
+
+ if (aCheckMsg !is 0) {
+ length = XPCOM.strlen_PRUnichar (aCheckMsg);
+ if (length > 0) {
+ dest = new char[length];
+ XPCOM.memmove (dest, aCheckMsg, length * 2);
+ checkLabel = new String (dest);
+ }
+ }
+
+ Shell shell = browser is null ? new Shell () : browser.getShell ();
+ PromptDialog dialog = new PromptDialog (shell);
+ int[] check = new int[1], result = new int[1];
+ if (aCheckState !is 0) XPCOM.memmove (check, aCheckState, 4); /* PRBool */
+ dialog.promptUsernameAndPassword (titleLabel, textLabel, checkLabel, userLabel, passLabel, check, result);
+
+ XPCOM.memmove (_retval, result, 4); /* PRBool */
+ if (result[0] is 1) {
+ /*
+ * User selected OK. User name and password are returned as PRUnichar values. Any default
+ * value that we override must be freed using the nsIMemory service.
+ */
+ int cnt, size;
+ int /*long*/ ptr;
+ char[] buffer;
+ int /*long*/[] result2 = new int /*long*/[1];
+ if (userLabel[0] !is null) {
+ cnt = userLabel[0].length ();
+ buffer = new char[cnt + 1];
+ userLabel[0].getChars (0, cnt, buffer, 0);
+ size = buffer.length * 2;
+ ptr = C.malloc (size);
+ XPCOM.memmove (ptr, buffer, size);
+ XPCOM.memmove (aUsername, new int /*long*/[] {ptr}, C.PTR_SIZEOF);
+
+ if (userAddr[0] !is 0) {
+ int rc = XPCOM.NS_GetServiceManager (result2);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+
+ nsIServiceManager serviceManager = new nsIServiceManager (result2[0]);
+ result2[0] = 0;
+ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_MEMORY_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (aContractID, nsIMemory.NS_IMEMORY_IID, result2);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ if (result[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+ serviceManager.Release ();
+
+ nsIMemory memory = new nsIMemory (result2[0]);
+ result2[0] = 0;
+ memory.Free (userAddr[0]);
+ memory.Release ();
+ }
+ }
+ if (passLabel[0] !is null) {
+ cnt = passLabel[0].length ();
+ buffer = new char[cnt + 1];
+ passLabel[0].getChars (0, cnt, buffer, 0);
+ size = buffer.length * 2;
+ ptr = C.malloc (size);
+ XPCOM.memmove (ptr, buffer, size);
+ XPCOM.memmove (aPassword, new int /*long*/[] {ptr}, C.PTR_SIZEOF);
+
+ if (passAddr[0] !is 0) {
+ int rc = XPCOM.NS_GetServiceManager (result2);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+
+ nsIServiceManager serviceManager = new nsIServiceManager (result2[0]);
+ result2[0] = 0;
+ byte[] aContractID = MozillaDelegate.wcsToMbcs (null, XPCOM.NS_MEMORY_CONTRACTID, true);
+ rc = serviceManager.GetServiceByContractID (aContractID, nsIMemory.NS_IMEMORY_IID, result2);
+ if (rc !is XPCOM.NS_OK) DWT.error (rc);
+ if (result2[0] is 0) DWT.error (XPCOM.NS_NOINTERFACE);
+ serviceManager.Release ();
+
+ nsIMemory memory = new nsIMemory (result2[0]);
+ result2[0] = 0;
+ memory.Free (passAddr[0]);
+ memory.Release ();
+ }
+ }
+ }
+ if (aCheckState !is 0) XPCOM.memmove (aCheckState, check, 4); /* PRBool */
+ return XPCOM.NS_OK;
+}
+
+int PromptPassword (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int /*long*/ aPassword, int /*long*/ aCheckMsg, int /*long*/ aCheckState, int /*long*/ _retval) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+int Select (int /*long*/ aParent, int /*long*/ aDialogTitle, int /*long*/ aText, int aCount, int /*long*/ aSelectList, int /*long*/ aOutSelection, int /*long*/ _retval) {
+ return XPCOM.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/PromptService2Factory.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/PromptService2Factory.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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 dwt.browser.PromptService2Factory;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.C;
+import dwt.internal.mozilla.XPCOM;
+import dwt.internal.mozilla.XPCOMObject;
+import dwt.internal.mozilla.nsID;
+import dwt.internal.mozilla.nsIFactory;
+import dwt.internal.mozilla.nsISupports;
+
+class PromptService2Factory {
+ XPCOMObject supports;
+ XPCOMObject factory;
+ int refCount = 0;
+
+PromptService2Factory () {
+ createCOMInterfaces ();
+}
+
+int AddRef () {
+ refCount++;
+ return refCount;
+}
+
+void createCOMInterfaces () {
+ /* Create each of the interfaces that this object implements */
+ supports = new XPCOMObject (new int[] {2, 0, 0}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ };
+
+ factory = new XPCOMObject (new int[] {2, 0, 0, 3, 1}) {
+ public int /*long*/ method0 (int /*long*/[] args) {return QueryInterface (args[0], args[1]);}
+ public int /*long*/ method1 (int /*long*/[] args) {return AddRef ();}
+ public int /*long*/ method2 (int /*long*/[] args) {return Release ();}
+ public int /*long*/ method3 (int /*long*/[] args) {return CreateInstance (args[0], args[1], args[2]);}
+ public int /*long*/ method4 (int /*long*/[] args) {return LockFactory ((int)/*64*/args[0]);}
+ };
+}
+
+void disposeCOMInterfaces () {
+ if (supports !is null) {
+ supports.dispose ();
+ supports = null;
+ }
+ if (factory !is null) {
+ factory.dispose ();
+ factory = null;
+ }
+}
+
+int /*long*/ getAddress () {
+ return factory.getAddress ();
+}
+
+int QueryInterface (int /*long*/ riid, int /*long*/ ppvObject) {
+ if (riid is 0 || ppvObject is 0) return XPCOM.NS_ERROR_NO_INTERFACE;
+ nsID guid = new nsID ();
+ XPCOM.memmove (guid, riid, nsID.sizeof);
+
+ if (guid.Equals (nsISupports.NS_ISUPPORTS_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {supports.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+ if (guid.Equals (nsIFactory.NS_IFACTORY_IID)) {
+ XPCOM.memmove (ppvObject, new int /*long*/[] {factory.getAddress ()}, C.PTR_SIZEOF);
+ AddRef ();
+ return XPCOM.NS_OK;
+ }
+
+ XPCOM.memmove (ppvObject, new int /*long*/[] {0}, C.PTR_SIZEOF);
+ return XPCOM.NS_ERROR_NO_INTERFACE;
+}
+
+int Release () {
+ refCount--;
+ if (refCount is 0) disposeCOMInterfaces ();
+ return refCount;
+}
+
+/* nsIFactory */
+
+int CreateInstance (int /*long*/ aOuter, int /*long*/ iid, int /*long*/ result) {
+ PromptService2 promptService = new PromptService2 ();
+ promptService.AddRef ();
+ XPCOM.memmove (result, new int /*long*/[] {promptService.getAddress ()}, C.PTR_SIZEOF);
+ return XPCOM.NS_OK;
+}
+
+int LockFactory (int lock) {
+ return XPCOM.NS_OK;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/Safari.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/Safari.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,1566 @@
+/*******************************************************************************
+ * 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:
+ * Jacob Carlborg StatusTextEvent
is sent by a {@link Browser} to
+ * {@link StatusTextListener}'s when the status text is changed.
+ * The status text is typically displayed in the status bar of
+ * a browser application.
+ *
+ * @since 3.0
+ */
+public class StatusTextEvent : TypedEvent {
+ /** status text */
+ public String text;
+
+ static const long serialVersionUID = 3258407348371600439L;
+
+ 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 String toString () {
+ String String = super.toString();
+ return String.substring(0, String.length() - 1) // remove trailing '}'
+ + " text=" + text + "}";
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/StatusTextListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/StatusTextListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg + * + *
The following fields in the StatusTextEvent
apply:
+ *
Browser
whose status text is changed
+ * StatusTextEvent
that contains the updated
+ * status description of a Browser
+ *
+ * @since 3.0
+ */
+ public void changed (StatusTextEvent event);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/TitleEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/TitleEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg TitleEvent
is sent by a {@link Browser} to
+ * {@link TitleListener}'s when the title of the current document
+ * is available or when it is modified.
+ *
+ * @since 3.0
+ */
+public class TitleEvent : TypedEvent {
+ /** the title of the current document */
+ public String title;
+
+ static const long serialVersionUID = 4121132532906340919L;
+
+ 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 String toString () {
+ String str = super.toString();
+ return str.substring(0, String.length() - 1) // remove trailing '}'
+ + " title=" + title + "}";
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/TitleListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/TitleListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg + * + *
The following fields in the TitleEvent
apply:
+ *
Browser
whose current document's
+ * title is known or modified
+ * TitleEvent
that contains the title
+ * of the document currently displayed in a Browser
+ *
+ * @since 3.0
+ */
+ public void changed (TitleEvent event);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/VisibilityWindowAdapter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/VisibilityWindowAdapter.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg + * Classes that wish to deal with {@link WindowEvent}'s can + * extend this class and override only the methods which they are + * interested in. + *
+ * + * @since 3.0 + */ +public abstract class VisibilityWindowAdapter : VisibilityWindowListener { + + public void hide (WindowEvent event) { + } + + public void show (WindowEvent event) { + } +} diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/VisibilityWindowListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/browser/VisibilityWindowListener.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2003, 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: + * Jacob CarlborgBrowser
+ * is requested to be hidden. Application would typically hide the
+ * {@link dwt.widgets.Shell} that hosts the Browser
.
+ * + * + *
The following fields in the WindowEvent
apply:
+ *
Browser
that needs to be hidden
+ * WindowEvent
that specifies the
+ * Browser
that needs to be hidden
+ *
+ * @see dwt.widgets.Shell#setVisible(bool)
+ *
+ * @since 3.0
+ */
+ public void hide (WindowEvent event);
+
+ /**
+ * This method is called when the window hosting a Browser
+ * is requested to be displayed. Application would typically set the
+ * location and the size of the {@link dwt.widgets.Shell}
+ * that hosts the Browser
, if a particular location and size
+ * are specified. The application would then open that Shell
.
+ * + * + *
The following fields in the WindowEvent
apply:
+ *
Browser
to display
+ * Shell
+ * hosting the browser. It is null
if no location is set.
+ * Browser
.
+ * The client area of the Shell
hosting the
+ * Browser
should be large enough to accommodate that size.
+ * It is null
if no size is set.
+ * true
if the Shell
+ * hosting the Browser
should display an address bar or
+ * false
otherwise
+ * true
if the Shell
+ * hosting the Browser
should display a menu bar or
+ * false
otherwise
+ * true
if the Shell
+ * hosting the Browser
should display a status bar or
+ * false
otherwise
+ * true
if the Shell
+ * hosting the Browser
should display a tool bar or
+ * false
otherwise
+ * WindowEvent
that specifies the
+ * Browser
that needs to be displayed
+ *
+ * @see dwt.widgets.Control#setLocation(dwt.graphics.Point)
+ * @see dwt.widgets.Control#setSize(dwt.graphics.Point)
+ * @see dwt.widgets.Shell#open()
+ *
+ * @since 3.0
+ */
+ public void show (WindowEvent event);
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/browser/WebBrowser.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/browser/WebBrowser.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,432 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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:
+ * Jacob Carlborg WindowEvent
is sent by a {@link Browser} when
+ * a new window needs to be created or when an existing window needs to be
+ * closed. This notification occurs when a javascript command such as
+ * window.open
or window.close
gets executed by
+ * a Browser
.
+ *
+ *
+ * The following example shows how WindowEvent
's are typically
+ * handled.
+ *
+ *
+ *
+ * The following notifications are emitted when the user selects a hyperlink that targets a new window
+ * or as the result of a javascript that executes window.open.
+ *
+ *
+ * public static void main(String[] args) {
+ * Display display = new Display();
+ * Shell shell = new Shell(display);
+ * shell.setText("Main Window");
+ * shell.setLayout(new FillLayout());
+ * Browser browser = new Browser(shell, DWT.NONE);
+ * initialize(display, browser);
+ * shell.open();
+ * browser.setUrl("http://www.eclipse.org");
+ * while (!shell.isDisposed()) {
+ * if (!display.readAndDispatch())
+ * display.sleep();
+ * }
+ * display.dispose();
+ * }
+ *
+ * static void initialize(final Display display, Browser browser) {
+ * browser.addOpenWindowListener(new OpenWindowListener() {
+ * public void open(WindowEvent event) {
+ * // Certain platforms can provide a default full browser.
+ * // simply return in that case if the application prefers
+ * // the default full browser to the embedded one set below.
+ * if (!event.required) return;
+ *
+ * // Embed the new window
+ * Shell shell = new Shell(display);
+ * shell.setText("New Window");
+ * shell.setLayout(new FillLayout());
+ * Browser browser = new Browser(shell, DWT.NONE);
+ * initialize(display, browser);
+ * event.browser = browser;
+ * }
+ * });
+ * browser.addVisibilityWindowListener(new VisibilityWindowListener() {
+ * public void hide(WindowEvent event) {
+ * Browser browser = (Browser)event.widget;
+ * Shell shell = browser.getShell();
+ * shell.setVisible(false);
+ * }
+ * public void show(WindowEvent event) {
+ * Browser browser = (Browser)event.widget;
+ * Shell shell = browser.getShell();
+ * if (event.location !is null) shell.setLocation(event.location);
+ * if (event.size !is null) {
+ * Point size = event.size;
+ * shell.setSize(shell.computeSize(size.x, size.y));
+ * }
+ * if (event.addressBar || event.menuBar || event.statusBar || event.toolBar) {
+ * // Create widgets for the address bar, menu bar, status bar and/or tool bar
+ * // leave enough space in the Shell to accommodate a Browser of the size
+ * // given by event.size
+ * }
+ * shell.open();
+ * }
+ * });
+ * browser.addCloseWindowListener(new CloseWindowListener() {
+ * public void close(WindowEvent event) {
+ * Browser browser = (Browser)event.widget;
+ * Shell shell = browser.getShell();
+ * shell.close();
+ * }
+ * });
+ * }
+ *
Main Browser + *
Second Browser + *
Browser
to handle the new window.
+ *
+ * @since 3.1
+ */
+ public bool required;
+
+ /**
+ * Browser
provided by the application.
+ */
+ public Browser browser;
+
+ /**
+ * Requested location for the Shell
hosting the Browser
.
+ * It is null
if no location has been requested.
+ */
+ public Point location;
+
+ /**
+ * Requested Browser
size. The client area of the Shell
+ * hosting the Browser
should be large enough to accommodate that size.
+ * It is null
if no size has been requested.
+ */
+ public Point size;
+
+ /**
+ * Specifies whether the Shell
hosting the Browser
should
+ * display an address bar.
+ *
+ * @since 3.1
+ */
+ public bool addressBar;
+
+ /**
+ * Specifies whether the Shell
hosting the Browser
should
+ * display a menu bar.
+ *
+ * @since 3.1
+ */
+ public bool menuBar;
+
+ /**
+ * Specifies whether the Shell
hosting the Browser
should
+ * display a status bar.
+ *
+ * @since 3.1
+ */
+ public bool statusBar;
+
+ /**
+ * Specifies whether the Shell
hosting the Browser
should
+ * display a tool bar.
+ *
+ * @since 3.1
+ */
+ public bool toolBar;
+
+ static final long serialVersionUID = 3617851997387174969L;
+
+ 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 String toString () {
+ String str = super.toString();
+ return str.substring(0, str.length() - 1) // remove trailing '}'
+ + " required=" + required + " browser=" + browser + " location=" + location + " size=" + size + " addressBar=" + addressBar + " menuBar=" + menuBar + " statusBar=" + statusBar + " toolBar=" + toolBar + "}";
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/AnimatedProgress.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/AnimatedProgress.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * 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:
+ * Jacob Carlborg
+ * The style value is either one of the style constants defined in
+ * class DWT
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 DWT
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" + *+ */ +public class BidiSegmentEvent : TypedEvent { + + /** + * line start offset + */ + public int lineOffset; + + /** + * line text + */ + public String lineText; + + /** + * bidi segments, see above + */ + public int[] segments; + + static final long serialVersionUID = 3257846571587547957L; + + this (StyledTextEvent e) { + super(e); + lineOffset = e.detail; + lineText = e.text; + } +} diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/BidiSegmentListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/custom/BidiSegmentListener.d Sat Aug 09 17:00:02 2008 +0200 @@ -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: + * Jacob Carlborg
+ * The following event fields are used:
StyledText
.
+ * + * The toHash() 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.
+ *
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. + *
+ * + * @since 3.0 + */ + +public class CBanner : Composite { + + Control left; + Control right; + Control bottom; + + bool simple = true; + + int[] curve = new int[0]; + int curveStart = 0; + Rectangle curveRect = new Rectangle(0, 0, 0, 0); + int curve_width = 5; + int curve_indent = -2; + + int rightWidth = DWT.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 = DWT.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 DWT
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 DWT
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 DWT.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(DWT.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 DWTException + * 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 DWTExceptiontrue
if the CBanner should render itself in a simple, traditional style
+ *
+ * @exception DWTException + * 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 DWT
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 DWT
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 DWTException+ * The current selection is first copied to the + * clipboard and then deleted from the widget. + *
+ * + * @exception DWTException
+ * 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 DWTExceptiontrue
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 DWTExceptionPoint
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 DWTException setTextLimit()
, it will be the constant
+ * Combo.LIMIT
.
+ *
+ * @return the text limit
+ *
+ * @exception DWTException + * The selected text is deleted from the widget + * and new text inserted from the clipboard. + *
+ * + * @exception DWTException+ * @exception DWTException
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 DWTExceptiontrue
,
+ * 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 DWTException
+ * 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. + *
+ */ +public class CLabel : Canvas +{ + + /** 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 alignnment. Either CENTER, RIGHT, LEFT. Default is LEFT*/ + private int alignn = DWT.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 = DWT.DRAW_MNEMONIC | DWT.DRAW_TAB | DWT.DRAW_TRANSPARENT | DWT.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 DWT
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 DWT
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 int getStyle ()
+ {
+ int style = super.getStyle();
+ switch (alignn)
+ {
+ case DWT.RIGHT:
+ style |= DWT.RIGHT;
+ break;
+ case DWT.CENTER:
+ style |= DWT.CENTER;
+ break;
+ case DWT.LEFT:
+ style |= DWT.LEFT;
+ break;
+ }
+ return style;
+ }
+
+ /**
+ * Return the Label's text.
+ *
+ * @return the text of the label or null
+ */
+ public String getText ()
+ {
+ //checkWidget();
+ return text;
+ }
+
+ public 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)
+ {
+ char mnemonic = _findMnemonic(this.text);
+ if (mnemonic !is '\0')
+ {
+ e.result = "Alt+" + mnemonic; //$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)
+ {
+ char mnemonic = _findMnemonic(text);
+ if (mnemonic is '\0')
+ return;
+ if (CharacterToLower(event.character) !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 = DWT.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 (alignn is DWT.CENTER)
+ {
+ x = (rect.width - extent.x) / 2;
+ }
+ if (alignn is DWT.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
+ const 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
+ {
+ const 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)
+ {
+ const int
+ gradientHeight = (gradientPercents[i] * rect.height / 100) - pos;
+ gc.fillGradientRectangle(0, pos, rect.width,
+ gradientHeight, true);
+ pos += gradientHeight;
+ }
+ else
+ {
+ const 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() & DWT.DOUBLE_BUFFERED) is 0)
+ {
+ gc.setBackground(getBackground());
+ gc.fillRectangle(rect);
+ }
+ }
+ }
+ catch (DWTException e)
+ {
+ if ((getStyle() & DWT.DOUBLE_BUFFERED) is 0)
+ {
+ gc.setBackground(getBackground());
+ gc.fillRectangle(rect);
+ }
+ }
+
+ // draw border
+ int style = getStyle();
+ if ((style & DWT.SHADOW_IN) !is 0 || (style & DWT.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 (alignn is DWT.CENTER)
+ {
+ int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
+ lineX = x + Math.max(0, (extent.x - lineWidth) / 2);
+ }
+ if (alignn is DWT.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 & DWT.SHADOW_IN) !is 0)
+ {
+ c1 = disp.getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW);
+ c2 = disp.getSystemColor(DWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
+ }
+ if ((style & DWT.SHADOW_OUT) !is 0)
+ {
+ c1 = disp.getSystemColor(DWT.COLOR_WIDGET_LIGHT_SHADOW);
+ c2 = disp.getSystemColor(DWT.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 alignnment of the CLabel.
+ * Use the values LEFT, CENTER and RIGHT to alignn image and text within the available space.
+ *
+ * @param alignn the alignnment style of LEFT, RIGHT or CENTER
+ *
+ * @exception DWTException 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(DWT.COLOR_DARK_BLUE), + * display.getSystemColor(DWT.COLOR_BLUE), + * display.getSystemColor(DWT.COLOR_WHITE), + * display.getSystemColor(DWT.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 DWTException 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(DWT.COLOR_DARK_BLUE), + * display.getSystemColor(DWT.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 DWTException null
clears it.
+ *
+ * @param image the image to be displayed in the label or null
+ *
+ * @exception DWTException null
clears it.
+ *
+ * @param text the text to be displayed in the label or null
+ *
+ * @exception DWTException 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.substring(0, mid);
+ 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, DWT.MOVEMENT_CLUSTER);
+ if (nextOffset !is offset)
+ return layout.getPreviousOffset(nextOffset, DWT.MOVEMENT_CLUSTER);
+ return offset;
+ }
+
+ private String[] splitString (String text)
+ {
+ String[] lines = new String[1];
+ int start = 0, pos;
+ do
+ {
+ pos = text.indexOf('\n', start);
+ if (pos is -1)
+ {
+ lines[lines.length - 1] = text.substring(start);
+ }
+ else
+ {
+ bool crlf = (pos > 0) && (text.charAt(pos - 1) is '\r');
+ lines[lines.length - 1] = text.substring(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 -1);
+ return lines;
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/CLayoutData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/CLayoutData.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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:
+ * Jacob Carlborg
+ * 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. + *
+ */ + +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 = new RGB(132, 130, 132); + /** + * 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 = new RGB(143, 141, 138); + /** + * 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 = new RGB(171, 168, 165); + + /* sizing, positioning */ + int xClient, yClient; + bool onBottom = false; + bool single = false; + bool simple = true; + int fixedTabHeight = DWT.DEFAULT; + int tabHeight; + int minChars = 20; + + /* item management */ + CTabItem items[] = new CTabItem[0]; + int firstIndex = -1; // index of the left most visible tab. + int selectedIndex = -1; + int[] priority = new int[0]; + bool mru = false; + Listener listener; + + /* External Listener management */ + CTabFolder2Listener[] folderListeners = new CTabFolder2Listener[0]; + // support for deprecated listener mechanism + CTabFolderListener[] tabListeners = new CTabFolderListener[0]; + + /* 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 = new Rectangle(0, 0, 0, 0); + int chevronImageState = NORMAL; + bool showChevron = false; + Menu showMenu; + + bool showMin = false; + Rectangle minRect = new Rectangle(0, 0, 0, 0); + bool minimized = false; + int minImageState = NORMAL; + + bool showMax = false; + Rectangle maxRect = new Rectangle(0, 0, 0, 0); + bool maximized = false; + int maxImageState = NORMAL; + + Control topRight; + Rectangle topRightRect = new Rectangle(0, 0, 0, 0); + int topRightAlignment = DWT.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 = new int[][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 = new int[][5 , 2 , 4 , 2 , 3 , 3 , 2 , 4 , 2 , 5 , 1 , 6]; + + static const int[] + TOP_RIGHT_CORNER = new int[][-6 , 0 , -5 , 1 , -4 , 1 , -1 , 4 , -1 , 5 , 0 , 6]; + static const int[] + BOTTOM_LEFT_CORNER = new int[][0 , -6 , 1 , -5 , 1 , -4 , 4 , -1 , 5 , -1 , 6 , 0]; + static const int[] + BOTTOM_RIGHT_CORNER = new int[][-6 , 0 , -5 , -1 , -4 , -1 , -1 , -4 , -1 , -5 , 0 , -6]; + + static const int[] + SIMPLE_TOP_LEFT_CORNER = new int[][0 , 2 , 1 , 1 , 2 , 0]; + static const int[] + SIMPLE_TOP_RIGHT_CORNER = new int[][-2 , 0 , -1 , 1 , 0 , 2]; + static const int[] + SIMPLE_BOTTOM_LEFT_CORNER = new int[][0 , -2 , 1 , -1 , 2 , 0]; + static const int[] + SIMPLE_BOTTOM_RIGHT_CORNER = new int[][-2 , 0 , -1 , -1 , 0 , -2]; + static const int[] SIMPLE_UNSELECTED_INNER_CORNER = new int[][0 , 0]; + + static const int[] + TOP_LEFT_CORNER_BORDERLESS = new int[][0 , 6 , 1 , 5 , 1 , 4 , 4 , 1 , 5 , 1 , 6 , 0]; + static const int[] + TOP_RIGHT_CORNER_BORDERLESS = new int[][-7 , 0 , -6 , 1 , -5 , 1 , -2 , 4 , -2 , 5 , -1 , 6]; + static const int[] + BOTTOM_LEFT_CORNER_BORDERLESS = new int[][0 , -6 , 1 , -6 , 1 , -5 , 2 , -4 , 4 , -2 , 5 , -1 , 6 , -1 , 6 , 0]; + static const int[] + BOTTOM_RIGHT_CORNER_BORDERLESS = new int[][-7 , 0 , -7 , -1 , -6 , -1 , -5 , -2 , -3 , -4 , -2 , -5 , -2 , -6 , -1 , -6]; + + static const int[] + SIMPLE_TOP_LEFT_CORNER_BORDERLESS = new int[][0 , 2 , 1 , 1 , 2 , 0]; + static const int[] + SIMPLE_TOP_RIGHT_CORNER_BORDERLESS = new int[][-3 , 0 , -2 , 1 , -1 , 2]; + static const int[] + SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS = new int[][0 , -3 , 1 , -2 , 2 , -1 , 3 , 0]; + static const int[] + SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS = new int[][-4 , 0 , -3 , -1 , -2 , -2 , -1 , -3]; + + static const int SELECTION_FOREGROUND = DWT.COLOR_LIST_FOREGROUND; + static const int SELECTION_BACKGROUND = DWT.COLOR_LIST_BACKGROUND; + static const int BORDER1_COLOR = DWT.COLOR_WIDGET_NORMAL_SHADOW; + static const int FOREGROUND = DWT.COLOR_WIDGET_FOREGROUND; + static const int BACKGROUND = DWT.COLOR_WIDGET_BACKGROUND; + static const int BUTTON_BORDER = DWT.COLOR_WIDGET_DARK_SHADOW; + static const int BUTTON_FILL = DWT.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 = new RGB(252, 160, 160); + + 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; + + /** + * 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 DWT
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 DWT
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 DWTException true
if the receiver is minimized.
+ *
+ * @return the receiver's minimized state
+ *
+ * @exception DWTException true
if the minimize button
+ * is visible.
+ *
+ * @return the visibility of the minimized button
+ *
+ * @exception DWTException true
if the receiver is maximized.
+ * + * + * @return the receiver's maximized state + * + * @exception DWTException
true
if the maximize button
+ * is visible.
+ *
+ * @return the visibility of the maximized button
+ *
+ * @exception DWTException 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 DWTExceptiontrue
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 int getStyle ()
+ {
+ int style = super.getStyle();
+ style &= ~(DWT.TOP | DWT.BOTTOM);
+ style |= onBottom ? DWT.BOTTOM : DWT.TOP;
+ style &= ~(DWT.SINGLE | DWT.MULTI);
+ style |= single ? DWT.SINGLE : DWT.MULTI;
+ if (borderLeft !is 0)
+ style |= DWT.BORDER;
+ style &= ~DWT.CLOSE;
+ if (showClose)
+ style |= DWT.CLOSE;
+ return style;
+ }
+
+ /**
+ * Returns the height of the tab
+ *
+ * @return the height of the tab
+ *
+ * @exception DWTException 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(DWT.COLOR_DARK_BLUE), + * display.getSystemColor(DWT.COLOR_BLUE), + * display.getSystemColor(DWT.COLOR_WHITE), + * display.getSystemColor(DWT.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 DWTException + * cfolder.setBackground(new Color[]{display.getSystemColor(DWT.COLOR_DARK_BLUE), + * display.getSystemColor(DWT.COLOR_BLUE), + * display.getSystemColor(DWT.COLOR_WHITE), + * display.getSystemColor(DWT.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 DWTException true
,
+ * and marks it invisible otherwise.
+ *
+ * @param visible the new visibility state
+ *
+ * @exception DWTException + * 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 DWTExceptiontrue
,
+ * and marks it invisible otherwise.
+ *
+ * @param visible the new visibility state
+ *
+ * @exception DWTException + * 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 DWTException+ * cfolder.setBackground(new Color[]{display.getSystemColor(DWT.COLOR_DARK_BLUE), + * display.getSystemColor(DWT.COLOR_BLUE), + * display.getSystemColor(DWT.COLOR_WHITE), + * display.getSystemColor(DWT.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 DWTException + * cfolder.setBackground(new Color[]{display.getSystemColor(DWT.COLOR_DARK_BLUE), + * display.getSystemColor(DWT.COLOR_BLUE), + * display.getSystemColor(DWT.COLOR_WHITE), + * display.getSystemColor(DWT.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 DWTException true
if the CTabFolder should render itself in a simple, traditional style
+ *
+ * @exception DWTException true
if only the selected tab should be displayed otherwise, multiple tabs will be shown.
+ *
+ * @exception DWTException DWT.TOP
for tabs along the top or DWT.BOTTOM
for tabs along the bottom
+ *
+ * @exception DWTException
+ * The alignment parameter sets the layout of the control in the tab area.
+ * DWT.RIGHT
will cause the control to be positioned on the far
+ * right of the folder and it will have its default size. DWT.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.
+ *
DWT.RIGHT
or DWT.FILL
+ *
+ * @exception DWTException true
makes the close button appear
+ *
+ * @exception DWTException true
makes the image appear
+ *
+ * @exception DWTException CTabFolder2Listener
interface.
+ *
+ * Classes that wish to dealF 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 380af2bdd8e5 dwt/custom/CTabFolder2Listener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/custom/CTabFolder2Listener.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,116 @@ +/******************************************************************************* + * 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: + * Jacob Carlborg
+ * 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);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/CTabFolderAdapter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/CTabFolderAdapter.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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:
+ * Jacob Carlborg 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 String toString () {
+ String str = super.toString();
+ return str.substring(0, str.length - 1) // remove trailing '}'
+ + " item=" + item + " doit=" + doit + " x=" + x + " y=" + y + " width=" + width + " height=" + height + "}";
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/CTabFolderLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/CTabFolderLayout.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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:
+ * Jacob Carlborg
+ * 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. + *
+ */ +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 = new Rectangle(0, 0, 0, 0); + 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 = DWT.DRAW_TRANSPARENT | DWT.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 DWT
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 DWT
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 DWT
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 DWT
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 DWTException true
to indicate that the receiver's close button should be shown.
+ * Otherwise return false
. The initial value is defined by the style (DWT.CLOSE)
+ * that was used to create the receiver.
+ *
+ * @return true
if the close button should be shown
+ *
+ * @exception DWTException 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 DWTException true
to indicate that the receiver's close button should be shown.
+ * If the parent (CTabFolder) was created with DWT.CLOSE style, changing this value has
+ * no effect.
+ *
+ * @param close the new state of the close button
+ *
+ * @exception DWTException Here is an example of using a ControlEditor:
+ *
+ *
+ */
+public class ControlEditor {
+
+ /**
+ * Specifies how the editor should be aligned relative to the control. Allowed values
+ * are DWT.LEFT, DWT.RIGHT and DWT.CENTER. The default value is DWT.CENTER.
+ */
+ public int horizontalAlignment = DWT.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 DWT.TOP, DWT.BOTTOM and DWT.CENTER. The default value is DWT.CENTER.
+ */
+ public int verticalAlignment = DWT.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 const static int[] EVENTS = [DWT.KeyDown, DWT.KeyUp, DWT.MouseDown, DWT.MouseUp, DWT.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 < EVENTS.length; i++) {
+ parent.addListener(EVENTS[i], controlListener);
+ }
+
+ scrollbarListener = new class Listener {
+ public void handleEvent (Event e) {
+ scroll(e);
+ }
+ };
+ ScrollBar hBar = parent.getHorizontalBar();
+ if (hBar !is null)
+ hBar.addListener(DWT.Selection, scrollbarListener);
+ ScrollBar vBar = parent.getVerticalBar();
+ if (vBar !is null)
+ vBar.addListener(DWT.Selection, scrollbarListener);
+ }
+
+ Rectangle computeBounds () {
+ Rectangle clientArea = parent.getClientArea();
+ Rectangle editorRect = new Rectangle(clientArea.x, clientArea.y, minimumWidth, minimumHeight);
+
+ if (grabHorizontal)
+ editorRect.width = Math.max(clientArea.width, minimumWidth);
+
+ if (grabVertical)
+ editorRect.height = Math.max(clientArea.height, minimumHeight);
+
+ switch (horizontalAlignment) {
+ case DWT.RIGHT:
+ editorRect.x += clientArea.width - editorRect.width;
+ break;
+ case DWT.LEFT:
+ // do nothing - clientArea.x is the right answer
+ break;
+ default:
+ // default is CENTER
+ editorRect.x += (clientArea.width - editorRect.width) / 2;
+ }
+
+ switch (verticalAlignment) {
+ case DWT.BOTTOM:
+ editorRect.y += clientArea.height - editorRect.height;
+ break;
+ case DWT.TOP:
+ // do nothing - clientArea.y is the right answer
+ break;
+ default:
+ // default is CENTER
+ editorRect.y += (clientArea.height - editorRect.height) / 2;
+ }
+
+ return editorRect;
+
+ }
+
+ /**
+ * Removes all associations between the Editor and the underlying composite. The
+ * composite and the editor Control are not disposed.
+ */
+ public void dispose () {
+ if (parent !is null && !parent.isDisposed()) {
+ for (int i = 0; i < EVENTS.length; i++) {
+ parent.removeListener(EVENTS[i], controlListener);
+ }
+ ScrollBar hBar = parent.getHorizontalBar();
+ if (hBar !is null)
+ hBar.removeListener(DWT.Selection, scrollbarListener);
+ ScrollBar vBar = parent.getVerticalBar();
+ if (vBar !is null)
+ vBar.removeListener(DWT.Selection, scrollbarListener);
+ }
+
+ parent = null;
+ editor = null;
+ hadFocus = false;
+ controlListener = null;
+ scrollbarListener = null;
+ }
+
+ /**
+ * Returns the Control that is displayed above the composite being edited.
+ *
+ * @return the Control that is displayed above the composite being edited
+ */
+ public Control getEditor () {
+ return editor;
+ }
+
+ /**
+ * Lays out the control within the underlying composite. This
+ * method should be called after changing one or more fields to
+ * force the Editor to resize.
+ *
+ * @since 2.1
+ */
+ public void layout () {
+ if (editor is null || editor.isDisposed())
+ return;
+ if (editor.getVisible()) {
+ hadFocus = editor.isFocusControl();
+ } // this doesn't work because
+ // resizing the column takes the focus away
+ // before we get here
+ editor.setBounds(computeBounds());
+ if (hadFocus) {
+ if (editor is null || editor.isDisposed())
+ return;
+ editor.setFocus();
+ }
+ }
+
+ void scroll (Event e) {
+ if (editor is null || editor.isDisposed())
+ return;
+ layout();
+ }
+
+ /**
+ * Specify the Control that is to be displayed.
+ *
+ *
+ * Canvas canvas = new Canvas(shell, DWT.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, DWT.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 = DWT.RIGHT;
+ * editor.verticalAlignment = DWT.BOTTOM;
+ * editor.grabHorizontal = false;
+ * editor.grabVertical = false;
+ * Point size = button.computeSize(DWT.DEFAULT, DWT.DEFAULT);
+ * editor.minimumWidth = size.x;
+ * editor.minimumHeight = size.y;
+ * editor.setEditor (button);
+ *
Note: The Control provided as the editor must be created with its parent
+ * being the Composite specified in the ControlEditor constructor.
+ *
+ * @param editor the Control that is displayed above the composite being edited
+ */
+ public void setEditor (Control editor) {
+
+ if (editor is null) {
+ // this is the case where the caller is setting the editor to be blank
+ // set all the values accordingly
+ this.editor = null;
+ return;
+ }
+
+ this.editor = editor;
+ layout();
+ if (this.editor is null || this.editor.isDisposed())
+ return;
+ editor.setVisible(true);
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/DefaultContent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/DefaultContent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,880 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.*;
+import dwt.internal.Compatibility;
+import dwt.widgets.*;
+import java.util.Vector;
+
+class DefaultContent : StyledTextContent {
+ private final static String LineDelimiter = System.getProperty("line.separator");
+
+ Vector textListeners = new Vector(); // stores text listeners for event sending
+ char[] textStore = new char[0]; // stores the actual text
+ int gapStart = -1; // the character position start of the gap
+ int gapEnd = -1; // the character position after the end of the gap
+ int gapLine = -1; // the line on which the gap exists, the gap will always be associated with one line
+ int highWatermark = 300;
+ int lowWatermark = 50;
+
+ int[][] lines = new int[50][2]; // array of character positions and lengths representing the lines of text
+ int lineCount = 0; // the number of lines of text
+ int expandExp = 1; // the expansion exponent, used to increase the lines array exponentially
+ int replaceExpandExp = 1; // the expansion exponent, used to increase the lines array exponentially
+
+/**
+ * Creates a new DefaultContent and initializes it. A
+ *
+ * @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 = new int[] {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 = new int[] {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 DWT.CR) {
+ // see if the next character is a LF
+ if (i + 1 < textLength) {
+ ch = textStore[i+1];
+ if (ch is DWT.LF) {
+ i++;
+ }
+ }
+ addLineIndex(start, i - start + 1);
+ start = i + 1;
+ } else if (ch is DWT.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 DWT.CR) return true;
+ if (ch is DWT.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).charAt(0);
+ if (before is '\r') {
+ char after = getTextRange(start, 1).charAt(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).charAt(0);
+ if (startChar is '\n') {
+ // see if char before delete position is \r
+ if (start !is 0) {
+ char before = getTextRange(start - 1, 1).charAt(0);
+ if (before is '\r') return false;
+ }
+ }
+ char endChar = getTextRange(start + replaceLength - 1, 1).charAt(0);
+ if (endChar is '\r') {
+ // see if char after delete position is \n
+ if (start + replaceLength !is getCharCount()) {
+ char after = getTextRange(start + replaceLength, 1).charAt(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 DWT.CR) {
+ // see if the next character is a LF
+ if (location+1 < textStore.length) {
+ ch = textStore[location+1];
+ if (ch is DWT.LF) {
+ i++;
+ }
+ }
+ indexedLines = addLineIndex(start, i - start + 1, indexedLines, lineCount);
+ lineCount++;
+ start = i + 1;
+ } else if (ch is DWT.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 = new int[] {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.charAt(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 DWT.CR) {
+ // see if the next character is a LF
+ if (i + 1 < textStore.length) {
+ ch = textStore[i+1];
+ if (ch is DWT.LF) {
+ i++;
+ count++;
+ }
+ }
+ lineCount++;
+ } else if (ch is DWT.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.charAt(i);
+ if (ch is DWT.CR) {
+ if (i + 1 < length && text.charAt(i + 1) is DWT.LF) {
+ i++;
+ }
+ lineCount++;
+ } else if (ch is DWT.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 new String(textStore, start, length);
+ } else {
+ // gap is in the specified range, strip out the gap
+ StringBuffer buffer = new StringBuffer();
+ int gapLength = gapEnd - gapStart;
+ buffer.append(textStore, start, gapStart - start);
+ buffer.append(textStore, gapEnd, length - gapLength - (gapStart - start));
+ return buffer.toString();
+ }
+}
+/**
+ * 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 DWT error.
+ *
+ *
+ * @param code the error code
+ */
+void error (int code) {
+ DWT.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 new String(textStore, start, length);
+}
+/**
+ * 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 new String(textStore, start, length);
+ if (gapStart < start) {
+ int gapLength= gapEnd - gapStart;
+ return new String(textStore, start + gapLength , length);
+ }
+ StringBuffer buf = new StringBuffer();
+ buf.append(textStore, start, gapStart - start);
+ buf.append(textStore, gapEnd, end - gapStart);
+ return buf.toString();
+}
+/**
+ * Removes the specified
+ *
+ * @param listener the listener
+ * @exception IllegalArgumentException
+ *
+ * When sending the TextChangingEvent, StyledTextContent> will always have
+ * at least one empty line.
+ */
+DefaultContent() {
+ super();
+ 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(DWT.ERROR_NULL_ARGUMENT);
+ StyledTextListener typedListener = new StyledTextListener(listener);
+ textListeners.addElement(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(DWT.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 new String(textStore, start, length);
+ } else {
+ // gap is in the specified range, strip out the gap
+ StringBuffer buf = new StringBuffer();
+ int gapLength = gapEnd - gapStart;
+ buf.append(textStore, start, gapStart - start);
+ buf.append(textStore, gapEnd, length - gapLength - (gapStart - start));
+ length = buf.length();
+ while ((length - 1 >=0) && isDelimiter(buf.charAt(length - 1))) {
+ length--;
+ }
+ return buf.toString().substring(0, length);
+ }
+}
+/**
+ * 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(DWT.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(DWT.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(DWT.ERROR_NULL_ARGUMENT);
+ for (int i = 0; i < textListeners.size(); i++) {
+ TypedListener typedListener = (TypedListener) textListeners.elementAt(i);
+ if (typedListener.getEventListener () is listener) {
+ textListeners.removeElementAt(i);
+ 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.toCharArray(); + 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.charAt(0) is DWT.CR) && (endText.charAt(1) is DWT.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 DWT.CR && (textStore[j+1] is DWT.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); +} +} diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/ExtendedModifyEvent.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/custom/ExtendedModifyEvent.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,34 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.custom; + +import dwt.events.*; + +/** + * This event is sent after a text change occurs. + */ +public final class ExtendedModifyEvent : TypedEvent { + /** start offset of the new text */ + public int start; + /** length of the new text */ + public int length; + /** replaced text or empty String if no text was replaced */ + public String replacedText; + + static final long serialVersionUID = 3258696507027830832L; + +public ExtendedModifyEvent(StyledTextEvent e) { + super(e); + start = e.start; + length = e.end - e.start; + replacedText = e.text; +} +} diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/ExtendedModifyListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/custom/ExtendedModifyListener.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.custom; + +import dwt.internal.DWTEventListener; + +public interface ExtendedModifyListener : DWTEventListener { +/** + * This method is called after a text change occurs. + *
+ * The following event fields are used:
+ * The following event fields are used:
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;
+
+public LineStyleEvent(StyledTextEvent e) {
+ super(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 380af2bdd8e5 dwt/custom/LineStyleListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/LineStyleListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.internal.DWTEventListener;
+
+public interface LineStyleListener : DWTEventListener {
+/**
+ * This method is called when a line is about to be drawn in order to get the
+ * line's style information.
+ * + * 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 DWTException
+* This operation will fail if the items cannot +* be queried from the OS. +* +* @return the items in the widget +* +* @exception DWTException
+* 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 DWTException
+* When new font is null, the font reverts +* to the default system font for the widget. +* +* @param font the new font (or null) +* +* @exception DWTException
+* 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
StyledText
.
+ */
+public class ST {
+
+ /*
+ * Navigation Key Actions. Key bindings for the actions are set
+ * by the StyledText widget.
+ */
+ public static final int LINE_UP = 16777217; // binding = DWT.ARROW_UP
+ public static final int LINE_DOWN = 16777218; // binding = DWT.ARROW_DOWN
+ public static final int LINE_START = 16777223; // binding = DWT.HOME
+ public static final int LINE_END = 16777224; // binding = DWT.END
+ public static final int COLUMN_PREVIOUS = 16777219; // binding = DWT.ARROW_LEFT
+ public static final int COLUMN_NEXT = 16777220; // binding = DWT.ARROW_RIGHT
+ public static final int PAGE_UP = 16777221; // binding = DWT.PAGE_UP
+ public static final int PAGE_DOWN = 16777222; // binding = DWT.PAGE_DOWN
+ public static final int WORD_PREVIOUS = 17039363; // binding = DWT.MOD1 + DWT.ARROW_LEFT
+ public static final int WORD_NEXT = 17039364; // binding = DWT.MOD1 + DWT.ARROW_RIGHT
+ public static final int TEXT_START = 17039367; // binding = DWT.MOD1 + DWT.HOME
+ public static final int TEXT_END = 17039368; // binding = DWT.MOD1 + DWT.END
+ public static final int WINDOW_START = 17039365; // binding = DWT.MOD1 + DWT.PAGE_UP
+ public static final int WINDOW_END = 17039366; // binding = DWT.MOD1 + DWT.PAGE_DOWN
+
+ /*
+ * Selection Key Actions
+ */
+ public static final int SELECT_ALL = 262209; // binding = DWT.MOD1 + 'A'
+ public static final int SELECT_LINE_UP = 16908289; // binding = DWT.MOD2 + DWT.ARROW_UP
+ public static final int SELECT_LINE_DOWN = 16908290; // binding = DWT.MOD2 + DWT.ARROW_DOWN
+ public static final int SELECT_LINE_START = 16908295; // binding = DWT.MOD2 + DWT.HOME
+ public static final int SELECT_LINE_END = 16908296; // binding = DWT.MOD2 + DWT.END
+ public static final int SELECT_COLUMN_PREVIOUS = 16908291; // binding = DWT.MOD2 + DWT.ARROW_LEFT
+ public static final int SELECT_COLUMN_NEXT = 16908292; // binding = DWT.MOD2 + DWT.ARROW_RIGHT
+ public static final int SELECT_PAGE_UP = 16908293; // binding = DWT.MOD2 + DWT.PAGE_UP
+ public static final int SELECT_PAGE_DOWN = 16908294; // binding = DWT.MOD2 + DWT.PAGE_DOWN
+ public static final int SELECT_WORD_PREVIOUS = 17170435; // binding = DWT.MOD1 + DWT.MOD2 + DWT.ARROW_LEFT
+ public static final int SELECT_WORD_NEXT = 17170436; // binding = DWT.MOD1 + DWT.MOD2 + DWT.ARROW_RIGHT
+ public static final int SELECT_TEXT_START = 17170439; // binding = DWT.MOD1 + DWT.MOD2 + DWT.HOME
+ public static final int SELECT_TEXT_END = 17170440; // binding = DWT.MOD1 + DWT.MOD2 + DWT.END
+ public static final int SELECT_WINDOW_START = 17170437; // binding = DWT.MOD1 + DWT.MOD2 + DWT.PAGE_UP
+ public static final int SELECT_WINDOW_END = 17170438; // binding = DWT.MOD1 + DWT.MOD2 + DWT.PAGE_DOWN
+
+ /*
+ * Modification Key Actions
+ */
+ public static final int CUT = 131199; // binding = DWT.MOD2 + DWT.DEL
+ public static final int COPY = 17039369; // binding = DWT.MOD1 + DWT.INSERT;
+ public static final int PASTE = 16908297; // binding = DWT.MOD2 + DWT.INSERT ;
+ public static final int DELETE_PREVIOUS = '\b'; // binding = DWT.BS;
+ public static final int DELETE_NEXT = 0x7F; // binding = DWT.DEL;
+ public static final int DELETE_WORD_PREVIOUS = 262152; // binding = DWT.BS | DWT.MOD1;
+ public static final int DELETE_WORD_NEXT = 262271; // binding = DWT.DEL | DWT.MOD1;
+
+ /*
+ * Miscellaneous Key Actions
+ */
+ public static final int TOGGLE_OVERWRITE = 16777225; // binding = DWT.INSERT;
+
+ /**
+ * Bullet style dot.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static final int BULLET_DOT = 1 << 0;
+
+ /**
+ * Bullet style number.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static final int BULLET_NUMBER = 1 << 1;
+
+ /**
+ * Bullet style lower case letter.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static final int BULLET_LETTER_LOWER = 1 << 2;
+
+ /**
+ * Bullet style upper case letter.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static final int BULLET_LETTER_UPPER = 1 << 3;
+
+ /**
+ * Bullet style text.
+ *
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static final int BULLET_TEXT = 1 << 4;
+
+ /**
+ * Bullet style custom draw.
+ *
+ * @see StyledText#addPaintObjectListener(PaintObjectListener)
+ * @see StyledText#removePaintObjectListener(PaintObjectListener)
+ * @see Bullet
+ *
+ * @since 3.2
+ */
+ public static final int BULLET_CUSTOM = 1 << 5;
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/SashForm.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/SashForm.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,428 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+
+import dwt.*;
+import dwt.widgets.*;
+import dwt.graphics.*;
+
+/**
+ * The SashForm is a composite control that lays out its children in a
+ * row or column arrangement (as specified by the orientation) and places
+ * a Sash between each child. One child may be maximized to occupy the
+ * entire size of the SashForm. The relative sizes of the children may
+ * be specified using weights.
+ * + *
+ * The style value is either one of the style constants defined in
+ * class DWT
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 DWT
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 DWTExceptionThere 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(DWT.COLOR_RED);
+ * Color blue = display.getSystemColor(DWT.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, DWT.H_SCROLL | DWT.V_SCROLL | DWT.BORDER);
+ * final Composite c1 = new Composite(sc1, DWT.NONE);
+ * sc1.setContent(c1);
+ * c1.setBackground(red);
+ * GridLayout layout = new GridLayout();
+ * layout.numColumns = 4;
+ * c1.setLayout(layout);
+ * Button b1 = new Button (c1, DWT.PUSH);
+ * b1.setText("first button");
+ * c1.setSize(c1.computeSize(DWT.DEFAULT, DWT.DEFAULT));
+ *
+ * // set the minimum width and height of the scrolled content - method 2
+ * final ScrolledComposite sc2 = new ScrolledComposite(shell, DWT.H_SCROLL | DWT.V_SCROLL | DWT.BORDER);
+ * sc2.setExpandHorizontal(true);
+ * sc2.setExpandVertical(true);
+ * final Composite c2 = new Composite(sc2, DWT.NONE);
+ * sc2.setContent(c2);
+ * c2.setBackground(blue);
+ * layout = new GridLayout();
+ * layout.numColumns = 4;
+ * c2.setLayout(layout);
+ * Button b2 = new Button (c2, DWT.PUSH);
+ * b2.setText("first button");
+ * sc2.setMinSize(c2.computeSize(DWT.DEFAULT, DWT.DEFAULT));
+ *
+ * Button add = new Button (shell, DWT.PUSH);
+ * add.setText("add children");
+ * final int[] index = new int[]{0};
+ * add.addListener(DWT.Selection, new Listener() {
+ * public void handleEvent(Event e) {
+ * index[0]++;
+ * Button button = new Button(c1, DWT.PUSH);
+ * button.setText("button "+index[0]);
+ * // reset size of content so children can be seen - method 1
+ * c1.setSize(c1.computeSize(DWT.DEFAULT, DWT.DEFAULT));
+ * c1.layout();
+ *
+ * button = new Button(c2, DWT.PUSH);
+ * button.setText("button "+index[0]);
+ * // reset the minimum width and height so children can be seen - method 2
+ * sc2.setMinSize(c2.computeSize(DWT.DEFAULT, DWT.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 DWT
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 DWT
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 DWTException true
if the content control
+ * will be expanded to fill available vertical space.
+ *
+ * @return the receiver's vertical expansion state
+ *
+ * @exception DWTException true
if the receiver automatically scrolls to a focused child control
+ * to make it visible. Otherwise, returns false
.
+ *
+ * @exception DWTException + * 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 DWTExceptionfalse
, show a focused control is off.
+ * By default, show a focused control is off.
+ *
+ * @param show true
to show a focused control.
+ *
+ * @exception DWTException 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, DWT.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, DWT.PUSH);
+ * bArray[i].setText("Button "+i);
+ * }
+ * layout.topControl = bArray[0];
+ *
+ * Button b = new Button(shell, DWT.PUSH);
+ * b.setText("Show Next Button");
+ * final int[] index = new int[1];
+ * b.addListener(DWT.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();
+ * }
+ * }
+ *
+ */
+
+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 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 DWT.DEFAULT) width = wHint;
+ if (hHint !is DWT.DEFAULT) height = hHint;
+ return new Point(width, height);
+}
+
+protected bool flushCache(Control control) {
+ return true;
+}
+
+protected 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 = getClass ().getName ();
+ int index = String.lastIndexOf ('.');
+ if (index is -1) return String;
+ return String.substring (index + 1, String.length ());
+}
+
+/**
+ * Returns a String containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a String representation of the layout
+ */
+public String toString () {
+ String String = getName ()+" {";
+ if (marginWidth !is 0) String += "marginWidth="+marginWidth+" ";
+ if (marginHeight !is 0) String += "marginHeight="+marginHeight+" ";
+ if (topControl !is null) String += "topControl="+topControl+" ";
+ String = String.trim();
+ String += "}";
+ return String;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/StyleRange.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/StyleRange.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.*;
+import dwt.graphics.*;
+import dwt.internal.CloneableCompatibility;
+
+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
+ * DWT.NORMAL, DWT.ITALIC or DWT.BOLD
+ *
+ * Note: the font style is not used if the font
attribute
+ * is set
+ */
+ public int fontStyle = DWT.NORMAL;
+
+/**
+ * Create a new style range with no styles
+ *
+ * @since 3.2
+ */
+public StyleRange() {
+}
+
+/**
+ * Create a new style range from an existing text style.
+ *
+ *@param style the text style to copy
+ *
+ *@since 3.4
+ */
+public StyleRange(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 StyleRange(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 DWT.NORMAL, DWT.ITALIC or DWT.BOLD
+ */
+public StyleRange(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 #toHash()
+ */
+public bool opEquals(Object object) {
+ if (object is this) return true;
+ if (object instanceof StyleRange) {
+ StyleRange style = (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
+ * opEquals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #opEquals(Object)
+ */
+public int 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 DWT.NORMAL) return false;
+ if (underline) return false;
+ if (strikeout) return false;
+ if (borderStyle !is DWT.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 Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+}
+
+/**
+ * Returns a String containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a String representation of the StyleRange
+ */
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("StyleRange {");
+ buffer.append(start);
+ buffer.append(", ");
+ buffer.append(length);
+ buffer.append(", fontStyle=");
+ switch (fontStyle) {
+ case DWT.BOLD:
+ buffer.append("bold");
+ break;
+ case DWT.ITALIC:
+ buffer.append("italic");
+ break;
+ case DWT.BOLD | DWT.ITALIC:
+ buffer.append("bold-italic");
+ break;
+ default:
+ buffer.append("normal");
+ }
+ String str = super.toString();
+ int index = str.indexOf('{');
+ str = str.substring(index + 1);
+ if (str.length() > 1) buffer.append(", ");
+ buffer.append(str);
+ return buffer.toString();
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/StyledText.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/StyledText.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,8302 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+
+import java.util.*;
+
+import dwt.*;
+import dwt.accessibility.*;
+import dwt.dnd.*;
+import dwt.events.*;
+import dwt.graphics.*;
+import dwt.internal.*;
+import dwt.printing.*;
+import dwt.widgets.*;
+
+/**
+ * A StyledText is an editable user interface object that displays lines
+ * of text. The following style attributes can be defined for the text:
+ * + * 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. + *
+ */ +public class StyledText : Canvas { + static final char TAB = '\t'; + static final String PlatformLineDelimiter = System.getProperty("line.separator"); + static final int BIDI_CARET_WIDTH = 3; + static final int DEFAULT_WIDTH = 64; + static final int DEFAULT_HEIGHT = 64; + static final int V_SCROLL_RATE = 50; + static final int H_SCROLL_RATE = 10; + + static final int ExtendedModify = 3000; + static final int LineGetBackground = 3001; + static final int LineGetStyle = 3002; + static final int TextChanging = 3003; + static final int TextSet = 3004; + static final int VerifyKey = 3005; + static final int TextChanged = 3006; + static final int LineGetSegments = 3007; + static final int PaintObject = 3008; + static final int WordNext = 3009; + static final int WordPrevious = 3010; + + static final int PREVIOUS_OFFSET_TRAILING = 0; + static final int OFFSET_LEADING = 1; + + Color selectionBackground; // selection background color + Color selectionForeground; // selection foreground color + StyledTextContent content; // native content (default or user specified) + StyledTextRenderer renderer; + Listener listener; + TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent + int verticalScrollOffset = 0; // pixel based + int horizontalScrollOffset = 0; // pixel based + int topIndex = 0; // top visible line + int topIndexY; + int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new visible lines during Resize callback + int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine if line wrap needs to be recalculated + int tabLength = 4; // number of characters in a tab + int leftMargin; + int topMargin; + int rightMargin; + int bottomMargin; + int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935 + int caretOffset = 0; + int caretAlignment; + Point selection = new Point(0, 0); // x and y are start and end caret offsets of selection + Point clipboardSelection; // x and y are start and end caret offsets of previous selection + int selectionAnchor; // position of selection anchor. 0 based offset from beginning of text + Point doubleClickSelection; // selection after last mouse double click + 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. + Hashtable keyActionMap = new Hashtable(); + Color background = null; // workaround for bug 4791 + Color foreground = null; // + Clipboard clipboard; + int clickCount; + int autoScrollDirection = DWT.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 = DWT.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; + + final static bool IS_CARBON, IS_GTK, IS_MOTIF; + static { + String platform = DWT.getPlatform(); + IS_CARBON = "carbon".opEquals(platform); + IS_GTK = "gtk".opEquals(platform); + IS_MOTIF = "motif".opEquals(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 {
+ final static int LEFT = 0; // left aligned header/footer segment
+ final static int CENTER = 1; // centered header/footer segment
+ final static int RIGHT = 2; // right aligned header/footer segment
+
+ Printer printer;
+ StyledTextRenderer printerRenderer;
+ StyledTextPrintOptions printOptions;
+ Rectangle clientArea;
+ FontData fontData;
+ Font printerFont;
+ Hashtable resources;
+ int tabLength;
+ GC gc; // printer GC
+ int pageWidth; // width of a printer page in pixels
+ int startPage; // first page to print
+ int endPage; // last page to print
+ int startLine; // first (wrapped) line to print
+ int endLine; // last (wrapped) line to print
+ 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
+ */
+ Printing(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) {
+ this.printer = printer;
+ this.printOptions = printOptions;
+ this.mirrored = (styledText.getStyle() & DWT.MIRRORED) !is 0;
+ singleLine = styledText.isSingleLine();
+ startPage = 1;
+ endPage = Integer.MAX_VALUE;
+ 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 = new Hashtable ();
+ for (int i = 0; i < lineCount; i++) {
+ Color color = printerRenderer.getLineBackground(i, null);
+ if (color !is null) {
+ if (printOptions.printLineBackground) {
+ Color printerColor = (Color)resources.get(color);
+ if (printerColor is null) {
+ printerColor = new Color (printer, color.getRGB());
+ resources.put(color, printerColor);
+ }
+ printerRenderer.setLineBackground(i, 1, printerColor);
+ } else {
+ printerRenderer.setLineBackground(i, 1, null);
+ }
+ }
+ int indent = printerRenderer.getLineIndent(i, 0);
+ if (indent !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 = (Font)resources.get(font);
+ if (printerFont is null) {
+ printerFont = new Font (printer, font.getFontData());
+ resources.put(font, printerFont);
+ }
+ style.font = printerFont;
+ }
+ Color color = style.foreground;
+ if (color !is null) {
+ Color printerColor = (Color)resources.get(color);
+ if (printOptions.printTextForeground) {
+ if (printerColor is null) {
+ printerColor = new Color (printer, color.getRGB());
+ resources.put(color, printerColor);
+ }
+ style.foreground = printerColor;
+ } else {
+ style.foreground = null;
+ }
+ }
+ color = style.background;
+ if (color !is null) {
+ Color printerColor = (Color)resources.get(color);
+ if (printOptions.printTextBackground) {
+ if (printerColor is null) {
+ printerColor = new Color (printer, color.getRGB());
+ resources.put(color, printerColor);
+ }
+ style.background = printerColor;
+ } else {
+ style.background = null;
+ }
+ }
+ if (!printOptions.printTextFontStyle) {
+ style.fontStyle = DWT.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;
+ }
+ if (resources !is null) {
+ Enumeration enumeration = resources.elements();
+ while (enumeration.hasMoreElements()) {
+ Resource resource = (Resource) enumeration.nextElement();
+ 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(printer, fontData.getName(), fontData.getHeight(), DWT.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 ? DWT.RIGHT_TO_LEFT : DWT.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() & (DWT.RIGHT_TO_LEFT | DWT.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((Rectangle)null);
+ printDecoration(page, false, printLayout);
+ printer.endPage();
+ page++;
+ if (page <= endPage) {
+ printer.startPage();
+ printDecoration(page, true, printLayout);
+ paintY = clientArea.y - height;
+ int layoutHeight = layout.getBounds().height;
+ gc.setClipping(clientArea.x, clientArea.y, clientArea.width, layoutHeight - height);
+ printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+ gc.setClipping((Rectangle)null);
+ paintY += layoutHeight;
+ }
+ }
+ }
+ printerRenderer.disposeTextLayout(layout);
+ }
+ if (page <= endPage && paintY > clientArea.y) {
+ // close partial page
+ printDecoration(page, false, printLayout);
+ printer.endPage();
+ }
+ if (printLayout !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();
+ }
+ 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(String.valueOf(index));
+ }
+ int paintX = x - printMargin - printLayout.getBounds().width;
+ printLayout.draw(gc, paintX, y);
+ printLayout.setAscent(-1);
+ printLayout.setDescent(-1);
+ }
+ gc.setForeground(foreground);
+ layout.draw(gc, x, y);
+ }
+ /**
+ * Starts a print job and prints the pages specified in the constructor.
+ */
+ 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 { + static final int DEFAULT_FOREGROUND = 0; + static final int DEFAULT_BACKGROUND = 1; + Vector colorTable, 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 RTFWriter(int start, int length) {
+ super(start, length);
+ colorTable = new Vector();
+ fontTable = new Vector();
+ colorTable.addElement(getForeground());
+ colorTable.addElement(getBackground());
+ fontTable.addElement(getFont());
+ setUnicode();
+ }
+ /**
+ * Closes the RTF writer. Once closed no more content can be written.
+ * NOTE: toString()
does not return a valid RTF String until
+ * close()
has been called.
+ */
+ public void close() {
+ if (!isClosed()) {
+ writeHeader();
+ write("\n}}\0");
+ super.close();
+ }
+ }
+ /**
+ * Returns the index of the specified color in the RTF color table.
+ *
+ * @param color the color
+ * @param defaultIndex return value if color is null
+ * @return the index of the specified color in the RTF color table
+ * or "defaultIndex" if "color" is null.
+ */
+ int getColorIndex(Color color, int defaultIndex) {
+ if (color is null) return defaultIndex;
+ int index = colorTable.indexOf(color);
+ if (index is -1) {
+ index = colorTable.size();
+ colorTable.addElement(color);
+ }
+ return index;
+ }
+ /**
+ * Returns the index of the specified color in the RTF color table.
+ *
+ * @param color the color
+ * @param defaultIndex return value if color is null
+ * @return the index of the specified color in the RTF color table
+ * or "defaultIndex" if "color" is null.
+ */
+ int getFontIndex(Font font) {
+ int index = fontTable.indexOf(font);
+ if (index is -1) {
+ index = fontTable.size();
+ fontTable.addElement(font);
+ }
+ return index;
+ }
+ /**
+ * Determines if Unicode RTF should be written.
+ * Don't write Unicode RTF on Windows 95/98/ME or NT.
+ */
+ void setUnicode() {
+ final String Win95 = "windows 95";
+ final String Win98 = "windows 98";
+ final String WinME = "windows me";
+ final String WinNT = "windows nt";
+ String osName = System.getProperty("os.name").toLowerCase();
+ String osVersion = System.getProperty("os.version");
+ int majorVersion = 0;
+
+ if (osName.startsWith(WinNT) && osVersion !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);
+ }
+ /**
+ * Appends the specified segment of "String" to the RTF data.
+ * Copy from start
up to, but excluding, end
.
+ *
+ * @param String String to copy a segment from. Must not contain
+ * line breaks. Line breaks should be written using writeLineDelimiter()
+ * @param start start offset of segment. 0 based.
+ * @param end end offset of segment
+ */
+ void write(String String, int start, int end) {
+ for (int index = start; index < end; index++) {
+ char ch = String.charAt(index);
+ if (ch > 0xFF && WriteUnicode) {
+ // write the sub String from the last escaped character
+ // to the current one. Fixes bug 21698.
+ if (index > start) {
+ write(String.substring(start, index));
+ }
+ write("\\u");
+ write(Integer.toString((short) ch));
+ write(' '); // control word delimiter
+ start = index + 1;
+ } else if (ch 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.substring(start, index));
+ }
+ write('\\');
+ write(ch);
+ start = index + 1;
+ }
+ }
+ // write from the last escaped character to the end.
+ // Fixes bug 21698.
+ if (start < end) {
+ write(String.substring(start, end));
+ }
+ }
+ /**
+ * Writes the RTF header including font table and color table.
+ */
+ void writeHeader() {
+ StringBuffer header = new StringBuffer();
+ FontData fontData = getFont().getFontData()[0];
+ header.append("{\\rtf1\\ansi");
+ // specify code page, necessary for copy to work in bidi
+ // systems that don't support Unicode RTF.
+ String cpg = System.getProperty("file.encoding").toLowerCase();
+ if (cpg.startsWith("cp") || cpg.startsWith("ms")) {
+ cpg = cpg.substring(2, cpg.length());
+ header.append("\\ansicpg");
+ header.append(cpg);
+ }
+ header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil ");
+ header.append(fontData.getName());
+ header.append(";");
+ for (int i = 1; i < fontTable.size(); i++) {
+ header.append("\\f");
+ header.append(i);
+ header.append(" ");
+ FontData fd = ((Font)fontTable.elementAt(i)).getFontData()[0];
+ header.append(fd.getName());
+ header.append(";");
+ }
+ header.append("}}\n{\\colortbl");
+ for (int i = 0; i < colorTable.size(); i++) {
+ Color color = (Color) colorTable.elementAt(i);
+ header.append("\\red");
+ header.append(color.getRed());
+ header.append("\\green");
+ header.append(color.getGreen());
+ header.append("\\blue");
+ header.append(color.getBlue());
+ header.append(";");
+ }
+ // some RTF readers ignore the deff0 font tag. Explicitly
+ // set the font for the whole document to work around this.
+ header.append("}\n{\\f0\\fs");
+ // font size is specified in half points
+ header.append(fontData.getHeight() * 2);
+ header.append(" ");
+ write(header.toString(), 0);
+ }
+ /**
+ * Appends the specified line text to the RTF data. Lines will be formatted
+ * using the styles queried from the LineStyleListener, if set, or those set
+ * directly in the widget.
+ *
+ * @param line line text to write as RTF. Must not contain line breaks
+ * Line breaks should be written using writeLineDelimiter()
+ * @param lineOffset offset of the line. 0 based from the start of the
+ * widget document. Any text occurring before the start offset or after the
+ * end offset specified during object creation is ignored.
+ * @exception DWTException + * 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 DWT.LEFT: write("\\ql"); break; + case DWT.CENTER: write("\\qc"); break; + case DWT.RIGHT: write("\\qr"); break; + } + 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 & DWT.BOLD) !is 0) { + write("\\b"); + } + if ((style.fontStyle & DWT.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 & DWT.BOLD) !is 0) { + write("\\b0"); + } + if ((style.fontStyle & DWT.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 TextWriter(int start, int length) {
+ buffer = new StringBuffer(length);
+ startOffset = start;
+ endOffset = start + length;
+ }
+ /**
+ * Closes the writer. Once closed no more content can be written.
+ * NOTE: toString()
is not guaranteed to return a valid String unless
+ * the writer is closed.
+ */
+ public void close() {
+ if (!isClosed) {
+ isClosed = true;
+ }
+ }
+ /**
+ * Returns the number of characters to write.
+ * @return the integer number of characters to write
+ */
+ public int getCharCount() {
+ return endOffset - startOffset;
+ }
+ /**
+ * Returns the offset where writing starts. 0 based from the start of
+ * the widget text. Used to write partial lines.
+ * @return the integer offset where writing starts
+ */
+ public int getStart() {
+ return startOffset;
+ }
+ /**
+ * Returns whether the writer is closed.
+ * @return a 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 String toString() {
+ return buffer.toString();
+ }
+ /**
+ * Appends the given String to the data.
+ */
+ void write(String String) {
+ buffer.append(String);
+ }
+ /**
+ * Inserts the given String to the data at the specified offset.
+ * + * Do nothing if "offset" is < 0 or > getCharCount() + *
+ * + * @param String text to insert + * @param offset offset in the existing data to insert "String" at. + */ + void write(String String, int offset) { + if (offset < 0 || offset > buffer.length()) { + return; + } + buffer.insert(offset, String); + } + /** + * Appends the given int to the data. + */ + void write(int i) { + buffer.append(i); + } + /** + * Appends the given character to the data. + */ + void write(char i) { + buffer.append(i); + } + /** + * Appends the specified line text to the data. + * + * @param line line text to write. Must not contain line breaks + * Line breaks should be written using writeLineDelimiter() + * @param lineOffset offset of the line. 0 based from the start of the + * widget document. Any text occurring before the start offset or after the + * end offset specified during object creation is ignored. + * @exception DWTException
+ * The style value is either one of the style constants defined in
+ * class DWT
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 DWT
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 DWTException
+ * 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 DWT.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 DWT.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(DWT.CR, i); + } + if (lfIndex !is -1) { + lfIndex = text.indexOf(DWT.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(DWT.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() ? DWT.ARROW_LEFT : DWT.ARROW_RIGHT; + int previousKey = isMirrored() ? DWT.ARROW_RIGHT : DWT.ARROW_LEFT; + + // Navigation + setKeyBinding(DWT.ARROW_UP, ST.LINE_UP); + setKeyBinding(DWT.ARROW_DOWN, ST.LINE_DOWN); + if (IS_CARBON) { + setKeyBinding(previousKey | DWT.MOD1, ST.LINE_START); + setKeyBinding(nextKey | DWT.MOD1, ST.LINE_END); + setKeyBinding(DWT.HOME, ST.TEXT_START); + setKeyBinding(DWT.END, ST.TEXT_END); + setKeyBinding(DWT.ARROW_UP | DWT.MOD1, ST.TEXT_START); + setKeyBinding(DWT.ARROW_DOWN | DWT.MOD1, ST.TEXT_END); + setKeyBinding(nextKey | DWT.MOD3, ST.WORD_NEXT); + setKeyBinding(previousKey | DWT.MOD3, ST.WORD_PREVIOUS); + } else { + setKeyBinding(DWT.HOME, ST.LINE_START); + setKeyBinding(DWT.END, ST.LINE_END); + setKeyBinding(DWT.HOME | DWT.MOD1, ST.TEXT_START); + setKeyBinding(DWT.END | DWT.MOD1, ST.TEXT_END); + setKeyBinding(nextKey | DWT.MOD1, ST.WORD_NEXT); + setKeyBinding(previousKey | DWT.MOD1, ST.WORD_PREVIOUS); + } + setKeyBinding(DWT.PAGE_UP, ST.PAGE_UP); + setKeyBinding(DWT.PAGE_DOWN, ST.PAGE_DOWN); + setKeyBinding(DWT.PAGE_UP | DWT.MOD1, ST.WINDOW_START); + setKeyBinding(DWT.PAGE_DOWN | DWT.MOD1, ST.WINDOW_END); + setKeyBinding(nextKey, ST.COLUMN_NEXT); + setKeyBinding(previousKey, ST.COLUMN_PREVIOUS); + + // Selection + setKeyBinding(DWT.ARROW_UP | DWT.MOD2, ST.SELECT_LINE_UP); + setKeyBinding(DWT.ARROW_DOWN | DWT.MOD2, ST.SELECT_LINE_DOWN); + if (IS_CARBON) { + setKeyBinding(previousKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_LINE_START); + setKeyBinding(nextKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_LINE_END); + setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(DWT.END | DWT.MOD2, ST.SELECT_TEXT_END); + setKeyBinding(DWT.ARROW_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(DWT.ARROW_DOWN | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_END); + setKeyBinding(nextKey | DWT.MOD2 | DWT.MOD3, ST.SELECT_WORD_NEXT); + setKeyBinding(previousKey | DWT.MOD2 | DWT.MOD3, ST.SELECT_WORD_PREVIOUS); + } else { + setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_LINE_START); + setKeyBinding(DWT.END | DWT.MOD2, ST.SELECT_LINE_END); + setKeyBinding(DWT.HOME | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(DWT.END | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_END); + setKeyBinding(nextKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_WORD_NEXT); + setKeyBinding(previousKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_WORD_PREVIOUS); + } + setKeyBinding(DWT.PAGE_UP | DWT.MOD2, ST.SELECT_PAGE_UP); + setKeyBinding(DWT.PAGE_DOWN | DWT.MOD2, ST.SELECT_PAGE_DOWN); + setKeyBinding(DWT.PAGE_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_WINDOW_START); + setKeyBinding(DWT.PAGE_DOWN | DWT.MOD1 | DWT.MOD2, ST.SELECT_WINDOW_END); + setKeyBinding(nextKey | DWT.MOD2, ST.SELECT_COLUMN_NEXT); + setKeyBinding(previousKey | DWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); + + // Modification + // Cut, Copy, Paste + setKeyBinding('X' | DWT.MOD1, ST.CUT); + setKeyBinding('C' | DWT.MOD1, ST.COPY); + setKeyBinding('V' | DWT.MOD1, ST.PASTE); + if (IS_CARBON) { + setKeyBinding(DWT.DEL | DWT.MOD2, ST.DELETE_NEXT); + setKeyBinding(DWT.BS | DWT.MOD3, ST.DELETE_WORD_PREVIOUS); + setKeyBinding(DWT.DEL | DWT.MOD3, ST.DELETE_WORD_NEXT); + } else { + // Cut, Copy, Paste Wordstar style + setKeyBinding(DWT.DEL | DWT.MOD2, ST.CUT); + setKeyBinding(DWT.INSERT | DWT.MOD1, ST.COPY); + setKeyBinding(DWT.INSERT | DWT.MOD2, ST.PASTE); + } + setKeyBinding(DWT.BS | DWT.MOD2, ST.DELETE_PREVIOUS); + setKeyBinding(DWT.BS, ST.DELETE_PREVIOUS); + setKeyBinding(DWT.DEL, ST.DELETE_NEXT); + setKeyBinding(DWT.BS | DWT.MOD1, ST.DELETE_WORD_PREVIOUS); + setKeyBinding(DWT.DEL | DWT.MOD1, ST.DELETE_WORD_NEXT); + + // Miscellaneous + setKeyBinding(DWT.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.opEquals(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(DWT.COLOR_BLACK)); + gc.fillRectangle(0, 0, caretWidth, lineHeight); + gc.setForeground(display.getSystemColor(DWT.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.opEquals(defaultCaret.getImage())) { + defaultCaret.setImage(null); + } + rightCaretBitmap.dispose(); + } + rightCaretBitmap = new Image(display, caretWidth, lineHeight); + gc = new GC (rightCaretBitmap); + gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); + gc.fillRectangle(0, 0, caretWidth, lineHeight); + gc.setForeground(display.getSystemColor(DWT.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 DWTException+ * If a carriage return was typed replace it with the line break character + * used by the widget on this platform. + *
+ * + * @param key the character typed by the user + */ +void doContent(char key) { + 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 DWT.CR || key is DWT.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++; + } + event.text = new String(new char[] {key}); + } else { + event.text = new String(new char[] {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, DWT.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, DWT.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 : 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 : 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, DWT.MOVEMENT_WORD_START); + } else { + newCaretOffset = content.getOffsetAtLine(line); + } + } else { + if (wordSelect) { + newCaretOffset = getWordNext(newCaretOffset, DWT.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, DWT.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, DWT.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, DWT.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 = DWT.NULL; +} +public Color getBackground() { + checkWidget(); + if (background is null) { + return getDisplay().getSystemColor(DWT.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 DWTException+ * + * @param lineIndex index of the line to return. + * @return the line text without delimiters + * + * @exception DWTException
+ * 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 DWTException+ * 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. + * + * @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. + * + * @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 DWTException+ * 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 DWTException
+ * 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 DWTException+ * 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 DWTException+ * 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 DWTException + * 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 DWTException + * 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 DWTException + * 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 DWTException+ * 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 DWTException+ * 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) { + point = layout.getLocation(offsetInLine - 1, true); + } else { + switch (caretAlignment) { + case OFFSET_LEADING: + point = layout.getLocation(offsetInLine, false); + break; + case PREVIOUS_OFFSET_TRAILING: + default: + if (offsetInLine is 0) { + point = layout.getLocation(offsetInLine, false); + } else { + point = layout.getLocation(offsetInLine - 1, true); + } + break; + } + } + } else { + point = new Point(layout.getIndent(), 0); + } + renderer.disposeTextLayout(layout); + point.x += leftMargin - horizontalScrollOffset; + point.y += getLinePixel(lineIndex); + return point; +} +/** + * Inserts a String. The old selection is replaced with the new text. + * + * @param String the String + * @see #replaceTextRange(int,int,String) + * @exception DWTExceptionDND.CLIPBOARD
+ * clipboard or, if there is no selection, inserts the text at the current
+ * caret offset. If the widget has the DWT.SINGLE style and the
+ * clipboard text contains more than one line, only the first line without
+ * line delimiters is inserted in the widget.
+ *
+ * @exception DWTException + * The runnable may be run in a non-UI thread. + *
+ * + * @param printer the printer to print to + * @exception DWTException+ * The runnable may be run in a non-UI thread. + *
+ * + * @param printer the printer to print to + * @param options print options to use during printing + * @exception DWTException
+ * 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 DWTException
+ * 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 DWTException+ * 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(DWT.Modify, event); +} +/** + * Sends the specified selection event. + */ +void sendSelectionEvent() { + getAccessible().textSelectionChanged(); + Event event = new Event(); + event.x = selection.x; + event.y = selection.y; + notifyListeners(DWT.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)) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + } + } + return offset; + } + return newOffset; +} +/** + * Sets the alignment of the widget. The argument should be one ofDWT.LEFT
,
+ * DWT.CENTER
or DWT.RIGHT
. The alignment applies for all lines.
+ *
+ * Note that if DWT.MULTI
is set, then DWT.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 DWTException+ * 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 DWTException+ * 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 DWTException+ * 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 DWTException+ * 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 DWT.java or a character. + * Optionally ORd with a state mask. Preferred state masks are one or more of + * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform + * differences. However, there may be cases where using the specific state masks + * (i.e., DWT.CTRL, DWT.SHIFT, DWT.ALT, DWT.COMMAND) makes sense. + * @param action one of the predefined actions defined in ST.java. + * Use DWT.NULL to remove a key binding. + * @exception DWTExceptionDWT.LEFT
,
+ * DWT.CENTER
or DWT.RIGHT
.
+ *
+ * Note that if DWT.MULTI
is set, then DWT.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 DWTException
+ * 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 DWTException+ * 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 DWTException+ * 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 DWTException+ * 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 DWTExceptionDWT.LEFT_TO_RIGHT
or DWT.RIGHT_TO_LEFT
.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception DWTException + * 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 DWTException+ * 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 DWTException+ * 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; + 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 DWTException+ * 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 DWTExceptionstart
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 DWTException+ * 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 DWTException
+ * 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 DWTException+ * Note: Only a single line of text should be set when the DWT.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 DWTException+ * The text limit specifies the amount of text that + * the user can type into the widget. + *
+ * + * @param limit the new text limit. + * @exception DWTException+ * 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 DWTException+ * 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 DWTException+ * This overrides the creation style bit DWT.WRAP. + *
+ * + * @param wrap true=widget wraps lines, false=widget does not wrap lines + * @since 2.0 + */ +public void setWordWrap(bool wrap) { + checkWidget(); + if ((getStyle() & DWT.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(); +} +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 DWTException+ * If the selection intersects with the replaced text, the selection is + * reset and the caret moved to the end of the new text. + * If the selection is behind the replaced text it is moved so that the + * same text remains selected. If the selection is before the replaced text + * it is left unchanged. + *
+ * + * @param startOffset offset of the text change + * @param replacedLength length of text being replaced + * @param newLength length of new text + */ +void updateSelection(int startOffset, int replacedLength, int newLength) { + if (selection.y <= startOffset) { + // selection ends before text change + return; + } + if (selection.x < startOffset) { + // clear selection fragment before text change + internalRedrawRange(selection.x, startOffset - selection.x); + } + if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) { + // clear selection fragment after text change. + // do this only when the selection is actually affected by the + // change. Selection is only affected if it intersects the change (1GDY217). + int netNewLength = newLength - replacedLength; + int redrawStart = startOffset + newLength; + internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart); + } + if (selection.y > startOffset && selection.x < startOffset + replacedLength) { + // selection intersects replaced text. set caret behind text change + setSelection(startOffset + newLength, 0, true); + } else { + // move selection to keep same text selected + setSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true); + } + setCaretLocation(); +} +} diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/StyledTextContent.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/custom/StyledTextContent.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.custom; + + +/** + * Clients may implement the StyledTextContent interface to provide a + * custom store for the StyledText widget content. The StyledText widget + * interacts with its StyledTextContent in order to access and update + * the text that is being displayed and edited in the widget. + * A custom content implementation can be set in the widget using the + * StyledText.setContent API. + */ +public interface StyledTextContent { + +/** + * Called by StyledText to add itself as an Observer to content changes. + * See TextChangeListener for a description of the listener methods that + * are called when text changes occur. + *+ * + * @param listener the listener + * @exception IllegalArgumentException
+ * + * @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 + * @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);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/StyledTextDropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/StyledTextDropTargetEffect.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.*;
+import dwt.dnd.*;
+import dwt.graphics.*;
+import dwt.widgets.*;
+
+/**
+ * This adapter class provides a default drag under effect (eg. select and scroll)
+ * when a drag occurs over a StyledText
.
+ *
+ *
Classes that wish to provide their own drag under effect for a 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.
+ *
+ * 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.
+ *
+ *
StyledTextDropTargetEffect
to handle the drag under effect on the specified
+ * StyledText
.
+ *
+ * @param styledText the StyledText
over which the user positions the cursor to drop the data
+ */
+ public StyledTextDropTargetEffect(StyledText styledText) {
+ super(styledText);
+ paintListener = new Listener () {
+ public void handleEvent (Event event) {
+ if (currentOffset !is -1) {
+ StyledText text = (StyledText) getControl();
+ Point position = text.getLocationAtOffset(currentOffset);
+ int height = text.getLineHeight(currentOffset);
+ event.gc.setBackground(event.display.getSystemColor (DWT.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 void dragEnter(DropTargetEvent event) {
+ currentOffset = -1;
+ scrollBeginTime = 0;
+ scrollX = -1;
+ scrollY = -1;
+ getControl().removeListener(DWT.Paint, paintListener);
+ getControl().addListener (DWT.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 void dragLeave(DropTargetEvent event) {
+ StyledText text = (StyledText) getControl();
+ if (currentOffset !is -1) {
+ refreshCaret(text, currentOffset, -1);
+ }
+ text.removeListener(DWT.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 void dragOver(DropTargetEvent event) {
+ int effect = event.feedback;
+ StyledText text = (StyledText) getControl();
+
+ Point pt = text.getDisplay().map(null, text, event.x, event.y);
+ if ((effect & DND.FEEDBACK_SCROLL) 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 void dropAccept(DropTargetEvent event) {
+ if (currentOffset !is -1) {
+ StyledText text = (StyledText) getControl();
+ text.setSelection(currentOffset);
+ currentOffset = -1;
+ }
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/StyledTextEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/StyledTextEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.graphics.*;
+import dwt.widgets.*;
+
+/**
+ *
+ */
+class StyledTextEvent : Event {
+ // used by LineStyleEvent
+ int[] ranges;
+ StyleRange[] styles;
+ int alignment;
+ int indent;
+ bool justify;
+ Bullet bullet;
+ int bulletIndex;
+ // used by LineBackgroundEvent
+ Color lineBackground;
+ // used by BidiSegmentEvent
+ int[] segments;
+ // used by TextChangedEvent
+ int replaceCharCount;
+ int newCharCount;
+ int replaceLineCount;
+ int newLineCount;
+ // used by PaintObjectEvent
+ int x;
+ int y;
+ int ascent;
+ int descent;
+ StyleRange style;
+
+StyledTextEvent (StyledTextContent content) {
+ super();
+ data = content;
+}
+}
+
+
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/StyledTextListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/StyledTextListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.events.*;
+import dwt.widgets.*;
+import dwt.internal.DWTEventListener;
+
+class StyledTextListener : TypedListener {
+/**
+ */
+StyledTextListener(DWTEventListener listener) {
+ super(listener);
+}
+/**
+ * Process StyledText events by invoking the event's handler.
+ */
+public void handleEvent(Event e) {
+
+ switch (e.type) {
+ case StyledText.ExtendedModify:
+ ExtendedModifyEvent extendedModifyEvent = new ExtendedModifyEvent((StyledTextEvent) e);
+ ((ExtendedModifyListener) eventListener).modifyText(extendedModifyEvent);
+ break;
+ case StyledText.LineGetBackground:
+ LineBackgroundEvent lineBgEvent = new LineBackgroundEvent((StyledTextEvent) e);
+ ((LineBackgroundListener) eventListener).lineGetBackground(lineBgEvent);
+ ((StyledTextEvent) e).lineBackground = lineBgEvent.lineBackground;
+ break;
+ case StyledText.LineGetSegments:
+ BidiSegmentEvent segmentEvent = new BidiSegmentEvent((StyledTextEvent) e);
+ ((BidiSegmentListener) eventListener).lineGetSegments(segmentEvent);
+ ((StyledTextEvent) e).segments = segmentEvent.segments;
+ break;
+ case StyledText.LineGetStyle:
+ LineStyleEvent lineStyleEvent = new LineStyleEvent((StyledTextEvent) e);
+ ((LineStyleListener) eventListener).lineGetStyle(lineStyleEvent);
+ ((StyledTextEvent) e).ranges = lineStyleEvent.ranges;
+ ((StyledTextEvent) e).styles = lineStyleEvent.styles;
+ ((StyledTextEvent) e).alignment = lineStyleEvent.alignment;
+ ((StyledTextEvent) e).indent = lineStyleEvent.indent;
+ ((StyledTextEvent) e).justify = lineStyleEvent.justify;
+ ((StyledTextEvent) e).bullet = lineStyleEvent.bullet;
+ ((StyledTextEvent) e).bulletIndex = lineStyleEvent.bulletIndex;
+ break;
+ case StyledText.PaintObject:
+ PaintObjectEvent paintObjectEvent = new PaintObjectEvent((StyledTextEvent) e);
+ ((PaintObjectListener) eventListener).paintObject(paintObjectEvent);
+ break;
+ case StyledText.VerifyKey:
+ VerifyEvent verifyEvent = new VerifyEvent(e);
+ ((VerifyKeyListener) eventListener).verifyKey(verifyEvent);
+ e.doit = verifyEvent.doit;
+ break;
+ case StyledText.TextChanged: {
+ TextChangedEvent textChangedEvent = new TextChangedEvent((StyledTextContent) e.data);
+ ((TextChangeListener) eventListener).textChanged(textChangedEvent);
+ break;
+ }
+ case StyledText.TextChanging:
+ TextChangingEvent textChangingEvent = new TextChangingEvent((StyledTextContent) e.data, (StyledTextEvent) e);
+ ((TextChangeListener) eventListener).textChanging(textChangingEvent);
+ break;
+ case StyledText.TextSet: {
+ TextChangedEvent textChangedEvent = new TextChangedEvent((StyledTextContent) e.data);
+ ((TextChangeListener) eventListener).textSet(textChangedEvent);
+ break;
+ }
+ case StyledText.WordNext: {
+ MovementEvent wordBoundaryEvent = new MovementEvent((StyledTextEvent) e);
+ ((MovementListener) eventListener).getNextOffset(wordBoundaryEvent);
+ ((StyledTextEvent) e).end = wordBoundaryEvent.newOffset;
+ break;
+ }
+ case StyledText.WordPrevious: {
+ MovementEvent wordBoundaryEvent = new MovementEvent((StyledTextEvent) e);
+ ((MovementListener) eventListener).getPreviousOffset(wordBoundaryEvent);
+ ((StyledTextEvent) e).end = wordBoundaryEvent.newOffset;
+ break;
+ }
+ }
+}
+}
+
+
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/StyledTextPrintOptions.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/StyledTextPrintOptions.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+/**
+ * Use StyledTextPrintOptions to specify printing options for the
+ * StyledText.print(Printer, StyledTextPrintOptions) API.
+ * + * The following example prints a right aligned page number in the footer, + * sets the job name to "Example" and prints line background colors but no other + * formatting: + *
+ *+ * StyledTextPrintOptions options = new StyledTextPrintOptions(); + * options.footer = "\t\t<page>"; + * options.jobName = "Example"; + * options.printLineBackground = true; + * + * Runnable runnable = styledText.print(new Printer(), options); + * runnable.run(); + *+ * @since 2.1 + */ +public class StyledTextPrintOptions { + /** + * Page number placeholder constant for use in
header
+ * and footer
. Value is <page>
+ */
+ public static final String PAGE_TAG = "header
and
+ * footer
. Value is \t
+ */
+ public static final String SEPARATOR = "\t";
+ /**
+ * Formatted text to print in the header of each page.
+ * "left '\t' center '\t' right"
+ *left, center, right = <page> | #CDATA
+ *Header and footer are defined as three separate regions for arbitrary
+ * text or the page number placeholder <page>
+ * (StyledTextPrintOptions.PAGE_TAG
). The three regions are
+ * left aligned, centered and right aligned. They are separated by a tab
+ * character (StyledTextPrintOptions.SEPARATOR
).
+ */
+ public String header = null;
+ /**
+ * Formatted text to print in the footer of each page.
+ *
"left '\t' center '\t' right"
+ *left, center, right = <page> | #CDATA
+ *Header and footer are defined as three separate regions for arbitrary
+ * text or the page number placeholder <page>
+ * (StyledTextPrintOptions.PAGE_TAG
). The three regions are
+ * left aligned, centered and right aligned. They are separated by a tab
+ * character (StyledTextPrintOptions.SEPARATOR
).
+ */
+ public String footer = null;
+ /**
+ * Name of the print job.
+ */
+ public String jobName = null;
+
+ /**
+ * Print the text foreground color. Default value is false
.
+ */
+ public 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 380af2bdd8e5 dwt/custom/StyledTextRenderer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/StyledTextRenderer.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,1519 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+
+import dwt.DWT;
+import dwt.graphics.*;
+import dwt.widgets.*;
+
+/**
+ * A StyledTextRenderer renders the content of a StyledText widget.
+ * This class can be used to render to the display or to a printer.
+ */
+class StyledTextRenderer {
+ Device device;
+ StyledText styledText;
+ StyledTextContent content;
+
+ /* Font info */
+ Font regularFont, boldFont, italicFont, boldItalicFont;
+ int tabWidth;
+ int ascent, descent;
+ int averageCharWidth;
+
+ /* Line data */
+ int topIndex = -1;
+ TextLayout[] layouts;
+ int lineCount;
+ int[] lineWidth;
+ int[] lineHeight;
+ LineInfo[] lines;
+ int maxWidth;
+ int maxWidthLineIndex;
+ bool idleRunning;
+
+ /* Bullet */
+ Bullet[] bullets;
+ int[] bulletsIndices;
+ int[] redrawLines;
+
+ /* Style data */
+ int[] ranges;
+ int styleCount;
+ StyleRange[] styles;
+ StyleRange[] stylesSet;
+ int stylesSetCount = 0;
+ final static int BULLET_MARGIN = 8;
+
+ final static bool COMPACT_STYLES = true;
+ final static bool MERGE_STYLES = true;
+
+ final static int GROW = 32;
+ final static int IDLE_TIME = 50;
+ final static int CACHE_SIZE = 128;
+
+ final static int BACKGROUND = 1 << 0;
+ final static int ALIGNMENT = 1 << 1;
+ final static int INDENT = 1 << 2;
+ final static int JUSTIFY = 1 << 3;
+ final static int SEGMENTS = 1 << 5;
+
+ static class LineInfo {
+ int flags;
+ Color background;
+ int alignment;
+ int indent;
+ bool justify;
+ int[] segments;
+
+ public LineInfo() {
+ }
+ public LineInfo(LineInfo info) {
+ if (info !is null) {
+ flags = info.flags;
+ background = info.background;
+ alignment = info.alignment;
+ indent = info.indent;
+ justify = info.justify;
+ segments = info.segments;
+ }
+ }
+ }
+
+StyledTextRenderer(Device device, StyledText styledText) {
+ this.device = device;
+ this.styledText = styledText;
+}
+int addMerge(int[] mergeRanges, StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
+ int rangeCount = styleCount << 1;
+ StyleRange endStyle = null;
+ int endStart = 0, endLength = 0;
+ if (modifyEnd < rangeCount) {
+ endStyle = styles[modifyEnd >> 1];
+ endStart = ranges[modifyEnd];
+ endLength = ranges[modifyEnd + 1];
+ }
+ int grow = mergeCount - (modifyEnd - modifyStart);
+ if (rangeCount + grow >= ranges.length) {
+ int[] tmpRanges = new int[ranges.length + grow + (GROW << 1)];
+ System.arraycopy(ranges, 0, tmpRanges, 0, modifyStart);
+ StyleRange[] tmpStyles = new StyleRange[styles.length + (grow >> 1) + GROW];
+ System.arraycopy(styles, 0, tmpStyles, 0, modifyStart >> 1);
+ if (rangeCount > modifyEnd) {
+ System.arraycopy(ranges, modifyEnd, tmpRanges, modifyStart + mergeCount, rangeCount - modifyEnd);
+ System.arraycopy(styles, modifyEnd >> 1, tmpStyles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
+ }
+ ranges = tmpRanges;
+ styles = tmpStyles;
+ } else {
+ if (rangeCount > modifyEnd) {
+ System.arraycopy(ranges, modifyEnd, ranges, modifyStart + mergeCount, rangeCount - modifyEnd);
+ System.arraycopy(styles, modifyEnd >> 1, styles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
+ }
+ }
+ if (MERGE_STYLES) {
+ int j = modifyStart;
+ for (int i = 0; i < mergeCount; i += 2) {
+ if (j > 0 && ranges[j - 2] + ranges[j - 1] is mergeRanges[i] && mergeStyles[i >> 1].similarTo(styles[(j - 2) >> 1])) {
+ ranges[j - 1] += mergeRanges[i + 1];
+ } else {
+ styles[j >> 1] = mergeStyles[i >> 1];
+ ranges[j++] = mergeRanges[i];
+ ranges[j++] = mergeRanges[i + 1];
+ }
+ }
+ if (endStyle !is null && ranges[j - 2] + ranges[j - 1] is endStart && endStyle.similarTo(styles[(j - 2) >> 1])) {
+ ranges[j - 1] += endLength;
+ modifyEnd += 2;
+ mergeCount += 2;
+ }
+ if (rangeCount > modifyEnd) {
+ System.arraycopy(ranges, modifyStart + mergeCount, ranges, j, rangeCount - modifyEnd);
+ System.arraycopy(styles, (modifyStart + mergeCount) >> 1, styles, j >> 1, styleCount - (modifyEnd >> 1));
+ }
+ grow = (j - modifyStart) - (modifyEnd - modifyStart);
+ } else {
+ System.arraycopy(mergeRanges, 0, ranges, modifyStart, mergeCount);
+ System.arraycopy(mergeStyles, 0, styles, modifyStart >> 1, mergeCount >> 1);
+ }
+ styleCount += grow >> 1;
+ return grow;
+}
+int addMerge(StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
+ int grow = mergeCount - (modifyEnd - modifyStart);
+ StyleRange endStyle = null;
+ if (modifyEnd < styleCount) endStyle = styles[modifyEnd];
+ if (styleCount + grow >= styles.length) {
+ StyleRange[] tmpStyles = new StyleRange[styles.length + grow + GROW];
+ System.arraycopy(styles, 0, tmpStyles, 0, modifyStart);
+ if (styleCount > modifyEnd) {
+ System.arraycopy(styles, modifyEnd, tmpStyles, modifyStart + mergeCount, styleCount - modifyEnd);
+ }
+ styles = tmpStyles;
+ } else {
+ if (styleCount > modifyEnd) {
+ System.arraycopy(styles, modifyEnd, styles, modifyStart + mergeCount, styleCount - modifyEnd);
+ }
+ }
+ if (MERGE_STYLES) {
+ int j = modifyStart;
+ for (int i = 0; i < mergeCount; i++) {
+ StyleRange newStyle = mergeStyles[i], style;
+ if (j > 0 && (style = styles[j - 1]).start + style.length is newStyle.start && newStyle.similarTo(style)) {
+ style.length += newStyle.length;
+ } else {
+ styles[j++] = newStyle;
+ }
+ }
+ StyleRange style = styles[j - 1];
+ if (endStyle !is null && style.start + style.length is endStyle.start && endStyle.similarTo(style)) {
+ style.length += endStyle.length;
+ modifyEnd++;
+ mergeCount++;
+ }
+ if (styleCount > modifyEnd) {
+ System.arraycopy(styles, modifyStart + mergeCount, styles, j, styleCount - modifyEnd);
+ }
+ grow = (j - modifyStart) - (modifyEnd - modifyStart);
+ } else {
+ System.arraycopy(mergeStyles, 0, styles, modifyStart, mergeCount);
+ }
+ styleCount += grow;
+ return grow;
+}
+void calculate(int startLine, int lineCount) {
+ int endLine = startLine + lineCount;
+ if (startLine < 0 || endLine > lineWidth.length) {
+ return;
+ }
+ int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth();
+ for (int i = startLine; i < endLine; i++) {
+ if (lineWidth[i] is -1 || lineHeight[i] is -1) {
+ TextLayout layout = getTextLayout(i);
+ Rectangle rect = layout.getBounds();
+ lineWidth[i] = rect.width + hTrim;
+ lineHeight[i] = rect.height;
+ disposeTextLayout(layout);
+ }
+ if (lineWidth[i] > maxWidth) {
+ maxWidth = lineWidth[i];
+ maxWidthLineIndex = i;
+ }
+ }
+}
+void calculateClientArea () {
+ int index = styledText.getTopIndex();
+ int lineCount = content.getLineCount();
+ int height = styledText.getClientArea().height;
+ int y = 0;
+ while (height > y && lineCount > index) {
+ calculate(index, 1);
+ y += lineHeight[index++];
+ }
+}
+void calculateIdle () {
+ if (idleRunning) return;
+ Runnable runnable = new Runnable() {
+ public void run() {
+ if (styledText is null) return;
+ int i;
+ long start = System.currentTimeMillis();
+ for (i = 0; i < lineCount; i++) {
+ if (lineHeight[i] is -1 || lineWidth[i] is -1) {
+ calculate(i, 1);
+ if (System.currentTimeMillis() - start > IDLE_TIME) break;
+ }
+ }
+ if (i < lineCount) {
+ Display display = styledText.getDisplay();
+ display.asyncExec(this);
+ } else {
+ idleRunning = false;
+ styledText.setScrollBars(true);
+ ScrollBar bar = styledText.getVerticalBar();
+ if (bar !is null) {
+ bar.setSelection(styledText.getVerticalScrollOffset());
+ }
+ }
+ }
+ };
+ Display display = styledText.getDisplay();
+ display.asyncExec(runnable);
+ idleRunning = true;
+}
+void clearLineBackground(int startLine, int count) {
+ if (lines is null) return;
+ for (int i = startLine; i < startLine + count; i++) {
+ LineInfo info = lines[i];
+ if (info !is null) {
+ info.flags &= ~BACKGROUND;
+ info.background = null;
+ if (info.flags is 0) lines[i] = null;
+ }
+ }
+}
+void clearLineStyle(int startLine, int count) {
+ if (lines is null) return;
+ for (int i = startLine; i < startLine + count; i++) {
+ LineInfo info = lines[i];
+ if (info !is null) {
+ info.flags &= ~(ALIGNMENT | INDENT | JUSTIFY);
+ if (info.flags is 0) lines[i] = null;
+ }
+ }
+}
+void copyInto(StyledTextRenderer renderer) {
+ if (ranges !is null) {
+ int[] newRanges = renderer.ranges = new int[styleCount << 1];
+ System.arraycopy(ranges, 0, newRanges, 0, newRanges.length);
+ }
+ if (styles !is null) {
+ StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount];
+ for (int i = 0; i < newStyles.length; i++) {
+ newStyles[i] = (StyleRange)styles[i].clone();
+ }
+ renderer.styleCount = styleCount;
+ }
+ if (lines !is null) {
+ LineInfo[] newLines = renderer.lines = new LineInfo[lineCount];
+ for (int i = 0; i < newLines.length; i++) {
+ newLines[i] = new LineInfo(lines[i]);
+ }
+ renderer.lineCount = lineCount;
+ }
+}
+void dispose() {
+ if (boldFont !is null) boldFont.dispose();
+ if (italicFont !is null) italicFont.dispose();
+ if (boldItalicFont !is null) boldItalicFont.dispose();
+ boldFont = italicFont = boldItalicFont = null;
+ reset();
+ content = null;
+ device = null;
+ styledText = null;
+}
+void disposeTextLayout (TextLayout layout) {
+ if (layouts !is null) {
+ for (int i = 0; i < layouts.length; i++) {
+ if (layouts[i] is layout) return;
+ }
+ }
+ layout.dispose();
+}
+void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) {
+ StyleRange style = bullet.style;
+ GlyphMetrics metrics = style.metrics;
+ Color color = style.foreground;
+ if (color !is null) gc.setForeground(color);
+ if ((bullet.type & ST.BULLET_DOT) !is 0 && StyledText.IS_MOTIF) {
+ int size = Math.max(4, (lineAscent + lineDescent) / 4);
+ if ((size & 1) is 0) size++;
+ if (color is null) {
+ Display display = styledText.getDisplay();
+ color = display.getSystemColor(DWT.COLOR_BLACK);
+ }
+ gc.setBackground(color);
+ int x = paintX + Math.max(0, metrics.width - size - BULLET_MARGIN);
+ gc.fillArc(x, paintY + size, size + 1, size + 1, 0, 360);
+ return;
+ }
+ Font font = style.font;
+ if (font !is null) gc.setFont(font);
+ String String = "";
+ int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER);
+ switch (type) {
+ case ST.BULLET_DOT: String = "\u2022"; break;
+ case ST.BULLET_NUMBER: String = String.valueOf(index); break;
+ case ST.BULLET_LETTER_LOWER: String = String.valueOf((char) (index % 26 + 97)); break;
+ case ST.BULLET_LETTER_UPPER: String = String.valueOf((char) (index % 26 + 65)); break;
+ }
+ if ((bullet.type & ST.BULLET_TEXT) !is 0) String += bullet.text;
+ Display display = styledText.getDisplay();
+ TextLayout layout = new TextLayout(display);
+ layout.setText(String);
+ layout.setAscent(lineAscent);
+ layout.setDescent(lineDescent);
+ style = (StyleRange)style.clone();
+ style.metrics = null;
+ if (style.font is null) style.font = getFont(style.fontStyle);
+ layout.setStyle(style, 0, String.length());
+ int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN);
+ layout.draw(gc, x, paintY);
+ layout.dispose();
+}
+int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackground, Color widgetForeground) {
+ TextLayout layout = getTextLayout(lineIndex);
+ String line = content.getLine(lineIndex);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ int lineLength = line.length();
+ Point selection = styledText.getSelection();
+ int selectionStart = selection.x - lineOffset;
+ int selectionEnd = selection.y - lineOffset;
+ Rectangle client = styledText.getClientArea();
+ Color lineBackground = getLineBackground(lineIndex, null);
+ StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
+ if (event !is null && event.lineBackground !is null) lineBackground = event.lineBackground;
+ int height = layout.getBounds().height;
+ if (lineBackground !is null) {
+ gc.setBackground(lineBackground);
+ gc.fillRectangle(client.x, paintY, client.width, height);
+ } else {
+ gc.setBackground(widgetBackground);
+ styledText.drawBackground(gc, client.x, paintY, client.width, height);
+ }
+ gc.setForeground(widgetForeground);
+ if (selectionStart is selectionEnd || (selectionEnd <= 0 && selectionStart > lineLength - 1)) {
+ layout.draw(gc, paintX, paintY);
+ } else {
+ int start = Math.max(0, selectionStart);
+ int end = Math.min(lineLength, selectionEnd);
+ Color selectionFg = styledText.getSelectionForeground();
+ Color selectionBg = styledText.getSelectionBackground();
+ int flags;
+ if ((styledText.getStyle() & DWT.FULL_SELECTION) !is 0) {
+ flags = DWT.FULL_SELECTION;
+ } else {
+ flags = DWT.DELIMITER_SELECTION;
+ }
+ if (selectionStart <= lineLength && lineLength < selectionEnd ) {
+ flags |= DWT.LAST_LINE_SELECTION;
+ }
+ layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg, flags);
+ }
+
+ // draw objects
+ Bullet bullet = null;
+ int bulletIndex = -1;
+ if (bullets !is null) {
+ if (bulletsIndices !is null) {
+ int index = lineIndex - topIndex;
+ if (0 <= index && index < CACHE_SIZE) {
+ bullet = bullets[index];
+ bulletIndex = bulletsIndices[index];
+ }
+ } else {
+ for (int i = 0; i < bullets.length; i++) {
+ bullet = bullets[i];
+ bulletIndex = bullet.indexOf(lineIndex);
+ if (bulletIndex !is -1) break;
+ }
+ }
+ }
+ if (bulletIndex !is -1 && bullet !is null) {
+ FontMetrics metrics = layout.getLineMetrics(0);
+ int lineAscent = metrics.getAscent() + metrics.getLeading();
+ if (bullet.type is ST.BULLET_CUSTOM) {
+ bullet.style.start = lineOffset;
+ styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex);
+ } else {
+ drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent());
+ }
+ }
+ TextStyle[] styles = layout.getStyles();
+ int[] ranges = null;
+ for (int i = 0; i < styles.length; i++) {
+ if (styles[i].metrics !is null) {
+ if (ranges is null) ranges = layout.getRanges();
+ int start = ranges[i << 1];
+ int length = ranges[(i << 1) + 1] - start;
+ Point point = layout.getLocation(start, false);
+ FontMetrics metrics = layout.getLineMetrics(layout.getLineIndex(start));
+ StyleRange style = (StyleRange)((StyleRange)styles[i]).clone();
+ style.start = start + lineOffset;
+ style.length = length;
+ int lineAscent = metrics.getAscent() + metrics.getLeading();
+ styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0);
+ }
+ }
+ disposeTextLayout(layout);
+ return height;
+}
+int getBaseline() {
+ return ascent;
+}
+Font getFont(int style) {
+ switch (style) {
+ case DWT.BOLD:
+ if (boldFont !is null) return boldFont;
+ return boldFont = new Font(device, getFontData(style));
+ case DWT.ITALIC:
+ if (italicFont !is null) return italicFont;
+ return italicFont = new Font(device, getFontData(style));
+ case DWT.BOLD | DWT.ITALIC:
+ if (boldItalicFont !is null) return boldItalicFont;
+ return boldItalicFont = new Font(device, getFontData(style));
+ default:
+ return regularFont;
+ }
+}
+FontData[] getFontData(int style) {
+ FontData[] fontDatas = regularFont.getFontData();
+ for (int i = 0; i < fontDatas.length; i++) {
+ fontDatas[i].setStyle(style);
+ }
+ return fontDatas;
+}
+int getHeight () {
+ int defaultLineHeight = getLineHeight();
+ if (styledText.isFixedLineHeight()) {
+ return lineCount * defaultLineHeight;
+ }
+ int totalHeight = 0;
+ int width = styledText.getWrapWidth();
+ for (int i = 0; i < lineCount; i++) {
+ int height = lineHeight[i];
+ if (height is -1) {
+ if (width > 0) {
+ int length = content.getLine(i).length();
+ height = ((length * averageCharWidth / width) + 1) * defaultLineHeight;
+ } else {
+ height = defaultLineHeight;
+ }
+ }
+ totalHeight += height;
+ }
+ return totalHeight + styledText.topMargin + styledText.bottomMargin;
+}
+int getLineAlignment(int index, int defaultAlignment) {
+ if (lines is null) return defaultAlignment;
+ LineInfo info = lines[index];
+ if (info !is null && (info.flags & ALIGNMENT) !is 0) {
+ return info.alignment;
+ }
+ return defaultAlignment;
+}
+Color getLineBackground(int index, Color defaultBackground) {
+ if (lines is null) return defaultBackground;
+ LineInfo info = lines[index];
+ if (info !is null && (info.flags & BACKGROUND) !is 0) {
+ return info.background;
+ }
+ return defaultBackground;
+}
+Bullet getLineBullet (int index, Bullet defaultBullet) {
+ if (bullets is null) return defaultBullet;
+ if (bulletsIndices !is null) return defaultBullet;
+ for (int i = 0; i < bullets.length; i++) {
+ Bullet bullet = bullets[i];
+ if (bullet.indexOf(index) !is -1) return bullet;
+ }
+ return defaultBullet;
+}
+int getLineHeight() {
+ return ascent + descent;
+}
+int getLineHeight(int lineIndex) {
+ if (lineHeight[lineIndex] is -1) {
+ calculate(lineIndex, 1);
+ }
+ return lineHeight[lineIndex];
+}
+int getLineIndent(int index, int defaultIndent) {
+ if (lines is null) return defaultIndent;
+ LineInfo info = lines[index];
+ if (info !is null && (info.flags & INDENT) !is 0) {
+ return info.indent;
+ }
+ return defaultIndent;
+}
+bool getLineJustify(int index, bool defaultJustify) {
+ if (lines is null) return defaultJustify;
+ LineInfo info = lines[index];
+ if (info !is null && (info.flags & JUSTIFY) !is 0) {
+ return info.justify;
+ }
+ return defaultJustify;
+}
+int[] getLineSegments(int index, int[] defaultSegments) {
+ if (lines is null) return defaultSegments;
+ LineInfo info = lines[index];
+ if (info !is null && (info.flags & SEGMENTS) !is 0) {
+ return info.segments;
+ }
+ return defaultSegments;
+}
+int getRangeIndex(int offset, int low, int high) {
+ if (styleCount is 0) return 0;
+ if (ranges !is null) {
+ while (high - low > 2) {
+ int index = ((high + low) / 2) / 2 * 2;
+ int end = ranges[index] + ranges[index + 1];
+ if (end > offset) {
+ high = index;
+ } else {
+ low = index;
+ }
+ }
+ } else {
+ while (high - low > 1) {
+ int index = ((high + low) / 2);
+ int end = styles[index].start + styles[index].length;
+ if (end > offset) {
+ high = index;
+ } else {
+ low = index;
+ }
+ }
+ }
+ return high;
+}
+int[] getRanges(int start, int length) {
+ int[] newRanges;
+ int end = start + length - 1;
+ if (ranges !is null) {
+ int rangeCount = styleCount << 1;
+ int rangeStart = getRangeIndex(start, -1, rangeCount);
+ if (rangeStart >= rangeCount) return null;
+ if (ranges[rangeStart] > end) return null;
+ int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount) + 1);
+ newRanges = new int[rangeEnd - rangeStart + 2];
+ System.arraycopy(ranges, rangeStart, newRanges, 0, newRanges.length);
+ } else {
+ int rangeStart = getRangeIndex(start, -1, styleCount);
+ if (rangeStart >= styleCount) return null;
+ if (styles[rangeStart].start > end) return null;
+ int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
+ newRanges = new int[(rangeEnd - rangeStart + 1) << 1];
+ for (int i = rangeStart, j = 0; i <= rangeEnd; i++, j += 2) {
+ StyleRange style = styles[i];
+ newRanges[j] = style.start;
+ newRanges[j + 1] = style.length;
+ }
+ }
+ if (start > newRanges[0]) {
+ newRanges[1] = newRanges[0] + newRanges[1] - start;
+ newRanges[0] = start;
+ }
+ if (end < newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1] - 1) {
+ newRanges[newRanges.length - 1] = end - newRanges[newRanges.length - 2] + 1;
+ }
+ return newRanges;
+}
+StyleRange[] getStyleRanges(int start, int length, bool includeRanges) {
+ StyleRange[] newStyles;
+ int end = start + length - 1;
+ if (ranges !is null) {
+ int rangeCount = styleCount << 1;
+ int rangeStart = getRangeIndex(start, -1, rangeCount);
+ if (rangeStart >= rangeCount) return null;
+ if (ranges[rangeStart] > end) return null;
+ int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount) + 1);
+ newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1];
+ if (includeRanges) {
+ for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) {
+ newStyles[j] = (StyleRange)styles[i >> 1].clone();
+ newStyles[j].start = ranges[i];
+ newStyles[j].length = ranges[i + 1];
+ }
+ } else {
+ System.arraycopy(styles, rangeStart >> 1, newStyles, 0, newStyles.length);
+ }
+ } else {
+ int rangeStart = getRangeIndex(start, -1, styleCount);
+ if (rangeStart >= styleCount) return null;
+ if (styles[rangeStart].start > end) return null;
+ int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
+ newStyles = new StyleRange[rangeEnd - rangeStart + 1];
+ System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length);
+ }
+ StyleRange style = newStyles[0];
+ if (start > style.start) {
+ if (!includeRanges || ranges is null) newStyles[0] = style = (StyleRange)style.clone();
+ style.length = style.start + style.length - start;
+ style.start = start;
+ }
+ style = newStyles[newStyles.length - 1];
+ if (end < style.start + style.length - 1) {
+ if (end < style.start) {
+ StyleRange[] tmp = new StyleRange[newStyles.length - 1];
+ System.arraycopy(newStyles, 0, tmp, 0, newStyles.length - 1);
+ newStyles = tmp;
+ } else {
+ if (!includeRanges || ranges is null) newStyles[newStyles.length - 1] = style = (StyleRange)style.clone();
+ style.length = end - style.start + 1;
+ }
+ }
+ return newStyles;
+}
+StyleRange getStyleRange(StyleRange style) {
+ if (style.start is 0 && style.length is 0 && style.fontStyle is DWT.NORMAL) return style;
+ StyleRange clone = (StyleRange)style.clone();
+ clone.start = clone.length = 0;
+ clone.fontStyle = DWT.NORMAL;
+ if (clone.font is null) clone.font = getFont(style.fontStyle);
+ return clone;
+}
+TextLayout getTextLayout(int lineIndex) {
+ return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing);
+}
+TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) {
+ TextLayout layout = null;
+ if (styledText !is null) {
+ int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0;
+ if (layouts is null || topIndex !is this.topIndex) {
+ TextLayout[] newLayouts = new TextLayout[CACHE_SIZE];
+ if (layouts !is null) {
+ for (int i = 0; i < layouts.length; i++) {
+ if (layouts[i] !is null) {
+ int layoutIndex = (i + this.topIndex) - topIndex;
+ if (0 <= layoutIndex && layoutIndex < newLayouts.length) {
+ newLayouts[layoutIndex] = layouts[i];
+ } else {
+ layouts[i].dispose();
+ }
+ }
+ }
+ }
+ if (bullets !is null && bulletsIndices !is null && topIndex !is this.topIndex) {
+ int delta = topIndex - this.topIndex;
+ if (delta > 0) {
+ if (delta < bullets.length) {
+ System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta);
+ System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta);
+ }
+ int startIndex = Math.max(0, bullets.length - delta);
+ for (int i = startIndex; i < bullets.length; i++) bullets[i] = null;
+ } else {
+ if (-delta < bullets.length) {
+ System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta);
+ System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta);
+ }
+ int endIndex = Math.min(bullets.length, -delta);
+ for (int i = 0; i < endIndex; i++) bullets[i] = null;
+ }
+ }
+ this.topIndex = topIndex;
+ layouts = newLayouts;
+ }
+ if (layouts !is null) {
+ int layoutIndex = lineIndex - topIndex;
+ if (0 <= layoutIndex && layoutIndex < layouts.length) {
+ layout = layouts[layoutIndex];
+ if (layout !is null) {
+ if (lineWidth[lineIndex] !is -1) return layout;
+ } else {
+ layout = layouts[layoutIndex] = new TextLayout(device);
+ }
+ }
+ }
+ }
+ if (layout is null) layout = new TextLayout(device);
+ String line = content.getLine(lineIndex);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ int[] segments = null;
+ int indent = 0;
+ int alignment = DWT.LEFT;
+ bool justify = false;
+ Bullet bullet = null;
+ int[] ranges = null;
+ StyleRange[] styles = null;
+ int rangeStart = 0, styleCount = 0;
+ StyledTextEvent event = null;
+ if (styledText !is null) {
+ event = styledText.getLineStyleData(lineOffset, line);
+ segments = styledText.getBidiSegments(lineOffset, line);
+ indent = styledText.indent;
+ alignment = styledText.alignment;
+ justify = styledText.justify;
+ }
+ if (event !is null) {
+ indent = event.indent;
+ alignment = event.alignment;
+ justify = event.justify;
+ bullet = event.bullet;
+ ranges = event.ranges;
+ styles = event.styles;
+ if (styles !is null) {
+ styleCount = styles.length;
+ if (styledText.isFixedLineHeight()) {
+ for (int i = 0; i < styleCount; i++) {
+ if (styles[i].isVariableHeight()) {
+ styledText.verticalScrollOffset = -1;
+ styledText.setVariableLineHeight();
+ styledText.redraw();
+ break;
+ }
+ }
+ }
+ }
+ if (bullets is null || bulletsIndices is null) {
+ bullets = new Bullet[CACHE_SIZE];
+ bulletsIndices = new int[CACHE_SIZE];
+ }
+ int index = lineIndex - topIndex;
+ if (0 <= index && index < CACHE_SIZE) {
+ bullets[index] = bullet;
+ bulletsIndices[index] = event.bulletIndex;
+ }
+ } else {
+ if (lines !is null) {
+ LineInfo info = lines[lineIndex];
+ if (info !is null) {
+ if ((info.flags & INDENT) !is 0) indent = info.indent;
+ if ((info.flags & ALIGNMENT) !is 0) alignment = info.alignment;
+ if ((info.flags & JUSTIFY) !is 0) justify = info.justify;
+ if ((info.flags & SEGMENTS) !is 0) segments = info.segments;
+ }
+ }
+ if (bulletsIndices !is null) {
+ bullets = null;
+ bulletsIndices = null;
+ }
+ if (bullets !is null) {
+ for (int i = 0; i < bullets.length; i++) {
+ if (bullets[i].indexOf(lineIndex) !is -1) {
+ bullet = bullets[i];
+ break;
+ }
+ }
+ }
+ ranges = this.ranges;
+ styles = this.styles;
+ styleCount = this.styleCount;
+ if (ranges !is null) {
+ rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1);
+ } else {
+ rangeStart = getRangeIndex(lineOffset, -1, styleCount);
+ }
+ }
+ if (bullet !is null) {
+ StyleRange style = bullet.style;
+ GlyphMetrics metrics = style.metrics;
+ indent += metrics.width;
+ }
+ layout.setFont(regularFont);
+ layout.setAscent(ascent);
+ layout.setDescent(descent);
+ layout.setText(line);
+ layout.setOrientation(orientation);
+ layout.setSegments(segments);
+ layout.setWidth(width);
+ layout.setSpacing(lineSpacing);
+ layout.setTabs(new int[]{tabWidth});
+ layout.setIndent(indent);
+ layout.setAlignment(alignment);
+ layout.setJustify(justify);
+
+ int lastOffset = 0;
+ int length = line.length();
+ if (styles !is null) {
+ if (ranges !is null) {
+ int rangeCount = styleCount << 1;
+ for (int i = rangeStart; i < rangeCount; i += 2) {
+ int start, end;
+ if (lineOffset > ranges[i]) {
+ start = 0;
+ end = Math.min (length, ranges[i + 1] - lineOffset + ranges[i]);
+ } else {
+ start = ranges[i] - lineOffset;
+ end = Math.min(length, start + ranges[i + 1]);
+ }
+ if (start >= length) break;
+ if (lastOffset < start) {
+ layout.setStyle(null, lastOffset, start - 1);
+ }
+ layout.setStyle(getStyleRange(styles[i >> 1]), start, end);
+ lastOffset = Math.max(lastOffset, end);
+ }
+ } else {
+ for (int i = rangeStart; i < styleCount; i++) {
+ int start, end;
+ if (lineOffset > styles[i].start) {
+ start = 0;
+ end = Math.min (length, styles[i].length - lineOffset + styles[i].start);
+ } else {
+ start = styles[i].start - lineOffset;
+ end = Math.min(length, start + styles[i].length);
+ }
+ if (start >= length) break;
+ if (lastOffset < start) {
+ layout.setStyle(null, lastOffset, start - 1);
+ }
+ layout.setStyle(getStyleRange(styles[i]), start, end);
+ lastOffset = Math.max(lastOffset, end);
+ }
+ }
+ }
+ if (lastOffset < length) layout.setStyle(null, lastOffset, length);
+ if (styledText !is null && styledText.ime !is null) {
+ IME ime = styledText.ime;
+ int compositionOffset = ime.getCompositionOffset();
+ if (compositionOffset !is -1) {
+ int commitCount = ime.getCommitCount();
+ int compositionLength = ime.getText().length();
+ if (compositionLength !is commitCount) {
+ int compositionLine = content.getLineAtOffset(compositionOffset);
+ if (compositionLine is lineIndex) {
+ int[] imeRanges = ime.getRanges();
+ TextStyle[] imeStyles = ime.getStyles();
+ if (imeRanges.length > 0) {
+ for (int i = 0; i < imeStyles.length; i++) {
+ int start = imeRanges[i*2] - lineOffset;
+ int end = imeRanges[i*2+1] - lineOffset;
+ TextStyle imeStyle = imeStyles[i], userStyle;
+ for (int j = start; j <= end; j++) {
+ userStyle = layout.getStyle(j);
+ if (userStyle is null && j > 0) userStyle = layout.getStyle(j - 1);
+ if (userStyle is null && j + 1 < length) userStyle = layout.getStyle(j + 1);
+ if (userStyle is null) {
+ layout.setStyle(imeStyle, j, j);
+ } else {
+ TextStyle newStyle = new TextStyle(imeStyle);
+ if (newStyle.font is null) newStyle.font = userStyle.font;
+ if (newStyle.foreground is null) newStyle.foreground = userStyle.foreground;
+ if (newStyle.background is null) newStyle.background = userStyle.background;
+ layout.setStyle(newStyle, j, j);
+ }
+ }
+ }
+ } else {
+ int start = compositionOffset - lineOffset;
+ int end = start + compositionLength - 1;
+ TextStyle userStyle = layout.getStyle(start);
+ if (userStyle is null) {
+ if (start > 0) userStyle = layout.getStyle(start - 1);
+ if (userStyle is null && end + 1 < length) userStyle = layout.getStyle(end + 1);
+ if (userStyle !is null) {
+ TextStyle newStyle = new TextStyle();
+ newStyle.font = userStyle.font;
+ newStyle.foreground = userStyle.foreground;
+ newStyle.background = userStyle.background;
+ layout.setStyle(newStyle, start, end);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (styledText !is null && styledText.isFixedLineHeight()) {
+ int index = -1;
+ int lineCount = layout.getLineCount();
+ int height = getLineHeight();
+ for (int i = 0; i < lineCount; i++) {
+ int lineHeight = layout.getLineBounds(i).height;
+ if (lineHeight > height) {
+ height = lineHeight;
+ index = i;
+ }
+ }
+ if (index !is -1) {
+ FontMetrics metrics = layout.getLineMetrics(index);
+ ascent = metrics.getAscent() + metrics.getLeading();
+ descent = metrics.getDescent();
+ if (layouts !is null) {
+ for (int i = 0; i < layouts.length; i++) {
+ if (layouts[i] !is null && layouts[i] !is layout) {
+ layouts[i].setAscent(ascent);
+ layouts[i].setDescent(descent);
+ }
+ }
+ }
+ if (styledText.verticalScrollOffset !is 0) {
+ int topIndex = styledText.topIndex;
+ int topIndexY = styledText.topIndexY;
+ int lineHeight = getLineHeight();
+ if (topIndexY >= 0) {
+ styledText.verticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY;
+ } else {
+ styledText.verticalScrollOffset = topIndex * lineHeight - topIndexY;
+ }
+ }
+ styledText.calculateScrollBars();
+ if (styledText.isBidiCaret()) styledText.createCaretBitmaps();
+ styledText.caretDirection = DWT.NULL;
+ styledText.setCaretLocation();
+ styledText.redraw();
+ }
+ }
+ return layout;
+}
+int getWidth() {
+ return maxWidth;
+}
+void reset() {
+ if (layouts !is null) {
+ for (int i = 0; i < layouts.length; i++) {
+ TextLayout layout = layouts[i];
+ if (layout !is null) layout.dispose();
+ }
+ layouts = null;
+ }
+ topIndex = -1;
+ stylesSetCount = styleCount = lineCount = 0;
+ ranges = null;
+ styles = null;
+ stylesSet = null;
+ lines = null;
+ lineWidth = null;
+ lineHeight = null;
+ bullets = null;
+ bulletsIndices = null;
+ redrawLines = null;
+}
+void reset(int startLine, int lineCount) {
+ int endLine = startLine + lineCount;
+ if (startLine < 0 || endLine > lineWidth.length) return;
+ for (int i = startLine; i < endLine; i++) {
+ lineWidth[i] = -1;
+ lineHeight[i] = -1;
+ }
+ if (startLine <= maxWidthLineIndex && maxWidthLineIndex < endLine) {
+ maxWidth = 0;
+ maxWidthLineIndex = -1;
+ if (lineCount !is this.lineCount) {
+ for (int i = 0; i < this.lineCount; i++) {
+ if (lineWidth[i] > maxWidth) {
+ maxWidth = lineWidth[i];
+ maxWidthLineIndex = i;
+ }
+ }
+ }
+ }
+}
+void setContent(StyledTextContent content) {
+ reset();
+ this.content = content;
+ lineCount = content.getLineCount();
+ lineWidth = new int[lineCount];
+ lineHeight = new int[lineCount];
+ reset(0, lineCount);
+}
+void setFont(Font font, int tabs) {
+ TextLayout layout = new TextLayout(device);
+ layout.setFont(regularFont);
+ if (font !is null) {
+ if (boldFont !is null) boldFont.dispose();
+ if (italicFont !is null) italicFont.dispose();
+ if (boldItalicFont !is null) boldItalicFont.dispose();
+ boldFont = italicFont = boldItalicFont = null;
+ regularFont = font;
+ layout.setText(" ");
+ layout.setFont(font);
+ layout.setStyle(new TextStyle(getFont(DWT.NORMAL), null, null), 0, 0);
+ layout.setStyle(new TextStyle(getFont(DWT.BOLD), null, null), 1, 1);
+ layout.setStyle(new TextStyle(getFont(DWT.ITALIC), null, null), 2, 2);
+ layout.setStyle(new TextStyle(getFont(DWT.BOLD | DWT.ITALIC), null, null), 3, 3);
+ FontMetrics metrics = layout.getLineMetrics(0);
+ ascent = metrics.getAscent() + metrics.getLeading();
+ descent = metrics.getDescent();
+ boldFont.dispose();
+ italicFont.dispose();
+ boldItalicFont.dispose();
+ boldFont = italicFont = boldItalicFont = null;
+ }
+ layout.dispose();
+ layout = new TextLayout(device);
+ layout.setFont(regularFont);
+ StringBuffer tabBuffer = new StringBuffer(tabs);
+ for (int i = 0; i < tabs; i++) {
+ tabBuffer.append(' ');
+ }
+ layout.setText(tabBuffer.toString());
+ tabWidth = layout.getBounds().width;
+ layout.dispose();
+ if (styledText !is null) {
+ GC gc = new GC(styledText);
+ averageCharWidth = gc.getFontMetrics().getAverageCharWidth();
+ gc.dispose();
+ }
+}
+void setLineAlignment(int startLine, int count, int alignment) {
+ if (lines is null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] is null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= ALIGNMENT;
+ lines[i].alignment = alignment;
+ }
+}
+void setLineBackground(int startLine, int count, Color background) {
+ if (lines is null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] is null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= BACKGROUND;
+ lines[i].background = background;
+ }
+}
+void setLineBullet(int startLine, int count, Bullet bullet) {
+ if (bulletsIndices !is null) {
+ bulletsIndices = null;
+ bullets = null;
+ }
+ if (bullets is null) {
+ if (bullet is null) return;
+ bullets = new Bullet[1];
+ bullets[0] = bullet;
+ }
+ int index = 0;
+ while (index < bullets.length) {
+ if (bullet is bullets[index]) break;
+ index++;
+ }
+ if (bullet !is null) {
+ if (index is bullets.length) {
+ Bullet[] newBulletsList = new Bullet[bullets.length + 1];
+ System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length);
+ newBulletsList[index] = bullet;
+ bullets = newBulletsList;
+ }
+ bullet.addIndices(startLine, count);
+ } else {
+ updateBullets(startLine, count, 0, false);
+ styledText.redrawLinesBullet(redrawLines);
+ redrawLines = null;
+ }
+}
+void setLineIndent(int startLine, int count, int indent) {
+ if (lines is null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] is null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= INDENT;
+ lines[i].indent = indent;
+ }
+}
+void setLineJustify(int startLine, int count, bool justify) {
+ if (lines is null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] is null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= JUSTIFY;
+ lines[i].justify = justify;
+ }
+}
+void setLineSegments(int startLine, int count, int[] segments) {
+ if (lines is null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] is null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= SEGMENTS;
+ lines[i].segments = segments;
+ }
+}
+void setStyleRanges (int[] newRanges, StyleRange[] newStyles) {
+ if (newStyles is null) {
+ stylesSetCount = styleCount = 0;
+ ranges = null;
+ styles = null;
+ stylesSet = null;
+ return;
+ }
+ if (newRanges is null && COMPACT_STYLES) {
+ newRanges = new int[newStyles.length << 1];
+ StyleRange[] tmpStyles = new StyleRange[newStyles.length];
+ if (stylesSet is null) stylesSet = new StyleRange[4];
+ for (int i = 0, j = 0; i < newStyles.length; i++) {
+ StyleRange newStyle = newStyles[i];
+ newRanges[j++] = newStyle.start;
+ newRanges[j++] = newStyle.length;
+ int index = 0;
+ while (index < stylesSetCount) {
+ if (stylesSet[index].similarTo(newStyle)) break;
+ index++;
+ }
+ if (index is stylesSetCount) {
+ if (stylesSetCount is stylesSet.length) {
+ StyleRange[] tmpStylesSet = new StyleRange[stylesSetCount + 4];
+ System.arraycopy(stylesSet, 0, tmpStylesSet, 0, stylesSetCount);
+ stylesSet = tmpStylesSet;
+ }
+ stylesSet[stylesSetCount++] = newStyle;
+ }
+ tmpStyles[i] = stylesSet[index];
+ }
+ newStyles = tmpStyles;
+ }
+
+ if (styleCount is 0) {
+ if (newRanges !is null) {
+ ranges = new int[newRanges.length];
+ System.arraycopy(newRanges, 0, ranges, 0, ranges.length);
+ }
+ styles = new StyleRange[newStyles.length];
+ System.arraycopy(newStyles, 0, styles, 0, styles.length);
+ styleCount = newStyles.length;
+ return;
+ }
+ if (newRanges !is null && ranges is null) {
+ ranges = new int[styles.length << 1];
+ for (int i = 0, j = 0; i < styleCount; i++) {
+ ranges[j++] = styles[i].start;
+ ranges[j++] = styles[i].length;
+ }
+ }
+ if (newRanges is null && ranges !is null) {
+ newRanges = new int[newStyles.length << 1];
+ for (int i = 0, j = 0; i < newStyles.length; i++) {
+ newRanges[j++] = newStyles[i].start;
+ newRanges[j++] = newStyles[i].length;
+ }
+ }
+ if (ranges !is null) {
+ int rangeCount = styleCount << 1;
+ int start = newRanges[0];
+ int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd;
+ bool insert = modifyStart is rangeCount;
+ if (!insert) {
+ int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1];
+ modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+ insert = modifyStart is modifyEnd && ranges[modifyStart] >= end;
+ }
+ if (insert) {
+ addMerge(newRanges, newStyles, newRanges.length, modifyStart, modifyStart);
+ return;
+ }
+ modifyEnd = modifyStart;
+ int[] mergeRanges = new int[6];
+ StyleRange[] mergeStyles = new StyleRange[3];
+ for (int i = 0; i < newRanges.length; i += 2) {
+ int newStart = newRanges[i];
+ int newEnd = newStart + newRanges[i + 1];
+ if (newStart is newEnd) continue;
+ int modifyLast = 0, mergeCount = 0;
+ while (modifyEnd < rangeCount) {
+ if (newStart >= ranges[modifyStart] + ranges[modifyStart + 1]) modifyStart += 2;
+ if (ranges[modifyEnd] + ranges[modifyEnd + 1] > newEnd) break;
+ modifyEnd += 2;
+ }
+ if (ranges[modifyStart] < newStart && newStart < ranges[modifyStart] + ranges[modifyStart + 1]) {
+ mergeStyles[mergeCount >> 1] = styles[modifyStart >> 1];
+ mergeRanges[mergeCount] = ranges[modifyStart];
+ mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart];
+ mergeCount += 2;
+ }
+ mergeStyles[mergeCount >> 1] = newStyles[i >> 1];
+ mergeRanges[mergeCount] = newStart;
+ mergeRanges[mergeCount + 1] = newRanges[i + 1];
+ mergeCount += 2;
+ if (modifyEnd < rangeCount && ranges[modifyEnd] < newEnd && newEnd < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+ mergeStyles[mergeCount >> 1] = styles[modifyEnd >> 1];
+ mergeRanges[mergeCount] = newEnd;
+ mergeRanges[mergeCount + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - newEnd;
+ mergeCount += 2;
+ modifyLast = 2;
+ }
+ int grow = addMerge(mergeRanges, mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
+ rangeCount += grow;
+ modifyStart = modifyEnd += grow;
+ }
+ } else {
+ int start = newStyles[0].start;
+ int modifyStart = getRangeIndex(start, -1, styleCount), modifyEnd;
+ bool insert = modifyStart is styleCount;
+ if (!insert) {
+ int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length;
+ modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+ insert = modifyStart is modifyEnd && styles[modifyStart].start >= end;
+ }
+ if (insert) {
+ addMerge(newStyles, newStyles.length, modifyStart, modifyStart);
+ return;
+ }
+ modifyEnd = modifyStart;
+ StyleRange[] mergeStyles = new StyleRange[3];
+ for (int i = 0; i < newStyles.length; i++) {
+ StyleRange newStyle = newStyles[i], style;
+ int newStart = newStyle.start;
+ int newEnd = newStart + newStyle.length;
+ if (newStart is newEnd) continue;
+ int modifyLast = 0, mergeCount = 0;
+ while (modifyEnd < styleCount) {
+ if (newStart >= styles[modifyStart].start + styles[modifyStart].length) modifyStart++;
+ if (styles[modifyEnd].start + styles[modifyEnd].length > newEnd) break;
+ modifyEnd++;
+ }
+ style = styles[modifyStart];
+ if (style.start < newStart && newStart < style.start + style.length) {
+ style = mergeStyles[mergeCount++] = (StyleRange)style.clone();
+ style.length = newStart - style.start;
+ }
+ mergeStyles[mergeCount++] = newStyle;
+ if (modifyEnd < styleCount) {
+ style = styles[modifyEnd];
+ if (style.start < newEnd && newEnd < style.start + style.length) {
+ style = mergeStyles[mergeCount++] = (StyleRange)style.clone();
+ style.length += style.start - newEnd;
+ style.start = newEnd;
+ modifyLast = 1;
+ }
+ }
+ int grow = addMerge(mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
+ modifyStart = modifyEnd += grow;
+ }
+ }
+}
+void textChanging(TextChangingEvent event) {
+ int start = event.start;
+ int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount;
+ int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount;
+
+ updateRanges(start, replaceCharCount, newCharCount);
+
+ int startLine = content.getLineAtOffset(start);
+ if (replaceCharCount is content.getCharCount()) lines = null;
+ if (replaceLineCount is lineCount) {
+ lineCount = newLineCount;
+ lineWidth = new int[lineCount];
+ lineHeight = new int[lineCount];
+ reset(0, lineCount);
+ } else {
+ int delta = newLineCount - replaceLineCount;
+ if (lineCount + delta > lineWidth.length) {
+ int[] newWidths = new int[lineCount + delta + GROW];
+ System.arraycopy(lineWidth, 0, newWidths, 0, lineCount);
+ lineWidth = newWidths;
+ int[] newHeights = new int[lineCount + delta + GROW];
+ System.arraycopy(lineHeight, 0, newHeights, 0, lineCount);
+ lineHeight = newHeights;
+ }
+ if (lines !is null) {
+ if (lineCount + delta > lines.length) {
+ LineInfo[] newLines = new LineInfo[lineCount + delta + GROW];
+ System.arraycopy(lines, 0, newLines, 0, lineCount);
+ lines = newLines;
+ }
+ }
+ int startIndex = startLine + replaceLineCount + 1;
+ int endIndex = startLine + newLineCount + 1;
+ System.arraycopy(lineWidth, startIndex, lineWidth, endIndex, lineCount - startIndex);
+ System.arraycopy(lineHeight, startIndex, lineHeight, endIndex, lineCount - startIndex);
+ for (int i = startLine; i < endIndex; i++) {
+ lineWidth[i] = lineHeight[i] = -1;
+ }
+ for (int i = lineCount + delta; i < lineCount; i++) {
+ lineWidth[i] = lineHeight[i] = -1;
+ }
+ if (layouts !is null) {
+ int layoutStartLine = startLine - topIndex;
+ int layoutEndLine = layoutStartLine + replaceLineCount + 1;
+ for (int i = layoutStartLine; i < layoutEndLine; i++) {
+ if (0 <= i && i < layouts.length) {
+ if (layouts[i] !is null) layouts[i].dispose();
+ layouts[i] = null;
+ if (bullets !is null && bulletsIndices !is null) bullets[i] = null;
+ }
+ }
+ if (delta > 0) {
+ for (int i = layouts.length - 1; i >= layoutEndLine; i--) {
+ if (0 <= i && i < layouts.length) {
+ endIndex = i + delta;
+ if (0 <= endIndex && endIndex < layouts.length) {
+ layouts[endIndex] = layouts[i];
+ layouts[i] = null;
+ if (bullets !is null && bulletsIndices !is null) {
+ bullets[endIndex] = bullets[i];
+ bulletsIndices[endIndex] = bulletsIndices[i];
+ bullets[i] = null;
+ }
+ } else {
+ if (layouts[i] !is null) layouts[i].dispose();
+ layouts[i] = null;
+ if (bullets !is null && bulletsIndices !is null) bullets[i] = null;
+ }
+ }
+ }
+ } else if (delta < 0) {
+ for (int i = layoutEndLine; i < layouts.length; i++) {
+ if (0 <= i && i < layouts.length) {
+ endIndex = i + delta;
+ if (0 <= endIndex && endIndex < layouts.length) {
+ layouts[endIndex] = layouts[i];
+ layouts[i] = null;
+ if (bullets !is null && bulletsIndices !is null) {
+ bullets[endIndex] = bullets[i];
+ bulletsIndices[endIndex] = bulletsIndices[i];
+ bullets[i] = null;
+ }
+ } else {
+ if (layouts[i] !is null) layouts[i].dispose();
+ layouts[i] = null;
+ if (bullets !is null && bulletsIndices !is null) bullets[i] = null;
+ }
+ }
+ }
+ }
+ }
+ if (replaceLineCount !is 0 || newLineCount !is 0) {
+ int startLineOffset = content.getOffsetAtLine(startLine);
+ if (startLineOffset !is start) startLine++;
+ updateBullets(startLine, replaceLineCount, newLineCount, true);
+ if (lines !is null) {
+ startIndex = startLine + replaceLineCount;
+ endIndex = startLine + newLineCount;
+ System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex);
+ for (int i = startLine; i < endIndex; i++) {
+ lines[i] = null;
+ }
+ for (int i = lineCount + delta; i < lineCount; i++) {
+ lines[i] = null;
+ }
+ }
+ }
+ lineCount += delta;
+ if (maxWidthLineIndex !is -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) {
+ maxWidth = 0;
+ maxWidthLineIndex = -1;
+ for (int i = 0; i < lineCount; i++) {
+ if (lineWidth[i] > maxWidth) {
+ maxWidth = lineWidth[i];
+ maxWidthLineIndex = i;
+ }
+ }
+ }
+ }
+}
+void updateBullets(int startLine, int replaceLineCount, int newLineCount, bool update) {
+ if (bullets is null) return;
+ if (bulletsIndices !is null) return;
+ for (int i = 0; i < bullets.length; i++) {
+ Bullet bullet = bullets[i];
+ int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update);
+ if (lines !is null) {
+ if (redrawLines is null) {
+ redrawLines = lines;
+ } else {
+ int[] newRedrawBullets = new int[redrawLines.length + lines.length];
+ System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length);
+ System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length);
+ redrawLines = newRedrawBullets;
+ }
+ }
+ }
+ int removed = 0;
+ for (int i = 0; i < bullets.length; i++) {
+ if (bullets[i].size() is 0) removed++;
+ }
+ if (removed > 0) {
+ if (removed is bullets.length) {
+ bullets = null;
+ } else {
+ Bullet[] newBulletsList = new Bullet[bullets.length - removed];
+ for (int i = 0, j = 0; i < bullets.length; i++) {
+ Bullet bullet = bullets[i];
+ if (bullet.size() > 0) newBulletsList[j++] = bullet;
+ }
+ bullets = newBulletsList;
+ }
+ }
+}
+void updateRanges(int start, int replaceCharCount, int newCharCount) {
+ if (styleCount is 0 || (replaceCharCount is 0 && newCharCount is 0)) return;
+ if (ranges !is null) {
+ int rangeCount = styleCount << 1;
+ int modifyStart = getRangeIndex(start, -1, rangeCount);
+ if (modifyStart is rangeCount) return;
+ int end = start + replaceCharCount;
+ int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+ int offset = newCharCount - replaceCharCount;
+ if (modifyStart is modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+ if (newCharCount is 0) {
+ ranges[modifyStart + 1] -= replaceCharCount;
+ modifyEnd += 2;
+ } else {
+ if (rangeCount + 2 > ranges.length) {
+ int[] newRanges = new int[ranges.length + (GROW << 1)];
+ System.arraycopy(ranges, 0, newRanges, 0, rangeCount);
+ ranges = newRanges;
+ StyleRange[] newStyles = new StyleRange[styles.length + GROW];
+ System.arraycopy(styles, 0, newStyles, 0, styleCount);
+ styles = newStyles;
+ }
+ System.arraycopy(ranges, modifyStart + 2, ranges, modifyStart + 4, rangeCount - (modifyStart + 2));
+ System.arraycopy(styles, (modifyStart + 2) >> 1, styles, (modifyStart + 4) >> 1, styleCount - ((modifyStart + 2) >> 1));
+ ranges[modifyStart + 3] = ranges[modifyStart] + ranges[modifyStart + 1] - end;
+ ranges[modifyStart + 2] = start + newCharCount;
+ ranges[modifyStart + 1] = start - ranges[modifyStart];
+ styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1];
+ rangeCount += 2;
+ styleCount++;
+ modifyEnd += 4;
+ }
+ if (offset !is 0) {
+ for (int i = modifyEnd; i < rangeCount; i += 2) {
+ ranges[i] += offset;
+ }
+ }
+ } else {
+ if (ranges[modifyStart] < start && start < ranges[modifyStart] + ranges[modifyStart + 1]) {
+ ranges[modifyStart + 1] = start - ranges[modifyStart];
+ modifyStart += 2;
+ }
+ if (modifyEnd < rangeCount && ranges[modifyEnd] < end && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+ ranges[modifyEnd + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - end;
+ ranges[modifyEnd] = end;
+ }
+ if (offset !is 0) {
+ for (int i = modifyEnd; i < rangeCount; i += 2) {
+ ranges[i] += offset;
+ }
+ }
+ System.arraycopy(ranges, modifyEnd, ranges, modifyStart, rangeCount - modifyEnd);
+ System.arraycopy(styles, modifyEnd >> 1, styles, modifyStart >> 1, styleCount - (modifyEnd >> 1));
+ styleCount -= (modifyEnd - modifyStart) >> 1;
+ }
+ } else {
+ int modifyStart = getRangeIndex(start, -1, styleCount);
+ if (modifyStart is styleCount) return;
+ int end = start + replaceCharCount;
+ int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+ int offset = newCharCount - replaceCharCount;
+ if (modifyStart is modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+ if (newCharCount is 0) {
+ styles[modifyStart].length -= replaceCharCount;
+ modifyEnd++;
+ } else {
+ if (styleCount + 1 > styles.length) {
+ StyleRange[] newStyles = new StyleRange[styles.length + GROW];
+ System.arraycopy(styles, 0, newStyles, 0, styleCount);
+ styles = newStyles;
+ }
+ System.arraycopy(styles, modifyStart + 1, styles, modifyStart + 2, styleCount - (modifyStart + 1));
+ styles[modifyStart + 1] = (StyleRange)styles[modifyStart].clone();
+ styles[modifyStart + 1].length = styles[modifyStart].start + styles[modifyStart].length - end;
+ styles[modifyStart + 1].start = start + newCharCount;
+ styles[modifyStart].length = start - styles[modifyStart].start;
+ styleCount++;
+ modifyEnd += 2;
+ }
+ if (offset !is 0) {
+ for (int i = modifyEnd; i < styleCount; i++) {
+ styles[i].start += offset;
+ }
+ }
+ } else {
+ if (styles[modifyStart].start < start && start < styles[modifyStart].start + styles[modifyStart].length) {
+ styles[modifyStart].length = start - styles[modifyStart].start;
+ modifyStart++;
+ }
+ if (modifyEnd < styleCount && styles[modifyEnd].start < end && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+ styles[modifyEnd].length = styles[modifyEnd].start + styles[modifyEnd].length - end;
+ styles[modifyEnd].start = end;
+ }
+ if (offset !is 0) {
+ for (int i = modifyEnd; i < styleCount; i++) {
+ styles[i].start += offset;
+ }
+ }
+ System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd);
+ styleCount -= modifyEnd - modifyStart;
+ }
+ }
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/TableCursor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/TableCursor.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,757 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.*;
+import dwt.graphics.*;
+import dwt.widgets.*;
+import dwt.events.*;
+
+/**
+ * A TableCursor provides a way for the user to navigate around a Table
+ * using the keyboard. It also provides a mechanism for selecting an
+ * individual cell in a table.
+ *
+ *
Here is an example of using a TableCursor to navigate to a cell and then edit it.
+ *
+ *
+ *
+ *
+ * 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, DWT.BORDER | DWT.MULTI | DWT.FULL_SELECTION);
+ * table.setLayoutData(new GridData(GridData.FILL_BOTH));
+ * TableColumn column1 = new TableColumn(table, DWT.NONE);
+ * TableColumn column2 = new TableColumn(table, DWT.NONE);
+ * TableColumn column3 = new TableColumn(table, DWT.NONE);
+ * for (int i = 0; i < 100; i++) {
+ * TableItem item = new TableItem(table, DWT.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, DWT.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, DWT.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 DWT.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 DWT.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 DWT.MOD1 ||
+ * e.keyCode is DWT.MOD2 ||
+ * (e.stateMask & DWT.MOD1) !is 0 ||
+ * (e.stateMask & DWT.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 DWT.MOD1 && (e.stateMask & DWT.MOD2) !is 0) return;
+ * if (e.keyCode is DWT.MOD2 && (e.stateMask & DWT.MOD1) !is 0) return;
+ * if (e.keyCode !is DWT.MOD1 && (e.stateMask & DWT.MOD1) !is 0) return;
+ * if (e.keyCode !is DWT.MOD2 && (e.stateMask & DWT.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();
+ * }
+ *
+ * The style value is either one of the style constants defined in
+ * class DWT
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 DWT
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 item field of the event object is valid.
+ * If the receiver has DWT.CHECK
style set and the check selection changes,
+ * the event object detail field contains the value DWT.CHECK
.
+ * widgetDefaultSelected
is typically called when an item is double-clicked.
+ *
+ * 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. + *
+ * @param color the new color (or null) + * + * @exception IllegalArgumentException Here is an example of using a TableEditor:
+*
+*/
+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 TableEditor (Table table) {
+ super(table);
+ this.table = table;
+
+ columnListener = new ControlListener() {
+ public void controlMoved(ControlEvent e){
+ layout ();
+ }
+ public void controlResized(ControlEvent e){
+ layout ();
+ }
+ };
+ timer = new Runnable () {
+ public void run() {
+ layout ();
+ }
+ };
+
+ // To be consistent with older versions of DWT, grabVertical defaults to true
+ grabVertical = true;
+}
+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 DWT.RIGHT) {
+ editorRect.x += cell.width - editorRect.width;
+ } else if (horizontalAlignment is DWT.LEFT) {
+ // do nothing - cell.x is the right answer
+ } else { // default is CENTER
+ editorRect.x += (cell.width - editorRect.width)/2;
+ }
+
+ if (verticalAlignment is DWT.BOTTOM) {
+ editorRect.y += cell.height - editorRect.height;
+ } else if (verticalAlignment is DWT.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 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();
+}
+public void setItem (TableItem item) {
+ this.item = item;
+ resize();
+}
+public 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.
+*
+*
+* final Table table = new Table(shell, DWT.FULL_SELECTION | DWT.HIDE_SELECTION);
+* TableColumn column1 = new TableColumn(table, DWT.NONE);
+* TableColumn column2 = new TableColumn(table, DWT.NONE);
+* for (int i = 0; i < 10; i++) {
+* TableItem item = new TableItem(table, DWT.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 = DWT.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, DWT.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);
+* }
+* });
+*
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 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 380af2bdd8e5 dwt/custom/TableTree.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/custom/TableTree.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,814 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.custom; + + +import dwt.*; +import dwt.events.*; +import dwt.graphics.*; +import dwt.widgets.*; + +/** + * A TableTree is a selectable user interface object + * that displays a hierarchy of items, and issues + * notification when an item is selected. + * A TableTree may be single or multi select. + *
+ * The item children that may be added to instances of this class
+ * must be of type TableTreeItem
.
+ *
+ * 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 SINGLE, and MULTI may be specified. + *
+ * + * @deprecated As of 3.1 use Tree, TreeItem and TreeColumn + */ +public class TableTree : Composite { + Table table; + TableTreeItem[] items = EMPTY_ITEMS; + Image plusImage, minusImage, sizeImage; + + /* + * TableTreeItems are not treated as children but rather as items. + * When the TableTree is disposed, all children are disposed because + * TableTree inherits this behaviour from Composite. The items + * must be disposed separately. Because TableTree is not part of + * the dwt.widgets module, the method releaseWidget can + * not be overridden (this is how items are disposed of in Table and Tree). + * Instead, the items are disposed of in response to the dispose event on the + * TableTree. The "inDispose" flag is used to distinguish between disposing + * one TableTreeItem (e.g. when removing an entry from the TableTree) and + * disposing the entire TableTree. + */ + bool inDispose = false; + + static final TableTreeItem[] EMPTY_ITEMS = new TableTreeItem [0]; + static final String[] EMPTY_TEXTS = new String [0]; + static final Image[] EMPTY_IMAGES = new Image [0]; + static final String ITEMID = "TableTreeItemID"; //$NON-NLS-1$ + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *
+ * The style value is either one of the style constants defined in
+ * class DWT
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 DWT
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 item field of the event object is valid.
+ * If the receiver has DWT.CHECK
style set and the check selection changes,
+ * the event object detail field contains the value DWT.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.
+ *
TreeListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException + * If an item is selected, it is deselected. + * If an item is not selected, it remains unselected. + * + * @exception DWTException
+ * @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 DWTException
+ * @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 DWTException
+ * 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 DWTException
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 = (TableItem)e.item; + TableTreeItem item = getItem(tableItem); + event.item = item; + + if (e.type is DWT.Selection && e.detail is DWT.CHECK && item !is null) { + event.detail = DWT.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 DWTException
+ * If the receiver is single-select, do nothing. + * + * @exception DWTException
+ * 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 DWTException
Here is an example of using a TableTreeEditor:
+*
+*
+* @deprecated As of 3.1 use TreeEditor with Tree, TreeItem and TreeColumn
+*/
+public class TableTreeEditor : ControlEditor {
+
+ 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 TableTreeEditor (TableTree tableTree) {
+ super(tableTree.getTable());
+ this.tableTree = tableTree;
+
+ treeListener = new TreeListener () {
+ final Runnable runnable = new Runnable() {
+ public void run() {
+ if (editor is null || editor.isDisposed()) return;
+ if (TableTreeEditor.this.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 ControlListener() {
+ public void controlMoved(ControlEvent e){
+ layout ();
+ }
+ public void controlResized(ControlEvent e){
+ layout ();
+ }
+ };
+
+ // To be consistent with older versions of DWT, grabVertical defaults to true
+ grabVertical = true;
+}
+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 DWT.RIGHT) {
+ editorRect.x += cell.width - editorRect.width;
+ } else if (horizontalAlignment is DWT.LEFT) {
+ // do nothing - cell.x is the right answer
+ } else { // default is CENTER
+ editorRect.x += (cell.width - editorRect.width)/2;
+ }
+
+ if (verticalAlignment is DWT.BOTTOM) {
+ editorRect.y += cell.height - editorRect.height;
+ } else if (verticalAlignment is DWT.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 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, DWT.FULL_SELECTION | DWT.HIDE_SELECTION);
+* final Table table = tableTree.getTable();
+* TableColumn column1 = new TableColumn(table, DWT.NONE);
+* TableColumn column2 = new TableColumn(table, DWT.NONE);
+* for (int i = 0; i < 10; i++) {
+* TableTreeItem item = new TableTreeItem(tableTree, DWT.NONE);
+* item.setText(0, "item " + i);
+* item.setText(1, "edit this value");
+* for (int j = 0; j < 3; j++) {
+* TableTreeItem subitem = new TableTreeItem(item, DWT.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 = DWT.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, DWT.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);
+* }
+* });
+*
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, TableTreeItem item, int column) {
+ setItem(item);
+ setColumn(column);
+ setEditor(editor);
+}
+public 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 380af2bdd8e5 dwt/custom/TableTreeItem.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/TableTreeItem.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,876 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+
+import dwt.*;
+import dwt.graphics.*;
+import dwt.widgets.*;
+
+/**
+ * A TableTreeItem is a selectable user interface object
+ * that represents an item in a hierarchy of items in a
+ * TableTree.
+ *
+ * @deprecated As of 3.1 use Tree, TreeItem and TreeColumn
+ */
+public class TableTreeItem : Item {
+ TableItem tableItem;
+ TableTree parent;
+ TableTreeItem parentItem;
+ TableTreeItem [] items = TableTree.EMPTY_ITEMS;
+ String[] texts = TableTree.EMPTY_TEXTS;
+ Image[] images = TableTree.EMPTY_IMAGES;
+ Color background;
+ Color foreground;
+ Font font;
+ bool expanded;
+ bool checked;
+ bool grayed;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a TableTree
)
+ * 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 DWT
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 DWT
style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
TableTree
,
+ * 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 DWT
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 DWT
style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
TableTreeItem
)
+ * 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 DWT
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 DWT
style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
TableTreeItem
),
+ * 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 DWT
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 DWT
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 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 DWTException
+ * - 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 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 DWTException
+ * - 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 bool getGrayed () {
+ checkWidget();
+ if (tableItem is null) return grayed;
+ return tableItem.getGrayed();
+}
+
+/**
+ * Returns true
if the receiver is expanded,
+ * and false otherwise.
+ *
+ *
+ * @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 DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public Font getFont () {
+ 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 DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ *
+ */
+public Color getForeground () {
+ checkWidget ();
+ return (foreground is null) ? parent.getForeground() : foreground;
+}
+/**
+ * Gets the first image.
+ *
+ * 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 DWTException
+ * - 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 getImage(0);
+}
+
+/**
+ * Gets the image at the specified index.
+ *
+ * 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
+ * - ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public TableTreeItem getItem (int index) {
+ checkWidget();
+ int count = items.length;
+ if (!(0 <= index && index < count)) DWT.error (DWT.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.
+ *
+ * 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
+ */
+public TableTreeItem[] getItems () {
+ //checkWidget();
+ TableTreeItem[] newItems = new TableTreeItem[items.length];
+ System.arraycopy(items, 0, newItems, 0, items.length);
+ return newItems;
+}
+
+TableTreeItem getItem(TableItem tableItem) {
+ if (tableItem is null) return null;
+ if (this.tableItem is tableItem) return this;
+ for (int i = 0; i < items.length; i++) {
+ TableTreeItem item = items[i].getItem(tableItem);
+ if (item !is null) return item;
+ }
+ return null;
+}
+
+/**
+ * Returns the receiver's parent, which must be a 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 String getText () {
+ checkWidget();
+ return getText(0);
+}
+
+/**
+ * Gets the item text at the specified index.
+ *
+ * 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(DWT.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 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
+ * - ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ *
+ */
+public void setBackground (Color color) {
+ checkWidget ();
+ if (color !is null && color.isDisposed ()) {
+ DWT.error (DWT.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 DWT.CHECK style.
+ *
+ * @param checked the new checked state of the checkbox
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setChecked (bool checked) {
+ checkWidget();
+ Table table = parent.getTable();
+ if ((table.getStyle() & DWT.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 DWT.CHECK style.
+ *
+ * @param grayed the new grayed state of the checkbox;
+ *
+ * @exception DWTException
+ * - 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 setGrayed (bool grayed) {
+ checkWidget();
+ Table table = parent.getTable();
+ if ((table.getStyle() & DWT.CHECK) is 0) return;
+ if (tableItem !is null) {
+ tableItem.setGrayed(grayed);
+ }
+ this.grayed = grayed;
+}
+
+/**
+ * Sets the expanded state.
+ *
+ * @param expanded the new expanded state.
+ *
+ * @exception DWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ * - ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ */
+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
+ * - ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void setFont (Font font){
+ checkWidget ();
+ if (font !is null && font.isDisposed ()) {
+ DWT.error (DWT.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
+ * - ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ *
+ */
+public void setForeground (Color color) {
+ checkWidget ();
+ if (color !is null && color.isDisposed ()) {
+ DWT.error (DWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (tableItem !is null) {
+ tableItem.setForeground(color);
+ }
+ foreground = color;
+}
+
+/**
+ * Sets the image at an index.
+ *
+ * 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 DWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ * - ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ */
+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.
+ *
+ * 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 DWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ * - ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ */
+public void setImage (Image image) {
+ setImage(0, image);
+}
+
+/**
+ * Sets the widget text.
+ *
+ *
+ * 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 IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception DWTException
+ * - ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ * - ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ */
+public void setText(int index, String text) {
+ checkWidget();
+ if (text is null) DWT.error (DWT.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 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 380af2bdd8e5 dwt/custom/TextChangeListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/TextChangeListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * The StyledText widget : this listener to receive
+ * notifications when changes to the model occur.
+ * It is not intended to be implemented by clients or by
+ * implementors of StyledTextContent.
+ * Clients should listen to the ModifyEvent or ExtendedModifyEvent
+ * that is sent by the StyledText widget to receive text change
+ * notifications.
+ * Implementors of StyledTextContent should call the textChanging
+ * and textChanged methods when text changes occur as described
+ * below. If the entire text is replaced the textSet method
+ * should be called instead.
+ */
+public interface TextChangeListener : DWTEventListener {
+
+/**
+ * This method is called when the content is about to be changed.
+ * Callers also need to call the textChanged method after the
+ * content change has been applied. The widget only updates the
+ * screen properly when it receives both events.
+ *
+ * @param event the text changing event. All event fields need
+ * to be set by the sender.
+ * @see TextChangingEvent
+ */
+public void textChanging(TextChangingEvent event);
+/**
+ * This method is called when the content has changed.
+ * Callers need to have called the textChanging method prior to
+ * applying the content change and calling this method. The widget
+ * only updates the screen properly when it receives both events.
+ *
+ * @param event the text changed event
+ */
+public void textChanged(TextChangedEvent event);
+/**
+ * This method is called instead of the textChanging/textChanged
+ * combination when the entire old content has been replaced
+ * (e.g., by a call to StyledTextContent.setText()).
+ *
+ * @param event the text changed event
+ */
+public void textSet(TextChangedEvent event);
+}
+
+
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/TextChangedEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/TextChangedEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.events.*;
+
+/**
+ * This event is sent by the StyledTextContent implementor when a change to
+ * the text occurs.
+ */
+public class TextChangedEvent : TypedEvent {
+
+ static final long serialVersionUID = 3258696524257835065L;
+
+/**
+ * Create the TextChangedEvent to be used by the StyledTextContent implementor.
+ *
+ *
+ * @param source the object that will be sending the TextChangedEvent,
+ * cannot be null
+ */
+public TextChangedEvent(StyledTextContent source) {
+ super(source);
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/TextChangingEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/TextChangingEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+
+import dwt.events.*;
+
+/**
+ * This event is sent by the StyledTextContent implementor when a change
+ * to the text is about to occur.
+ */
+public class TextChangingEvent : TypedEvent {
+ /**
+ * Start offset of the text that is going to be replaced
+ */
+ public int start;
+ /**
+ * Text that is going to be inserted or empty String
+ * if no text will be inserted
+ */
+ public String newText;
+ /**
+ * Length of text that is going to be replaced
+ */
+ public int replaceCharCount;
+ /**
+ * Length of text that is going to be inserted
+ */
+ public int newCharCount;
+ /**
+ * Number of lines that are going to be replaced
+ */
+ public int replaceLineCount;
+ /**
+ * Number of new lines that are going to be inserted
+ */
+ public int newLineCount;
+
+ static final long serialVersionUID = 3257290210114352439L;
+
+/**
+ * Create the TextChangedEvent to be used by the StyledTextContent implementor.
+ *
+ *
+ * @param source the object that will be sending the new TextChangingEvent,
+ * cannot be null
+ */
+public TextChangingEvent(StyledTextContent source) {
+ super(source);
+}
+TextChangingEvent(StyledTextContent source, StyledTextEvent e) {
+ super(source);
+ start = e.start;
+ replaceCharCount = e.replaceCharCount;
+ newCharCount = e.newCharCount;
+ replaceLineCount = e.replaceLineCount;
+ newLineCount = e.newLineCount;
+ newText = e.text;
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/TreeEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/TreeEditor.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+
+import dwt.*;
+import dwt.events.*;
+import dwt.graphics.*;
+import dwt.widgets.*;
+
+/**
+*
+* A TreeEditor is a manager for a Control that appears above a cell in a Tree and tracks with the
+* moving and resizing of that cell. It can be used to display a text widget above a cell
+* in a Tree so that the user can edit the contents of that cell. It can also be used to display
+* a button that can launch a dialog for modifying the contents of the associated cell.
+*
+*
Here is an example of using a TreeEditor:
+*
+* final Tree tree = new Tree(shell, DWT.BORDER);
+* for (int i = 0; i < 3; i++) {
+* TreeItem item = new TreeItem(tree, DWT.NONE);
+* item.setText("item " + i);
+* for (int j = 0; j < 3; j++) {
+* TreeItem subItem = new TreeItem(item, DWT.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 = DWT.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, DWT.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);
+* }
+* });
+*
+*/
+public class TreeEditor : ControlEditor {
+ Tree tree;
+ TreeItem item;
+ int column = 0;
+ ControlListener columnListener;
+ TreeListener treeListener;
+ Runnable timer;
+ static final int TIMEOUT = 1500;
+
+/**
+* Creates a TreeEditor for the specified Tree.
+*
+* @param tree the Tree Control above which this editor will be displayed
+*
+*/
+public TreeEditor (Tree tree) {
+ super(tree);
+ this.tree = tree;
+
+ columnListener = new ControlListener() {
+ public void controlMoved(ControlEvent e){
+ layout();
+ }
+ public void controlResized(ControlEvent e){
+ layout();
+ }
+ };
+ timer = new Runnable () {
+ public void run() {
+ layout ();
+ }
+ };
+ treeListener = new TreeListener () {
+ final Runnable runnable = new Runnable() {
+ public void run() {
+ if (editor is null || editor.isDisposed()) return;
+ if (TreeEditor.this.tree.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);
+ }
+ };
+ tree.addTreeListener(treeListener);
+
+ // To be consistent with older versions of DWT, grabVertical defaults to true
+ grabVertical = true;
+}
+
+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 DWT.RIGHT) {
+ editorRect.x += cell.width - editorRect.width;
+ } else if (horizontalAlignment is DWT.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 DWT.BOTTOM) {
+ editorRect.y += cell.height - editorRect.height;
+ } else if (verticalAlignment is DWT.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 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();
+}
+
+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.
+*
+*
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 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 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 380af2bdd8e5 dwt/custom/VerifyKeyListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/VerifyKeyListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.events.*;
+import dwt.internal.DWTEventListener;
+
+public interface VerifyKeyListener : DWTEventListener {
+/**
+ * The following event fields are used:
+ * - event.character is the character that was typed (input)
+ * - event.keyCode is the key code that was typed (input)
+ * - event.stateMask is the state of the keyboard (input)
+ * - event.doit is processed or not (output)
+ *
+ * @param event the verify event
+ * @see VerifyEvent
+ */
+public void verifyKey (VerifyEvent event);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/ViewForm.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/ViewForm.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,468 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+
+import dwt.graphics.*;
+import dwt.widgets.*;
+import dwt.*;
+
+/**
+ * Instances of this class implement a Composite that positions and sizes
+ * children and allows programmatic control of layout and border parameters.
+ * ViewForm is used in the workbench to lay out a view's label/menu/toolbar
+ * local bar.
+ *
+ * Note that although this class is a subclass of Composite
,
+ * it does not make sense to set a layout on it.
+ *
+ *
+ * - Styles:
+ * - BORDER, FLAT
+ * - Events:
+ * - (None)
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class ViewForm : 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;
+ /**
+ * 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 1.
+ */
+ public int horizontalSpacing = 1;
+ /**
+ * 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 1.
+ */
+ public int verticalSpacing = 1;
+
+ /**
+ * 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
+ */
+ public static RGB borderInsideRGB = new RGB (132, 130, 132);
+ /**
+ * 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
+ */
+ public static RGB borderMiddleRGB = new RGB (143, 141, 138);
+ /**
+ * 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
+ */
+ public static RGB borderOutsideRGB = new RGB (171, 168, 165);
+
+ // DWT widgets
+ Control topLeft;
+ Control topCenter;
+ Control topRight;
+ Control content;
+
+ // Configuration and state info
+ bool separateTopCenter = false;
+ bool showBorder = false;
+
+ int separator = -1;
+ int borderTop = 0;
+ int borderBottom = 0;
+ int borderLeft = 0;
+ int borderRight = 0;
+ int highlight = 0;
+ Point oldSize;
+
+ Color selectionBackground;
+
+ static final int OFFSCREEN = -200;
+ static final int BORDER1_COLOR = DWT.COLOR_WIDGET_NORMAL_SHADOW;
+ static final int SELECTION_BACKGROUND = DWT.COLOR_LIST_BACKGROUND;
+/**
+ * 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 DWT
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 DWT
style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception DWTException
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
+ *
+ * @see DWT#BORDER
+ * @see DWT#FLAT
+ * @see #getStyle()
+ */
+public ViewForm(Composite parent, int style) {
+ super(parent, checkStyle(style));
+ super.setLayout(new ViewFormLayout());
+
+ setBorderVisible((style & DWT.BORDER) !is 0);
+
+ Listener listener = new Listener() {
+ public void handleEvent(Event e) {
+ switch (e.type) {
+ case DWT.Dispose: onDispose(); break;
+ case DWT.Paint: onPaint(e.gc); break;
+ case DWT.Resize: onResize(); break;
+ }
+ }
+ };
+
+ int[] events = new int[] {DWT.Dispose, DWT.Paint, DWT.Resize};
+
+ for (int i = 0; i < events.length; i++) {
+ addListener(events[i], listener);
+ }
+}
+
+static int checkStyle (int style) {
+ int mask = DWT.FLAT | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
+ return style & mask | DWT.NO_REDRAW_RESIZE;
+}
+
+//protected void checkSubclass () {
+// String name = getClass().getName ();
+// String validName = ViewForm.class.getName();
+// if (!validName.opEquals(name)) {
+// DWT.error (DWT.ERROR_INVALID_SUBCLASS);
+// }
+//}
+
+public 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 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 = new int[] {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(DWT.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 DWTException
+* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+* - ERROR_INVALID_ARGUMENT - if the control is not a child of this ViewForm
+*
+*/
+public void setContent(Control content) {
+ checkWidget();
+ if (content !is null && content.getParent() !is this) {
+ DWT.error(DWT.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.
+ *
+ * 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 DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLayout (Layout layout) {
+ checkWidget();
+ 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 DWTException
+* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+* - ERROR_INVALID_ARGUMENT - if the control is not a child of this ViewForm
+*
+*/
+public void setTopCenter(Control topCenter) {
+ checkWidget();
+ if (topCenter !is null && topCenter.getParent() !is this) {
+ DWT.error(DWT.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 DWTException
+* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+* - ERROR_INVALID_ARGUMENT - if the control is not a child of this ViewForm
+*
+*/
+public void setTopLeft(Control c) {
+ checkWidget();
+ if (c !is null && c.getParent() !is this) {
+ DWT.error(DWT.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 DWTException
+* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+* - ERROR_INVALID_ARGUMENT - if the control is not a child of this ViewForm
+*
+*/
+public void setTopRight(Control c) {
+ checkWidget();
+ if (c !is null && c.getParent() !is this) {
+ DWT.error(DWT.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 DWTException
+* - 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 setBorderVisible(bool show) {
+ checkWidget();
+ if (showBorder is show) return;
+
+ showBorder = show;
+ if (showBorder) {
+ borderLeft = borderTop = borderRight = borderBottom = 1;
+ if ((getStyle() & DWT.FLAT)== 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 DWTException
+* - 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 setTopCenterSeparate(bool show) {
+ checkWidget();
+ separateTopCenter = show;
+ layout(false);
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/custom/ViewFormLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/custom/ViewFormLayout.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.custom;
+
+import dwt.*;
+import dwt.graphics.*;
+import dwt.widgets.*;
+
+/**
+ * This class provides the layout for ViewForm
+ *
+ * @see ViewForm
+ */
+class ViewFormLayout : Layout {
+
+protected Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+ ViewForm form = (ViewForm)composite;
+ Control left = form.topLeft;
+ Control center = form.topCenter;
+ Control right = form.topRight;
+ Control content = form.content;
+
+ Point leftSize = new Point(0, 0);
+ if (left !is null) {
+ leftSize = computeChildSize(left, DWT.DEFAULT, DWT.DEFAULT, flushCache);
+ }
+ Point centerSize = new Point(0, 0);
+ if (center !is null) {
+ centerSize = computeChildSize(center, DWT.DEFAULT, DWT.DEFAULT, flushCache);
+ }
+ Point rightSize = new Point(0, 0);
+ if (right !is null) {
+ rightSize = computeChildSize(right, DWT.DEFAULT, DWT.DEFAULT, flushCache);
+ }
+ Point size = new Point(0, 0);
+ // calculate width of title bar
+ if (form.separateTopCenter ||
+ (wHint !is DWT.DEFAULT && leftSize.x + centerSize.x + rightSize.x > wHint)) {
+ size.x = leftSize.x + rightSize.x;
+ if (leftSize.x > 0 && rightSize.x > 0) size.x += form.horizontalSpacing;
+ size.x = Math.max(centerSize.x, size.x);
+ size.y = Math.max(leftSize.y, rightSize.y);
+ if (center !is null){
+ size.y += centerSize.y;
+ if (left !is null ||right !is null)size.y += form.verticalSpacing;
+ }
+ } else {
+ size.x = leftSize.x + centerSize.x + rightSize.x;
+ int count = -1;
+ if (leftSize.x > 0) count++;
+ if (centerSize.x > 0) count++;
+ if (rightSize.x > 0) count++;
+ if (count > 0) size.x += count * form.horizontalSpacing;
+ size.y = Math.max(leftSize.y, Math.max(centerSize.y, rightSize.y));
+ }
+
+ if (content !is null) {
+ if (left !is null || right !is null || center !is null) size.y += 1; // allow space for a vertical separator
+ Point contentSize = new Point(0, 0);
+ contentSize = computeChildSize(content, DWT.DEFAULT, DWT.DEFAULT, flushCache);
+ size.x = Math.max (size.x, contentSize.x);
+ size.y += contentSize.y;
+ if (size.y > contentSize.y) size.y += form.verticalSpacing;
+ }
+
+ size.x += 2*form.marginWidth;
+ size.y += 2*form.marginHeight;
+
+ if (wHint !is DWT.DEFAULT) size.x = wHint;
+ if (hHint !is DWT.DEFAULT) size.y = hHint;
+
+ return size;
+}
+
+Point computeChildSize(Control control, int wHint, int hHint, bool flushCache) {
+ Object data = control.getLayoutData();
+ if (data is null || !(data instanceof CLayoutData)) {
+ data = new CLayoutData();
+ control.setLayoutData(data);
+ }
+ return ((CLayoutData)data).computeSize(control, wHint, hHint, flushCache);
+}
+
+int computeTrim(Control c) {
+ if (c instanceof Scrollable) {
+ Rectangle rect = ((Scrollable) c).computeTrim (0, 0, 0, 0);
+ return rect.width;
+ }
+ return c.getBorderWidth () * 2;
+}
+
+protected bool flushCache(Control control) {
+ Object data = control.getLayoutData();
+ if (data !is null && data instanceof CLayoutData) ((CLayoutData)data).flushCache();
+ return true;
+}
+
+protected void layout(Composite composite, bool flushCache) {
+ ViewForm form = (ViewForm)composite;
+ Control left = form.topLeft;
+ Control center = form.topCenter;
+ Control right = form.topRight;
+ Control content = form.content;
+
+ Rectangle rect = composite.getClientArea();
+
+ Point leftSize = new Point(0, 0);
+ if (left !is null && !left.isDisposed()) {
+ leftSize = computeChildSize(left, DWT.DEFAULT, DWT.DEFAULT, flushCache);
+ }
+ Point centerSize = new Point(0, 0);
+ if (center !is null && !center.isDisposed()) {
+ centerSize = computeChildSize(center, DWT.DEFAULT, DWT.DEFAULT, flushCache);
+ }
+ Point rightSize = new Point(0, 0);
+ if (right !is null && !right.isDisposed()) {
+ rightSize = computeChildSize(right, DWT.DEFAULT, DWT.DEFAULT, flushCache);
+ }
+
+ int minTopWidth = leftSize.x + centerSize.x + rightSize.x + 2*form.marginWidth + 2*form.highlight;
+ int count = -1;
+ if (leftSize.x > 0) count++;
+ if (centerSize.x > 0) count++;
+ if (rightSize.x > 0) count++;
+ if (count > 0) minTopWidth += count * form.horizontalSpacing;
+
+ int x = rect.x + rect.width - form.marginWidth - form.highlight;
+ int y = rect.y + form.marginHeight + form.highlight;
+
+ bool top = false;
+ if (form.separateTopCenter || minTopWidth > rect.width) {
+ int topHeight = Math.max(rightSize.y, leftSize.y);
+ if (right !is null && !right.isDisposed()) {
+ top = true;
+ x -= rightSize.x;
+ right.setBounds(x, y, rightSize.x, topHeight);
+ x -= form.horizontalSpacing;
+ }
+ if (left !is null && !left.isDisposed()) {
+ top = true;
+ int trim = computeTrim(left);
+ int leftW = x - rect.x - form.marginWidth - form.highlight - trim;
+ leftSize = computeChildSize(left, leftW, DWT.DEFAULT, false);
+ left.setBounds(rect.x + form.marginWidth + form.highlight, y, leftSize.x, topHeight);
+ }
+ if (top) y += topHeight + form.verticalSpacing;
+ if (center !is null && !center.isDisposed()) {
+ top = true;
+ int trim = computeTrim(center);
+ int w = rect.width - 2*form.marginWidth - 2*form.highlight - trim;
+ centerSize = computeChildSize(center, w, DWT.DEFAULT, false);
+ center.setBounds(rect.x + rect.width - form.marginWidth - form.highlight - centerSize.x, y, centerSize.x, centerSize.y);
+ y += centerSize.y + form.verticalSpacing;
+ }
+ } else {
+ int topHeight = Math.max(rightSize.y, Math.max(centerSize.y, leftSize.y));
+ if (right !is null && !right.isDisposed()) {
+ top = true;
+ x -= rightSize.x;
+ right.setBounds(x, y, rightSize.x, topHeight);
+ x -= form.horizontalSpacing;
+ }
+ if (center !is null && !center.isDisposed()) {
+ top = true;
+ x -= centerSize.x;
+ center.setBounds(x, y, centerSize.x, topHeight);
+ x -= form.horizontalSpacing;
+ }
+ if (left !is null && !left.isDisposed()) {
+ top = true;
+ Rectangle trim = left instanceof Composite ? ((Composite)left).computeTrim(0, 0, 0, 0) : new Rectangle(0, 0, 0, 0);
+ int w = x - rect.x - form.marginWidth - form.highlight - trim.width;
+ int h = topHeight - trim.height;
+ leftSize = computeChildSize(left, w, h, false);
+ left.setBounds(rect.x + form.marginWidth + form.highlight, y, leftSize.x, topHeight);
+ }
+ if (top)y += topHeight + form.verticalSpacing;
+ }
+ int oldSeperator = form.separator;
+ form.separator = -1;
+ if (content !is null && !content.isDisposed()) {
+ if (left !is null || right!= null || center !is null){
+ form.separator = y;
+ y++;
+ }
+ content.setBounds(rect.x + form.marginWidth + form.highlight, y, rect.width - 2 * form.marginWidth - 2*form.highlight, rect.y + rect.height - y - form.marginHeight - form.highlight);
+ }
+ if (oldSeperator !is -1 && form.separator !is -1) {
+ int t = Math.min(form.separator, oldSeperator);
+ int b = Math.max(form.separator, oldSeperator);
+ form.redraw(form.borderLeft, t, form.getSize().x - form.borderLeft - form.borderRight, b - t, false);
+ }
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/ByteArrayTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/ByteArrayTransfer.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+/**
+ * The class ByteArrayTransfer
provides a platform specific
+ * mechanism for converting a java byte[]
to a platform
+ * specific representation of the byte array and vice versa. See
+ * Transfer
for additional information.
+ *
+ * ByteArrayTransfer
is never used directly but is sub-classed
+ * by transfer agents that convert between data in a java format such as a
+ * String
and a platform specific byte array.
+ *
+ *
If the data you are converting does not map to a
+ * byte[]
, you should sub-class Transfer
directly
+ * and do your own mapping to a platform data type.
+ *
+ * The following snippet shows a subclass of ByteArrayTransfer that transfers
+ * data defined by the class MyType
.
+ *
+ *
+ * public class MyType {
+ * public String fileName;
+ * public long fileLength;
+ * public long lastModified;
+ * }
+ *
+ *
+ *
+ * public class MyTypeTransfer : 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};
+ * }
+ * }
+ *
+ */
+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];
+ }
+ return data;
+}
+
+public bool isSupportedType(TransferData transferData){
+ if (transferData is null) return false;
+ int[] types = getTypeIds();
+ for (int i = 0; i < types.length; i++) {
+ if (transferData.type is types[i]) return true;
+ }
+ return false;
+}
+
+/**
+ * This implementation of javaToNative
converts a java
+ * byte[]
to a platform specific representation. For additional
+ * information see Transfer#javaToNative
.
+ *
+ * @see Transfer#javaToNative
+ *
+ * @param object a java byte[]
containing the data to be converted
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+protected void javaToNative (Object object, TransferData transferData) {
+ if (!checkByteArray(object) && !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ byte[] orig = (byte[])object;
+ byte[] buffer = new byte[orig.length];
+ System.arraycopy(orig, 0, buffer, 0, orig.length);
+ transferData.data = new byte[1][];
+ transferData.data[0] = buffer;
+ transferData.result = 0;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of a byte array to a java byte[]
.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @see Transfer#nativeToJava
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java byte[]
containing the converted data if the
+ * conversion was successful; otherwise null
+ */
+protected Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.data is null) return null;
+ if (transferData.data.length is 0 || transferData.data[0].length is 0) return null;
+ return transferData.data[0];
+}
+bool checkByteArray(Object object) {
+ return (object !is null && object instanceof byte[] && ((byte[])object).length > 0);
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/Clipboard.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/Clipboard.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,567 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+import dwt.*;
+import dwt.widgets.*;
+import dwt.internal.cocoa.OS;
+
+/**
+ * The Clipboard
provides a mechanism for transferring data from one
+ * application to another or within an application.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ */
+public class Clipboard {
+
+ Display display;
+ int scrap = 0;
+
+/**
+ * Constructs a new instance of this class. Creating an instance of a Clipboard
+ * may cause system resources to be allocated depending on the platform. It is therefore
+ * mandatory that the Clipboard instance be disposed when no longer required.
+ *
+ * @param display the display on which to allocate the clipboard
+ *
+ * @exception DWTException
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ * - ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see Clipboard#dispose
+ * @see Clipboard#checkSubclass
+ */
+public Clipboard(Display display) {
+ checkSubclass ();
+ if (display is null) {
+ display = Display.getCurrent();
+ if (display is null) {
+ display = Display.getDefault();
+ }
+ }
+ if (display.getThread() !is Thread.currentThread()) {
+ DND.error(DWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ this.display = display;
+}
+
+/**
+ * Checks that this class can be subclassed.
+ *
+ * The DWT 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 DWT 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 DWT classes
+ * is intended purely to enable those not on the DWT development
+ * team to implement patches in order to get around specific
+ * limitations in advance of when those limitations can be
+ * addressed by the team. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the hierarchy.
+ *
+ *
+ * @exception DWTException
+ * - ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+protected void checkSubclass () {
+ String name = getClass().getName ();
+ String validName = Clipboard.class.getName();
+ if (!validName.opEquals(name)) {
+ DND.error (DWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+/**
+ * Throws an DWTException
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 DWT invariants.
+ *
+ * Currently, it is an error to invoke any method (other than
+ * isDisposed()
) on a widget that has had its
+ * dispose()
method called. It is also an error
+ * to call widget methods from any thread that is different
+ * from the thread that created the widget.
+ *
+ * In future releases of DWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ *
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+protected void checkWidget () {
+ Display display = this.display;
+ if (display is null) DND.error (DWT.ERROR_WIDGET_DISPOSED);
+ if (display.getThread() !is Thread.currentThread ()) DND.error (DWT.ERROR_THREAD_INVALID_ACCESS);
+ if (display.isDisposed()) DND.error(DWT.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 DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void clearContents() {
+ clearContents(DND.CLIPBOARD);
+}
+
+/**
+ * If this clipboard is currently the owner of the data on the specified
+ * clipboard, clear the contents. If this clipboard is not the owner, then
+ * nothing is done.
+ *
+ * Note that there are clipboard assistant applications that take ownership
+ * of data or make copies of data when it is placed on the clipboard. In these
+ * cases, it may not be possible to clear the clipboard.
+ *
+ * The clipboards value is either one of the clipboard constants defined in
+ * class DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ * @param clipboards to be cleared
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public void clearContents(int clipboards) {
+ checkWidget();
+ if ((clipboards & DND.CLIPBOARD) is 0 || scrap is 0) return;
+ int oldScrap = scrap;
+ scrap = 0;
+ int[] currentScrap = new int[1];
+ if (OS.GetCurrentScrap(currentScrap) !is OS.noErr) return;
+ if (currentScrap[0] is oldScrap) {
+ OS.ClearCurrentScrap();
+ }
+}
+
+/**
+ * Disposes of the operating system resources associated with the clipboard.
+ * The data will still be available on the system clipboard after the dispose
+ * method is called.
+ *
+ * NOTE: On some platforms the data will not be available once the application
+ * has exited or the display has been disposed.
+ *
+ * @exception DWTException
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
+ */
+public void dispose () {
+ if (isDisposed()) return;
+ if (display.getThread() !is Thread.currentThread()) DND.error(DWT.ERROR_THREAD_INVALID_ACCESS);
+ display = null;
+}
+
+/**
+ * Retrieve the data of the specified type currently available on the system
+ * clipboard. Refer to the specific subclass of Transfer
to
+ * determine the type of object returned.
+ *
+ * The following snippet shows text and RTF text being retrieved from the
+ * clipboard:
+ *
+ *
+ * Clipboard clipboard = new Clipboard(display);
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String textData = (String)clipboard.getContents(textTransfer);
+ * if (textData !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();
+ *
+ *
+ * @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 DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if transfer is null
+ *
+ *
+ * @see Transfer
+ */
+public Object getContents(Transfer transfer) {
+ return getContents(transfer, DND.CLIPBOARD);
+}
+
+/**
+ * Retrieve the data of the specified type currently available on the specified
+ * clipboard. Refer to the specific subclass of Transfer
to
+ * determine the type of object returned.
+ *
+ * The following snippet shows text and RTF text being retrieved from the
+ * clipboard:
+ *
+ *
+ * Clipboard clipboard = new Clipboard(display);
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String textData = (String)clipboard.getContents(textTransfer);
+ * if (textData !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();
+ *
+ *
+ * The clipboards value is either one of the clipboard constants defined in
+ * class DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ * @param transfer the transfer agent for the type of data being requested
+ * @param clipboards on which to look for data
+ *
+ * @return the data obtained from the clipboard or null if no data of this type is available
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if transfer is null
+ *
+ *
+ * @see Transfer
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public Object getContents(Transfer transfer, int clipboards) {
+ checkWidget();
+ if (transfer is null) DND.error(DWT.ERROR_NULL_ARGUMENT);
+ if ((clipboards & DND.CLIPBOARD) is 0) return null;
+ int[] scrap = new int[1];
+ if (OS.GetCurrentScrap(scrap) !is OS.noErr) return null;
+ int[] typeIds = transfer.getTypeIds();
+ int[] size = new int[1];
+ // get data from system clipboard
+ for (int i=0; i 0) {
+ byte[] buffer = new byte[size[0]];
+ if (OS.GetScrapFlavorData(scrap[0], type, size, buffer) is OS.noErr) {
+ TransferData tdata = new TransferData();
+ tdata.type = type;
+ tdata.data = new byte[1][];
+ tdata.data[0] = buffer;
+ return transfer.nativeToJava(tdata);
+ }
+ }
+ }
+ return null; // No data available for this transfer
+}
+
+/**
+ * Returns true
if the clipboard has been disposed,
+ * and false
otherwise.
+ *
+ * This method gets the dispose state for the clipboard.
+ * When a clipboard has been disposed, it is an error to
+ * invoke any other method using the clipboard.
+ *
+ *
+ * @return true
when the widget is disposed and false
otherwise
+ *
+ * @since 3.0
+ */
+public 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.
+ *
+ * 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:
+ *
+ *
+ *
+ * Clipboard clipboard = new Clipboard(display);
+ * String textData = "Hello World";
+ * String rtfData = "{\\rtf1\\b\\i Hello World}";
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer};
+ * Object[] data = new Object[]{textData, rtfData};
+ * clipboard.setContents(data, transfers);
+ * clipboard.dispose();
+ *
+ *
+ * @param data the data to be set in the clipboard
+ * @param dataTypes the transfer agents that will convert the data to its
+ * platform specific format; each entry in the data array must have a
+ * corresponding dataType
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_INVALID_ARGUMENT - if data is null or datatypes is null
+ * or the length of data is not the same as the length of dataTypes
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception DWTError
+ * - ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable
+ *
+ *
+ * NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an DWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.
+ */
+public void setContents(Object[] data, Transfer[] dataTypes) {
+ setContents(data, dataTypes, DND.CLIPBOARD);
+}
+
+/**
+ * Place data of the specified type on the specified clipboard. More than one
+ * type of data can be placed on the specified clipboard at the same time.
+ * Setting the data clears any previous data from the specified
+ * clipboard, regardless of type.
+ *
+ * NOTE: On some platforms, the data is immediately copied to the specified
+ * clipboard but on other platforms it is provided upon request. As a result,
+ * if the application 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 DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ * The following snippet shows text and RTF text being set on the copy/paste
+ * clipboard:
+ *
+ *
+ *
+ * Clipboard clipboard = new Clipboard(display);
+ * String textData = "Hello World";
+ * String rtfData = "{\\rtf1\\b\\i Hello World}";
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer};
+ * Object[] data = new Object[]{textData, rtfData};
+ * clipboard.setContents(data, transfers, DND.CLIPBOARD);
+ * clipboard.dispose();
+ *
+ *
+ * @param data the data to be set in the clipboard
+ * @param dataTypes the transfer agents that will convert the data to its
+ * platform specific format; each entry in the data array must have a
+ * corresponding dataType
+ * @param clipboards on which to set the data
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_INVALID_ARGUMENT - if data is null or datatypes is null
+ * or the length of data is not the same as the length of dataTypes
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception DWTError
+ * - ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable
+ *
+ *
+ * NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an DWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.
+ *
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public void setContents(Object[] data, Transfer[] dataTypes, int clipboards) {
+ checkWidget();
+ if (data is null || dataTypes is null || data.length !is dataTypes.length || data.length is 0) {
+ DND.error(DWT.ERROR_INVALID_ARGUMENT);
+ }
+ for (int i = 0; i < data.length; i++) {
+ if (data[i] is null || dataTypes[i] is null || !dataTypes[i].validate(data[i])) {
+ DND.error(DWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+ if ((clipboards & DND.CLIPBOARD) is 0) return;
+ if (OS.ClearCurrentScrap() !is OS.noErr) {
+ DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+ }
+ scrap = 0;
+ int[] currentScrap = new int[1];
+ if (OS.GetCurrentScrap(currentScrap) !is OS.noErr) {
+ DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+ }
+ scrap = currentScrap[0];
+ // copy data directly over to System clipboard (not deferred)
+ for (int i=0; i
+ * ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Transfer#isSupportedType
+ *
+ * @since 3.0
+ */
+public TransferData[] getAvailableTypes() {
+ return getAvailableTypes(DND.CLIPBOARD);
+}
+
+/**
+ * Returns an array of the data types currently available on the specified
+ * clipboard. Use with Transfer.isSupportedType.
+ *
+ * The clipboards value is either one of the clipboard constants defined in
+ * class DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ * @param clipboards from which to get the data types
+ * @return array of data types currently available on the specified clipboard
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Transfer#isSupportedType
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public TransferData[] getAvailableTypes(int clipboards) {
+ checkWidget();
+ if ((clipboards & DND.CLIPBOARD) is 0) return new TransferData[0];
+ int[] types = _getAvailableTypes();
+ TransferData[] result = new TransferData[types.length];
+ for (int i = 0; i < types.length; i++) {
+ result[i] = new TransferData();
+ result[i].type = types[i];
+ }
+ return result;
+}
+
+/**
+ * Returns a platform specific list of the data types currently available on the
+ * system clipboard.
+ *
+ * Note: getAvailableTypeNames
is a utility for writing a Transfer
+ * sub-class. It should NOT be used within an application because it provides
+ * platform specific information.
+ *
+ * @return a platform specific list of the data types currently available on the
+ * system clipboard
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String[] getAvailableTypeNames() {
+ checkWidget();
+ int[] types = _getAvailableTypes();
+ String[] names = new String[types.length];
+ for (int i = 0; i < types.length; i++) {
+ int type = types[i];
+ StringBuffer sb = new StringBuffer();
+ sb.append((char)((type & 0xff000000) >> 24));
+ sb.append((char)((type & 0x00ff0000) >> 16));
+ sb.append((char)((type & 0x0000ff00) >> 8));
+ sb.append((char)((type & 0x000000ff) >> 0));
+ names[i] = sb.toString();
+ }
+ return names;
+}
+
+int[] _getAvailableTypes() {
+ int[] types = new int[0];
+ int[] scrap = new int[1];
+ if (OS.GetCurrentScrap(scrap) !is OS.noErr) return types;
+ int[] count = new int[1];
+ if (OS.GetScrapFlavorCount(scrap[0], count) !is OS.noErr || count[0] is 0) return types;
+ int[] info = new int[count[0] * 2];
+ if (OS.GetScrapFlavorInfoList(scrap[0], count, info) !is OS.noErr) return types;
+ types = new int[count[0]];
+ for (int i= 0; i < count [0]; i++) {
+ types[i] = info[i*2];
+ }
+ return types;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DND.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DND.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+import dwt.*;
+
+/**
+ *
+ * Class DND contains all the constants used in defining a
+ * DragSource or a DropTarget.
+ *
+ */
+public class DND {
+
+ /**
+ * The transfer mechanism for data that is being cut
+ * and then pasted or copied and then pasted (value is 1).
+ *
+ * @see Clipboard
+ *
+ * @since 3.1
+ */
+ public final static int CLIPBOARD = 1 << 0;
+
+ /**
+ * The transfer mechanism for clients that use the selection
+ * mechanism (value is 2).
+ *
+ * @see Clipboard
+ *
+ * @since 3.1
+ */
+ public final static int SELECTION_CLIPBOARD = 1 << 1;
+
+ /**
+ * Drag and Drop Operation: no drag/drop operation performed
+ * (value is 0).
+ */
+ public final static int DROP_NONE = 0;
+
+ /**
+ * Drag and Drop Operation: a copy of the data in the drag source is
+ * added to the drop target (value is 1 << 0).
+ */
+ public final static int DROP_COPY = 1 << 0;
+
+ /**
+ * Drag and Drop Operation: a copy of the data is added to the drop target and
+ * the original data is removed from the drag source (value is 1 << 1).
+ */
+ public final static int DROP_MOVE = 1 << 1;
+
+ /**
+ * Drag and Drop Operation: the drop target makes a link to the data in
+ * the drag source (value is 1 << 2).
+ */
+ public final static int DROP_LINK = 1 << 2;
+
+ /**
+ * Drag and Drop Operation: the drop target moves the data and the drag source removes
+ * any references to the data and updates its display. This is not available on all platforms
+ * and is only used when a non-DWT application is the drop target. In this case, the DWT
+ * drag source is informed in the dragFinished event that the drop target has moved the data.
+ * (value is 1 << 3).
+ *
+ * @see DragSourceListener#dragFinished
+ */
+ public final static int DROP_TARGET_MOVE = 1 << 3;
+
+ /**
+ * Drag and Drop Operation: During a dragEnter event or a dragOperationChanged, if no modifier keys
+ * are pressed, the operation is set to DROP_DEFAULT. The application can choose what the default
+ * operation should be by setting a new value in the operation field. If no value is choosen, the
+ * default operation for the platform will be selected (value is 1 << 4).
+ *
+ * @see DropTargetListener#dragEnter
+ * @see DropTargetListener#dragOperationChanged
+ * @since 2.0
+ */
+ public final static int DROP_DEFAULT = 1 << 4;
+
+ /**
+ * DragSource Event: the drop has successfully completed or has been terminated (such as hitting
+ * the ESC key); perform cleanup such as removing data on a move operation (value is 2000).
+ */
+ public static final int DragEnd = 2000;
+
+ /**
+ * DragSource Event: the data to be dropped is required from the drag source (value is 2001).
+ */
+ public static final int DragSetData = 2001;
+
+ /**
+ * DropTarget Event: the cursor has entered the drop target boundaries (value is 2002).
+ */
+ public static final int DragEnter = 2002;
+
+ /**
+ * DropTarget Event: the cursor has left the drop target boundaries OR the drop
+ * operation has been cancelled (such as by hitting ECS) OR the drop is about to
+ * happen (user has released the mouse button over this target) (value is 2003).
+ */
+ public static final int DragLeave = 2003;
+
+ /**
+ * DropTarget Event: the cursor is over the drop target (value is 2004).
+ */
+ public static final int DragOver = 2004;
+
+ /**
+ * DropTarget Event: the operation being performed has changed usually due to the user
+ * changing the selected modifier keys while dragging (value is 2005).
+ */
+ public static final int DragOperationChanged = 2005;
+
+ /**
+ * DropTarget Event: the data has been dropped (value is 2006).
+ */
+ public static final int Drop = 2006;
+
+ /**
+ * DropTarget Event: the drop target is given a last chance to modify the drop (value is 2007).
+ */
+ public static final int DropAccept = 2007;
+
+ /**
+ * DragSource Event: a drag is about to begin (value is 2008).
+ */
+ public static final int DragStart = 2008;
+
+ /**
+ * DropTarget drag under effect: No effect is shown (value is 0).
+ */
+ public static final int FEEDBACK_NONE = 0;
+
+ /**
+ * DropTarget drag under effect: The item under the cursor is selected; applies to tables
+ * and trees (value is 1).
+ */
+ public static final int FEEDBACK_SELECT = 1;
+
+ /**
+ * DropTarget drag under effect: An insertion mark is shown before the item under the cursor; applies to
+ * trees (value is 2).
+ */
+ public static final int FEEDBACK_INSERT_BEFORE = 2;
+
+ /**
+ * DropTarget drag under effect:An insertion mark is shown after the item under the cursor; applies to
+ * trees (value is 4).
+ */
+ public static final int FEEDBACK_INSERT_AFTER = 4;
+
+ /**
+ * DropTarget drag under effect: The widget is scrolled up or down to allow the user to drop on items that
+ * are not currently visible; applies to tables and trees (value is 8).
+ */
+ public static final int FEEDBACK_SCROLL = 8;
+
+ /**
+ * DropTarget drag under effect: The item currently under the cursor is expanded to allow the user to
+ * select a drop target from a sub item; applies to trees (value is 16).
+ */
+ public static final int FEEDBACK_EXPAND = 16;
+
+ /**
+ * Error code: drag source can not be initialized (value is 2000).
+ */
+ public static final int ERROR_CANNOT_INIT_DRAG = 2000;
+
+ /**
+ * Error code: drop target cannot be initialized (value is 2001).
+ */
+ public static final int ERROR_CANNOT_INIT_DROP = 2001;
+
+ /**
+ * Error code: Data can not be set on system clipboard (value is 2002).
+ */
+ public static final int ERROR_CANNOT_SET_CLIPBOARD = 2002;
+
+ /**
+ * Error code: Data does not have correct format for type (value is 2003).
+ * @since 3.1
+ */
+ public static final int ERROR_INVALID_DATA = 2003;
+
+ /**
+ * DropTarget Key: The String constant for looking up the drop target
+ * for a control using 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 final String INIT_DRAG_MESSAGE = "Cannot initialize Drag"; //$NON-NLS-1$
+ static final String INIT_DROP_MESSAGE = "Cannot initialize Drop"; //$NON-NLS-1$
+ static final String CANNOT_SET_CLIPBOARD_MESSAGE = "Cannot set data in clipboard"; //$NON-NLS-1$
+ static final 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.
+ *
+ * In DND, errors are reported by throwing one of three exceptions:
+ *
+ * - java.lang.IllegalArgumentException
+ * - thrown whenever one of the API methods is invoked with an illegal argument
+ * - dwt.DWTException (: java.lang.RuntimeException)
+ * - thrown whenever a recoverable error happens internally in DWT
+ * - dwt.DWTError (: java.lang.Error)
+ * - thrown whenever a non-recoverable error happens internally in DWT
+ *
+ * This method provides the logic which maps between error codes
+ * and one of the above exceptions.
+ *
+ *
+ * @param code the DND error code.
+ * @param hresult the platform specific error code.
+ *
+ * @see DWTError
+ * @see DWTException
+ * @see IllegalArgumentException
+ */
+public static void error (int code, int hresult) {
+ switch (code) {
+ /* OS Failure/Limit (fatal, may occur only on some platforms) */
+ case DND.ERROR_CANNOT_INIT_DRAG:{
+ String msg = DND.INIT_DRAG_MESSAGE;
+ if (hresult !is 0) msg += " result = "+hresult; //$NON-NLS-1$
+ throw new DWTError (code, msg);
+ }
+ case DND.ERROR_CANNOT_INIT_DROP:{
+ String msg = DND.INIT_DROP_MESSAGE;
+ if (hresult !is 0) msg += " result = "+hresult; //$NON-NLS-1$
+ throw new DWTError (code, msg);
+ }
+ case DND.ERROR_CANNOT_SET_CLIPBOARD:{
+ String msg = DND.CANNOT_SET_CLIPBOARD_MESSAGE;
+ if (hresult !is 0) msg += " result = "+hresult; //$NON-NLS-1$
+ throw new DWTError (code, msg);
+ }
+ case DND.ERROR_INVALID_DATA:{
+ String msg = DND.INVALID_DATA_MESSAGE;
+ if (hresult !is 0) msg += " result = "+hresult; //$NON-NLS-1$
+ throw new DWTException (code, msg);
+ }
+ }
+
+ /* Unknown/Undefined Error */
+ DWT.error(code);
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DNDEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DNDEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+import dwt.graphics.*;
+import dwt.widgets.*;
+
+class DNDEvent : Event {
+ public TransferData dataType;
+ public TransferData[] dataTypes;
+ public int operations;
+ public int feedback;
+ public Image image;
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DNDListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DNDListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.internal.*;
+import dwt.widgets.*;
+
+
+class DNDListener : TypedListener {
+ Widget dndWidget;
+/**
+ * DNDListener constructor comment.
+ * @param listener dwt.internal.DWTEventListener
+ */
+DNDListener(DWTEventListener listener) {
+ super(listener);
+}
+public void handleEvent (Event e) {
+ switch (e.type) {
+ case DND.DragStart: {
+ DragSourceEvent event = new DragSourceEvent((DNDEvent)e);
+ DragSourceEffect sourceEffect = ((DragSource) dndWidget).getDragSourceEffect();
+ if (sourceEffect !is null) {
+ sourceEffect.dragStart (event);
+ }
+ ((DragSourceListener) eventListener).dragStart (event);
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+ case DND.DragEnd: {
+ DragSourceEvent event = new DragSourceEvent((DNDEvent)e);
+ DragSourceEffect sourceEffect = ((DragSource) dndWidget).getDragSourceEffect();
+ if (sourceEffect !is null) {
+ sourceEffect.dragFinished (event);
+ }
+ ((DragSourceListener) eventListener).dragFinished (event);
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+ case DND.DragSetData: {
+ DragSourceEvent event = new DragSourceEvent((DNDEvent)e);
+ DragSourceEffect sourceEffect = ((DragSource) dndWidget).getDragSourceEffect();
+ if (sourceEffect !is null) {
+ sourceEffect.dragSetData (event);
+ }
+ ((DragSourceListener) eventListener).dragSetData (event);
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+ case DND.DragEnter: {
+ DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+ ((DropTargetListener) eventListener).dragEnter (event);
+ DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+ if (dropEffect !is null) {
+ dropEffect.dragEnter (event);
+ }
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+ case DND.DragLeave: {
+ DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+ ((DropTargetListener) eventListener).dragLeave (event);
+ DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+ if (dropEffect !is null) {
+ dropEffect.dragLeave (event);
+ }
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+ case DND.DragOver: {
+ DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+ ((DropTargetListener) eventListener).dragOver (event);
+ DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+ if (dropEffect !is null) {
+ dropEffect.dragOver (event);
+ }
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+ case DND.Drop: {
+ DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+ ((DropTargetListener) eventListener).drop (event);
+ DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+ if (dropEffect !is null) {
+ dropEffect.drop (event);
+ }
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+ case DND.DropAccept: {
+ DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+ ((DropTargetListener) eventListener).dropAccept (event);
+ DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+ if (dropEffect !is null) {
+ dropEffect.dropAccept (event);
+ }
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+ case DND.DragOperationChanged: {
+ DropTargetEvent event = new DropTargetEvent((DNDEvent)e);
+ ((DropTargetListener) eventListener).dragOperationChanged (event);
+ DropTargetEffect dropEffect = ((DropTarget) dndWidget).getDropTargetEffect();
+ if (dropEffect !is null) {
+ dropEffect.dragOperationChanged (event);
+ }
+ event.updateEvent((DNDEvent)e);
+ break;
+ }
+
+ }
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DragSource.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DragSource.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,556 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+import dwt.*;
+import dwt.graphics.*;
+import dwt.widgets.*;
+import dwt.internal.Callback;
+import dwt.internal.cocoa.CGPoint;
+import dwt.internal.cocoa.EventRecord;
+import dwt.internal.cocoa.OS;
+import dwt.internal.cocoa.Point;
+
+/**
+ *
+ * DragSource
defines the source object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ * A drag source is the object which originates a drag and drop operation. For the specified widget,
+ * it defines the type of data that is available for dragging and the set of operations that can
+ * be performed on that data. The operations can be any bit-wise combination of DND.MOVE, DND.COPY or
+ * DND.LINK. The type of data that can be transferred is specified by subclasses of Transfer such as
+ * TextTransfer or FileTransfer. The type of data transferred can be a predefined system type or it
+ * can be a type defined by the application. For instructions on how to define your own transfer type,
+ * refer to ByteArrayTransfer
.
+ *
+ * You may have several DragSources in an application but you can only have one DragSource
+ * per Control. Data dragged from this DragSource can be dropped on a site within this application
+ * or it can be dropped on another application such as an external Text editor.
+ *
+ * The application supplies the content of the data being transferred by implementing the
+ * DragSourceListener
and associating it with the DragSource via DragSource#addDragListener.
+ *
+ * When a successful move operation occurs, the application is required to take the appropriate
+ * action to remove the data from its display and remove any associated operating system resources or
+ * internal references. Typically in a move operation, the drop target makes a copy of the data
+ * and the drag source deletes the original. However, sometimes copying the data can take a long
+ * time (such as copying a large file). Therefore, on some platforms, the drop target may actually
+ * move the data in the operating system rather than make a copy. This is usually only done in
+ * file transfers. In this case, the drag source is informed in the DragEnd event that a
+ * DROP_TARGET_MOVE was performed. It is the responsibility of the drag source at this point to clean
+ * up its displayed information. No action needs to be taken on the operating system resources.
+ *
+ * The following example shows a Label widget that allows text to be dragged from it.
+ *
+ *
+ * // Enable a label as a Drag Source
+ * Label label = new Label(shell, DWT.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("");
+ * }
+ * });
+ *
+ *
+ *
+ *
+ * - Styles
- DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ * - Events
- DND.DragStart, DND.DragSetData, DND.DragEnd
+ *
+ */
+public class DragSource : Widget {
+
+ // info for registering as a drag source
+ Control control;
+ Listener controlListener;
+ Transfer[] transferAgents = new Transfer[0];
+ DragSourceEffect dragEffect;
+
+ static final String DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; //$NON-NLS-1$
+ static Callback DragSendDataProc;
+
+ static {
+ DragSendDataProc = new Callback(DragSource.class, "DragSendDataProc", 4); //$NON-NLS-1$
+ int dragSendDataProcAddress = DragSendDataProc.getAddress();
+ if (dragSendDataProcAddress is 0) DWT.error(DWT.ERROR_NO_MORE_CALLBACKS);
+ }
+
+/**
+ * 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 DWTException
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ * - ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ * @exception DWTError
+ * - ERROR_CANNOT_INIT_DRAG - unable to initiate drag source; this will occur if more than one
+ * drag source is created for a control or if the operating system will not allow the creation
+ * of the drag source
+ *
+ *
+ * NOTE: ERROR_CANNOT_INIT_DRAG should be an DWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.
+ *
+ * @see Widget#dispose
+ * @see DragSource#checkSubclass
+ * @see DND#DROP_NONE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_LINK
+ */
+public DragSource(Control control, int style) {
+ super (control, checkStyle(style));
+ this.control = control;
+ if (control.getData(DND.DRAG_SOURCE_KEY) !is null) {
+ DND.error(DND.ERROR_CANNOT_INIT_DRAG);
+ }
+ control.setData(DND.DRAG_SOURCE_KEY, this);
+
+ controlListener = new Listener () {
+ public void handleEvent (Event event) {
+ if (event.type is DWT.Dispose) {
+ if (!DragSource.this.isDisposed()) {
+ DragSource.this.dispose();
+ }
+ }
+ if (event.type is DWT.DragDetect) {
+ if (!DragSource.this.isDisposed()) {
+ DragSource.this.drag(event);
+ }
+ }
+ }
+ };
+ control.addListener (DWT.Dispose, controlListener);
+ control.addListener (DWT.DragDetect, controlListener);
+
+ this.addListener(DWT.Dispose, new Listener() {
+ public void handleEvent(Event e) {
+ onDispose();
+ }
+ });
+
+ Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT);
+ if (effect instanceof DragSourceEffect) {
+ dragEffect = (DragSourceEffect) effect;
+ } else if (control instanceof Tree) {
+ dragEffect = new TreeDragSourceEffect((Tree) control);
+ } else if (control instanceof Table) {
+ dragEffect = new TableDragSourceEffect((Table) control);
+ }
+}
+
+static int checkStyle (int style) {
+ if (style is DWT.NONE) return DND.DROP_MOVE;
+ return style;
+}
+
+static int DragSendDataProc(int theType, int dragSendRefCon, int theItemRef, int theDrag) {
+ DragSource source = FindDragSource(dragSendRefCon, theDrag);
+ if (source is null) return OS.cantGetFlavorErr;
+ return source.dragSendDataProc(theType, dragSendRefCon, theItemRef, theDrag);
+}
+
+static DragSource FindDragSource(int dragSendRefCon, int theDrag) {
+ if (dragSendRefCon is 0) return null;
+ Display display = Display.findDisplay(Thread.currentThread());
+ if (display is null || display.isDisposed()) return null;
+ Widget widget = display.findWidget(dragSendRefCon);
+ if (widget is null) return null;
+ return (DragSource)widget.getData(DND.DRAG_SOURCE_KEY);
+}
+
+/**
+ * Adds the listener to the collection 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.
+ *
+ *
+ * dragStart
is called when the user has begun the actions required to drag the widget.
+ * This event gives the application the chance to decide if a drag should be started.
+ * dragSetData
is called when the data is required from the drag source.
+ * dragFinished
is called when the drop has successfully completed (mouse up
+ * over a valid target) or has been terminated (such as hitting the ESC key). Perform cleanup
+ * such as removing data from the source side on a successful move operation.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DragSourceListener
+ * @see #removeDragListener
+ * @see DragSourceEvent
+ */
+public void addDragListener(DragSourceListener listener) {
+ if (listener is null) DND.error (DWT.ERROR_NULL_ARGUMENT);
+ DNDListener typedListener = new DNDListener (listener);
+ typedListener.dndWidget = this;
+ addListener (DND.DragStart, typedListener);
+ addListener (DND.DragSetData, typedListener);
+ addListener (DND.DragEnd, typedListener);
+}
+
+protected void checkSubclass () {
+ String name = getClass().getName ();
+ String validName = DragSource.class.getName();
+ if (!validName.opEquals(name)) {
+ DND.error (DWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+
+void drag(Event dragEvent) {
+ DNDEvent event = new DNDEvent();
+ event.widget = this;
+ event.x = dragEvent.x;
+ event.y = dragEvent.y;
+ event.time = dragEvent.time;
+ event.doit = true;
+ notifyListeners(DND.DragStart, event);
+ if (!event.doit || transferAgents is null || transferAgents.length is 0) return;
+
+ int[] theDrag = new int[1];
+ if (OS.NewDrag(theDrag) !is OS.noErr) {
+ event = new DNDEvent();
+ event.widget = this;
+ event.time = (int)System.currentTimeMillis();
+ event.doit = false;
+ event.detail = DND.DROP_NONE;
+ notifyListeners(DND.DragEnd, event);
+ return;
+ }
+
+ Point pt = new Point();
+ OS.GetGlobalMouse (pt);
+
+ for (int i = 0; i < transferAgents.length; i++) {
+ Transfer transfer = transferAgents[i];
+ if (transfer !is null) {
+ int[] types = transfer.getTypeIds();
+ if (transfer instanceof FileTransfer) {
+ TransferData transferData = new TransferData();
+ transferData.type = types[0];
+ DNDEvent event2 = new DNDEvent();
+ event2.widget = this;
+ event2.time = (int)System.currentTimeMillis();
+ event2.dataType = transferData;
+ notifyListeners(DND.DragSetData, event2);
+ if (event2.data !is null) {
+ for (int j = 0; j < types.length; j++) {
+ transferData.type = types[j];
+ transfer.javaToNative(event2.data, transferData);
+ if (transferData.result is OS.noErr) {
+ for (int k = 0; k < transferData.data.length; k++) {
+ byte[] datum = transferData.data[k];
+ OS.AddDragItemFlavor(theDrag[0], 1 + k, types[j], datum, datum.length, 0);
+ }
+ }
+ }
+ }
+ } else {
+ for (int j = 0; j < types.length; j++) {
+ OS.AddDragItemFlavor(theDrag[0], 1, types[j], null, 0, 0);
+ }
+ }
+ }
+ }
+
+ OS.SetDragSendProc(theDrag[0], DragSendDataProc.getAddress(), control.handle);
+
+ int theRegion = 0;
+ Image newImage = null;
+ try {
+ theRegion = OS.NewRgn();
+ OS.SetRectRgn(theRegion, (short)(pt.h), (short)(pt.v), (short)(pt.h+20), (short)(pt.v+20));
+
+ int operations = opToOsOp(getStyle());
+ //set operations twice - local and not local
+ OS.SetDragAllowableActions(theDrag[0], operations, true);
+ OS.SetDragAllowableActions(theDrag[0], operations, false);
+
+ Image image = event.image;
+ if (image !is null) {
+ CGPoint imageOffsetPt = new CGPoint();
+ imageOffsetPt.x = 0;
+ imageOffsetPt.y = 0;
+ /*
+ * Bug in the Macintosh. For some reason, it seems that SetDragImageWithCGImage()
+ * expects an image with the alpha, otherwise the image does not draw. The fix is
+ * to make sure that the image has an alpha by creating a new image with alpha
+ * when necessary.
+ */
+ if (OS.CGImageGetAlphaInfo(image.handle) is OS.kCGImageAlphaNoneSkipFirst) {
+ ImageData data = image.getImageData();
+ data.alpha = 0xFF;
+ newImage = new Image(image.getDevice(), data);
+ image = newImage;
+ }
+ OS.SetDragImageWithCGImage(theDrag[0], image.handle, imageOffsetPt, 0);
+ }
+ EventRecord theEvent = new EventRecord();
+ theEvent.message = OS.kEventMouseMoved;
+ theEvent.modifiers = (short)OS.GetCurrentEventKeyModifiers();
+ theEvent.what = (short)OS.osEvt;
+ theEvent.where_h = pt.h;
+ theEvent.where_v = pt.v;
+ int result = OS.TrackDrag(theDrag[0], theEvent, theRegion);
+ int operation = DND.DROP_NONE;
+ if (result is OS.noErr) {
+ int[] outAction = new int[1];
+ OS.GetDragDropAction(theDrag[0], outAction);
+ operation = osOpToOp(outAction[0]);
+ }
+ event = new DNDEvent();
+ event.widget = this;
+ event.time = (int)System.currentTimeMillis();
+ event.doit = result is OS.noErr;
+ event.detail = operation;
+ notifyListeners(DND.DragEnd, event);
+ } finally {
+ if (theRegion !is 0) OS.DisposeRgn(theRegion);
+ if (newImage !is null) newImage.dispose();
+ }
+ OS.DisposeDrag(theDrag[0]);
+}
+
+int dragSendDataProc(int theType, int dragSendRefCon, int theItemRef, int theDrag) {
+ if (theType is 0) return OS.badDragFlavorErr;
+ TransferData transferData = new TransferData();
+ transferData.type = theType;
+ DNDEvent event = new DNDEvent();
+ event.widget = this;
+ event.time = (int)System.currentTimeMillis();
+ event.dataType = transferData;
+ notifyListeners(DND.DragSetData, event);
+ 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 OS.badDragFlavorErr;
+ transfer.javaToNative(event.data, transferData);
+ if (transferData.result !is OS.noErr) return transferData.result;
+ // Except for FileTransfer (see #drag), only one item can be transferred
+ // in a Drag operation
+ byte[] datum = transferData.data[0];
+ if (datum is null) return OS.cantGetFlavorErr;
+ return OS.SetDragItemFlavorData(theDrag, theItemRef, theType, datum, datum.length, 0);
+}
+
+/**
+ * Returns the Control which is registered for this DragSource. This is the control that the
+ * user clicks in to initiate dragging.
+ *
+ * @return the Control which is registered for this DragSource
+ */
+public Control getControl () {
+ return control;
+}
+
+/**
+ * Returns 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.
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DragSourceListener
+ * @see #addDragListener
+ * @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 (listener instanceof DNDListener) {
+ dragListeners[count] = (DragSourceListener) ((DNDListener) listener).getEventListener();
+ count++;
+ }
+ }
+ if (count is length) return dragListeners;
+ DragSourceListener[] result = new DragSourceListener[count];
+ System.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;
+}
+
+void onDispose() {
+ if (control is null)
+ return;
+ if (controlListener !is null) {
+ control.removeListener(DWT.Dispose, controlListener);
+ control.removeListener(DWT.DragDetect, controlListener);
+ }
+ controlListener = null;
+ control.setData(DND.DRAG_SOURCE_KEY, null);
+ control = null;
+ transferAgents = null;
+}
+
+int opToOsOp(int operation) {
+ int osOperation = 0;
+ if ((operation & DND.DROP_COPY) !is 0){
+ osOperation |= OS.kDragActionCopy;
+ }
+ if ((operation & DND.DROP_LINK) !is 0) {
+ osOperation |= OS.kDragActionAlias;
+ }
+ if ((operation & DND.DROP_MOVE) !is 0) {
+ osOperation |= OS.kDragActionMove;
+ }
+ if ((operation & DND.DROP_TARGET_MOVE) !is 0) {
+ osOperation |= OS.kDragActionDelete;
+ }
+ return osOperation;
+}
+
+int osOpToOp(int osOperation){
+ int operation = 0;
+ if ((osOperation & OS.kDragActionCopy) !is 0){
+ operation |= DND.DROP_COPY;
+ }
+ if ((osOperation & OS.kDragActionAlias) !is 0) {
+ operation |= DND.DROP_LINK;
+ }
+ if ((osOperation & OS.kDragActionDelete) !is 0) {
+ operation |= DND.DROP_TARGET_MOVE;
+ }
+ if ((osOperation & OS.kDragActionMove) !is 0) {
+ operation |= DND.DROP_MOVE;
+ }
+ if (osOperation is OS.kDragActionAll) {
+ operation = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
+ }
+ return operation;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a drag and drop operation is in progress.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DragSourceListener
+ * @see #addDragListener
+ */
+public void removeDragListener(DragSourceListener listener) {
+ if (listener is null) DND.error (DWT.ERROR_NULL_ARGUMENT);
+ removeListener (DND.DragStart, listener);
+ removeListener (DND.DragSetData, listener);
+ removeListener (DND.DragEnd, listener);
+}
+
+/**
+ * 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;
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DragSourceAdapter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DragSourceAdapter.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the DragSourceListener
interface.
+ *
+ * Classes that wish to deal with DragSourceEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ * @see DragSourceListener
+ * @see DragSourceEvent
+ */
+public class DragSourceAdapter : DragSourceListener {
+ /**
+ * This implementation of dragStart
permits the drag operation to start.
+ * For additional information see DragSourceListener.dragStart
.
+ */
+ public void dragStart(DragSourceEvent event){}
+ /**
+ * This implementation of dragFinished
does nothing.
+ * For additional information see DragSourceListener.dragFinished
.
+ */
+ public void dragFinished(DragSourceEvent event){}
+ /**
+ * This implementation of dragSetData
does nothing.
+ * For additional information see DragSourceListener.dragSetData
.
+ */
+ public void dragSetData(DragSourceEvent event){}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DragSourceEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DragSourceEffect.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.*;
+import dwt.widgets.*;
+
+/**
+ * This class provides default implementations to display a drag source
+ * effect during a drag and drop operation. The current implementation
+ * does not provide any visual feedback.
+ *
+ * The drag source effect has the same API as the
+ * DragSourceAdapter
so that it can provide custom visual
+ * feedback when a DragSourceEvent
occurs.
+ *
+ *
+ * Classes that wish to provide their own drag source effect such as
+ * displaying a default source image during a drag can extend the 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.
+ *
+ *
+ * @see DragSourceAdapter
+ * @see DragSourceEvent
+ *
+ * @since 3.3
+ */
+public class DragSourceEffect : DragSourceAdapter {
+ Control control = null;
+
+ /**
+ * Creates a new DragSourceEffect
to handle drag effect from the specified Control
.
+ *
+ * @param control the Control
that the user clicks on to initiate the drag
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if the control is null
+ *
+ */
+ public DragSourceEffect(Control control) {
+ if (control is null) DWT.error(DWT.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 380af2bdd8e5 dwt/dnd/DragSourceEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DragSourceEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.events.TypedEvent;
+import dwt.graphics.*;
+
+/**
+ * The DragSourceEvent contains the event information passed in the methods of the DragSourceListener.
+ *
+ * @see DragSourceListener
+ */
+public class DragSourceEvent : TypedEvent {
+ /**
+ * The operation that was performed.
+ * @see DND#DROP_NONE
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_LINK
+ * @see DND#DROP_TARGET_MOVE
+ */
+ public int detail;
+
+ /**
+ * In dragStart, the doit field determines if the drag and drop operation
+ * should proceed; in dragFinished, the doit field indicates whether
+ * the operation was performed successfully.
+ *
+ * In dragStart:
+ * 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.
+ */
+ public bool doit;
+
+ /**
+ * In dragStart, the x coordinate (relative to the control) of the
+ * position the mouse went down to start the drag.
+ * @since 3.2
+ */
+ public int x;
+ /**
+ * In dragStart, the y coordinate (relative to the control) of the
+ * position the mouse went down to start the drag .
+ * @since 3.2
+ */
+ public int y;
+
+ /**
+ * The type of data requested.
+ * Data provided in the data field must be of the same type.
+ */
+ public TransferData dataType;
+
+ /**
+ * The drag source image to be displayed during the drag.
+ * A value of null indicates that no drag image will be displayed.
+ * The default value is null.
+ *
+ * @since 3.3
+ */
+ public Image image;
+
+ static final long serialVersionUID = 3257002142513770808L;
+
+/**
+ * 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 DragSourceEvent(DNDEvent e) {
+ super(e);
+ this.data = e.data;
+ this.detail = e.detail;
+ this.doit = e.doit;
+ this.dataType = e.dataType;
+ this.x = e.x;
+ this.y = e.y;
+ this.image = e.image;
+}
+void updateEvent(DNDEvent e) {
+ e.widget = this.widget;
+ e.time = this.time;
+ e.data = this.data;
+ e.detail = this.detail;
+ e.doit = this.doit;
+ e.dataType = this.dataType;
+ e.x = this.x;
+ e.y = this.y;
+ e.image = this.image;
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DragSourceListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DragSourceListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * The DragSourceListener
class provides event notification to the application for DragSource events.
+ *
+ * When the user drops data on a 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.
+ *
+ * After the drop has completed successfully or has been aborted, the application which defines the
+ * 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.
+ *
+ */
+public interface DragSourceListener : DWTEventListener {
+
+/**
+ * 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.
+ *
+ * The following fields in the DragSourceEvent apply:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in,out)doit
+ *
+ *
+ * @param event the information associated with the drag start event
+ *
+ * @see DragSourceEvent
+ */
+public void dragStart(DragSourceEvent event);
+
+/**
+ * The data is required from the drag source.
+ *
+ * The following fields in the DragSourceEvent apply:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in)dataType - the type of data requested.
+ *
- (out)data - the application inserts the actual data here (must match the dataType)
+ *
+ *
+ * @param event the information associated with the drag set data event
+ *
+ * @see DragSourceEvent
+ */
+public void dragSetData(DragSourceEvent event);
+
+/**
+ * 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.
+ *
+ * The following fields in the DragSourceEvent apply:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in)doit
+ *
- (in)detail
+ *
+ *
+ * @param event the information associated with the drag finished event
+ *
+ * @see DragSourceEvent
+ */
+public void dragFinished(DragSourceEvent event);
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DropTarget.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DropTarget.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,804 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+import dwt.*;
+import dwt.widgets.*;
+import dwt.internal.*;
+import dwt.internal.carbon.*;
+
+/**
+ *
+ * Class DropTarget
defines the target object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ * This class identifies the Control
over which the user must position the cursor
+ * in order to drop the data being transferred. It also specifies what data types can be dropped on
+ * this control and what operations can be performed. You may have several DropTragets in an
+ * application but there can only be a one to one mapping between a Control
and a DropTarget
.
+ * The DropTarget can receive data from within the same application or from other applications
+ * (such as text dragged from a text editor like Word).
+ *
+ *
+ * int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
+ * Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ * DropTarget target = new DropTarget(label, operations);
+ * target.setTransfer(types);
+ *
+ *
+ * The application is notified of data being dragged over this control and of when a drop occurs by
+ * implementing the interface DropTargetListener
which uses the class
+ * DropTargetEvent
. The application can modify the type of drag being performed
+ * on this Control at any stage of the drag by modifying the event.detail
field or the
+ * event.currentDataType
field. When the data is dropped, it is the responsibility of
+ * the application to copy this data for its own purposes.
+ *
+ *
+ * target.addDropListener (new DropTargetListener() {
+ * public void dragEnter(DropTargetEvent event) {};
+ * public void dragOver(DropTargetEvent event) {};
+ * public void dragLeave(DropTargetEvent event) {};
+ * public void dragOperationChanged(DropTargetEvent event) {};
+ * public void dropAccept(DropTargetEvent event) {}
+ * public void drop(DropTargetEvent event) {
+ * // A drop has occurred, copy over the data
+ * if (event.data 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
+ * }
+ * });
+ *
+ *
+ *
+ * - Styles
- DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ * - Events
- DND.DragEnter, DND.DragLeave, DND.DragOver, DND.DragOperationChanged,
+ * DND.DropAccept, DND.Drop
+ *
+ */
+public class DropTarget : Widget {
+
+ Control control;
+ Listener controlListener;
+ Transfer[] transferAgents = new Transfer[0];
+ DropTargetEffect dropEffect;
+ int feedback = DND.FEEDBACK_NONE;
+
+ // 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 - Simulate events when mouse is not moving
+ long dragOverStart;
+ Runnable dragOverHeartbeat;
+ DNDEvent dragOverEvent;
+
+ // workaround - OS events are relative to the application, not the control.
+ // Track which control is the current target to determine when drag and
+ // drop enters or leaves a widget.
+ static DropTarget CurrentDropTarget = null;
+
+ static final String DEFAULT_DROP_TARGET_EFFECT = "DEFAULT_DROP_TARGET_EFFECT"; //$NON-NLS-1$
+ static final int DRAGOVER_HYSTERESIS = 50;
+
+ static Callback DragTrackingHandler;
+ static Callback DragReceiveHandler;
+
+ static {
+ DragTrackingHandler = new Callback(DropTarget.class, "DragTrackingHandler", 4); //$NON-NLS-1$
+ int dragTrackingHandlerAddress = DragTrackingHandler.getAddress();
+ if (dragTrackingHandlerAddress is 0) DWT.error(DWT.ERROR_NO_MORE_CALLBACKS);
+ DragReceiveHandler = new Callback(DropTarget.class, "DragReceiveHandler", 3); //$NON-NLS-1$
+ int dragReceiveHandlerAddress = DragReceiveHandler.getAddress();
+ if (dragReceiveHandlerAddress is 0) DWT.error(DWT.ERROR_NO_MORE_CALLBACKS);
+ OS.InstallTrackingHandler(dragTrackingHandlerAddress, 0, null);
+ OS.InstallReceiveHandler(dragReceiveHandlerAddress, 0, null);
+ }
+
+/**
+ * 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 DWTException
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ * - ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ * @exception DWTError
+ * - ERROR_CANNOT_INIT_DROP - unable to initiate drop target; this will occur if more than one
+ * drop target is created for a control or if the operating system will not allow the creation
+ * of the drop target
+ *
+ *
+ * NOTE: ERROR_CANNOT_INIT_DROP should be an DWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.
+ *
+ * @see Widget#dispose
+ * @see DropTarget#checkSubclass
+ * @see DND#DROP_NONE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_LINK
+ */
+public DropTarget(Control control, int style) {
+ super(control, checkStyle(style));
+ this.control = control;
+ if (DragTrackingHandler is null || DragTrackingHandler is null) {
+ DND.error(DND.ERROR_CANNOT_INIT_DROP);
+ }
+ if (control.getData(DND.DROP_TARGET_KEY) !is null) {
+ DND.error(DND.ERROR_CANNOT_INIT_DROP);
+ }
+ control.setData(DND.DROP_TARGET_KEY, this);
+
+ controlListener = new Listener () {
+ public void handleEvent (Event event) {
+ if (!DropTarget.this.isDisposed()) {
+ DropTarget.this.dispose();
+ }
+ }
+ };
+ control.addListener (DWT.Dispose, controlListener);
+
+ this.addListener(DWT.Dispose, new Listener() {
+ public void handleEvent (Event event) {
+ onDispose();
+ }
+ });
+
+ Object effect = control.getData(DEFAULT_DROP_TARGET_EFFECT);
+ if (effect instanceof DropTargetEffect) {
+ dropEffect = (DropTargetEffect) effect;
+ } else if (control instanceof Table) {
+ dropEffect = new TableDropTargetEffect((Table) control);
+ } else if (control instanceof Tree) {
+ dropEffect = new TreeDropTargetEffect((Tree) control);
+ }
+
+ dragOverHeartbeat = new Runnable() {
+ public void run() {
+ Control control = DropTarget.this.control;
+ if (control is null || control.isDisposed() || dragOverStart is 0) return;
+ long time = System.currentTimeMillis();
+ int delay = DRAGOVER_HYSTERESIS;
+ if (time < dragOverStart) {
+ delay = (int)(dragOverStart - time);
+ } else {
+ int allowedOperations = dragOverEvent.operations;
+ TransferData[] allowedTypes = dragOverEvent.dataTypes;
+ //pass a copy of data types in to listeners in case application modifies it
+ TransferData[] dataTypes = new TransferData[allowedTypes.length];
+ System.arraycopy(allowedTypes, 0, dataTypes, 0, dataTypes.length);
+
+ DNDEvent event = new DNDEvent();
+ event.widget = dragOverEvent.widget;
+ event.x = dragOverEvent.x;
+ event.y = dragOverEvent.y;
+ event.time = (int)time;
+ event.feedback = DND.FEEDBACK_SELECT;
+ event.dataTypes = dataTypes;
+ event.dataType = selectedDataType;
+ event.operations = dragOverEvent.operations;
+ event.detail = selectedOperation;
+ if (dropEffect !is null) {
+ event.item = dropEffect.getItem(event.x, event.y);
+ }
+ selectedDataType = null;
+ selectedOperation = DND.DROP_NONE;
+ notifyListeners(DND.DragOver, event);
+ if (event.dataType !is null) {
+ for (int i = 0; i < allowedTypes.length; i++) {
+ if (allowedTypes[i].type is event.dataType.type) {
+ selectedDataType = event.dataType;
+ break;
+ }
+ }
+ }
+ if (selectedDataType !is null && (event.detail & allowedOperations) !is 0) {
+ selectedOperation = event.detail;
+ }
+ }
+ control = DropTarget.this.control;
+ if (control is null || control.isDisposed()) return;
+ control.getDisplay().timerExec(delay, dragOverHeartbeat);
+ }
+ };
+}
+
+static int checkStyle (int style) {
+ if (style is DWT.NONE) return DND.DROP_MOVE;
+ return style;
+}
+
+static int DragReceiveHandler(int theWindow, int handlerRefCon, int theDrag) {
+ DropTarget target = FindDropTarget(theWindow, theDrag);
+ if (target is null) return OS.noErr;
+ return target.dragReceiveHandler(theWindow, handlerRefCon, theDrag);
+}
+
+static int DragTrackingHandler(int message, int theWindow, int handlerRefCon, int theDrag) {
+ if (message is OS.kDragTrackingLeaveHandler || message is OS.kDragTrackingEnterHandler) {
+ CurrentDropTarget = null;
+ return OS.noErr;
+ }
+ DropTarget target = FindDropTarget(theWindow, theDrag);
+ if (CurrentDropTarget !is null) {
+ if (target is null || CurrentDropTarget.control.handle !is target.control.handle) {
+ CurrentDropTarget.dragTrackingHandler(OS.kDragTrackingLeaveWindow, theWindow, handlerRefCon, theDrag);
+ CurrentDropTarget = target;
+ message = OS.kDragTrackingEnterWindow;
+ }
+ } else {
+ CurrentDropTarget = target;
+ message = OS.kDragTrackingEnterWindow;
+ }
+ if (target is null) return OS.noErr;
+ return target.dragTrackingHandler(message, theWindow, handlerRefCon, theDrag);
+}
+
+static DropTarget FindDropTarget(int theWindow, int theDrag) {
+ Display display = Display.findDisplay(Thread.currentThread());
+ if (display is null || display.isDisposed()) return null;
+ Point mouse = new Point();
+ OS.GetDragMouse(theDrag, mouse, null);
+ int[] theRoot = new int[1];
+ OS.GetRootControl(theWindow, theRoot);
+ int[] theControl = new int[1];
+ Rect rect = new Rect();
+ OS.GetWindowBounds (theWindow, (short) OS.kWindowContentRgn, rect);
+ CGPoint inPoint = new CGPoint();
+ inPoint.x = mouse.h - rect.left;
+ inPoint.y = mouse.v - rect.top;
+ OS.HIViewGetSubviewHit(theRoot[0], inPoint, true, theControl);
+ if (!OS.IsControlEnabled(theControl[0])) return null;
+ Widget widget = display.findWidget(theControl[0]);
+ if (widget is null) return null;
+ return (DropTarget)widget.getData(DND.DROP_TARGET_KEY);
+}
+/**
+ * Adds the listener to the collection 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 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
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DropTargetListener
+ * @see #removeDropListener
+ * @see DropTargetEvent
+ */
+public void addDropListener(DropTargetListener listener) {
+ if (listener is null) DND.error (DWT.ERROR_NULL_ARGUMENT);
+ DNDListener typedListener = new DNDListener (listener);
+ typedListener.dndWidget = this;
+ addListener (DND.DragEnter, typedListener);
+ addListener (DND.DragLeave, typedListener);
+ addListener (DND.DragOver, typedListener);
+ addListener (DND.DragOperationChanged, typedListener);
+ addListener (DND.Drop, typedListener);
+ addListener (DND.DropAccept, typedListener);
+}
+
+protected void checkSubclass () {
+ String name = getClass().getName ();
+ String validName = DropTarget.class.getName();
+ if (!validName.opEquals(name)) {
+ DND.error (DWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+
+int dragReceiveHandler(int theWindow, int handlerRefCon, int theDrag) {
+ updateDragOverHover(0, null);
+ if (keyOperation is -1) return OS.dragNotAcceptedErr;
+
+ DNDEvent event = new DNDEvent();
+ event.widget = this;
+ event.time = (int)System.currentTimeMillis();
+ event.detail = DND.DROP_NONE;
+ notifyListeners(DND.DragLeave, event);
+
+ event = new DNDEvent();
+ if (!setEventData(theDrag, event)) {
+ return OS.dragNotAcceptedErr;
+ }
+
+ keyOperation = -1;
+ int allowedOperations = event.operations;
+ TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length];
+ System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, event.dataTypes.length);
+ event.dataType = selectedDataType;
+ event.detail = selectedOperation;
+ selectedDataType = null;
+ selectedOperation = DND.DROP_NONE;
+ notifyListeners(DND.DropAccept, event);
+
+ if (event.dataType !is null) {
+ for (int i = 0; i < allowedDataTypes.length; i++) {
+ if (allowedDataTypes[i].type is event.dataType.type) {
+ selectedDataType = allowedDataTypes[i];
+ break;
+ }
+ }
+ }
+ if (selectedDataType !is null && (event.detail & allowedOperations) !is 0) {
+ selectedOperation = event.detail;
+ }
+ if (selectedOperation is DND.DROP_NONE) {
+ // this was not a successful drop
+ return OS.dragNotAcceptedErr;
+ }
+ // ask drag source for dropped data
+ byte[][] data = new byte[0][];
+ // locate all the items with data of the desired type
+ short[] numItems = new short[1];
+ OS.CountDragItems(theDrag, numItems);
+ for (short i = 0; i < numItems[0]; i++) {
+ int[] theItemRef = new int[1];
+ OS.GetDragItemReferenceNumber(theDrag, (short) (i+1), theItemRef);
+ int[] size = new int[1];
+ OS.GetFlavorDataSize(theDrag, theItemRef[0], selectedDataType.type, size);
+ if (size[0] > 0) {
+ byte[] buffer = new byte[size[0]];
+ OS.GetFlavorData(theDrag, theItemRef[0], selectedDataType.type, buffer, size, 0);
+ byte[][] newData = new byte[data.length + 1][];
+ System.arraycopy(data, 0, newData, 0, data.length);
+ newData[data.length] = buffer;
+ data = newData;
+ }
+ }
+ // Get Data in a Java format
+ Object object = null;
+ for (int i = 0; i < transferAgents.length; i++) {
+ Transfer transfer = transferAgents[i];
+ if (transfer !is null && transfer.isSupportedType(selectedDataType)) {
+ selectedDataType.data = data;
+ object = transfer.nativeToJava(selectedDataType);
+ break;
+ }
+ }
+
+ if (object is null) {
+ selectedOperation = DND.DROP_NONE;
+ }
+
+ event.dataType = selectedDataType;
+ event.detail = selectedOperation;
+ event.data = object;
+ notifyListeners(DND.Drop, event);
+ selectedOperation = DND.DROP_NONE;
+ if ((allowedOperations & event.detail) is event.detail) {
+ selectedOperation = event.detail;
+ }
+ //notify source of action taken
+ int action = opToOsOp(selectedOperation);
+ OS.SetDragDropAction(theDrag, action);
+ return (selectedOperation is DND.DROP_NONE) ? OS.dragNotAcceptedErr : OS.noErr;
+}
+
+int dragTrackingHandler(int message, int theWindow, int handlerRefCon, int theDrag) {
+
+ if (message is OS.kDragTrackingLeaveWindow) {
+ updateDragOverHover(0, null);
+ OS.SetThemeCursor(OS.kThemeArrowCursor);
+ if (keyOperation is -1) return OS.dragNotAcceptedErr;
+ keyOperation = -1;
+
+ DNDEvent event = new DNDEvent();
+ event.widget = this;
+ event.time = (int)System.currentTimeMillis();
+ event.detail = DND.DROP_NONE;
+ notifyListeners(DND.DragLeave, event);
+ return OS.noErr;
+ }
+
+ int oldKeyOperation = keyOperation;
+
+ if (message is OS.kDragTrackingEnterWindow) {
+ selectedDataType = null;
+ selectedOperation = 0;
+ }
+
+ DNDEvent event = new DNDEvent();
+ if (!setEventData(theDrag, event)) {
+ keyOperation = -1;
+ OS.SetThemeCursor(OS.kThemeNotAllowedCursor);
+ return OS.dragNotAcceptedErr;
+ }
+
+ int allowedOperations = event.operations;
+ TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length];
+ System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length);
+
+ switch (message) {
+ case OS.kDragTrackingEnterWindow:
+ event.type = DND.DragEnter;
+ break;
+ case OS.kDragTrackingInWindow:
+ if (keyOperation is oldKeyOperation) {
+ event.type = DND.DragOver;
+ event.dataType = selectedDataType;
+ event.detail = selectedOperation;
+ }else {
+ event.type = DND.DragOperationChanged;
+ event.dataType = selectedDataType;
+ }
+ break;
+ }
+
+ updateDragOverHover(DRAGOVER_HYSTERESIS, event);
+ selectedDataType = null;
+ selectedOperation = DND.DROP_NONE;
+ notifyListeners(event.type, event);
+
+ if (event.detail is DND.DROP_DEFAULT) {
+ event.detail = (allowedOperations & DND.DROP_MOVE) !is 0 ? DND.DROP_MOVE : DND.DROP_NONE;
+ }
+
+ if (event.dataType !is null) {
+ for (int i = 0; i < allowedDataTypes.length; i++) {
+ if (allowedDataTypes[i].type is event.dataType.type) {
+ selectedDataType = allowedDataTypes[i];
+ break;
+ }
+ }
+ }
+
+ if (selectedDataType !is null && (allowedOperations & event.detail) !is 0) {
+ selectedOperation = event.detail;
+ }
+
+ OS.SetDragDropAction(theDrag, opToOsOp(selectedOperation));
+
+ switch (selectedOperation) {
+ case DND.DROP_COPY:
+ OS.SetThemeCursor(OS.kThemeCopyArrowCursor);
+ break;
+ case DND.DROP_LINK:
+ OS.SetThemeCursor(OS.kThemeAliasArrowCursor);
+ break;
+ case DND.DROP_MOVE:
+ OS.SetThemeCursor(OS.kThemeArrowCursor);
+ break;
+ default:
+ OS.SetThemeCursor(OS.kThemeNotAllowedCursor);
+ }
+
+ if (message is OS.kDragTrackingEnterWindow) {
+ dragOverHeartbeat.run();
+ }
+ return OS.noErr;
+}
+
+/**
+ * Returns the Control which is registered for this DropTarget. This is the control over which the
+ * user positions the cursor to drop the data.
+ *
+ * @return the Control which is registered for this DropTarget
+ */
+public Control getControl () {
+ return control;
+}
+
+/**
+ * Returns 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 DropTargetListener
interface.
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DropTargetListener
+ * @see #addDropListener
+ * @see #removeDropListener
+ * @see DropTargetEvent
+ *
+ * @since 3.4
+ */
+public DropTargetListener[] getDropListeners() {
+ Listener[] listeners = getListeners(DND.DragEnter);
+ int length = listeners.length;
+ DropTargetListener[] dropListeners = new DropTargetListener[length];
+ int count = 0;
+ for (int i = 0; i < length; i++) {
+ Listener listener = listeners[i];
+ if (listener instanceof DNDListener) {
+ dropListeners[count] = (DropTargetListener) ((DNDListener) listener).getEventListener();
+ count++;
+ }
+ }
+ if (count is length) return dropListeners;
+ DropTargetListener[] result = new DropTargetListener[count];
+ System.arraycopy(dropListeners, 0, result, 0, count);
+ return result;
+}
+
+/**
+ * Returns the drop effect for this DropTarget. This drop effect will be
+ * used during a drag and drop to display the drag under effect on the
+ * target widget.
+ *
+ * @return the drop effect that is registered for this DropTarget
+ *
+ * @since 3.3
+ */
+public DropTargetEffect getDropTargetEffect() {
+ return dropEffect;
+}
+
+int getOperationFromKeyState(int theDrag) {
+ short[] modifiers = new short[1];
+ OS.GetDragModifiers(theDrag, modifiers, null, null);
+ bool option = (modifiers[0] & OS.optionKey) is OS.optionKey;
+ bool command = (modifiers[0] & OS.cmdKey) is OS.cmdKey;
+ if (option && command) return DND.DROP_LINK;
+ if (option) return DND.DROP_COPY;
+ if (command) return DND.DROP_MOVE;
+ return DND.DROP_DEFAULT;
+}
+
+/**
+ * Returns a list of the data types that can be transferred to this DropTarget.
+ *
+ * @return a list of the data types that can be transferred to this DropTarget
+ */
+public Transfer[] getTransfer() {
+ return transferAgents;
+}
+
+void onDispose () {
+ if (control is null)
+ return;
+ if (controlListener !is null)
+ control.removeListener(DWT.Dispose, controlListener);
+ controlListener = null;
+ control.setData(DND.DROP_TARGET_KEY, null);
+ transferAgents = null;
+ control = null;
+}
+
+int opToOsOp(int operation) {
+ int osOperation = 0;
+ if ((operation & DND.DROP_COPY) !is 0){
+ osOperation |= OS.kDragActionCopy;
+ }
+ if ((operation & DND.DROP_LINK) !is 0) {
+ osOperation |= OS.kDragActionAlias;
+ }
+ if ((operation & DND.DROP_MOVE) !is 0) {
+ osOperation |= OS.kDragActionMove;
+ }
+ return osOperation;
+}
+
+int osOpToOp(int osOperation){
+ int operation = 0;
+ if ((osOperation & OS.kDragActionCopy) !is 0){
+ operation |= DND.DROP_COPY;
+ }
+ if ((osOperation & OS.kDragActionAlias) !is 0) {
+ operation |= DND.DROP_LINK;
+ }
+ if ((osOperation & OS.kDragActionMove) !is 0) {
+ operation |= DND.DROP_MOVE;
+ }
+ if (osOperation is OS.kDragActionAll) {
+ operation = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
+ }
+ return operation;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a drag and drop operation is in progress.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception DWTException
+ * - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ * - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DropTargetListener
+ * @see #addDropListener
+ */
+public void removeDropListener(DropTargetListener listener) {
+ if (listener is null) DND.error (DWT.ERROR_NULL_ARGUMENT);
+ removeListener (DND.DragEnter, listener);
+ removeListener (DND.DragLeave, listener);
+ removeListener (DND.DragOver, listener);
+ removeListener (DND.DragOperationChanged, listener);
+ removeListener (DND.Drop, listener);
+ removeListener (DND.DropAccept, listener);
+}
+
+/**
+ * Specifies the drop effect for this DropTarget. This drop effect will be
+ * used during a drag and drop to display the drag under effect on the
+ * target widget.
+ *
+ * @param effect the drop effect that is registered for this DropTarget
+ *
+ * @since 3.3
+ */
+public void setDropTargetEffect(DropTargetEffect effect) {
+ dropEffect = effect;
+}
+
+bool setEventData(int theDrag, DNDEvent event) {
+ if (theDrag is 0) return false;
+
+ // get allowed operations
+ int style = getStyle();
+ int[] outActions = new int[1];
+ OS.GetDragAllowableActions(theDrag, outActions);
+ int operations = osOpToOp(outActions[0]) & style;
+ if (operations is DND.DROP_NONE) return false;
+
+ //get current operation
+ int operation = getOperationFromKeyState(theDrag);
+ keyOperation = operation;
+ if (operation is DND.DROP_DEFAULT) {
+ if ((style & DND.DROP_DEFAULT) is 0) {
+ operation = (operations & DND.DROP_MOVE) !is 0 ? DND.DROP_MOVE : DND.DROP_NONE;
+ }
+ } else {
+ if ((operation & operations) is 0) operation = DND.DROP_NONE;
+ }
+
+ // get allowed transfer types
+ short[] numItems = new short[1];
+ OS.CountDragItems(theDrag, numItems);
+ int[] flavors = new int[10];
+ int index = -1;
+ //Get a unique list of flavors
+ for (short i = 0; i < numItems[0]; i++) {
+ int[] theItemRef = new int[1];
+ OS.GetDragItemReferenceNumber(theDrag, (short) (i+1), theItemRef);
+ short[] numFlavors = new short[1];
+ OS.CountDragItemFlavors(theDrag, theItemRef[0], numFlavors);
+ int[] theType = new int[1];
+ for (int j = 0; j < numFlavors[0]; j++) {
+ theType[0] = 0;
+ if (OS.GetFlavorType(theDrag, theItemRef[0], (short) (j+1), theType) is OS.noErr) {
+ bool unique = true;
+ for (int k = 0; k < flavors.length; k++) {
+ if (flavors[k] is theType[0]) {
+ unique = false;
+ break;
+ }
+ }
+ if (unique) {
+ if (index is flavors.length - 1) {
+ int[] temp = new int[flavors.length + 10];
+ System.arraycopy(flavors, 0, temp, 0, flavors.length);
+ flavors = temp;
+ }
+ flavors[++index] = theType[0];
+ }
+ }
+ }
+ }
+ if (index is -1) return false;
+
+ TransferData[] dataTypes = new TransferData[index+1];
+ index = -1;
+ for (int i = 0; i < dataTypes.length; i++) {
+ if (flavors[i] !is 0) {
+ TransferData data = new TransferData();
+ data.type = flavors[i];
+ for (int j = 0; j < transferAgents.length; j++) {
+ Transfer transfer = transferAgents[j];
+ if (transfer !is null && transfer.isSupportedType(data)) {
+ dataTypes[++index] = data;
+ break;
+ }
+ }
+ }
+ }
+ if (index is -1) return false;
+
+ if (index < dataTypes.length - 1) {
+ TransferData[] temp = new TransferData[index + 1];
+ System.arraycopy(dataTypes, 0, temp, 0, index + 1);
+ dataTypes = temp;
+ }
+
+ Point mouse = new Point();
+ OS.GetDragMouse(theDrag, mouse, null);
+
+ event.widget = this;
+ event.x = mouse.h;
+ event.y = mouse.v;
+ event.time = (int)System.currentTimeMillis();
+ event.feedback = DND.FEEDBACK_SELECT;
+ event.dataTypes = dataTypes;
+ event.dataType = dataTypes[0];
+ event.operations = operations;
+ event.detail = operation;
+ if (dropEffect !is null) {
+ event.item = dropEffect.getItem(event.x, event.y);
+ }
+
+ return true;
+}
+
+/**
+ * Specifies the data types that can be transferred to this DropTarget. If data is
+ * being dragged that does not match one of these types, the drop target will be notified of
+ * the drag and drop operation but the currentDataType will be null and the operation
+ * will be DND.NONE.
+ *
+ * @param transferAgents a list of Transfer objects which define the types of data that can be
+ * dropped on this target
+ *
+ * @exception IllegalArgumentException
+ * - ERROR_NULL_ARGUMENT - if transferAgents is null
+ *
+ */
+public void setTransfer(Transfer[] transferAgents){
+ if (transferAgents is null) DND.error(DWT.ERROR_NULL_ARGUMENT);
+ this.transferAgents = transferAgents;
+}
+
+void updateDragOverHover(long delay, DNDEvent event) {
+ if (delay is 0) {
+ dragOverStart = 0;
+ dragOverEvent = null;
+ return;
+ }
+ dragOverStart = System.currentTimeMillis() + delay;
+ if (dragOverEvent is null) dragOverEvent = new DNDEvent();
+ dragOverEvent.x = event.x;
+ dragOverEvent.y = event.y;
+ dragOverEvent.dataTypes = event.dataTypes;
+ dragOverEvent.operations = event.operations;
+ dragOverEvent.dataType = event.dataType;
+ dragOverEvent.detail = event.detail;
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DropTargetAdapter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DropTargetAdapter.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the DropTargetListener
interface.
+ *
+ * Classes that wish to deal with DropTargetEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
+ *
+ * @see DropTargetListener
+ * @see DropTargetEvent
+ */
+public class DropTargetAdapter : DropTargetListener {
+
+/**
+ * This implementation of 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
.
+ */
+public void dragEnter(DropTargetEvent event){}
+/**
+ * This implementation of dragLeave
does nothing.
+ * For additional information see DropTargetListener.dragOperationChanged
.
+ */
+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
.
+ */
+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
.
+ */
+public void dragOver(DropTargetEvent event){}
+/**
+ * This implementation of drop
does nothing.
+ * For additional information see DropTargetListener.drop
.
+ */
+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
.
+ */
+public void dropAccept(DropTargetEvent event){}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DropTargetEffect.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.*;
+import dwt.graphics.*;
+import dwt.widgets.*;
+
+
+/**
+ * This class provides a default drag under effect during a drag and drop.
+ * The current implementation does not provide any visual feedback.
+ *
+ * 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.
+ *
+ *
+ *
+ * - Feedback:
+ * - FEEDBACK_EXPAND, FEEDBACK_INSERT_AFTER, FEEDBACK_INSERT_BEFORE,
+ * FEEDBACK_NONE, FEEDBACK_SELECT, FEEDBACK_SCROLL
+ *
+ *
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ *
+ * @since 3.3
+ */
+public class DropTargetEffect : DropTargetAdapter {
+ Control control;
+
+ /**
+ * Creates a new 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
+ * - ERROR_NULL_ARGUMENT - if the control is null
+ *
+ */
+ public DropTargetEffect(Control control) {
+ if (control is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+ this.control = control;
+ }
+
+ /**
+ * Returns the Control which is registered for this DropTargetEffect. This is the control over which the
+ * user positions the cursor to drop the data.
+ *
+ * @return the Control which is registered for this DropTargetEffect
+ */
+ public Control getControl() {
+ return control;
+ }
+
+ /**
+ * Returns the item at the given x-y coordinate in the receiver
+ * or null if no such item exists. The x-y coordinate is in the
+ * display relative coordinates.
+ *
+ * @param x the x coordinate used to locate the item
+ * @param y the y coordinate used to locate the item
+ * @return the item at the given x-y coordinate, or null if the coordinate is not in a selectable item
+ */
+ public Widget getItem(int x, int y) {
+ if (control instanceof Table) {
+ return getItem((Table) control, x, y);
+ }
+ if (control instanceof Tree) {
+ return getItem((Tree) control, x, y);
+ }
+ return null;
+ }
+
+ Widget getItem(Table table, int x, int y) {
+ Point coordinates = new Point(x, y);
+ coordinates = table.toControl(coordinates);
+ TableItem item = table.getItem(coordinates);
+ if (item !is null) return item;
+ Rectangle area = table.getClientArea();
+ int tableBottom = area.y + area.height;
+ int itemCount = table.getItemCount();
+ for (int i=table.getTopIndex(); i tableBottom) break;
+ }
+ return null;
+ }
+
+ Widget getItem(Tree tree, int x, int y) {
+ Point point = new Point(x, y);
+ point = tree.toControl(point);
+ TreeItem item = tree.getItem(point);
+ if (item is null) {
+ Rectangle area = tree.getClientArea();
+ if (area.contains(point)) {
+ int treeBottom = area.y + area.height;
+ item = tree.getTopItem();
+ while (item !is null) {
+ Rectangle rect = item.getBounds();
+ int itemBottom = rect.y + rect.height;
+ if (rect.y <= point.y && point.y < itemBottom) return item;
+ if (itemBottom > treeBottom) break;
+ item = nextItem(tree, item);
+ }
+ return null;
+ }
+ }
+ return item;
+ }
+
+ TreeItem nextItem(Tree tree, TreeItem item) {
+ if (item is null) return null;
+ if (item.getExpanded() && item.getItemCount() > 0) return item.getItem(0);
+ TreeItem childItem = item;
+ TreeItem parentItem = childItem.getParentItem();
+ int index = parentItem is null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
+ int count = parentItem is null ? tree.getItemCount() : parentItem.getItemCount();
+ while (true) {
+ if (index + 1 < count) return parentItem is null ? tree.getItem(index + 1) : parentItem.getItem(index + 1);
+ if (parentItem is null) return null;
+ childItem = parentItem;
+ parentItem = childItem.getParentItem();
+ index = parentItem is null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
+ count = parentItem is null ? tree.getItemCount() : parentItem.getItemCount();
+ }
+ }
+
+ TreeItem previousItem(Tree tree, TreeItem item) {
+ if (item is null) return null;
+ TreeItem childItem = item;
+ TreeItem parentItem = childItem.getParentItem();
+ int index = parentItem is null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
+ if (index is 0) return parentItem;
+ TreeItem nextItem = parentItem is null ? tree.getItem(index-1) : parentItem.getItem(index-1);
+ int count = nextItem.getItemCount();
+ while (count > 0 && nextItem.getExpanded()) {
+ nextItem = nextItem.getItem(count - 1);
+ count = nextItem.getItemCount();
+ }
+ return nextItem;
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/DropTargetEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DropTargetEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.events.TypedEvent;
+import dwt.widgets.Widget;
+
+/**
+ * The DropTargetEvent contains the event information passed in the methods of the DropTargetListener.
+ */
+public class DropTargetEvent : TypedEvent {
+ /**
+ * The x-cordinate of the cursor relative to the 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 final 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 DropTargetEvent(DNDEvent e) {
+ super(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 380af2bdd8e5 dwt/dnd/DropTargetListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DropTargetListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * The DropTargetListener
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 : DWTEventListener {
+
+/**
+ * The cursor has entered the drop target boundaries.
+ *
+ * The following fields in the DropTargetEvent apply:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in)x
+ *
- (in)y
+ *
- (in)dataTypes
+ *
- (in,out)currentDataType
+ *
- (in)operations
+ *
- (in,out)detail
+ *
- (in,out)feedback
+ *
+ *
+ * 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.
+ *
+ * @param event the information associated with the drag enter event
+ *
+ * @see DropTargetEvent
+ */
+public void dragEnter(DropTargetEvent event);
+
+/**
+ * The cursor has left the drop target boundaries OR the drop has been cancelled OR the data
+ * is about to be dropped.
+ *
+ * The following fields in the DropTargetEvent apply:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in)x
+ *
- (in)y
+ *
- (in)dataTypes
+ *
- (in)currentDataType
+ *
- (in)operations
+ *
- (in)detail
+ *
+ *
+ * @param event the information associated with the drag leave event
+ *
+ * @see DropTargetEvent
+ */
+public void dragLeave(DropTargetEvent event);
+
+/**
+ * The operation being performed has changed (usually due to the user changing the selected modifier key(s)
+ * while dragging).
+ *
+ * The following fields in the DropTargetEvent apply:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in)x
+ *
- (in)y
+ *
- (in)dataTypes
+ *
- (in,out)currentDataType
+ *
- (in)operations
+ *
- (in,out)detail
+ *
- (in,out)feedback
+ *
+ *
+ * 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.
+ *
+ * @param event the information associated with the drag operation changed event
+ *
+ * @see DropTargetEvent
+ */
+public void dragOperationChanged(DropTargetEvent event);
+
+/**
+ * The cursor is moving over the drop target.
+ *
+ * The following fields in the DropTargetEvent apply:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in)x
+ *
- (in)y
+ *
- (in)dataTypes
+ *
- (in,out)currentDataType
+ *
- (in)operations
+ *
- (in,out)detail
+ *
- (in,out)feedback
+ *
+ *
+ * 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:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in)x
+ *
- (in)y
+ *
- (in,out)detail
+ *
- (in)currentDataType
+ *
- (in)data
+ *
+ *
+ * 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:
+ *
+ * - (in)widget
+ *
- (in)time
+ *
- (in)x
+ *
- (in)y
+ *
- (in)dataTypes
+ *
- (in,out)currentDataType
+ *
- (in)operations
+ *
- (in,out)detail
+ *
+ *
+ * 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.
+ *
+ * @param event the information associated with the drop accept event
+ *
+ * @see DropTargetEvent
+ */
+public void dropAccept(DropTargetEvent event);
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/FileTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/FileTransfer.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * 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
+ * Outhink - support for typeFileURL
+ *******************************************************************************/
+module dwt.dnd;
+
+import java.io.*;
+import dwt.internal.carbon.*;
+
+/**
+ * The class FileTransfer
provides a platform specific mechanism
+ * for converting a list of files represented as a java String[]
to a
+ * platform specific representation of the data and vice versa.
+ * Each String
in the array contains the absolute path for a single
+ * file or directory.
+ * See Transfer
for additional information.
+ *
+ * An example of a java String[]
containing a list of files is shown
+ * below:
+ * File file1 = new File("C:\temp\file1");
+ * File file2 = new File("C:\temp\file2");
+ * String[] fileData = new String[2];
+ * fileData[0] = file1.getAbsolutePath();
+ * fileData[1] = file2.getAbsolutePath();
+ *
+ */
+public class FileTransfer : ByteArrayTransfer {
+
+ static FileTransfer _instance = new FileTransfer();
+ static final String HFS = "hfs "; //$NON-NLS-1$
+ static final String FURL = "furl"; //$NON-NLS-1$
+ static final int HFSID = registerType(HFS);
+ static final int FURLID = registerType(FURL);
+
+FileTransfer() {}
+
+/**
+ * Returns the singleton instance of the FileTransfer class.
+ *
+ * @return the singleton instance of the FileTransfer class
+ */
+public static FileTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts a list of file names
+ * represented by a java String[]
to a platform specific representation.
+ * Each String
in the array contains the absolute path for a single
+ * file or directory. For additional information see
+ * Transfer#javaToNative
.
+ *
+ * @param object a java String[]
containing the file names to be
+ * converted
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative(Object object, TransferData transferData) {
+ if (!checkFile(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String[] files = (String[])object;
+ transferData.result = -1;
+ byte[][] data = new byte[files.length][];
+ for (int i = 0; i < data.length; i++) {
+ File file = new File(files[i]);
+ bool isDirectory = file.isDirectory();
+ String fileName = files[i];
+ char [] chars = new char [fileName.length ()];
+ fileName.getChars (0, chars.length, chars, 0);
+ int cfString = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, chars, chars.length);
+ if (cfString is 0) return;
+ try {
+ int url = OS.CFURLCreateWithFileSystemPath(OS.kCFAllocatorDefault, cfString, OS.kCFURLPOSIXPathStyle, isDirectory);
+ if (url is 0) return;
+ try {
+ if (transferData.type is HFSID) {
+ byte[] fsRef = new byte[80];
+ if (!OS.CFURLGetFSRef(url, fsRef)) return;
+ byte[] fsSpec = new byte[70];
+ if (OS.FSGetCatalogInfo(fsRef, 0, null, null, fsSpec, null) !is OS.noErr) return;
+ byte[] hfsflavor = new byte[10 + fsSpec.length];
+ byte[] finfo = new byte[16];
+ OS.FSpGetFInfo(fsSpec, finfo);
+ System.arraycopy(finfo, 0, hfsflavor, 0, 10);
+ System.arraycopy(fsSpec, 0, hfsflavor, 10, fsSpec.length);
+ data[i] = hfsflavor;
+ }
+ if (transferData.type is FURLID) {
+ int encoding = OS.CFStringGetSystemEncoding();
+ int theData = OS.CFURLCreateData(OS.kCFAllocatorDefault, url, encoding, true);
+ if (theData is 0) return;
+ try {
+ int length = OS.CFDataGetLength(theData);
+ byte[] buffer = new byte[length];
+ CFRange range = new CFRange();
+ range.length = length;
+ OS.CFDataGetBytes(theData, range, buffer);
+ data[i] = buffer;
+ } finally {
+ OS.CFRelease(theData);
+ }
+ }
+ } finally {
+ OS.CFRelease(url);
+ }
+ } finally {
+ OS.CFRelease(cfString);
+ }
+ }
+ transferData.data = data;
+ transferData.result = 0;
+}
+/**
+ * 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.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String[]
containing a list of file names if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.data is null) return null;
+ if (transferData.data.length is 0) return null;
+ int count = transferData.data.length;
+ String[] fileNames = new String[count];
+ for (int i=0; iString
+ * to a platform specific representation of the data and vice versa. See
+ * Transfer
for additional information.
+ *
+ * An example of a java String
containing HTML text is shown
+ * below:
+ * String htmlData = "This is a paragraph of text.
";
+ *
+ */
+public class HTMLTransfer : ByteArrayTransfer {
+
+ static HTMLTransfer _instance = new HTMLTransfer();
+ static final String HTML = "HTML"; //$NON-NLS-1$
+ static final int HTMLID = registerType(HTML);
+
+HTMLTransfer() {}
+
+/**
+ * Returns the singleton instance of the HTMLTransfer class.
+ *
+ * @return the singleton instance of the HTMLTransfer class
+ */
+public static HTMLTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts HTML-formatted text
+ * represented by a java String
to a platform specific representation.
+ * For additional information see Transfer#javaToNative
.
+ *
+ * @param object a java String
containing HTML text
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkHTML(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String String = (String)object;
+ int count = String.length();
+ char[] chars = new char[count];
+ String.getChars(0, count, chars, 0);
+ byte[] buffer = new byte[chars.length * 2];
+ OS.memmove(buffer, chars, buffer.length);
+ transferData.data = new byte[1][];
+ transferData.data[0] = buffer;
+ transferData.result = OS.noErr;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of HTML text to a java String
.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String
containing HTML text if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.data is null) return null;
+ if (transferData.data.length is 0 || transferData.data[0].length is 0) return null;
+ byte[] buffer = transferData.data[0];
+ char[] chars = new char[(buffer.length + 1) / 2];
+ OS.memmove(chars, buffer, buffer.length);
+ return new String(chars);
+}
+
+protected int[] getTypeIds() {
+ return new int[] {HTMLID};
+}
+
+protected String[] getTypeNames() {
+ return new String[] {HTML};
+}
+
+bool checkHTML(Object object) {
+ return (object !is null && object instanceof String && ((String)object).length() > 0);
+}
+
+protected bool validate(Object object) {
+ return checkHTML(object);
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/ImageTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/ImageTransfer.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ * Outhink - support for typeFileURL
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.DWT;
+import dwt.graphics.*;
+import dwt.internal.carbon.*;
+import dwt.widgets.*;
+
+/**
+ * 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. The
+ * ImageData
contains infomration about the Image. See
+ * Transfer
for additional information.
+ *
+ *
+ * An example of a java Image
containing an ImageData is shown
+ * below:
+ *
+ * Image image = new Image(display, fileName);
+ * ImageData imgData = image.getImageData();
+ *
+ */
+public class ImageTransfer : ByteArrayTransfer {
+
+static ImageTransfer _instance = new ImageTransfer();
+static final String PICT = "PICT"; //$NON-NLS-1$
+static final String TIFF = "TIFF"; //$NON-NLS-1$
+static final int PICTID = registerType(PICT);
+static final int TIFFID = registerType(TIFF);
+
+ImageTransfer() {
+}
+
+/**
+ * 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 a java ImageData
to a platform
+ * specific representation. For additional information see
+ * Transfer#javaToNative
.
+ *
+ * @param object
+ * a java ImageData
+ * @param transferData
+ * an empty TransferData
object; this object will
+ * be filled in on return with the platform specific format of
+ * the data
+ */
+public void javaToNative(Object object, TransferData transferData) {
+ if (!checkImage(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.result = -1;
+
+ ImageData imgData = (ImageData) object;
+ Image image = new Image(Display.getCurrent(), imgData);
+ int handle = image.handle;
+ int width = OS.CGImageGetWidth(handle);
+ int height = OS.CGImageGetHeight(handle);
+ int alphaInfo = OS.CGImageGetAlphaInfo(handle);
+ int bpr = OS.CGImageGetBytesPerRow(handle);
+
+ Rect rect = new Rect();
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = (short) width;
+ rect.bottom = (short) height;
+
+ int[] gWorld = new int[1];
+ int format = OS.k24RGBPixelFormat;
+ if (alphaInfo !is OS.kCGImageAlphaNoneSkipFirst) {
+ format = OS.k32ARGBPixelFormat;
+ }
+ OS.NewGWorldFromPtr(gWorld, format, rect, 0, 0, 0, image.data, bpr);
+ int[] curPort = new int[1];
+ int[] curGWorld = new int[1];
+ OS.GetGWorld(curPort, curGWorld);
+ OS.SetGWorld(gWorld[0], curGWorld[0]);
+ int pictHandle = OS.OpenPicture(rect);
+ int portBitMap = OS.GetPortBitMapForCopyBits(gWorld[0]);
+ OS.CopyBits(portBitMap, portBitMap, rect, rect, (short) OS.srcCopy, 0);
+ OS.ClosePicture();
+ OS.SetGWorld(curPort[0], curGWorld[0]);
+ OS.DisposeGWorld(gWorld[0]);
+ int length = OS.GetHandleSize(pictHandle);
+ OS.HLock(pictHandle);
+ int[] buffer = new int[1];
+ OS.memmove(buffer, pictHandle, 4);
+ byte[] pictData = new byte[length];
+ OS.memmove(pictData, buffer[0], length);
+ OS.HUnlock(pictHandle);
+ OS.KillPicture(pictHandle);
+ image.dispose();
+
+ transferData.data = new byte[][] { pictData };
+ transferData.result = OS.noErr;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform
+ * specific representation of an ImageData ImageData
. For
+ * additional information see Transfer#nativeToJava
.
+ *
+ * @param transferData
+ * the platform specific representation of the data to be been
+ * converted
+ * @return a java ImageData
object if the conversion was
+ * successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.data is null)
+ return null;
+ if (transferData.data.length is 0)
+ return null;
+ byte[] dataArr = transferData.data[0];
+ int size = dataArr.length;
+ int pictPtr = OS.NewPtr(size);
+ OS.memmove(pictPtr, dataArr, size);
+ int dataProvider = OS.CGDataProviderCreateWithData(0, pictPtr, size, 0);
+ if (dataProvider !is 0) {
+ int pictDataRef = OS.QDPictCreateWithProvider(dataProvider);
+ // get bounds for the image
+ CGRect rect = new CGRect();
+ OS.QDPictGetBounds(pictDataRef, rect);
+ int width = (int) rect.width;
+ int height = (int) rect.height;
+
+ /* Create the image */
+ int bpr = width * 4;
+ int dataSize = height * bpr;
+ int data = OS.NewPtr(dataSize);
+ if (data is 0)
+ DWT.error(DWT.ERROR_NO_HANDLES);
+ int provider = OS
+ .CGDataProviderCreateWithData(0, data, dataSize, 0);
+ if (provider is 0) {
+ OS.DisposePtr(data);
+ DWT.error(DWT.ERROR_NO_HANDLES);
+ }
+ int colorspace = OS.CGColorSpaceCreateDeviceRGB();
+ if (colorspace is 0)
+ DWT.error(DWT.ERROR_NO_HANDLES);
+ int handle = OS.CGImageCreate(width, height, 8, 32, bpr,
+ colorspace, OS.kCGImageAlphaNoneSkipFirst, provider, null,
+ true, 0);
+ OS.CGDataProviderRelease(provider);
+ if (handle is 0) {
+ OS.DisposePtr(data);
+ DWT.error(DWT.ERROR_NO_HANDLES);
+ }
+ int bpc = OS.CGImageGetBitsPerComponent(handle);
+ int context = OS.CGBitmapContextCreate(data, width, height, bpc,
+ bpr, colorspace, OS.kCGImageAlphaNoneSkipFirst);
+ if (context is 0) {
+ OS.CGImageRelease(handle);
+ OS.DisposePtr(data);
+ DWT.error(DWT.ERROR_NO_HANDLES);
+ }
+ int status = OS.QDPictDrawToCGContext(context, rect, pictDataRef);
+ ImageData imgData = null;
+ if (status is 0) {
+ Image image = Image.carbon_new(Display.getCurrent(),
+ DWT.BITMAP, handle, data);
+ imgData = image.getImageData();
+ image.dispose();
+ }
+ OS.CGContextRelease(context);
+ OS.QDPictRelease(pictDataRef);
+ return imgData;
+ }
+ return null;
+}
+
+protected int[] getTypeIds() {
+ return new int[] { PICTID };
+}
+
+protected String[] getTypeNames() {
+ return new String[] { PICT };
+}
+
+bool checkImage(Object object) {
+ if (object is null || !(object instanceof ImageData)) return false;
+ return true;
+}
+
+protected bool validate(Object object) {
+ return checkImage(object);
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/RTFTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/RTFTransfer.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.internal.carbon.OS;
+import dwt.internal.carbon.CFRange;
+
+/**
+ * The class RTFTransfer
provides a platform specific mechanism
+ * for converting text in RTF format represented as a java String
+ * to a platform specific representation of the data and vice versa. See
+ * Transfer
for additional information.
+ *
+ * An example of a java String
containing RTF text is shown
+ * below:
+ * String rtfData = "{\\rtf1{\\colortbl;\\red255\\green0\\blue0;}\\uc1\\b\\i Hello World}";
+ *
+ */
+public class RTFTransfer : ByteArrayTransfer {
+
+ static RTFTransfer _instance = new RTFTransfer();
+ static final String RTF = "RTF "; //$NON-NLS-1$
+ static final int RTFID = registerType(RTF);
+
+RTFTransfer() {}
+
+/**
+ * Returns the singleton instance of the RTFTransfer class.
+ *
+ * @return the singleton instance of the RTFTransfer class
+ */
+public static RTFTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts RTF-formatted text
+ * represented by a java String
to a platform specific representation.
+ * For additional information see Transfer#javaToNative
.
+ *
+ * @param object a java String
containing RTF text
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkRTF(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.result = -1;
+ String String = (String)object;
+ int count = String.length();
+ char[] chars = new char[count];
+ String.getChars(0, count, chars, 0);
+ int cfString = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, chars, count);
+ if (cfString is 0) return;
+ try {
+ CFRange range = new CFRange();
+ range.length = chars.length;
+ int encoding = OS.CFStringGetSystemEncoding();
+ int[] size = new int[1];
+ int numChars = OS.CFStringGetBytes(cfString, range, encoding, (byte)'?', true, null, 0, size);
+ if (numChars is 0 || size[0] is 0) return;
+ byte[] buffer = new byte[size[0]];
+ numChars = OS.CFStringGetBytes(cfString, range, encoding, (byte)'?', true, buffer, size [0], size);
+ if (numChars is 0) return;
+ transferData.data = new byte[1][];
+ transferData.data[0] = buffer;
+ transferData.result = 0;
+ } finally {
+ OS.CFRelease(cfString);
+ }
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of RTF text to a java String
.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String
containing RTF text if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.data is null) return null;
+ if (transferData.data.length is 0 || transferData.data[0].length is 0) return null;
+ byte[] buffer = transferData.data[0];
+ int encoding = OS.CFStringGetSystemEncoding();
+ int cfString = OS.CFStringCreateWithBytes(OS.kCFAllocatorDefault, buffer, buffer.length, encoding, true);
+ if (cfString is 0) return null;
+ try {
+ int length = OS.CFStringGetLength(cfString);
+ if (length is 0) return null;
+ char[] chars = new char[length];
+ CFRange range = new CFRange();
+ range.length = length;
+ OS.CFStringGetCharacters(cfString, range, chars);
+ return new String(chars);
+ } finally {
+ OS.CFRelease(cfString);
+ }
+}
+
+protected int[] getTypeIds() {
+ return new int[] {RTFID};
+}
+
+protected String[] getTypeNames() {
+ return new String[] {RTF};
+}
+
+bool checkRTF(Object object) {
+ return (object !is null && object instanceof String && ((String)object).length() > 0);
+}
+
+protected bool validate(Object object) {
+ return checkRTF(object);
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/TableDragSourceEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/TableDragSourceEffect.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.widgets.*;
+
+/**
+ * This class provides default implementations to display a source image
+ * when a drag is initiated from a 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
+ *
+ * @since 3.3
+ */
+public class TableDragSourceEffect : DragSourceEffect {
+ /**
+ * 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 TableDragSourceEffect(Table table) {
+ super(table);
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/TableDropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/TableDropTargetEffect.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.DWT;
+import dwt.graphics.*;
+import dwt.internal.Callback;
+import dwt.internal.carbon.DataBrowserCallbacks;
+import dwt.internal.carbon.OS;
+import dwt.widgets.*;
+
+/**
+ * This class provides a default drag under effect (eg. select, insert and scroll)
+ * when a drag occurs over a 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 TableDropTargetEffect(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) {
+ if (callbacks is null) {
+ Table table = (Table) control;
+ DataBrowserCallbacks callbacks = new DataBrowserCallbacks ();
+ OS.GetDataBrowserCallbacks (table.handle, callbacks);
+ callbacks.v1_acceptDragCallback = AcceptDragProc.getAddress();
+ OS.SetDataBrowserCallbacks(table.handle, callbacks);
+ }
+ scrollBeginTime = 0;
+ scrollItem = 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) {
+ scrollBeginTime = 0;
+ scrollItem = null;
+ }
+
+ /**
+ * 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 = (Table) control;
+ int effect = checkEffect(event.feedback);
+
+ TableItem item = (TableItem)getItem(table, event.x, event.y);
+
+ if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+ scrollBeginTime = 0;
+ scrollItem = null;
+ } else {
+ if (item !is null && item.opEquals(scrollItem) && scrollBeginTime !is 0) {
+ if (System.currentTimeMillis() >= scrollBeginTime) {
+ Rectangle area = table.getClientArea();
+ int headerHeight = table.getHeaderHeight();
+ int itemHeight= table.getItemHeight();
+ Point pt = new Point(event.x, event.y);
+ pt = table.getDisplay().map(null, table, pt);
+ TableItem nextItem = null;
+ if (pt.y < area.y + headerHeight + 2 * itemHeight) {
+ int index = Math.max(0, table.indexOf(item)-1);
+ nextItem = table.getItem(index);
+ }
+ if (pt.y > area.y + area.height - 2 * itemHeight) {
+ int index = Math.min(table.getItemCount()-1, table.indexOf(item)+1);
+ nextItem = table.getItem(index);
+ }
+ if (nextItem !is null) table.showItem(nextItem);
+ scrollBeginTime = 0;
+ scrollItem = null;
+ }
+ } else {
+ scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+ scrollItem = item;
+ }
+ }
+
+ // store current effect for selection feedback
+ ((DropTarget)event.widget).feedback = effect;
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/TextTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/TextTransfer.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.internal.carbon.CFRange;
+import dwt.internal.carbon.OS;
+
+/**
+ * The class TextTransfer
provides a platform specific mechanism
+ * for converting plain text represented as a java String
+ * to a platform specific representation of the data and vice versa.
+ *
+ * An example of a java String
containing plain text is shown
+ * below:
+ * String textData = "Hello World";
+ *
+ *
+ * @see Transfer
+ */
+public class TextTransfer : ByteArrayTransfer {
+
+ static TextTransfer _instance = new TextTransfer();
+ static final String TEXT = "TEXT"; //$NON-NLS-1$
+ static final String UTEXT = "utxt"; //$NON-NLS-1$
+ static final int TEXTID = OS.kScrapFlavorTypeText;
+ static final int UTEXTID = OS.kScrapFlavorTypeUnicode;
+
+TextTransfer() {}
+
+/**
+ * Returns the singleton instance of the TextTransfer class.
+ *
+ * @return the singleton instance of the TextTransfer class
+ */
+public static TextTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts plain text
+ * represented by a java String
to a platform specific representation.
+ *
+ * @param object a java String
containing text
+ * @param transferData an empty TransferData
object; this object
+ * will be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#javaToNative
+ */
+public void javaToNative (Object object, TransferData transferData) {
+ if (!checkText(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String String = (String)object;
+ char[] chars = new char[String.length()];
+ String.getChars (0, chars.length, chars, 0);
+ transferData.result = -1;
+ switch (transferData.type) {
+ case TEXTID: {
+ int cfString = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, chars, chars.length);
+ if (cfString is 0) return;
+ byte[] buffer = null;
+ try {
+ CFRange range = new CFRange();
+ range.length = chars.length;
+ int encoding = OS.CFStringGetSystemEncoding();
+ int[] size = new int[1];
+ int numChars = OS.CFStringGetBytes(cfString, range, encoding, (byte)'?', true, null, 0, size);
+ if (numChars is 0) return;
+ buffer = new byte[size[0]];
+ numChars = OS.CFStringGetBytes(cfString, range, encoding, (byte)'?', true, buffer, size [0], size);
+ if (numChars is 0) return;
+ } finally {
+ OS.CFRelease(cfString);
+ }
+ transferData.data = new byte[1][];
+ transferData.data[0] = buffer;
+ transferData.result = OS.noErr;
+ break;
+ }
+ case UTEXTID: {
+ byte[] buffer = new byte[chars.length * 2];
+ OS.memmove(buffer, chars, buffer.length);
+ transferData.data = new byte[1][];
+ transferData.data[0] = buffer;
+ transferData.result = OS.noErr;
+ break;
+ }
+ }
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of plain text to a java String
.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java String
containing text if the conversion was successful; otherwise null
+ *
+ * @see Transfer#nativeToJava
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.data is null) return null;
+ if (transferData.data.length is 0 || transferData.data[0].length is 0) return null;
+ byte[] buffer = transferData.data[0];
+ switch (transferData.type) {
+ case TEXTID: {
+ int encoding = OS.CFStringGetSystemEncoding();
+ int cfString = OS.CFStringCreateWithBytes(OS.kCFAllocatorDefault, buffer, buffer.length, encoding, true);
+ if (cfString is 0) return null;
+ try {
+ int length = OS.CFStringGetLength(cfString);
+ if (length is 0) return null;
+ char[] chars = new char[length];
+ CFRange range = new CFRange();
+ range.length = length;
+ OS.CFStringGetCharacters(cfString, range, chars);
+ return new String(chars);
+ } finally {
+ OS.CFRelease(cfString);
+ }
+ }
+ case UTEXTID: {
+ char[] chars = new char[(buffer.length + 1) / 2];
+ OS.memmove(chars, buffer, buffer.length);
+ return new String(chars);
+ }
+ }
+ return null;
+}
+
+protected int[] getTypeIds() {
+ return new int[] {UTEXTID, TEXTID};
+}
+
+protected String[] getTypeNames() {
+ return new String[] {UTEXT, TEXT};
+}
+
+bool checkText(Object object) {
+ return (object !is null && object instanceof String && ((String)object).length() > 0);
+}
+protected bool validate(Object object) {
+ return checkText(object);
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/Transfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/Transfer.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+
+/**
+ * Transfer
provides a mechanism for converting between a java
+ * representation of data and a platform specific representation of data and
+ * vice versa. It is used in data transfer operations such as drag and drop and
+ * clipboard copy/paste.
+ *
+ * You should only need to become familiar with this class if you are + * implementing a Transfer subclass and you are unable to subclass the + * ByteArrayTransfer class.
+ * + * @see ByteArrayTransfer + */ +public abstract class Transfer { + +/** + * 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 dwt.DWTException null
null
then
+ * null
is returned. The type of Object that is returned is
+ * dependent on the Transfer
subclass.
+ */
+abstract protected 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) { + int length = formatName.length(); + // TODO - hashcode may not be unique - need another way + if (length > 4) return formatName.toHash(); + int type = 0; + if (length > 0) type |= (formatName.charAt(0) & 0xff) << 24; + if (length > 1) type |= (formatName.charAt(1) & 0xff) << 16; + if (length > 2) type |= (formatName.charAt(2) & 0xff) << 8; + if (length > 3) type |= formatName.charAt(3) & 0xff; + return type; +} + +/** + * Test that the object is of the correct format for this Transfer class. + * + * @param object a java representation of the data to be converted + * + * @return true if object is of the correct form for this transfer type + * + * @since 3.1 + */ +protected bool validate(Object object) { + return true; +} +} diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/TransferData.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/TransferData.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,69 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.dnd; + + +/** + * TheTransferData
class is a platform specific data structure for
+ * describing the type and the contents of data being converted by a transfer agent.
+ *
+ * As an application writer, you do not need to know the specifics of + * TransferData. TransferData instances are passed to a subclass of Transfer + * and the Transfer object manages the platform specific issues. + * You can ask a Transfer subclass if it can handle this data by calling + * Transfer.isSupportedType(transferData).
+ * + *You should only need to become familiar with the fields in this class if you + * are implementing a Transfer subclass and you are unable to subclass the + * ByteArrayTransfer class.
+ */ +public class TransferData { + /** + * The 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 DWT + * public API. It is marked public only so that it can be shared + * within the modules provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public int type; + + /** + * The data being transferred. + * The data field may contain multiple values. + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the modules provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public byte[][] data; + + /** + * 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 DWT + * public API. It is marked public only so that it can be shared + * within the modules provided by DWT. 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; + +} diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/TreeDragSourceEffect.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/TreeDragSourceEffect.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 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 + *******************************************************************************/ +module dwt.dnd; + +import dwt.widgets.*; + +/** + * This class provides default implementations to display a source image + * when a drag is initiated from aTree
.
+ *
+ * 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
+ *
+ * @since 3.3
+ */
+public class TreeDragSourceEffect : DragSourceEffect {
+ /**
+ * 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 TreeDragSourceEffect(Tree tree) {
+ super(tree);
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/TreeDropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/TreeDropTargetEffect.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.dnd;
+
+import dwt.*;
+import dwt.graphics.*;
+import dwt.internal.Callback;
+import dwt.internal.carbon.DataBrowserCallbacks;
+import dwt.internal.carbon.OS;
+import dwt.widgets.*;
+
+/**
+ * This class provides a default drag under effect (eg. select, insert, scroll and expand)
+ * when a drag occurs over a 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 + * + * @since 3.3 + */ +public class TreeDropTargetEffect : DropTargetEffect { + static final int SCROLL_HYSTERESIS = 150; // milli seconds + static final int EXPAND_HYSTERESIS = 1000; // milli seconds + + int currentEffect = DND.FEEDBACK_NONE; + TreeItem currentItem; + + TreeItem insertItem = null; + bool insertBefore = false; + + TreeItem scrollItem; + long scrollBeginTime; + + TreeItem expandItem; + long expandBeginTime; + + DataBrowserCallbacks callbacks = null; + + int acceptDragProc(int theControl, int itemID, int property, int theRect, int theDrag) { + return (currentEffect & DND.FEEDBACK_SELECT) !is 0 ? 1 : 0; + } + + static Callback AcceptDragProc; + static { + AcceptDragProc = new Callback(TreeDropTargetEffect.class, "AcceptDragProc", 5); //$NON-NLS-1$ + int acceptDragProc = AcceptDragProc.getAddress(); + if (acceptDragProc is 0) DWT.error(DWT.ERROR_NO_MORE_CALLBACKS); + } + + static int AcceptDragProc(int theControl, int itemID, int property, int theRect, int theDrag) { + DropTarget target = FindDropTarget(theControl, theDrag); + if (target is null) return 0; + return (target.feedback & DND.FEEDBACK_SELECT) !is 0 ? 1 : 0; + } + + static DropTarget FindDropTarget(int theControl, int theDrag) { + if (theControl is 0) return null; + Display display = Display.findDisplay(Thread.currentThread()); + if (display is null || display.isDisposed()) return null; + Widget widget = display.findWidget(theControl); + if (widget is null) return null; + return (DropTarget)widget.getData(DND.DROP_TARGET_KEY); + } + + /** + * 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 TreeDropTargetEffect(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) {
+ if (callbacks is null) {
+ Tree table = (Tree) control;
+ DataBrowserCallbacks callbacks = new DataBrowserCallbacks ();
+ OS.GetDataBrowserCallbacks (table.handle, callbacks);
+ callbacks.v1_acceptDragCallback = AcceptDragProc.getAddress();
+ OS.SetDataBrowserCallbacks(table.handle, callbacks);
+ }
+ insertItem = null;
+ expandBeginTime = 0;
+ expandItem = null;
+ scrollBeginTime = 0;
+ scrollItem = 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) {
+ Tree tree = (Tree) control;
+ if (insertItem !is null) {
+ setInsertMark(tree, null, false);
+ insertItem = null;
+ }
+ expandBeginTime = 0;
+ expandItem = null;
+ scrollBeginTime = 0;
+ scrollItem = null;
+ }
+
+ /**
+ * 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 = (Tree) control;
+ TreeItem item = (TreeItem)getItem(tree, event.x, event.y);
+ int effect = checkEffect(event.feedback);
+ if ((effect & DND.FEEDBACK_EXPAND) is 0) {
+ expandBeginTime = 0;
+ expandItem = null;
+ } else {
+ if (item !is null && item.opEquals(expandItem) && expandBeginTime !is 0) {
+ if (System.currentTimeMillis() >= expandBeginTime) {
+ if (item.getItemCount() > 0 && !item.getExpanded()) {
+ Event e = new Event();
+ e.x = event.x;
+ e.y = event.y;
+ e.item = item;
+ e.time = (int) System.currentTimeMillis();
+ tree.notifyListeners(DWT.Expand, e);
+ if (item.isDisposed()) return;
+ item.setExpanded(true);
+ }
+ expandBeginTime = 0;
+ expandItem = null;
+ }
+ } else {
+ expandBeginTime = System.currentTimeMillis() + EXPAND_HYSTERESIS;
+ expandItem = item;
+ }
+ }
+
+ if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+ scrollBeginTime = 0;
+ scrollItem = null;
+ } else {
+ if (item !is null && item.opEquals(scrollItem) && scrollBeginTime !is 0) {
+ if (System.currentTimeMillis() >= scrollBeginTime) {
+ Rectangle area = tree.getClientArea();
+ int headerHeight = tree.getHeaderHeight();
+ int itemHeight= tree.getItemHeight();
+ Point pt = new Point(event.x, event.y);
+ pt = tree.getDisplay().map(null, tree, pt);
+ TreeItem nextItem = null;
+ if (pt.y < area.y + headerHeight + 2 * itemHeight) {
+ nextItem = previousItem(tree, item);
+ }
+ if (pt.y > area.y + area.height - 2 * itemHeight) {
+ nextItem = nextItem(tree, item);
+ }
+ if (nextItem !is null) tree.showItem(nextItem);
+ scrollBeginTime = 0;
+ scrollItem = null;
+ }
+ } else {
+ scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+ scrollItem = item;
+ }
+ }
+
+ if ((effect & DND.FEEDBACK_INSERT_AFTER) !is 0 ||
+ (effect & DND.FEEDBACK_INSERT_BEFORE) !is 0) {
+ if (currentItem !is item ||
+ ((effect & DND.FEEDBACK_INSERT_AFTER) !is (currentEffect & DND.FEEDBACK_INSERT_AFTER)) ||
+ ((effect & DND.FEEDBACK_INSERT_BEFORE) !is (currentEffect & DND.FEEDBACK_INSERT_BEFORE))) {
+ setInsertMark(tree, item, (effect & DND.FEEDBACK_INSERT_BEFORE) !is 0);
+ currentEffect = effect;
+ currentItem = item;
+ }
+ } else {
+ setInsertMark(tree, null, false);
+ }
+ // save current effect for selection feedback
+ ((DropTarget)event.widget).feedback = effect;
+ }
+
+ void setInsertMark(Tree tree, TreeItem item, bool before) {
+ if (item is insertItem && before is insertBefore) return;
+ insertItem = item;
+ insertBefore = before;
+ tree.setInsertMark(item, before);
+ }
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dnd/URLTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/URLTransfer.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,1 @@
+/*******************************************************************************
* Copyright (c) 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
*******************************************************************************/
module dwt.dnd;
import dwt.internal.carbon.*;
/**
* The class URLTransfer
provides a platform specific mechanism
* for converting text in URL format represented as a java String
* to a platform specific representation of the data and vice versa. See
* Transfer
for additional information. The String
* must contain the fully specified url.
*
* An example of a java String[]
containing a URL is shown
* below:
* String url = "http://www.eclipse.org";
*
*/
public class URLTransfer : ByteArrayTransfer {
static URLTransfer _instance = new URLTransfer();
static final String URL = "url "; //$NON-NLS-1$
static final int URL_ID = registerType(URL);
static final String URLN = "urln"; //$NON-NLS-1$
static final int URLN_ID = registerType(URLN);
private URLTransfer() {}
/**
* Returns the singleton instance of the URLTransfer class.
*
* @return the singleton instance of the URLTransfer class
*/
public static URLTransfer getInstance () {
return _instance;
}
/**
* This implementation of javaToNative
converts a URL
* represented by a java String
to a platform specific representation.
* For additional information see Transfer#javaToNative
.
*
* @param object a java String[]
containing a URL
* @param transferData an empty TransferData
object; this
* object will be filled in on return with the platform specific format of the data
*/
public void javaToNative (Object object, TransferData transferData){
if (!checkURL(object) || !isSupportedType(transferData)) {
DND.error(DND.ERROR_INVALID_DATA);
}
transferData.result = -1;
String url = (String)object;
int count = url.length();
char[] chars = new char[count];
url.getChars(0, count, chars, 0);
int cfString = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, chars, count);
if (cfString is 0) return;
try {
CFRange range = new CFRange();
range.length = chars.length;
int encoding = OS.CFStringGetSystemEncoding();
int[] size = new int[1];
int numChars = OS.CFStringGetBytes(cfString, range, encoding, (byte)'?', true, null, 0, size);
if (numChars is 0 || size[0] is 0) return;
byte[] buffer = new byte[size[0]];
numChars = OS.CFStringGetBytes(cfString, range, encoding, (byte)'?', true, buffer, size [0], size);
if (numChars is 0) return;
transferData.data = new byte[][] {buffer};
transferData.result = 0;
} finally {
OS.CFRelease(cfString);
}
}
/**
* This implementation of nativeToJava
converts a platform specific
* representation of a URL to a java String
.
* For additional information see Transfer#nativeToJava
.
*
* @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
*/
public Object nativeToJava(TransferData transferData){
if (!isSupportedType(transferData) || transferData.data is null) return null;
if (transferData.data.length is 0) return null;
byte[] buffer = transferData.data[0];
int encoding = OS.CFStringGetSystemEncoding();
int cfString = OS.CFStringCreateWithBytes(OS.kCFAllocatorDefault, buffer, buffer.length, encoding, true);
if (cfString is 0) return null;
try {
int length = OS.CFStringGetLength(cfString);
if (length is 0) return null;
char[] chars = new char[length];
CFRange range = new CFRange();
range.length = length;
OS.CFStringGetCharacters(cfString, range, chars);
return new String(chars);
} finally {
OS.CFRelease(cfString);
}
}
protected int[] getTypeIds(){
return new int[] {URL_ID, URLN_ID};
}
protected String[] getTypeNames(){
return new String[] {URL, URLN};
}
bool checkURL(Object object) {
return object !is null && (object instanceof String) && ((String)object).length() > 0;
}
protected bool validate(Object object) {
return checkURL(object);
}
}
diff -r 000000000000 -r 380af2bdd8e5 dwt/dwthelper/BufferedInputStream.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dwthelper/BufferedInputStream.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,107 @@
+/**
+ * Authors: Frank Benoit
+ * After creating an instance of a class that implements
+ * 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 380af2bdd8e5 dwt/events/ControlEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/ControlEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.events.ControlEvent;
+
+import dwt.dwthelper.utils;
+
+
+import dwt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * controls being moved or resized.
+ *
+ * @see ControlListener
+ */
+
+public final class ControlEvent : TypedEvent {
+
+ static final long serialVersionUID = 3258132436155119161L;
+
+/**
+ * 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 ControlEvent(Event e) {
+ super(e);
+}
+
+}
+
+
diff -r 000000000000 -r 380af2bdd8e5 dwt/events/ControlListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/ControlListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -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
+ *******************************************************************************/
+module dwt.events.ControlListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated by moving
+ * and resizing controls.
+ *
+ * After creating an instance of a class that implements
+ * 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 380af2bdd8e5 dwt/events/DisposeEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/DisposeEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.events.DisposeEvent;
+
+import dwt.dwthelper.utils;
+
+
+import dwt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets being disposed.
+ *
+ * @see DisposeListener
+ */
+
+public final class DisposeEvent : TypedEvent {
+
+ static final long serialVersionUID = 3257566187633521206L;
+
+/**
+ * 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 DisposeEvent(Event e) {
+ super(e);
+}
+
+}
+
diff -r 000000000000 -r 380af2bdd8e5 dwt/events/DisposeListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/DisposeListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.events.DisposeListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when a widget
+ * is disposed.
+ *
+ * After creating an instance of a class that implements
+ * 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 implements
+ * 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
+ *
+ * @since 3.2
+ */
+
+public class ExpandEvent extends 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 ExpandEvent(Event e) {
+ super(e);
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/events/ExpandListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/ExpandListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.events.ExpandListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the expanding and collapsing of ExpandItem
s.
+ *
+ *
+ * After creating an instance of a class that implements
+ * 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 implements
+ * 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 implements
+ * 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 + */ + +public class KeyEvent extends 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 DWT.CTRL) or the resulting + * character will not be correct. + */ + public char character; + + /** + * the key code of the key that was typed, + * as defined by the key code constants in classDWT
.
+ * 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 dwt.DWT
+ */
+ 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 DWT
.
+ *
+ * @see dwt.DWT
+ */
+ 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 KeyEvent(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 String toString() {
+ String string = super.toString ();
+ return string.substring (0, string.length() - 1) // remove trailing '}'
+ + " character='" + ((character is 0) ? "\\0" : "" + character) + "'"
+ + " keyCode=" + keyCode
+ + " stateMask=" + stateMask
+ + " doit=" + doit
+ + "}";
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/events/KeyListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/KeyListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -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
+ *******************************************************************************/
+module dwt.events.KeyListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as keys
+ * are pressed on the system keyboard.
+ *
+ * After creating an instance of a class that implements
+ * 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 MenuDetectEvent(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 String toString() {
+ String string = super.toString ();
+ return string.substring (0, string.length() - 1) // remove trailing '}'
+ + " x=" + x
+ + " y=" + y
+ + " doit=" + doit
+ + "}";
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/events/MenuDetectListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/MenuDetectListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.events.MenuDetectListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when the
+ * platform-specific trigger for showing a context menu is
+ * detected.
+ *
+ * After creating an instance of a class that implements
+ * 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 implements
+ * 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 implements
+ * 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 DWT
mask constants BUTTONx
.
+ *
+ * After creating an instance of a class that implements
+ * 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 implements
+ * 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 implements
+ * 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 implements
+ * 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 implements
+ * 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 + */ + +public class SelectionEvent extends 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 SelectionEvent(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 String toString() {
+ String string = super.toString ();
+ return string.substring (0, string.length() - 1) // remove trailing '}'
+ + " item=" + item
+ + " detail=" + detail
+ + " x=" + x
+ + " y=" + y
+ + " width=" + width
+ + " height=" + height
+ + " stateMask=" + stateMask
+ + " text=" + text
+ + " doit=" + doit
+ + "}";
+}
+}
+
diff -r 000000000000 -r 380af2bdd8e5 dwt/events/SelectionListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/SelectionListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.events.SelectionListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when selection
+ * occurs in a control.
+ *
+ * After creating an instance of a class that implements
+ * 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); +} diff -r 000000000000 -r 380af2bdd8e5 dwt/events/ShellAdapter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/events/ShellAdapter.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,74 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.events.ShellAdapter; + +import dwt.dwthelper.utils; + + +/** + * This adapter class provides default implementations for the + * methods described by theShellListener
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 ShellEvent(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 String toString() {
+ String string = super.toString ();
+ return string.substring (0, string.length() - 1) // remove trailing '}'
+ + " doit=" + doit
+ + "}";
+}
+}
+
diff -r 000000000000 -r 380af2bdd8e5 dwt/events/ShellListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/ShellListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.events.ShellListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with changes in state of Shell
s.
+ *
+ * After creating an instance of a class that implements
+ * 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 + */ + +public final class TraverseEvent extends 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 TraverseEvent(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 String toString() {
+ String string = super.toString ();
+ return string.substring (0, string.length() - 1) // remove trailing '}'
+ + " detail=" + detail
+ + "}";
+}
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/events/TraverseListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/events/TraverseListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.events.TraverseListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated when a
+ * traverse event occurs in a control.
+ *
+ * After creating an instance of a class that implements
+ * 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 DWT
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 implements
+ * 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 implements
+ * 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 380af2bdd8e5 dwt/graphics/Color.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/graphics/Color.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,266 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.graphics.Color; + +import dwt.dwthelper.utils; + + +import dwt.DWT; +import dwt.DWTException; + +/** + * Instances of this class manage the operating system resources that + * implement DWT's RGB color model. To create a color you can either + * specify the individual color components as integers in the range + * 0 to 255 or provide an instance of anRGB
.
+ *
+ * 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 DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public float[] handle; + +Color(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 (!(object instanceof Color)) return false;
+ Color color = (Color)object;
+ float[] rgbColor = color.handle;
+ if (handle is rgbColor) return true;
+ return device is color.device &&
+ (int)(handle[0] * 255) is (int)(rgbColor[0] * 255) &&
+ (int)(handle[1] * 255) is (int)(rgbColor[1] * 255) &&
+ (int)(handle[2] * 255) is (int)(rgbColor[2] * 255);
+}
+
+/**
+ * Returns the amount of blue in the color, from 0 to 255.
+ *
+ * @return the blue component of the color
+ *
+ * @exception DWTException true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode() {
+ if (isDisposed()) return 0;
+ return (int)(handle[0] * 255) ^ (int)(handle[1] * 255) ^ (int)(handle[2] * 255);
+}
+
+/**
+ * Returns an RGB
representing the receiver.
+ *
+ * @return the RGB for the color
+ *
+ * @exception DWTException
+ * 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 DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
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
+ */
+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
+ */
+public String toString () {
+ if (isDisposed()) return "Color {*DISPOSED*}";
+ return "Color {" + getRed() + ", " + getGreen() + ", " + getBlue() + "}";
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/Cursor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/Cursor.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,415 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.Cursor;
+
+import dwt.dwthelper.utils;
+
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.internal.cocoa.NSBitmapImageRep;
+import dwt.internal.cocoa.NSCursor;
+import dwt.internal.cocoa.NSImage;
+import dwt.internal.cocoa.NSPoint;
+import dwt.internal.cocoa.NSSize;
+import dwt.internal.cocoa.NSString;
+import dwt.internal.cocoa.OS;
+
+/**
+ * Instances of this class manage operating system resources that
+ * specify the appearance of the on-screen pointer. To create a
+ * cursor you specify the device and either a simple cursor style
+ * describing one of the standard operating system provided cursors
+ * or the image and mask data for the desired appearance.
+ *
+ * Application code must explicitly invoke the Cursor.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ * Note: Only one of the above styles may be specified. + *
+ */ + +public final class Cursor extends Resource { + + /** + * the handle to the OS cursor resource + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public NSCursor handle; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +Cursor(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 bool equals (Object object) {
+ if (object is this) return true;
+ if (!(object instanceof Cursor)) return false;
+ Cursor cursor = (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 int hashCode () {
+ return handle !is null ? handle.id : 0;
+}
+
+/**
+ * Returns true
if the cursor has been disposed,
+ * and false
otherwise.
+ *
+ * This method gets the dispose state for the cursor.
+ * When a cursor has been disposed, it is an error to
+ * invoke any other method using the cursor.
+ *
+ * @return true
when the cursor is disposed and false
otherwise
+ */
+public 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
+ */
+public String toString () {
+ if (isDisposed()) return "Cursor {*DISPOSED*}";
+ return "Cursor {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new cursor.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Cursor
. It is marked public only so that it
+ * can be shared within the packages provided by DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ * You must dispose the device when it is no longer required. + *
+ * + * @see #create + * @see #init + * + * @since 3.1 + */ +public Device() { + this(null); +} + +/** + * Constructs a new instance of this class. + *+ * You must dispose the device when it is no longer required. + *
+ * + * @param data the DeviceData which describes the receiver + * + * @see #create + * @see #init + * @see DeviceData + */ +public Device(DeviceData data) { + synchronized (Device.class) { + if (data !is null) { + debug = data.debug; + tracking = data.tracking; + } + if (tracking) { + errors = new Error [128]; + objects = new Object [128]; + trackingLock = new Object (); + } + create (data); + init (); + } +} + +/** + * Throws anDWTException
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 DWT 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 DWT, there may be more or fewer error + * checks and exceptions may be thrown for different reasons. + *
+ * + * @exception DWTException
+ * This method is called before init
.
+ *
+ * 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.class) {
+ if (isDisposed()) return;
+ checkDevice ();
+ release ();
+ destroy ();
+ disposed = true;
+ if (tracking) {
+ synchronized (trackingLock) {
+ objects = null;
+ errors = null;
+ trackingLock = null;
+ }
+ }
+ }
+}
+
+void dispose_Object (Object object) {
+ synchronized (trackingLock) {
+ for (int i=0; irelease
.
+ *
+ * Subclasses are supposed to reimplement this method and not
+ * call the super
implementation.
+ *
DeviceData
based on the receiver.
+ * Modifications made to this DeviceData
will not
+ * affect the receiver.
+ *
+ * @return a DeviceData
containing the device's data and attributes
+ *
+ * @exception DWTException 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 DWTException DWT
. Any value other
+ * than one of the DWT color constants which is passed
+ * in will result in the color black. This color should
+ * not be freed because it was allocated by the system,
+ * not the application.
+ *
+ * @param id the color constant
+ * @return the matching color
+ *
+ * @exception DWTException + * 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 DWTExceptiontrue
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 DWTException
+ * 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 DWT. 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 DWT. 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.class) {
+ 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 DWTException
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 DWTException Drawable
can have a graphics context (GC)
+ * created for them, and then they can be drawn on by sending messages to
+ * their associated GC. DWT images, and device objects such as the Display
+ * device and the Printer device, are drawables.
+ * + * IMPORTANT: This class is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. 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 DWT. 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 DWT. 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 DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public NSFont handle; + +Font(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 bool equals(Object object) {
+ if (object is this) return true;
+ if (!(object instanceof Font)) return false;
+ Font font = (Font)object;
+ return handle is font.handle;
+}
+
+/**
+ * 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 DWTException
+ * 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 DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
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 !is null ? handle.id : 0;
+}
+
+void init(String name, float height, int style, String nsName) {
+ if (name is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+ if (height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+ if (nsName !is null) {
+ handle = NSFont.static_fontWithName_size_(NSString.stringWith(nsName), height);
+ } else {
+ nsName = name;
+ if ((style & DWT.BOLD) !is 0) nsName += " Bold";
+ if ((style & DWT.ITALIC) !is 0) nsName += " Italic";
+ handle = NSFont.static_fontWithName_size_(NSString.stringWith(nsName), height);
+ if (handle is null && (style & DWT.ITALIC) !is 0) {
+ nsName = name;
+ if ((style & DWT.BOLD) !is 0) nsName += " Bold";
+ handle = NSFont.static_fontWithName_size_(NSString.stringWith(nsName), height);
+ }
+ if (handle is null && (style & DWT.BOLD) !is 0) {
+ nsName = name;
+ handle = NSFont.static_fontWithName_size_(NSString.stringWith(nsName), height);
+ }
+ }
+ if (handle is null) {
+ handle = device.systemFont.handle;
+ }
+ handle.retain();
+}
+
+/**
+ * Returns true
if the font has been disposed,
+ * and false
otherwise.
+ *
+ * This method gets the dispose state for the font.
+ * When a font has been disposed, it is an error to
+ * invoke any other method using the font.
+ *
+ * @return true
when the font is disposed and false
otherwise
+ */
+public 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
+ */
+public String toString () {
+ if (isDisposed()) return "Font {*DISPOSED*}";
+ return "Font {" + handle + "}";
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/FontData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/FontData.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.FontData;
+
+import dwt.dwthelper.utils;
+
+
+import dwt.DWT;
+
+/**
+ * Instances of this class describe operating system fonts.
+ *
+ * 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
+ */
+public final class FontData {
+ /**
+ * the font name
+ * (Warning: This field is platform dependent)
+ * + * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public String name; + + /** + * The height of the font data in points + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public float height; + + /** + * the font style + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public int style; + + /** + * the NSFont font name + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public String nsName; + + /** + * The locales of the font + */ + String lang, country, variant; + +/** + * Constructs a new uninitialized font data. + */ +public FontData () { + this("", 12, DWT.NORMAL); +} + +/** + * Constructs a new FontData given a string representation + * in the form generated by theFontData.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
+ */
+public bool equals (Object object) {
+ if (object is this) return true;
+ if (!(object instanceof FontData)) return false;
+ FontData data = (FontData)object;
+ return name.equals(data.name) && height is data.height && style is data.style;
+}
+
+/**
+ * Returns the height of the receiver in points.
+ *
+ * @return the height of this FontData
+ *
+ * @see #setHeight(int)
+ */
+public int getHeight() {
+ return (int)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 name;
+}
+
+/**
+ * Returns the style of the receiver which is a bitwise OR of
+ * one or more of the DWT
constants NORMAL, BOLD
+ * and ITALIC.
+ *
+ * @return the style of this FontData
+ *
+ * @see #setStyle
+ */
+public int getStyle() {
+ return style;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return name.hashCode() ^ getHeight() ^ style;
+}
+
+/**
+ * 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);
+ }
+}
+
+/**
+ * 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()
.
+ *
DWT
+ * constants NORMAL, BOLD and ITALIC. All other style bits are
+ * ignored.
+ *
+ * @param style the new style for this FontData
+ *
+ * @see #getStyle
+ */
+public void setStyle(int style) {
+ this.style = style;
+ nsName = null;
+}
+
+/**
+ * Returns a string representation of the receiver which is suitable
+ * for constructing an equivalent instance using the
+ * FontData(String)
constructor.
+ *
+ * @return a string representation of the FontData
+ *
+ * @see FontData
+ */
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("1|");
+ buffer.append(getName());
+ buffer.append("|");
+ buffer.append(getHeightF());
+ buffer.append("|");
+ buffer.append(getStyle());
+ buffer.append("|");
+ buffer.append("COCOA|1|");
+ if (nsName !is null) buffer.append(nsName);
+ return buffer.toString();
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/FontMetrics.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/FontMetrics.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.FontMetrics;
+
+import dwt.dwthelper.utils;
+
+
+/**
+ * Instances of this class provide measurement information
+ * about fonts including ascent, descent, height, leading
+ * space between rows, and average character width.
+ * FontMetrics
are obtained from GC
s
+ * using the getFontMetrics()
method.
+ *
+ * @see GC#getFontMetrics
+ */
+public final class FontMetrics {
+ int ascent, descent, averageCharWidth, leading, height;
+
+FontMetrics() {
+}
+
+public static FontMetrics cocoa_new(int ascent, int descent, int averageCharWidth, int leading, int height) {
+ FontMetrics fontMetrics = new FontMetrics();
+ fontMetrics.ascent = ascent;
+ fontMetrics.descent = descent;
+ fontMetrics.averageCharWidth = averageCharWidth;
+ fontMetrics.leading = leading;
+ fontMetrics.height = height;
+ return fontMetrics;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+public bool equals (Object object) {
+ if (object is this) return true;
+ if (!(object instanceof FontMetrics)) return false;
+ FontMetrics metrics = (FontMetrics)object;
+ return ascent is metrics.ascent && descent is metrics.descent &&
+ averageCharWidth is metrics.averageCharWidth && leading is metrics.leading &&
+ height is metrics.height;
+}
+
+/**
+ * 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 ascent;
+}
+
+/**
+ * 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 averageCharWidth;
+}
+
+/**
+ * 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 descent;
+}
+
+/**
+ * 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 height;
+}
+
+/**
+ * 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 leading;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode() {
+ return ascent ^ descent ^ averageCharWidth ^ leading ^ height;
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/GC.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/GC.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,3424 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.GC;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.DWTException;
+import dwt.internal.cocoa.NSAffineTransform;
+import dwt.internal.cocoa.NSAffineTransformStruct;
+import dwt.internal.cocoa.NSAttributedString;
+import dwt.internal.cocoa.NSBezierPath;
+import dwt.internal.cocoa.NSColor;
+import dwt.internal.cocoa.NSFont;
+import dwt.internal.cocoa.NSGradient;
+import dwt.internal.cocoa.NSGraphicsContext;
+import dwt.internal.cocoa.NSImage;
+import dwt.internal.cocoa.NSMutableDictionary;
+import dwt.internal.cocoa.NSPoint;
+import dwt.internal.cocoa.NSRect;
+import dwt.internal.cocoa.NSSize;
+import dwt.internal.cocoa.NSString;
+import dwt.internal.cocoa.OS;
+
+/**
+ * Class GC
is where all of the drawing capabilities that are
+ * supported by DWT are located. Instances are used to draw on either an
+ * Image
, a Control
, or directly on a Display
.
+ * + * The DWT 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 dwt.events.PaintEvent + */ +public final class GC extends Resource { + /** + * the handle to the OS device context + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public NSGraphicsContext handle; + + Drawable drawable; + GCData data; + + static final int TAB_COUNT = 32; + + final static int FOREGROUND = 1 << 0; + final static int BACKGROUND = 1 << 1; + final static int FONT = 1 << 2; + final static int LINE_STYLE = 1 << 3; + final static int LINE_CAP = 1 << 4; + final static int LINE_JOIN = 1 << 5; + final static int LINE_WIDTH = 1 << 6; + final static int LINE_MITERLIMIT = 1 << 7; + final static int FOREGROUND_FILL = 1 << 8; + final static int DRAW_OFFSET = 1 << 9; + final static int CLIPPING = 1 << 10; + final static int TRANSFORM = 1 << 11; + final static int DRAW = CLIPPING | TRANSFORM | FOREGROUND | LINE_WIDTH | LINE_STYLE | LINE_CAP | LINE_JOIN | LINE_MITERLIMIT | DRAW_OFFSET; + final static int FILL = CLIPPING | TRANSFORM | BACKGROUND; + + static final float[] LINE_DOT = new float[]{1, 1}; + static final float[] LINE_DASH = new float[]{3, 1}; + static final float[] LINE_DASHDOT = new float[]{3, 1, 1, 1}; + static final float[] LINE_DASHDOTDOT = new float[]{3, 1, 1, 1, 1, 1}; + static final float[] LINE_DOT_ZERO = new float[]{3, 3}; + static final float[] LINE_DASH_ZERO = new float[]{18, 6}; + static final float[] LINE_DASHDOT_ZERO = new float[]{9, 6, 3, 6}; + static final float[] LINE_DASHDOTDOT_ZERO = new float[]{9, 3, 3, 3, 3, 3}; + +GC() { +} + +/** + * 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 IllegalArgumentException
+ * 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 DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
GC
+ *
+ * @private
+ */
+public static GC cocoa_new(Drawable drawable, GCData data) {
+ GC gc = new GC();
+ int context = drawable.internal_new_GC(data);
+ gc.device = data.device;
+ gc.init(drawable, data, context);
+ 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 DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
GC
+ */
+public static GC carbon_new(int context, GCData data) {
+ GC gc = new GC();
+ gc.device = data.device;
+ gc.init(null, data, context);
+ return gc;
+}
+
+void checkGC (int mask) {
+ if ((data.state & CLIPPING) is 0 || (data.state & TRANSFORM) is 0) {
+ handle.restoreGraphicsState();
+ handle.saveGraphicsState();
+ if (data.clipPath !is null) data.clipPath.addClip();
+ if (data.transform !is null) data.transform.concat();
+ mask &= ~(TRANSFORM | CLIPPING);
+ data.state |= TRANSFORM | CLIPPING;
+ data.state &= ~(BACKGROUND | FOREGROUND);
+ }
+
+ int state = data.state;
+ if ((state & mask) is mask) return;
+ state = (state ^ mask) & mask;
+ data.state |= mask;
+
+ if ((state & FOREGROUND) !is 0) {
+ Pattern pattern = data.foregroundPattern;
+ if (pattern !is null) {
+ if (pattern.color !is null) pattern.color.setStroke();
+ } else {
+ float[] color = data.foreground;
+ NSColor.colorWithDeviceRed(color[0], color[1], color[2], data.alpha / 255f).setStroke();
+ }
+ }
+ if ((state & FOREGROUND_FILL) !is 0) {
+ Pattern pattern = data.foregroundPattern;
+ if (pattern !is null) {
+ if (pattern.color !is null) pattern.color.setFill();
+ } else {
+ float[] color = data.foreground;
+ NSColor.colorWithDeviceRed(color[0], color[1], color[2], data.alpha / 255f).setFill();
+ }
+ data.state &= ~BACKGROUND;
+ }
+ if ((state & BACKGROUND) !is 0) {
+ Pattern pattern = data.backgroundPattern;
+ if (pattern !is null) {
+ if (pattern.color !is null) pattern.color.setFill();
+ } else {
+ float[] color = data.background;
+ NSColor.colorWithDeviceRed(color[0], color[1], color[2], data.alpha / 255f).setFill();
+ }
+ data.state &= ~FOREGROUND_FILL;
+ }
+ NSBezierPath path = data.path;
+ if ((state & LINE_WIDTH) !is 0) {
+ path.setLineWidth(data.lineWidth is 0 ? 1 : data.lineWidth);
+ switch (data.lineStyle) {
+ case DWT.LINE_DOT:
+ case DWT.LINE_DASH:
+ case DWT.LINE_DASHDOT:
+ case DWT.LINE_DASHDOTDOT:
+ state |= LINE_STYLE;
+ }
+ }
+ if ((state & LINE_STYLE) !is 0) {
+ float[] dashes = null;
+ float width = data.lineWidth;
+ switch (data.lineStyle) {
+ case DWT.LINE_SOLID: break;
+ case DWT.LINE_DASH: dashes = width !is 0 ? LINE_DASH : LINE_DASH_ZERO; break;
+ case DWT.LINE_DOT: dashes = width !is 0 ? LINE_DOT : LINE_DOT_ZERO; break;
+ case DWT.LINE_DASHDOT: dashes = width !is 0 ? LINE_DASHDOT : LINE_DASHDOT_ZERO; break;
+ case DWT.LINE_DASHDOTDOT: dashes = width !is 0 ? LINE_DASHDOTDOT : LINE_DASHDOTDOT_ZERO; break;
+ case DWT.LINE_CUSTOM: dashes = data.lineDashes; break;
+ }
+ if (dashes !is null) {
+ float[] lengths = new float[dashes.length];
+ for (int i = 0; i < lengths.length; i++) {
+ lengths[i] = width is 0 || data.lineStyle is DWT.LINE_CUSTOM ? dashes[i] : dashes[i] * width;
+ }
+ path.setLineDash(lengths, lengths.length, data.lineDashesOffset);
+ } else {
+ path.setLineDash(null, 0, 0);
+ }
+ }
+ if ((state & LINE_MITERLIMIT) !is 0) {
+ path.setMiterLimit(data.lineMiterLimit);
+ }
+ if ((state & LINE_JOIN) !is 0) {
+ int joinStyle = 0;
+ switch (data.lineJoin) {
+ case DWT.JOIN_MITER: joinStyle = OS.NSMiterLineJoinStyle; break;
+ case DWT.JOIN_ROUND: joinStyle = OS.NSRoundLineJoinStyle; break;
+ case DWT.JOIN_BEVEL: joinStyle = OS.NSBevelLineJoinStyle; break;
+ }
+ path.setLineJoinStyle(joinStyle);
+ }
+ if ((state & LINE_CAP) !is 0) {
+ int capStyle = 0;
+ switch (data.lineCap) {
+ case DWT.CAP_ROUND: capStyle = OS.NSRoundLineCapStyle; break;
+ case DWT.CAP_FLAT: capStyle = OS.NSButtLineCapStyle; break;
+ case DWT.CAP_SQUARE: capStyle = OS.NSSquareLineCapStyle; break;
+ }
+ path.setLineCapStyle(capStyle);
+ }
+ if ((state & DRAW_OFFSET) !is 0) {
+ data.drawXOffset = data.drawYOffset = 0;
+ NSSize size = new NSSize();
+ size.width = size.height = 1;
+ if (data.transform !is null) {
+ size = data.transform.transformSize(size);
+ }
+ float scaling = size.width;
+ if (scaling < 0) scaling = -scaling;
+ float strokeWidth = data.lineWidth * scaling;
+ if (strokeWidth is 0 || ((int)strokeWidth % 2) is 1) {
+ data.drawXOffset = 0.5f / scaling;
+ }
+ scaling = size.height;
+ if (scaling < 0) scaling = -scaling;
+ strokeWidth = data.lineWidth * scaling;
+ if (strokeWidth is 0 || ((int)strokeWidth % 2) is 1) {
+ data.drawYOffset = 0.5f / scaling;
+ }
+ }
+}
+
+/**
+ * Copies a rectangular area of the receiver at the specified
+ * position into the image, which must be of type DWT.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 DWTException
+ * 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 DWTException
+ * 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 DWTExceptionx
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 DWTException 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 DWTException isTransparent
is true
,
+ * then the background of the rectangular area where the string is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param isTransparent if true
the background will be transparent, otherwise it will be opaque
+ *
+ * @exception IllegalArgumentException isTransparent
is true
,
+ * then the background of the rectangular area where the text is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param isTransparent if true
the background will be transparent, otherwise it will be opaque
+ *
+ * @exception IllegalArgumentException 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) {
+ if (object is this) return true;
+ if (!(object instanceof GC)) return false;
+ return handle is ((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 DWTExceptionnull
.
+ *
+ * @return the receiver's background pattern
+ *
+ * @exception DWTException true
if receiver is using the operating system's
+ * advanced graphics subsystem. Otherwise, false
is returned
+ * to indicate that normal graphics are in use.
+ *
+ * Advanced graphics may not be installed for the operating system. In this
+ * case, false
is always returned. Some operating system have
+ * only one graphics subsystem. If this subsystem supports advanced graphics,
+ * then true
is always returned. If any graphics operation such
+ * as alpha, antialias, patterns, interpolation, paths, clipping or transformation
+ * has caused the receiver to switch from regular to advanced graphics mode,
+ * true
is returned. If the receiver has been explicitly switched
+ * to advanced mode and this mode is supported, true
is returned.
+ *
DWT.DEFAULT
, DWT.OFF
or
+ * DWT.ON
. Note that this controls anti-aliasing for all
+ * non-text drawing operations.
+ *
+ * @return the anti-aliasing setting
+ *
+ * @exception DWTException + * 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 DWTExceptionDWT.FILL_EVEN_ODD
or DWT.FILL_WINDING
.
+ *
+ * @return the receiver's fill rule
+ *
+ * @exception DWTException null
.
+ *
+ * @return the receiver's foreground pattern
+ *
+ * @exception DWTException
+ * 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 DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
DWT.DEFAULT
, DWT.NONE
,
+ * DWT.LOW
or DWT.HIGH
.
+ *
+ * @return the receiver's interpolation setting
+ *
+ * @exception DWTException DWT.CAP_FLAT
, DWT.CAP_ROUND
,
+ * or DWT.CAP_SQUARE
.
+ *
+ * @return the cap style used for drawing lines
+ *
+ * @exception DWTException null
.
+ *
+ * @return the line dash style used for drawing lines
+ *
+ * @exception DWTException DWT.JOIN_MITER
, DWT.JOIN_ROUND
,
+ * or DWT.JOIN_BEVEL
.
+ *
+ * @return the join style used for drawing lines
+ *
+ * @exception DWTException DWT.LINE_SOLID
, DWT.LINE_DASH
,
+ * DWT.LINE_DOT
, DWT.LINE_DASHDOT
or
+ * DWT.LINE_DASHDOTDOT
.
+ *
+ * @return the style used for drawing lines
+ *
+ * @exception DWTException drawLine
, drawRectangle
,
+ * drawPolyline
, and so forth.
+ *
+ * @return the receiver's line width
+ *
+ * @exception DWTException + * 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 DWTExceptionDWT.DEFAULT
, DWT.OFF
or
+ * DWT.ON
. Note that this controls anti-aliasing
+ * only for text drawing operations.
+ *
+ * @return the anti-aliasing setting
+ *
+ * @exception DWTException 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 DWTException true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @exception DWTException 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 DWTException true
if the GC has been disposed,
+ * and false
otherwise.
+ *
+ * This method gets the dispose state for the GC.
+ * When a GC has been disposed, it is an error to
+ * invoke any other method using the GC.
+ *
+ * @return true
when the GC is disposed and false
otherwise
+ */
+public bool isDisposed() {
+ return handle is null;
+}
+
+bool isIdentity(float[] transform) {
+ return transform[0] is 1 && transform[1] is 0 && transform[2] is 0
+ && transform[3] is 1 && transform[4] is 0 && transform[5] is 0;
+}
+
+/**
+ * Sets the receiver to always use the operating system's advanced graphics
+ * subsystem for all graphics operations if the argument is true
.
+ * If the argument is false
, the advanced graphics subsystem is
+ * no longer used, advanced graphics state is cleared and the normal graphics
+ * subsystem is used from now on.
+ *
+ * Normally, the advanced graphics subsystem is invoked automatically when + * any one of the alpha, antialias, patterns, interpolation, paths, clipping + * or transformation operations in the receiver is requested. When the receiver + * is switched into advanced mode, the advanced graphics subsystem performs both + * advanced and normal graphics operations. Because the two subsystems are + * different, their output may differ. Switching to advanced graphics before + * any graphics operations are performed ensures that the output is consistent. + *
+ * Advanced graphics may not be installed for the operating system. In this + * case, this operation does nothing. Some operating system have only one + * graphics subsystem, so switching from normal to advanced graphics does + * nothing. However, switching from advanced to normal graphics will always + * clear the advanced graphics state, even for operating systems that have + * only one graphics subsystem. + *
+ * + * @param advanced the new advanced graphics state + * + * @exception DWTException+ * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *
+ * @param alpha the alpha value + * + * @exception DWTExceptionDWT.DEFAULT
, DWT.OFF
+ * or DWT.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 IllegalArgumentExceptionDWT.DEFAULT
,
+ * DWT.OFF
or DWT.ON
null
.
+ * + * 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 DWTException null
for the
+ * region reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param region the clipping region or null
+ *
+ * @exception IllegalArgumentException DWT.FILL_EVEN_ODD
or DWT.FILL_WINDING
.
+ *
+ * @param rule the new fill rule
+ *
+ * @exception IllegalArgumentException DWT.FILL_EVEN_ODD
+ * or DWT.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 IllegalArgumentExceptionDWT.DEFAULT
, DWT.NONE
,
+ * DWT.LOW
or DWT.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 IllegalArgumentExceptionDWT.DEFAULT
,
+ * DWT.NONE
, DWT.LOW
or DWT.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 IllegalArgumentExceptionDWT.CAP_FLAT
, DWT.CAP_ROUND
,
+ * or DWT.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 DWT.LINE_CUSTOM
, otherwise
+ * it is set to DWT.LINE_SOLID
.
+ *
+ * @param dashes the dash style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException DWT.JOIN_MITER
, DWT.JOIN_ROUND
,
+ * or DWT.JOIN_BEVEL
.
+ *
+ * @param join the join style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException DWT.LINE_SOLID
, DWT.LINE_DASH
,
+ * DWT.LINE_DOT
, DWT.LINE_DASHDOT
or
+ * DWT.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 DWTExceptiontrue
, 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 DWTException DWT.DEFAULT
, DWT.OFF
+ * or DWT.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 IllegalArgumentExceptionDWT.DEFAULT
,
+ * DWT.OFF
or DWT.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 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 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 + * @param flags the flags specifying how to process the text + * @return a point containing the extent of the string + * + * @exception IllegalArgumentException+ * IMPORTANT: This class is not part of the public + * API for DWT. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms, and should never be called from application code. + *
+ */ +public final class GCData { + public Device device; + public int style, state = -1; + public float[] foreground; + public float[] background; + public Pattern foregroundPattern; + public Pattern backgroundPattern; + public Font font; + public int alpha = 0xFF; + public float lineWidth; + public int lineStyle = DWT.LINE_SOLID; + public int lineCap = DWT.CAP_FLAT; + public int lineJoin = DWT.JOIN_MITER; + public float lineDashesOffset; + public float[] lineDashes; + public float lineMiterLimit = 10; + public bool xorMode; + public int antialias = DWT.DEFAULT; + public int textAntialias = DWT.DEFAULT; + public int fillRule = DWT.FILL_EVEN_ODD; + public int bitmapDataAddress; + + public Image image; + + public float drawXOffset, drawYOffset; + public NSRect paintRect; + public NSBezierPath path; + public NSAffineTransform transform, inverseTransform; + public NSBezierPath clipPath; + public NSView view; + public NSSize size; +} diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/GlyphMetrics.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/graphics/GlyphMetrics.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,111 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.graphics.GlyphMetrics; + +import dwt.dwthelper.utils; + +import dwt.DWT; + +/** + * Instances of this class represent glyph metrics. + *+ * 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 bool equals (Object object) {
+ if (object is this) return true;
+ if (!(object instanceof GlyphMetrics)) return false;
+ GlyphMetrics metrics = (GlyphMetrics)object;
+ return metrics.ascent is ascent && metrics.descent is descent && metrics.width is width;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public int hashCode () {
+ return ascent ^ descent ^ width;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the GlyphMetrics
+ */
+public String toString () {
+ return "GlyphMetrics {" + ascent + ", " + descent + ", " + width + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/Image.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/Image.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,998 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.Image;
+
+import dwt.dwthelper.utils;
+
+
+import java.io.InputStream;
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.DWTException;
+import dwt.internal.cocoa.NSAffineTransform;
+import dwt.internal.cocoa.NSBitmapImageRep;
+import dwt.internal.cocoa.NSGraphicsContext;
+import dwt.internal.cocoa.NSImage;
+import dwt.internal.cocoa.NSImageRep;
+import dwt.internal.cocoa.NSSize;
+import dwt.internal.cocoa.NSString;
+import dwt.internal.cocoa.OS;
+
+/**
+ * Instances of this class are graphics which have been prepared
+ * for display on a specific device. That is, they are ready
+ * to paint using methods such as GC.drawImage()
+ * and display on widgets with, for example, Button.setImage()
.
+ *
+ * If loaded from a file format that supports it, an
+ * Image
may have transparency, meaning that certain
+ * pixels are specified as being transparent when drawn. Examples
+ * of file formats that support transparency are GIF and PNG.
+ *
+ * There are two primary ways to use Images
.
+ * The first is to load a graphic file from disk and create an
+ * Image
from it. This is done using an Image
+ * constructor, for example:
+ *
+ * Image i = new Image(device, "C:\\graphic.bmp"); + *+ * A graphic file may contain a color table specifying which + * colors the image was intended to possess. In the above example, + * these colors will be mapped to the closest available color in + * DWT. 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.
+ *
DWT.BITMAP
, DWT.ICON
)
+ * + * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. 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 DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public NSImage handle; + NSBitmapImageRep imageRep; + + /** + * specifies the transparent pixel + */ + int transparentPixel = -1; + + /** + * The GC the image is currently selected in. + */ + GC memGC; + + /** + * The alpha data of the image. + */ + byte[] alphaData; + + /** + * The global alpha value to be used for every pixel. + */ + int alpha = -1; + + /** + * The width of the image. + */ + int width = -1; + + /** + * The height of the image. + */ + int height = -1; + + /** + * Specifies the default scanline padding. + */ + static final int DEFAULT_SCANLINE_PAD = 4; + +Image(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 DWT.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 (DWTException 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
+ */
+public bool equals (Object object) {
+ if (object is this) return true;
+ if (!(object instanceof Image)) return false;
+ Image image = (Image)object;
+ return device is image.device && handle is image.handle &&
+ transparentPixel is image.transparentPixel;
+}
+
+/**
+ * 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 DWTException
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 DWTException
+ * 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 DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
DWT.BITMAP
or DWT.ICON
)
+ * @param handle the OS handle for the image
+ * @param data the OS data for the image
+ *
+ * @private
+ */
+public static Image cocoa_new(Device device, int type, NSImage nsImage) {
+ Image image = new Image(device);
+ image.type = type;
+ image.handle = nsImage;
+ NSImageRep rep = nsImage.bestRepresentationForDevice(null);
+ if (rep.isKindOfClass(NSBitmapImageRep.static_class())) {
+ image.imageRep = new NSBitmapImageRep(rep.id);
+ }
+ return image;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle !is null ? handle.id : 0;
+}
+
+void init(int width, int height) {
+ if (width <= 0 || height <= 0) {
+ DWT.error (DWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.type = DWT.BITMAP;
+ this.width = width;
+ this.height = height;
+
+ handle = (NSImage)new NSImage().alloc();
+ NSSize size = new NSSize();
+ size.width = width;
+ size.height = height;
+ handle = handle.initWithSize(size);
+ NSBitmapImageRep rep = imageRep = (NSBitmapImageRep)new NSBitmapImageRep().alloc();
+ rep = rep.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(0, width, height, 8, 3, false, false, new NSString(OS.NSDeviceRGBColorSpace()), OS.NSAlphaFirstBitmapFormat | OS.NSAlphaNonpremultipliedBitmapFormat, width * 4, 32);
+ OS.memset(rep.bitmapData(), 0xFF, width * height * 4);
+ handle.addRepresentation(rep);
+// rep.release();
+}
+
+void init(ImageData image) {
+ if (image is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+ this.width = image.width;
+ this.height = image.height;
+ PaletteData palette = image.palette;
+ if (!(((image.depth is 1 || image.depth is 2 || image.depth is 4 || image.depth is 8) && !palette.isDirect) ||
+ ((image.depth is 8) || (image.depth is 16 || image.depth is 24 || image.depth is 32) && palette.isDirect)))
+ DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH);
+
+ /* Create the image */
+ int dataSize = width * height * 4;
+
+ /* Initialize data */
+ int bpr = width * 4;
+ byte[] buffer = new byte[dataSize];
+ if (palette.isDirect) {
+ ImageData.blit(ImageData.BLIT_SRC,
+ image.data, image.depth, image.bytesPerLine, image.getByteOrder(), 0, 0, width, height, palette.redMask, palette.greenMask, palette.blueMask,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ buffer, 32, bpr, ImageData.MSB_FIRST, 0, 0, width, height, 0xFF0000, 0xFF00, 0xFF,
+ false, false);
+ } else {
+ RGB[] rgbs = palette.getRGBs();
+ int length = rgbs.length;
+ byte[] srcReds = new byte[length];
+ byte[] srcGreens = new byte[length];
+ byte[] srcBlues = new byte[length];
+ for (int i = 0; i < rgbs.length; i++) {
+ RGB rgb = rgbs[i];
+ if (rgb is null) continue;
+ srcReds[i] = (byte)rgb.red;
+ srcGreens[i] = (byte)rgb.green;
+ srcBlues[i] = (byte)rgb.blue;
+ }
+ ImageData.blit(ImageData.BLIT_SRC,
+ image.data, image.depth, image.bytesPerLine, image.getByteOrder(), 0, 0, width, height, srcReds, srcGreens, srcBlues,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ buffer, 32, bpr, ImageData.MSB_FIRST, 0, 0, width, height, 0xFF0000, 0xFF00, 0xFF,
+ false, false);
+ }
+
+ /* Initialize transparency */
+ int transparency = image.getTransparencyType();
+ bool hasAlpha = transparency !is DWT.TRANSPARENCY_NONE;
+ if (transparency is DWT.TRANSPARENCY_MASK || image.transparentPixel !is -1) {
+ this.type = image.transparentPixel !is -1 ? DWT.BITMAP : DWT.ICON;
+ if (image.transparentPixel !is -1) {
+ int transRed = 0, transGreen = 0, transBlue = 0;
+ if (palette.isDirect) {
+ RGB rgb = palette.getRGB(image.transparentPixel);
+ transRed = rgb.red;
+ transGreen = rgb.green;
+ transBlue = rgb.blue;
+ } else {
+ RGB[] rgbs = palette.getRGBs();
+ if (image.transparentPixel < rgbs.length) {
+ RGB rgb = rgbs[image.transparentPixel];
+ transRed = rgb.red;
+ transGreen = rgb.green;
+ transBlue = rgb.blue;
+ }
+ }
+ transparentPixel = transRed << 16 | transGreen << 8 | transBlue;
+ }
+ ImageData maskImage = image.getTransparencyMask();
+ byte[] maskData = maskImage.data;
+ int maskBpl = maskImage.bytesPerLine;
+ int offset = 0, maskOffset = 0;
+ for (int y = 0; yImage
. It is marked public only so that it
+ * can be shared within the packages provided by DWT. 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 int internal_new_GC (GCData data) {
+ if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
+ if (type !is DWT.BITMAP || memGC !is null) {
+ DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+ }
+ NSGraphicsContext current = NSGraphicsContext.currentContext();
+ NSBitmapImageRep rep = imageRep;
+ if (imageRep.hasAlpha()) {
+ int bpr = width * 4;
+ rep = (NSBitmapImageRep)new NSBitmapImageRep().alloc();
+ int bitmapData = imageRep.bitmapData();
+ if (data.bitmapDataAddress !is 0) OS.free(data.bitmapDataAddress);
+ data.bitmapDataAddress = OS.malloc(4);
+ OS.memmove(data.bitmapDataAddress, new int[] {bitmapData}, 4);
+ rep = rep.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(
+ data.bitmapDataAddress, width, height, 8, 3, false, false, new NSString(OS.NSDeviceRGBColorSpace()), OS.NSAlphaFirstBitmapFormat , bpr, 32);
+ rep.autorelease();
+ }
+ NSGraphicsContext context = NSGraphicsContext.graphicsContextWithBitmapImageRep(rep);
+ NSGraphicsContext.setCurrentContext(context);
+ NSAffineTransform transform = NSAffineTransform.transform();
+ NSSize size = handle.size();
+ transform.translateXBy(0, size.height);
+ transform.scaleXBy(1, -1);
+ transform.set();
+ if (data !is null) {
+ int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
+ if ((data.style & mask) is 0) {
+ data.style |= DWT.LEFT_TO_RIGHT;
+ }
+ data.device = device;
+ data.background = device.COLOR_WHITE.handle;
+ data.foreground = device.COLOR_BLACK.handle;
+ data.font = device.systemFont;
+ data.image = this;
+ }
+ NSGraphicsContext.setCurrentContext(current);
+ return context.id;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Image
. It is marked public only so that it
+ * can be shared within the packages provided by DWT. 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
+ */
+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 IllegalArgumentExceptionImage
.
+ *
+ * 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 (DWTException 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. + *
+ */ +ImageData( + 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) DWT.error(DWT.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)) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (width <= 0 || height <= 0) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (scanlinePad is 0) DWT.error (DWT.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 DWT.IMAGE_PNG ? ((((width + 7) / 8) + 3) / 4) * 4 : bytesPerLine; + if (data !is null && data.length < minBytesPerLine * height) { + DWT.error(DWT.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 DWT 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 DWT. 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, DWT.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) DWT.error(DWT.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.
+ *
+ * @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
.
+ *
+ * @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 DWT.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
+ * DWT.TRANSPARENCY_NONE
, DWT.TRANSPARENCY_MASK
,
+ * DWT.TRANSPARENCY_PIXEL
or DWT.TRANSPARENCY_ALPHA
.
+ *
+ * @return the receiver's transparency type
+ */
+public int getTransparencyType() {
+ if (maskData !is null) return DWT.TRANSPARENCY_MASK;
+ if (transparentPixel !is -1) return DWT.TRANSPARENCY_PIXEL;
+ if (alphaData !is null) return DWT.TRANSPARENCY_ALPHA;
+ return DWT.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 */
+ final bool flipX = (width < 0);
+ if (flipX) width = - width;
+ final 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.
+ *
+ * @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
.
+ *
+ * @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) { + if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; + + // these should be supplied as params later + final int srcAlphaMask = 0, destAlphaMask = 0; + + /*** Prepare scaling data ***/ + final int dwm1 = destWidth - 1; + final int sfxi = (dwm1 !is 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0; + final int dhm1 = destHeight - 1; + final int sfyi = (dhm1 !is 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0; + + /*** Prepare source-related data ***/ + final 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 ***/ + final 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; + final int dprxi = (flipX) ? -dbpp : dbpp; + final 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; + } + return; + } + /*** Comprehensive blit (apply transformations) ***/ + final int srcRedShift = getChannelShift(srcRedMask); + final byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)]; + final int srcGreenShift = getChannelShift(srcGreenMask); + final byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)]; + final int srcBlueShift = getChannelShift(srcBlueMask); + final byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)]; + final int srcAlphaShift = getChannelShift(srcAlphaMask); + final byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)]; + + final int destRedShift = getChannelShift(destRedMask); + final int destRedWidth = getChannelWidth(destRedMask, destRedShift); + final byte[] destReds = ANY_TO_EIGHT[destRedWidth]; + final int destRedPreShift = 8 - destRedWidth; + final int destGreenShift = getChannelShift(destGreenMask); + final int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift); + final byte[] destGreens = ANY_TO_EIGHT[destGreenWidth]; + final int destGreenPreShift = 8 - destGreenWidth; + final int destBlueShift = getChannelShift(destBlueMask); + final int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift); + final byte[] destBlues = ANY_TO_EIGHT[destBlueWidth]; + final int destBluePreShift = 8 - destBlueWidth; + final int destAlphaShift = getChannelShift(destAlphaMask); + final int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift); + final byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth]; + final 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: { + final 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: { + final 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: { + final 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: { + final 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: { + final 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: { + final 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; + } + + /*** 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; + } + if (alpha !is 0x10000) { + if (alpha is 0x0000) continue; + switch (dtype) { + case TYPE_GENERIC_8: { + final 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: { + final 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: { + final 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: { + final 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: { + final 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: { + final 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; + } + // 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 ***/ + final int data = + (r >>> destRedPreShift << destRedShift) | + (g >>> destGreenPreShift << destGreenShift) | + (b >>> destBluePreShift << destBlueShift) | + (a >>> destAlphaPreShift << destAlphaShift); + switch (dtype) { + case TYPE_GENERIC_8: { + destData[dp] = (byte) data; + } break; + case TYPE_GENERIC_16_MSB: { + destData[dp] = (byte) (data >>> 8); + destData[dp + 1] = (byte) (data & 0xff); + } break; + case TYPE_GENERIC_16_LSB: { + destData[dp] = (byte) (data & 0xff); + destData[dp + 1] = (byte) (data >>> 8); + } break; + case TYPE_GENERIC_24: { + destData[dp] = (byte) (data >>> 16); + destData[dp + 1] = (byte) (data >>> 8); + destData[dp + 2] = (byte) (data & 0xff); + } break; + case TYPE_GENERIC_32_MSB: { + destData[dp] = (byte) (data >>> 24); + destData[dp + 1] = (byte) (data >>> 16); + destData[dp + 2] = (byte) (data >>> 8); + destData[dp + 3] = (byte) (data & 0xff); + } break; + case TYPE_GENERIC_32_LSB: { + destData[dp] = (byte) (data & 0xff); + destData[dp + 1] = (byte) (data >>> 8); + destData[dp + 2] = (byte) (data >>> 16); + destData[dp + 3] = (byte) (data >>> 24); + } break; + } + } + } +} + +/** + * 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) { + if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; + + /*** Prepare scaling data ***/ + final int dwm1 = destWidth - 1; + final int sfxi = (dwm1 !is 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0; + final int dhm1 = destHeight - 1; + final int sfyi = (dhm1 !is 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0; + + /*** Prepare source-related data ***/ + final 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 ***/ + final 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); + final int dprxi = (flipX) ? -1 : 1; + final 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; + } + final 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] = (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] = (byte)index; + if (minDistance !is 0) isExactPaletteMapping = false; + } + break; + } + 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) { + final 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] = (byte)((destData[dp >> 1] & 0xf0) | v); + else destData[dp >> 1] = (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) { + final int index = paletteMapping[(srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03]; + sp += (sfx >>> 16); + final int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = (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) { + final int index = paletteMapping[(srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01]; + sp += (sfx >>> 16); + final int shift = 7 - (dp & 7); + destData[dp >> 3] = (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) { + final int index = paletteMapping[(srcData[sp >> 3] >>> (sp & 7)) & 0x01]; + sp += (sfx >>> 16); + final int shift = dp & 7; + destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); + } + } + break; + } + } 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: { + final byte mask = alphaData[ap]; + ap += (sfx >> 16); + if (mask is 0) continue; + } break; + case ALPHA_MASK_PACKED: { + final 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: { + final 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; + } + index = paletteMapping[index] & 0xff; + + /*** WRITE NEXT PIXEL ***/ + switch (dtype) { + case TYPE_INDEX_8: + destData[dp] = (byte) index; + break; + case TYPE_INDEX_4: + if ((dp & 1) !is 0) destData[dp >> 1] = (byte)((destData[dp >> 1] & 0xf0) | index); + else destData[dp >> 1] = (byte)((destData[dp >> 1] & 0x0f) | (index << 4)); + break; + case TYPE_INDEX_2: { + final int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = (byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift)); + } break; + case TYPE_INDEX_1_MSB: { + final int shift = 7 - (dp & 7); + destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); + } break; + case TYPE_INDEX_1_LSB: { + final int shift = dp & 7; + destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); + } break; + } + } + } + } + return; + } + + /*** Comprehensive blit (apply transformations) ***/ + int alpha = alphaMode; + int index = 0; + int indexq = 0; + int lastindex = 0, lastr = -1, lastg = -1, lastb = -1; + final 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; + } + + /*** 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; + } + 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; + } + // Perform alpha blending + final int rq = destReds[indexq] & 0xff; + final int gq = destGreens[indexq] & 0xff; + final 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... + final 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] = (byte) lastindex; + break; + case TYPE_INDEX_4: + if ((dp & 1) !is 0) destData[dp >> 1] = (byte)((destData[dp >> 1] & 0xf0) | lastindex); + else destData[dp >> 1] = (byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4)); + break; + case TYPE_INDEX_2: { + final int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = (byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift)); + } break; + case TYPE_INDEX_1_MSB: { + final int shift = 7 - (dp & 7); + destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); + } break; + case TYPE_INDEX_1_LSB: { + final int shift = dp & 7; + destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); + } break; + } + } + } +} + +/** + * 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) { + if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; + + // these should be supplied as params later + final int destAlphaMask = 0; + + /*** Prepare scaling data ***/ + final int dwm1 = destWidth - 1; + final int sfxi = (dwm1 !is 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0; + final int dhm1 = destHeight - 1; + final int sfyi = (dhm1 !is 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0; + + /*** Prepare source-related data ***/ + final 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 ***/ + final 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; + final int dprxi = (flipX) ? -dbpp : dbpp; + final 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) ***/ + final int destRedShift = getChannelShift(destRedMask); + final int destRedWidth = getChannelWidth(destRedMask, destRedShift); + final byte[] destReds = ANY_TO_EIGHT[destRedWidth]; + final int destRedPreShift = 8 - destRedWidth; + final int destGreenShift = getChannelShift(destGreenMask); + final int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift); + final byte[] destGreens = ANY_TO_EIGHT[destGreenWidth]; + final int destGreenPreShift = 8 - destGreenWidth; + final int destBlueShift = getChannelShift(destBlueMask); + final int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift); + final byte[] destBlues = ANY_TO_EIGHT[destBlueWidth]; + final int destBluePreShift = 8 - destBlueWidth; + final int destAlphaShift = getChannelShift(destAlphaMask); + final int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift); + final byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth]; + final 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; + } + + /*** 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; + } + if (alpha !is 0x10000) { + if (alpha is 0x0000) continue; + switch (dtype) { + case TYPE_GENERIC_8: { + final 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: { + final 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: { + final 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: { + final 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: { + final 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: { + final 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; + } + // 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 ***/ + final int data = + (r >>> destRedPreShift << destRedShift) | + (g >>> destGreenPreShift << destGreenShift) | + (b >>> destBluePreShift << destBlueShift) | + (a >>> destAlphaPreShift << destAlphaShift); + switch (dtype) { + case TYPE_GENERIC_8: { + destData[dp] = (byte) data; + } break; + case TYPE_GENERIC_16_MSB: { + destData[dp] = (byte) (data >>> 8); + destData[dp + 1] = (byte) (data & 0xff); + } break; + case TYPE_GENERIC_16_LSB: { + destData[dp] = (byte) (data & 0xff); + destData[dp + 1] = (byte) (data >>> 8); + } break; + case TYPE_GENERIC_24: { + destData[dp] = (byte) (data >>> 16); + destData[dp + 1] = (byte) (data >>> 8); + destData[dp + 2] = (byte) (data & 0xff); + } break; + case TYPE_GENERIC_32_MSB: { + destData[dp] = (byte) (data >>> 24); + destData[dp + 1] = (byte) (data >>> 16); + destData[dp + 2] = (byte) (data >>> 8); + destData[dp + 3] = (byte) (data & 0xff); + } break; + case TYPE_GENERIC_32_LSB: { + destData[dp] = (byte) (data & 0xff); + destData[dp + 1] = (byte) (data >>> 8); + destData[dp + 2] = (byte) (data >>> 16); + destData[dp + 3] = (byte) (data >>> 24); + } break; + } + } + } +} + +/** + * 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) { + if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; + + // these should be supplied as params later + final int srcAlphaMask = 0; + + /*** Prepare scaling data ***/ + final int dwm1 = destWidth - 1; + final int sfxi = (dwm1 !is 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0; + final int dhm1 = destHeight - 1; + final int sfyi = (dhm1 !is 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0; + + /*** Prepare source-related data ***/ + final 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 ***/ + final 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); + final int dprxi = (flipX) ? -1 : 1; + final 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; + } + final bool ditherEnabled = (op & BLIT_DITHER) !is 0; + + /*** Comprehensive blit (apply transformations) ***/ + final int srcRedShift = getChannelShift(srcRedMask); + final byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)]; + final int srcGreenShift = getChannelShift(srcGreenMask); + final byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)]; + final int srcBlueShift = getChannelShift(srcBlueMask); + final byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)]; + final int srcAlphaShift = getChannelShift(srcAlphaMask); + final 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; + final 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: { + final 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: { + final 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: { + final 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: { + final 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: { + final 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: { + final 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; + } + + /*** 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; + } + 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; + } + // Perform alpha blending + final int rq = destReds[indexq] & 0xff; + final int gq = destGreens[indexq] & 0xff; + final 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... + final 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] = (byte) lastindex; + break; + case TYPE_INDEX_4: + if ((dp & 1) !is 0) destData[dp >> 1] = (byte)((destData[dp >> 1] & 0xf0) | lastindex); + else destData[dp >> 1] = (byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4)); + break; + case TYPE_INDEX_2: { + final int shift = 6 - (dp & 3) * 2; + destData[dp >> 2] = (byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift)); + } break; + case TYPE_INDEX_1_MSB: { + final int shift = 7 - (dp & 7); + destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); + } break; + case TYPE_INDEX_1_LSB: { + final int shift = dp & 7; + destData[dp >> 3] = (byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); + } break; + } + } + } +} + +/** + * 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) { + final 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 */
+ final int bandWidth, bandHeight, bitmapDepth;
+ final byte[] bitmapData;
+ final 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 */
+ final 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;
+ }
+ final 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 */
+ final 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;
+ }
+ final 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(new RGB[] { fromRGB, toRGB });
+ bitmapDepth = 8;
+ final 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;
+ }
+ final 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 ? (byte)0 : (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 ? (byte)0 : (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;
+ final int inc = ((to << 16) - val) / steps + 1;
+ if (vertical) {
+ for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
+ bitmapData[dp] = (byte)(val >>> 16);
+ val += inc;
+ }
+ } else {
+ for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
+ bitmapData[dp] = (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) {
+ final int mask = 0xff00 >>> bits;
+ int val = from << 16;
+ final 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) {
+ final int thresh = DITHER_MATRIX[dy & 7][dx] >>> bits;
+ int temp = val + thresh;
+ if (temp > 0xffffff) bitmapData[dptr] = -1;
+ else bitmapData[dptr] = (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) {
+ final int thresh = DITHER_MATRIX[dy][dx & 7] >>> bits;
+ int temp = val + thresh;
+ if (temp > 0xffffff) bitmapData[dptr] = -1;
+ else bitmapData[dptr] = (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 380af2bdd8e5 dwt/graphics/ImageDataLoader.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/graphics/ImageDataLoader.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.graphics.ImageDataLoader; + +import dwt.dwthelper.utils; + +import java.io.InputStream; + +/** + * Internal class that separates ImageData from ImageLoader + * to allow removal of ImageLoader from the toolkit. + */ +class ImageDataLoader { + + public static ImageData[] load(InputStream stream) { + return new ImageLoader().load(stream); + } + + public static ImageData[] load(String filename) { + return new ImageLoader().load(filename); + } + +} diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/ImageLoader.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/graphics/ImageLoader.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,326 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.graphics.ImageLoader; + +import dwt.dwthelper.utils; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Vector; + +import dwt.DWT; +import dwt.DWTException; +import dwt.internal.Compatibility; +import dwt.internal.image.FileFormat; + +/** + * Instances of this class are used to load images from, + * and save images to, a file or stream. + *+ * 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 !is null && imageLoaderListeners.size() > 0;
+}
+
+/**
+ * Notifies all image loader listeners that an image loader event
+ * has occurred. Pass the specified event object to each listener.
+ *
+ * @param event the ImageLoaderEvent
to send to each ImageLoaderListener
+ */
+public void notifyListeners(ImageLoaderEvent event) {
+ if (!hasListeners()) return;
+ int size = imageLoaderListeners.size();
+ for (int i = 0; i < size; i++) {
+ ImageLoaderListener listener = (ImageLoaderListener) imageLoaderListeners.elementAt(i);
+ listener.imageDataLoaded(event);
+ }
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/ImageLoaderEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/ImageLoaderEvent.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.ImageLoaderEvent;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventObject;
+
+/**
+ * Instances of this class are sent as a result of the incremental
+ * loading of image data.
+ * + * 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 ImageLoaderEvent(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 String toString () {
+ return "ImageLoaderEvent {source=" + source + " imageData=" + imageData + " incrementCount=" + incrementCount + " endOfImage=" + endOfImage + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/ImageLoaderListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/ImageLoaderListener.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.ImageLoaderListener;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.DWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the incremental loading of image data.
+ *
+ * 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 380af2bdd8e5 dwt/graphics/LineAttributes.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/graphics/LineAttributes.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,123 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.graphics.LineAttributes; + +import dwt.dwthelper.utils; + +import dwt.DWT; + +/** + *LineAttributes
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 380af2bdd8e5 dwt/graphics/Path.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/Path.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,569 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.Path;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.DWTException;
+import dwt.internal.cocoa.NSAffineTransform;
+import dwt.internal.cocoa.NSBezierPath;
+import dwt.internal.cocoa.NSLayoutManager;
+import dwt.internal.cocoa.NSPoint;
+import dwt.internal.cocoa.NSRange;
+import dwt.internal.cocoa.NSRect;
+import dwt.internal.cocoa.NSSize;
+import dwt.internal.cocoa.NSString;
+import dwt.internal.cocoa.NSTextContainer;
+import dwt.internal.cocoa.NSTextStorage;
+import dwt.internal.cocoa.OS;
+
+/**
+ * Instances of this class represent paths through the two-dimensional
+ * coordinate system. Paths do not have to be continuous, and can be
+ * described using lines, rectangles, arcs, cubic or quadratic bezier curves,
+ * glyphs, or other paths.
+ *
+ * Application code must explicitly invoke the Path.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ * This class requires the operating system's advanced graphics subsystem + * which may not be available on some platforms. + *
+ * + * @since 3.1 + */ +public class Path extends Resource { + + /** + * the OS resource for the Path + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public NSBezierPath handle; + +/** + * 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 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
+ */
+public bool isDisposed() {
+ return handle is null;
+}
+
+/**
+ * Adds to the receiver a line from the current point to
+ * the point specified by (x, y).
+ *
+ * @param x the x coordinate of the end of the line to add
+ * @param y the y coordinate of the end of the line to add
+ *
+ * @exception DWTException
+ * 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. + *
+ * + * @since 3.1 + */ +public class Pattern extends Resource { + NSColor color; + NSGradient gradient; + NSPoint pt1, pt2; + Image image; + float[] color1, color2; + int alpha1, alpha2; + +/** + * 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 true
when the Pattern is disposed, and false
otherwise
+ */
+public bool isDisposed() {
+ return device is null;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Pattern {*DISPOSED*}";
+ return "Pattern {" + (color !is null ? color.id : gradient.id) + "}";
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/Point.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/Point.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.Point;
+
+import dwt.dwthelper.utils;
+
+import dwt.internal.SerializableCompatibility;
+
+/**
+ * Instances of this class represent places on the (x, y)
+ * coordinate plane.
+ *
+ * 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 dispose()
method is provided.
+ *
true
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 (!(object instanceof Point)) return false;
+ Point p = (Point)object;
+ return (p.x is this.x) && (p.y is this.y);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public int hashCode () {
+ return x ^ y;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the point
+ */
+public String toString () {
+ return "Point {" + x + ", " + y + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+}
+
+}
+
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/RGB.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/RGB.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.RGB;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.SerializableCompatibility;
+
+/**
+ * Instances of this class are descriptions of colors in
+ * terms of the primary additive color model (red, green and
+ * blue). A color may be described in terms of the relative
+ * intensities of these three primary colors. The brightness
+ * of each color is specified by a value in the range 0 to 255,
+ * where 0 indicates no color (blackness) and 255 indicates
+ * maximum intensity.
+ * + * 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 bool equals(Object object) {
+ if (object is this) return true;
+ if (!(object instanceof RGB)) return false;
+ RGB rgb = (RGB)object;
+ return (rgb.red is this.red) && (rgb.green is this.green) && (rgb.blue is this.blue);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public int hashCode() {
+ return (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 String toString() {
+ return "RGB {" + red + ", " + green + ", " + blue + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/Rectangle.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/Rectangle.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.graphics.Rectangle;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.internal.SerializableCompatibility;
+
+/**
+ * Instances of this class represent rectangular areas in an
+ * (x, y) coordinate system. The top left corner of the rectangle
+ * is specified by its x and y values, and the extent of the
+ * rectangle is specified by its width and height.
+ * + * 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 dispose()
method is provided.
+ *
+ * The union of two rectangles is the smallest single rectangle + * that completely covers both of the areas covered by the two + * given rectangles. + *
+ * + * @param rect the rectangle to merge with the receiver + * + * @exception IllegalArgumentExceptiontrue
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 true
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 (!(object instanceof Rectangle)) return false;
+ Rectangle r = (Rectangle)object;
+ return (r.x is this.x) && (r.y is this.y) && (r.width is this.width) && (r.height is this.height);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true
when passed to
+ * equals
must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public int hashCode () {
+ 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 + * The intersection of two rectangles is the rectangle that + * covers the area which is contained within both rectangles. + *
+ * + * @param rect the rectangle to intersect with the receiver + * @return the intersection of the receiver and the argument + * + * @exception IllegalArgumentExceptiontrue
if the rectangle described by the
+ * arguments intersects with the receiver and false
+ * otherwise.
+ * + * Two rectangles intersect if the area of the rectangle + * representing their intersection is not empty. + *
+ * + * @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 + * @returntrue
if the rectangle intersects with the receiver, and false
otherwise
+ *
+ * @exception IllegalArgumentException true
if the given rectangle intersects
+ * with the receiver and false
otherwise.
+ * + * Two rectangles intersect if the area of the rectangle + * representing their intersection is not empty. + *
+ * + * @param rect the rectangle to test for intersection + * @returntrue
if the rectangle intersects with the receiver, and false
otherwise
+ *
+ * @exception IllegalArgumentException 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.
+ * + * A rectangle is considered to cover area in the + * (x, y) coordinate plane if both its width and height are + * non-zero. + *
+ * + * @returntrue
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 String toString () {
+ return "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.
+ * + * The union of two rectangles is the smallest single rectangle + * that completely covers both of the areas covered by the two + * given rectangles. + *
+ * + * @param rect the rectangle to perform union with + * @return the union of the receiver and the argument + * + * @exception IllegalArgumentException
+ * Application code must explicitly invoke the Region.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public int handle; + +/** + * Constructs a new empty region. + * + * @exception DWTError+ * You must dispose the region when it is no longer required. + *
+ * + * @param device the device on which to allocate the region + * + * @exception IllegalArgumentExceptiontrue
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 DWTException 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 true
if the object is the same as this object and false
otherwise
+ *
+ * @see #hashCode
+ */
+public bool equals(Object object) {
+ if (this is object) return true;
+ if (!(object instanceof Region)) return false;
+ Region region = (Region)object;
+ return handle is region.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 DWTException 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;
+}
+
+/**
+ * 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 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 DWTException 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 true
if the region has been disposed,
+ * and false
otherwise.
+ *
+ * This method gets the dispose state for the region.
+ * When a region has been disposed, it is an error to
+ * invoke any other method using the region.
+ *
+ * @return true
when the region is disposed, and false
otherwise
+ */
+public bool isDisposed() {
+ return handle is 0;
+}
+
+/**
+ * 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 DWTException
+ * IMPORTANT: This class is intended to be subclassed only + * within the DWT implementation. However, it has not been marked + * final to allow those outside of the DWT development team to implement + * patched versions of the class in order to get around specific + * limitations in advance of when those limitations can be addressed + * by the team. Any class built using subclassing to access the internals + * of this class will likely fail to compile or run between releases and + * may be strongly platform specific. Subclassing should not be attempted + * without an intimate and detailed understanding of the workings of the + * hierarchy. No support is provided for user-written classes which are + * implemented as subclasses of this class. + *
+ * + * @see #dispose + * @see #isDisposed + * + * @since 3.1 + */ +public abstract class Resource { + + /** + * the device where this resource was created + */ + Device device; + +Resource() { +} + +Resource(Device device) { + if (device is null) device = Device.getDevice(); + if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + this.device = device; +} + +void destroy() { +} + +/** + * Disposes of the operating system resources associated with + * this resource. Applications must dispose of all resources + * which they allocate. + */ +public void dispose() { + if (device is null) return; + if (device.isDisposed()) return; + destroy(); + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Returns theDevice
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 ()) DWT.error (DWT.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.
+ *
+ * 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 true
when the resource is disposed and false
otherwise
+ */
+public abstract bool isDisposed();
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/TextLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/TextLayout.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,1450 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.TextLayout;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.DWTException;
+import dwt.internal.cocoa.NSColor;
+import dwt.internal.cocoa.NSFont;
+import dwt.internal.cocoa.NSLayoutManager;
+import dwt.internal.cocoa.NSMutableParagraphStyle;
+import dwt.internal.cocoa.NSNumber;
+import dwt.internal.cocoa.NSPoint;
+import dwt.internal.cocoa.NSRange;
+import dwt.internal.cocoa.NSRect;
+import dwt.internal.cocoa.NSSize;
+import dwt.internal.cocoa.NSString;
+import dwt.internal.cocoa.NSTextContainer;
+import dwt.internal.cocoa.NSTextStorage;
+import dwt.internal.cocoa.OS;
+
+/**
+ * TextLayout
is a graphic object that represents
+ * styled text.
+ *
+ * Instances of this class provide support for drawing, cursor + * navigation, hit testing, text wrapping, alignment, tab expansion + * line breaking, etc. These are aspects required for rendering internationalized text. + *
+ * Application code must explicitly invoke the TextLayout#dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ * You must dispose the text layout when it is no longer required. + *
+ * + * @param device the device on which to allocate the text layout + * + * @exception IllegalArgumentException
+ * The parameter flags
can include one of DWT.DELIMITER_SELECTION
+ * or DWT.FULL_SELECTION
to specify the selection behavior on all lines except
+ * for the last line, and can also include DWT.LAST_LINE_SELECTION
to extend
+ * the specified selection behavior to the last line.
+ *
DWT.LEFT
, DWT.CENTER
or
+ * DWT.RIGHT
.
+ *
+ * @return the alignment used to positioned text horizontally
+ *
+ * @exception DWTException 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 DWTException DWT.MOVEMENT_CHAR
,
+ * DWT.MOVEMENT_CLUSTER
, DWT.MOVEMENT_WORD
,
+ * DWT.MOVEMENT_WORD_END
or DWT.MOVEMENT_WORD_START
.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the next offset
+ *
+ * @exception IllegalArgumentException 1
1
DWT.MOVEMENT_CHAR
,
+ * DWT.MOVEMENT_CLUSTER
or DWT.MOVEMENT_WORD
,
+ * DWT.MOVEMENT_WORD_END
or DWT.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 DWTException 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
+ */
+public bool isDisposed () {
+ return device is null;
+}
+
+/**
+ * Sets the text alignment for the receiver. The alignment controls
+ * how a line of text is positioned horizontally. The argument should
+ * be one of DWT.LEFT
, DWT.RIGHT
or DWT.CENTER
.
+ *
+ * The default alignment is DWT.LEFT
. Note that the receiver's
+ * width must be set in order to use DWT.RIGHT
or DWT.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
DWT.LEFT_TO_RIGHT
or DWT.RIGHT_TO_LEFT
.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception DWTException
+ * 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.
+ *
DWT.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 DWT.UNDERLINE_SINGLE
,
+ * DWT.UNDERLINE_DOUBLE
, DWT.UNDERLINE_ERROR
,
+ * or DWT.UNDERLINE_SQUIGGLE
.
+ *
DWT.NONE
.
+ *
+ * This value should be one of DWT.BORDER_SOLID
,
+ * DWT.BORDER_DASH
,DWT.BORDER_DOT
or
+ * DWT.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 TextStyle (Font font, Color foreground, Color background) {
+ if (font !is null && font.isDisposed()) DWT.error (DWT.ERROR_INVALID_ARGUMENT);
+ if (foreground !is null && foreground.isDisposed()) DWT.error (DWT.ERROR_INVALID_ARGUMENT);
+ if (background !is null && background.isDisposed()) DWT.error (DWT.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 TextStyle (TextStyle style) {
+ if (style is null) DWT.error (DWT.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 bool equals(Object object) {
+ if (object is this) return true;
+ if (object is null) return false;
+ if (!(object instanceof TextStyle)) return false;
+ TextStyle style = (TextStyle)object;
+ if (foreground !is null) {
+ if (!foreground.equals(style.foreground)) return false;
+ } else if (style.foreground !is null) return false;
+ if (background !is null) {
+ if (!background.equals(style.background)) return false;
+ } else if (style.background !is null) return false;
+ if (font !is null) {
+ if (!font.equals(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 int hashCode() {
+ int hash = 0;
+ if (foreground !is null) hash ^= foreground.hashCode();
+ if (background !is null) hash ^= background.hashCode();
+ if (font !is null) hash ^= font.hashCode();
+ if (metrics !is null) hash ^= metrics.hashCode();
+ 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
+ */
+public String toString () {
+ StringBuffer buffer = new StringBuffer("TextStyle {");
+ int startLength = buffer.length();
+ if (font !is null) {
+ if (buffer.length() > startLength) buffer.append(", ");
+ buffer.append("font=");
+ buffer.append(font);
+ }
+ if (foreground !is null) {
+ if (buffer.length() > startLength) buffer.append(", ");
+ buffer.append("foreground=");
+ buffer.append(foreground);
+ }
+ if (background !is null) {
+ if (buffer.length() > startLength) buffer.append(", ");
+ buffer.append("background=");
+ buffer.append(background);
+ }
+ if (underline) {
+ if (buffer.length() > startLength) buffer.append(", ");
+ buffer.append("underlined");
+ }
+ if (strikeout) {
+ if (buffer.length() > startLength) buffer.append(", ");
+ buffer.append("striked out");
+ }
+ if (rise !is 0) {
+ if (buffer.length() > startLength) buffer.append(", ");
+ buffer.append("rise=");
+ buffer.append(rise);
+ }
+ if (metrics !is null) {
+ if (buffer.length() > startLength) buffer.append(", ");
+ buffer.append("metrics=");
+ buffer.append(metrics);
+ }
+ buffer.append("}");
+ return buffer.toString();
+}
+
+}
diff -r 000000000000 -r 380af2bdd8e5 dwt/graphics/Transform.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/graphics/Transform.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+module dwt.graphics.Transform;
+
+import dwt.dwthelper.utils;
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.DWTException;
+import dwt.internal.cocoa.NSAffineTransform;
+import dwt.internal.cocoa.NSAffineTransformStruct;
+import dwt.internal.cocoa.NSPoint;
+
+/**
+ * Instances of this class represent transformation matrices for
+ * points expressed as (x, y) pairs of floating point numbers.
+ *
+ * Application code must explicitly invoke the Transform.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ * This class requires the operating system's advanced graphics subsystem + * which may not be available on some platforms. + *
+ * + * @since 3.1 + */ +public class Transform extends Resource { + /** + * the OS resource for the Transform + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public NSAffineTransform 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
+ */
+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()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
+ NSAffineTransformStruct struct = handle.transformStruct();
+ return struct.m11 is 1 && struct.m12 is 0 && struct.m21 is 0 && struct.m22 is 1 && struct.tX is 0 && struct.tY is 0;
+}
+
+/**
+ * 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 DWTException
+ * IMPORTANT: A callback is only valid when invoked on the
+ * thread which created it. The results are undefined (and
+ * typically bad) when a callback is passed out to the
+ * operating system (or other code) in such a way that the
+ * callback is called from a different thread.
+ */
+
+public class Callback
+{
+
+ Object object;
+ String method, signature;
+ int argCount;
+ int /*long*/address, errorResult;
+ bool isStatic, isArrayBased;
+
+ static const String PTR_SIGNATURE = C.PTR_SIZEOF is 4 ? "I" : "J"; //$NON-NLS-1$ //$NON-NLS-2$
+ static const String SIGNATURE_0 = getSignature(0);
+ static const String SIGNATURE_1 = getSignature(1);
+ static const String SIGNATURE_2 = getSignature(2);
+ static const String SIGNATURE_3 = getSignature(3);
+ static const String SIGNATURE_4 = getSignature(4);
+ static const String
+ SIGNATURE_N = "([" + PTR_SIGNATURE + ")" + PTR_SIGNATURE; //$NON-NLS-1$ //$NON-NLS-2$
+
+ /**
+ * Constructs a new instance of this class given an object
+ * to send the message to, a string naming the method to
+ * invoke and an argument count. Note that, if the object
+ * is an instance of Class
it is assumed that
+ * the method is a static method on that class.
+ *
+ * @param object the object to send the message to
+ * @param method the name of the method to invoke
+ * @param argCount the number of arguments that the method takes
+ */
+ public this (Object object, String method, int argCount)
+ {
+ this(object, method, argCount, false);
+ }
+
+ /**
+ * Constructs a new instance of this class given an object
+ * to send the message to, a string naming the method to
+ * invoke, an argument count and a flag indicating whether
+ * or not the arguments will be passed in an array. Note
+ * that, if the object is an instance of Class
+ * it is assumed that the method is a static method on that
+ * class.
+ *
+ * @param object the object to send the message to
+ * @param method the name of the method to invoke
+ * @param argCount the number of arguments that the method takes
+ * @param isArrayBased true
if the arguments should be passed in an array and false otherwise
+ */
+ public this (Object object, String method, int argCount, bool isArrayBased)
+ {
+ this(object, method, argCount, isArrayBased, 0);
+ }
+
+ /**
+ * Constructs a new instance of this class given an object
+ * to send the message to, a string naming the method to
+ * invoke, an argument count, a flag indicating whether
+ * or not the arguments will be passed in an array and a value
+ * to return when an exception happens. Note that, if
+ * the object is an instance of Class
+ * it is assumed that the method is a static method on that
+ * class.
+ *
+ * @param object the object to send the message to
+ * @param method the name of the method to invoke
+ * @param argCount the number of arguments that the method takes
+ * @param isArrayBased true
if the arguments should be passed in an array and false otherwise
+ * @param errorResult the return value if the java code throws an exception
+ */
+ public this (Object object, String method, int argCount, bool isArrayBased,
+ int /*long*/errorResult)
+ {
+
+ /* Set the callback fields */
+ this.object = object;
+ this.method = method;
+ this.argCount = argCount;
+ this.isStatic = cast(ClassInfo) object;
+ this.isArrayBased = isArrayBased;
+ this.errorResult = errorResult;
+
+ /* Inline the common cases */
+ if (isArrayBased)
+ {
+ signature = SIGNATURE_N;
+ }
+ else
+ {
+ switch (argCount)
+ {
+ case 0:
+ signature = SIGNATURE_0;
+ break; //$NON-NLS-1$
+ case 1:
+ signature = SIGNATURE_1;
+ break; //$NON-NLS-1$
+ case 2:
+ signature = SIGNATURE_2;
+ break; //$NON-NLS-1$
+ case 3:
+ signature = SIGNATURE_3;
+ break; //$NON-NLS-1$
+ case 4:
+ signature = SIGNATURE_4;
+ break; //$NON-NLS-1$
+ default:
+ signature = getSignature(argCount);
+ }
+ }
+
+ /* Bind the address */
+ address = bind(this, object, method, signature, argCount, isStatic,
+ isArrayBased, errorResult);
+ }
+
+ /**
+ * Allocates the native level resources associated with the
+ * callback. This method is only invoked from within the
+ * constructor for the argument.
+ *
+ * @param callback the callback to bind
+ * @param object the callback's object
+ * @param method the callback's method
+ * @param signature the callback's method signature
+ * @param argCount the callback's method argument count
+ * @param isStatic whether the callback's method is static
+ * @param isArrayBased whether the callback's method is array based
+ * @param errorResult the callback's error result
+ */
+ static synchronized int /*long*/ bind (Callback callback, Object object, String method, String signature, int argCount, bool isStatic, bool isArrayBased, int /*long*/ errorResult)
+ {
+
+ }
+
+ /**
+ * Releases the native level resources associated with the callback,
+ * and removes all references between the callback and
+ * other objects. This helps to prevent (bad) application code
+ * from accidentally holding onto extraneous garbage.
+ */
+ public void dispose ()
+ {
+ if (object is null)
+ return;
+ unbind(this);
+ object = method = signature = null;
+ address = 0;
+ }
+
+ /**
+ * Returns the address of a block of machine code which will
+ * invoke the callback represented by the receiver.
+ *
+ * @return the callback address
+ */
+ public int /*long*/getAddress ()
+ {
+ return address;
+ }
+
+ /**
+ * Returns the DWT platform name.
+ *
+ * @return the platform name of the currently running DWT
+ */
+ //public static native String getPlatform ();
+ /**
+ * Returns the number of times the system has been recursively entered
+ * through a callback.
+ *
+ * Note: This should not be called by application code. + *
+ * + * @return the entry count + * + * @since 2.1 + */ + //public static native int getEntryCount (); + static String getSignature (int argCount) + { + String signature = "("; //$NON-NLS-1$ + for (int i = 0; i < argCount; i++) + signature += PTR_SIGNATURE; + signature += ")" + PTR_SIGNATURE; //$NON-NLS-1$ + return signature; + } + + /** + * Indicates whether or not callbacks which are triggered at the + * native level should cause the messages described by the matching + *Callback
objects to be invoked. This method is used
+ * to safely shut down DWT when it is run within environments
+ * which can generate spurious events.
+ * + * Note: This should not be called by application code. + *
+ * + * @param enable true if callbacks should be invoked + */ + //public static final native synchronized void setEnabled (bool enable); + /** + * Returns whether or not callbacks which are triggered at the + * native level should cause the messages described by the matching + *Callback
objects to be invoked. This method is used
+ * to safely shut down DWT when it is run within environments
+ * which can generate spurious events.
+ * + * Note: This should not be called by application code. + *
+ * + * @return true if callbacks should not be invoked + */ + //public static final native synchronized bool getEnabled (); + /** + * This might be called directly from native code in environments + * which can generate spurious events. Check before removing it. + * + * @deprecated + * + * @param ignore true if callbacks should not be invoked + */ + static final void ignoreCallbacks (bool ignore) + { + setEnabled(!ignore); + } + + /** + * Immediately wipes out all native level state associated + * with all callbacks. + *+ * WARNING: This operation is extremely dangerous, + * and should never be performed by application code. + *
+ */ + //public static final native synchronized void reset (); + /** + * Releases the native level resources associated with the callback. + * + * @see #dispose + */ + //static final native synchronized void unbind (Callback callback); +} diff -r 000000000000 -r 380af2bdd8e5 dwt/internal/CloneableCompatibility.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/internal/CloneableCompatibility.d Sat Aug 09 17:00:02 2008 +0200 @@ -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: + * Jacob Carlborg+ * 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. + *
+ */ +public interface CloneableCompatibility : Cloneable +{ +} diff -r 000000000000 -r 380af2bdd8e5 dwt/internal/Compatibility.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/internal/Compatibility.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,418 @@ +/******************************************************************************* + * 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: + * Jacob Carlborg+ * 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). + *
+ * + * @param angle the angle in degrees + * @param length the length of the triangle's hypotenuse + * @return the integer conversion of length * cos (angle) + */ + public static int cos (int angle, int length) + { + return cast(int) (Math.cos(angle * toRadians) * length); + } + + /** + * Answers the length of the side opposite to the given angle + * of a right triangle. In other words, it returns the integer + * conversion of length * sin (angle). + *+ * IMPORTANT: the j2me version has an additional restriction on + * the argument. length must be between -32767 and 32767 (inclusive). + *
+ * + * @param angle the angle in degrees + * @param length the length of the triangle's hypotenuse + * @return the integer conversion of length * sin (angle) + */ + public static int sin (int angle, int length) + { + return cast(int) (Math.sin(angle * toRadians) * length); + } + + /** + * Answers the most negative (i.e. closest to negative infinity) + * integer value which is greater than the number obtained by dividing + * the first argument p by the second argument q. + * + * @param p numerator + * @param q denominator (must be different from zero) + * @return the ceiling of the rational number p / q. + */ + public static int ceil (int p, int q) + { + return cast(int) Math.ceil(cast(float) p / q); + } + + /** + * Answers whether the indicated file exists or not. + * + * @param parent the file's parent directory + * @param child the file's name + * @return true if the file exists + */ + public static bool fileExists (String parent, String child) + { + return (new File(parent, child)).exists(); + } + + /** + * Answers the most positive (i.e. closest to positive infinity) + * integer value which is less than the number obtained by dividing + * the first argument p by the second argument q. + * + * @param p numerator + * @param q denominator (must be different from zero) + * @return the floor of the rational number p / q. + */ + public static int floor (int p, int q) + { + return cast(int) Math.floor(cast(double) p / q); + } + + /** + * Answers the result of rounding to the closest integer the number obtained + * by dividing the first argument p by the second argument q. + *+ * 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). + *
+ * + * @param p numerator + * @param q denominator (must be different from zero) + * @return the closest integer to the rational number p / q + */ + public static int round (int p, int q) + { + return Math.round(cast(float) p / q); + } + + /** + * Returns 2 raised to the power of the argument. + * + * @param n an int value between 0 and 30 (inclusive) + * @return 2 raised to the power of the argument + * + * @exception IllegalArgumentExceptionnull
+ * @exception IOException
+ *
+ * @since 3.4
+ */
+ public static OutputStream newDeflaterOutputStream (OutputStream stream)
+ {
+ 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 InputStream newInflaterInputStream (InputStream stream)
+ {
+ return new BufferedInputStream(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 (char c)
+ {
+ return Character.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 (char c)
+ {
+ return Character.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 (char c)
+ {
+ return Character.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 (char c)
+ {
+ return Character.isWhitespace(c);
+ }
+
+ /**
+ * Execute a program in a separate platform process if the
+ * underlying platform support this.
+ * + * The new process inherits the environment of the caller. + *
+ * + * @param prog the name of the program to execute + * + * @exception IOException + * if the program cannot be executed + * @exception SecurityException + * if the current SecurityManager disallows program execution + */ + public static void exec (String prog) + { + //Runtime.getRuntime().exec(prog); + } + + /** + * Execute progArray[0] in a separate platform process if the + * underlying platform support this. + *+ * The new process inherits the environment of the caller. + *
+ * + * @param progArray array containing the program to execute and its arguments + * + * @exception IOException + * if the program cannot be executed + * @exception SecurityException + * if the current SecurityManager disallows program execution + */ + public static void exec (String[] progArray) + { + Runtime.getRuntime().exec(progArray); + } + + private static ResourceBundle msgs = null; + + /** + * Returns the NLS'ed message for the given argument. This is only being + * called from DWT. + * + * @param key the key to look up + * @return the message for the given key + * + * @see DWT#getMessage(String) + */ + public static String getMessage (String key) + { + String answer = key; + + if (key is null) + { + DWT.error(DWT.ERROR_NULL_ARGUMENT); + } + if (msgs is null) + { + try + { + msgs = ResourceBundle.getBundle("dwt.internal.SWTMessages"); //$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) + { + DWT.error(DWT.ERROR_NULL_ARGUMENT); + } + if (msgs is null) + { + try + { + msgs = ResourceBundle.getBundle("dwt.internal.SWTMessages"); //$NON-NLS-1$ + } + catch (MissingResourceException ex) + { + answer = key + " (no resource bundle)"; //$NON-NLS-1$ + } + } + if (msgs !is null) + { + try + { + MessageFormat formatter = new MessageFormat(""); + formatter.applyPattern(msgs.getString(key)); + answer = formatter.format(args); + } + catch (MissingResourceException ex2) + { + } + } + return answer; + } + + /** + * Interrupt the current thread. + *
+ * Note that this is not available on CLDC. + *
+ */ + public static void interrupt () + { + Thread.currentThread().interrupt(); + } + + /** + * Compares two instances of class String ignoring the case of the + * characters and answers if they are equal. + * + * @param s1 string + * @param s2 string + * @return true if the two instances of class String are equal + */ + public static bool equalsIgnoreCase (String s1, String s2) + { + return s1.equalsIgnoreCase(s2); + } + +} diff -r 000000000000 -r 380af2bdd8e5 dwt/internal/DWTEventListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/internal/DWTEventListener.d Sat Aug 09 17:00:02 2008 +0200 @@ -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: + * Jacob Carlborg+ * It is part of our effort to provide support for both J2SE + * and J2ME platforms. Under this scheme, classes need to + * implement DWTEventListener instead of java.util.EventListener. + *
+ *+ * Note: java.util.EventListener is not part of CDC and CLDC. + *
+ */ +public interface DWTEventListener : EventListener +{ +} \ No newline at end of file diff -r 000000000000 -r 380af2bdd8e5 dwt/internal/DWTEventObject.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/internal/DWTEventObject.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,46 @@ +/******************************************************************************* + * 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: + * Jacob Carlborg+ * It is part of our effort to provide support for both J2SE + * and J2ME platforms. Under this scheme, classes need to + * extend DWTEventObject instead of java.util.EventObject. + *
+ *+ * Note: java.util.EventObject is not part of CDC and CLDC. + *
+ */ +public class DWTEventObject : EventObject +{ + + static const long serialVersionUID = 3258125873411470903L; + + /** + * Constructs a new instance of this class. + * + * @param source the object which fired the event + */ + public this (Object source) + { + super(source); + } +} diff -r 000000000000 -r 380af2bdd8e5 dwt/internal/LONG.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/internal/LONG.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,41 @@ +/******************************************************************************* + * 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 Benoitname
is used to load the library. If this fails,
+ * name
is used in another attempt to load the library,
+ * this time ignoring the DWT 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. DWT 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 DWT 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, bool 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 DWT 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 DWT 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 is 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 !is 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 is 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 !is 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 380af2bdd8e5 dwt/internal/Lock.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/internal/Lock.d Sat Aug 09 17:00:02 2008 +0200
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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 + * 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. + *
+ */ +public interface SerializableCompatibility : Serializable +{ +} diff -r 000000000000 -r 380af2bdd8e5 dwt/internal/c/callback.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/internal/c/callback.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,270 @@ +/******************************************************************************* + * 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: + * Jacob Carlborg