# HG changeset patch # User Frank Benoit # Date 1223389795 -7200 # Node ID 6337764516f1b3ed3f4ca54d629cbb883f445528 # Parent fbe68c33eeee7231a0dc352d471ad43eb1de8e69 Sync dwt/custom with dwt-linux (took copy of complete folder) diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/AnimatedProgress.d --- a/dwt/custom/AnimatedProgress.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/AnimatedProgress.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,13 +7,14 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.AnimatedProgress; + import dwt.DWT; +import dwt.DWTException; import dwt.events.ControlAdapter; import dwt.events.ControlEvent; import dwt.events.DisposeEvent; @@ -23,20 +24,26 @@ import dwt.graphics.Color; import dwt.graphics.GC; import dwt.graphics.Point; +import dwt.graphics.Rectangle; import dwt.widgets.Canvas; import dwt.widgets.Composite; +import dwt.widgets.Display; +import dwt.dwthelper.Runnable; /** * A control for showing progress feedback for a long running operation. * * @deprecated As of Eclipse 2.1, use ProgressBar with the style DWT.INDETERMINATE - * + * *
*
Styles:
VERTICAL, HORIZONTAL, BORDER *
+ * + * @see Sample code and further information */ -public class AnimatedProgress : Canvas -{ +public class AnimatedProgress : Canvas { + + alias Canvas.computeSize computeSize; static const int SLEEP = 70; static const int DEFAULT_WIDTH = 160; @@ -47,236 +54,192 @@ int orientation = DWT.HORIZONTAL; bool showBorder = false; - /** - * 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#VERTICAL - * @see DWT#HORIZONTAL - * @see DWT#BORDER - * @see #getStyle() - */ - public this (Composite parent, int style) - { - super(parent, checkStyle(style)); +/** + * 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#VERTICAL + * @see DWT#HORIZONTAL + * @see DWT#BORDER + * @see #getStyle() + */ +public this(Composite parent, int style) { + super(parent, checkStyle(style)); - if ((style & DWT.VERTICAL) !is 0) - { - orientation = DWT.VERTICAL; - } - showBorder = (style & DWT.BORDER) !is 0; + if ((style & DWT.VERTICAL) !is 0) { + orientation = DWT.VERTICAL; + } + showBorder = (style & DWT.BORDER) !is 0; - addControlListener(new class ControlAdapter - { - public void controlResized (ControlEvent e) - { - redraw(); - } - }); - addPaintListener(new class PaintListener - { - public void paintControl (PaintEvent e) - { - paint(e); - } - }); - addDisposeListener(new class DisposeListener - { - public void widgetDisposed (DisposeEvent e) - { - stop(); - } - }); + addControlListener(new class() ControlAdapter { + public void controlResized(ControlEvent e) { + redraw(); + } + }); + addPaintListener(new class() PaintListener { + public void paintControl(PaintEvent e) { + paint(e); + } + }); + addDisposeListener(new class() DisposeListener { + public void widgetDisposed(DisposeEvent e){ + stop(); + } + }); +} +private static int checkStyle (int style) { + int mask = DWT.NONE; + return style & mask; +} +/** + * Stop the animation if it is not already stopped and + * reset the presentation to a blank appearance. + * + * @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 synchronized void clear(){ + checkWidget(); + if (active) stop(); + showStripes = false; + redraw(); +} +public override Point computeSize(int wHint, int hHint, bool changed) { + checkWidget(); + Point size = null; + if (orientation is DWT.HORIZONTAL) { + size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT); + } else { + size = new Point(DEFAULT_HEIGHT, DEFAULT_WIDTH); } + if (wHint !is DWT.DEFAULT) size.x = wHint; + if (hHint !is DWT.DEFAULT) size.y = hHint; - private static int checkStyle (int style) - { - int mask = DWT.NONE; - return style & mask; - } + return size; +} +private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) { + gc.setForeground(topleft); + gc.drawLine(x, y, x+w-1, y); + gc.drawLine(x, y, x, y+h-1); - /** - * Stop the animation if it is not already stopped and - * reset the presentation to a blank appearance. - * - * @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 synchronized void clear () - { - checkWidget(); - if (active) - stop(); - showStripes = false; - redraw(); + gc.setForeground(bottomright); + gc.drawLine(x+w, y, x+w, y+h); + gc.drawLine(x, y+h, x+w, y+h); +} +void paint(PaintEvent event) { + GC gc = event.gc; + Display disp= getDisplay(); + + Rectangle rect= getClientArea(); + gc.fillRectangle(rect); + if (showBorder) { + drawBevelRect(gc, rect.x, rect.y, rect.width-1, rect.height-1, + disp.getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW), + disp.getSystemColor(DWT.COLOR_WIDGET_HIGHLIGHT_SHADOW)); } - public Point computeSize (int wHint, int hHint, bool changed) - { - checkWidget(); - Point size = null; - if (orientation is DWT.HORIZONTAL) - { - size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT); - } - else - { - size = new Point(DEFAULT_HEIGHT, DEFAULT_WIDTH); - } - if (wHint !is DWT.DEFAULT) - size.x = wHint; - if (hHint !is DWT.DEFAULT) - size.y = hHint; - - return size; - } + paintStripes(gc); +} +void paintStripes(GC gc) { - private void drawBevelRect (GC gc, int x, int y, int w, int h, - Color topleft, Color bottomright) - { - gc.setForeground(topleft); - gc.drawLine(x, y, x + w - 1, y); - gc.drawLine(x, y, x, y + h - 1); - - gc.setForeground(bottomright); - gc.drawLine(x + w, y, x + w, y + h); - gc.drawLine(x, y + h, x + w, y + h); - } + if (!showStripes) return; - void paint (PaintEvent event) - { - GC gc = event.gc; - Display disp = getDisplay(); - - Rectangle rect = getClientArea(); - gc.fillRectangle(rect); - if (showBorder) - { - drawBevelRect(gc, rect.x, rect.y, rect.width - 1, rect.height - 1, - disp.getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW), - disp.getSystemColor(DWT.COLOR_WIDGET_HIGHLIGHT_SHADOW)); - } + Rectangle rect= getClientArea(); + // Subtracted border painted by paint. + rect = new Rectangle(rect.x+2, rect.y+2, rect.width-4, rect.height-4); - paintStripes(gc); - } - - void paintStripes (GC gc) - { - - if (!showStripes) - return; - - Rectangle rect = getClientArea(); - // Subtracted border painted by paint. - rect = new Rectangle(rect.x + 2, rect.y + 2, rect.width - 4, - rect.height - 4); + gc.setLineWidth(2); + gc.setClipping(rect); + Color color = getDisplay().getSystemColor(DWT.COLOR_LIST_SELECTION); + gc.setBackground(color); + gc.fillRectangle(rect); + gc.setForeground(this.getBackground()); + int step = 12; + int foregroundValue = value is 0 ? step - 2 : value - 2; + if (orientation is DWT.HORIZONTAL) { + int y = rect.y - 1; + int w = rect.width; + int h = rect.height + 2; + for (int i= 0; i < w; i+= step) { + int x = i + foregroundValue; + gc.drawLine(x, y, x, h); + } + } else { + int x = rect.x - 1; + int w = rect.width + 2; + int h = rect.height; - gc.setLineWidth(2); - gc.setClipping(rect); - Color color = getDisplay().getSystemColor(DWT.COLOR_LIST_SELECTION); - gc.setBackground(color); - gc.fillRectangle(rect); - gc.setForeground(this.getBackground()); - int step = 12; - int foregroundValue = value is 0 ? step - 2 : value - 2; - if (orientation is DWT.HORIZONTAL) - { - int y = rect.y - 1; - int w = rect.width; - int h = rect.height + 2; - for (int i = 0; i < w; i += step) - { - int x = i + foregroundValue; - gc.drawLine(x, y, x, h); - } - } - else - { - int x = rect.x - 1; - int w = rect.width + 2; - int h = rect.height; - - for (int i = 0; i < h; i += step) - { - int y = i + foregroundValue; - gc.drawLine(x, y, w, y); - } - } - - if (active) - { - value = (value + 2) % step; + for (int i= 0; i < h; i+= step) { + int y = i + foregroundValue; + gc.drawLine(x, y, w, y); } } - /** - * Start the animation. - * - * @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 synchronized void start () - { - checkWidget(); - if (active) - return; - - active = true; - showStripes = true; - - const Display display = getDisplay(); - const Runnable[] timer = new Runnable[1]; - timer[0] = new class (display) Runnable - { - Display display; - - this (Display display) - { - this.display = display; - } - - public void run () - { - if (!active) - return; - GC gc = new GC(this); - paintStripes(gc); - gc.dispose(); - display.timerExec(SLEEP, timer[0]); - } - }; - display.timerExec(SLEEP, timer[0]); - } - - /** - * Stop the animation. Freeze the presentation at its current appearance. - */ - public synchronized void stop () - { - //checkWidget(); - active = false; + if (active) { + value = (value + 2) % step; } } +/** +* Start the animation. +* +* @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 synchronized void start() { + checkWidget(); + if (active) return; + + active = true; + showStripes = true; + + Display display = getDisplay(); + Runnable [] timer = new Runnable [1]; + + timer [0] = new class( display, timer ) Runnable { + Display disp; + Runnable [] runs; + this( Display disp, Runnable[] runs ){ + this.disp = disp; + this.runs = runs; + } + public void run () { + if (!active) return; + GC gc = new GC(this.outer); + paintStripes(gc); + gc.dispose(); + disp.timerExec (SLEEP, runs [0]); + } + }; + display.timerExec (SLEEP, timer [0]); +} +/** +* Stop the animation. Freeze the presentation at its current appearance. +*/ +public synchronized void stop() { + //checkWidget(); + active = false; +} +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/BidiSegmentEvent.d --- a/dwt/custom/BidiSegmentEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/BidiSegmentEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,25 +7,25 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.BidiSegmentEvent; -import dwt.custom.StyledTextEvent; +import dwt.dwthelper.utils; + + import dwt.events.TypedEvent; - -import dwt.dwthelper.string; +import dwt.custom.StyledTextEvent; /** * This event is sent to BidiSegmentListeners when a line is to - * be measured or rendered in a bidi locale. The segments field is - * used to specify text ranges in the line that should be treated as - * separate segments for bidi reordering. Each segment will be reordered + * be measured or rendered in a bidi locale. The segments field is + * used to specify text ranges in the line that should be treated as + * separate segments for bidi reordering. Each segment will be reordered * and rendered separately. *

- * The elements in the segments field specify the start offset of + * 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: *

    @@ -33,57 +33,57 @@ *
  • elements must be in ascending order and must not have duplicates *
  • elements must not exceed the line length *
- * In addition, the last element may be set to the end of the line + * In addition, the last element may be set to the end of the line * but this is not required. * - * The segments field may be left null if the entire line should + * The segments field may be left null if the entire line should * be reordered as is. *

- * A BidiSegmentListener may be used when adjacent segments of - * right-to-left text should not be reordered relative to each other. - * For example, within a Java editor, you may wish multiple - * right-to-left String literals to be reordered differently than the - * bidi algorithm specifies. + * A BidiSegmentListener may be used when adjacent segments of + * right-to-left text should not be reordered relative to each other. + * For example, within a Java editor, you may wish multiple + * right-to-left string literals to be reordered differently than the + * bidi algorithm specifies. * * Example: *
  *  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). 
+ *
+ *  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". 
+ *
+ *  segments = [0, 5, 8]
+ *      "R1R2R3" will be reordered, followed by [blank]+[blank] and
+ *      "R4R5R6".
  *      visual line = "R3R2R1" + "R6R5R4"
  * 
+ * + * @see Sample code and further information */ public class BidiSegmentEvent : TypedEvent { - /** - * line start offset + /** + * line start offset */ public int lineOffset; - /** - * line text + /** + * line text */ public String lineText; - /** - * bidi segments, see above + /** + * bidi segments, see above */ public int[] segments; - static final long serialVersionUID = 3257846571587547957L; - - this (StyledTextEvent e) { - super(e); - lineOffset = e.detail; - lineText = e.text; - } +this(StyledTextEvent e) { + super(cast(Object)e); + lineOffset = e.detail; + lineText = e.text; } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/BidiSegmentListener.d --- a/dwt/custom/BidiSegmentListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/BidiSegmentListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * 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 @@ -7,14 +7,13 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.BidiSegmentListener; +import dwt.internal.DWTEventListener; import dwt.custom.BidiSegmentEvent; -import dwt.internal.DWTEventListener; /** * This listener interface may be implemented in order to receive @@ -23,21 +22,22 @@ */ public interface BidiSegmentListener : DWTEventListener { - /** - * This method is called when a line needs to be reordered for - * measuring or rendering in a bidi locale. - *

- * The following event fields are used:

    - *
  • event.lineOffset line start offset (input)
  • - *
  • event.lineText line text (input)
  • - *
  • event.segments text segments that should be reordered - * separately. (output)
  • - *
- * - * @param event the given event - * separately. (output) - * @see BidiSegmentEvent - */ - public void lineGetSegments (BidiSegmentEvent event); +/** + * This method is called when a line needs to be reordered for + * measuring or rendering in a bidi locale. + *

+ * The following event fields are used:

    + *
  • event.lineOffset line start offset (input)
  • + *
  • event.lineText line text (input)
  • + *
  • event.segments text segments that should be reordered + * separately. (output)
  • + *
+ * + * @param event the given event + * separately. (output) + * @see BidiSegmentEvent + */ +public void lineGetSegments(BidiSegmentEvent event); } + diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/Bullet.d --- a/dwt/custom/Bullet.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/Bullet.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,154 +7,157 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.Bullet; +import dwt.dwthelper.utils; + import dwt.DWT; import dwt.custom.StyleRange; - -import dwt.dwthelper.string; +import dwt.custom.ST; import dwt.dwthelper.System; /** * Instances of this class represent bullets in the StyledText. *

- * The toHash() method in this class uses the values of the public + * 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. + * 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. *

- * + * * @see StyledText#setLineBullet(int, int, Bullet) - * + * @see Sample code and further information + * * @since 3.2 */ public class Bullet { + /** + * The bullet type. Possible values are: + *
    + *
  • ST.BULLET_DOT
  • + *
  • ST.BULLET_NUMBER
  • + *
  • ST.BULLET_LETTER_LOWER
  • + *
  • ST.BULLET_LETTER_UPPER
  • + *
  • ST.BULLET_TEXT
  • + *
  • ST.BULLET_CUSTOM
  • + *
+ */ public int type; + + /** + * The bullet style. + */ public StyleRange style; + + /** + * The bullet text. + */ public String text; + int[] linesIndices; int count; - /** - * Create a new bullet the specified style, the type is set to ST.BULLET_DOT. - * The style must have a glyph metrics set. - * - * @param style the style - * - * @exception IllegalArgumentException
    - *
  • ERROR_NULL_ARGUMENT when the style or the glyph metrics are null
  • - *
- */ - public this (StyleRange style) { - this(DWT.BULLET_DOT, style); - } - - /** - * Create a new bullet the specified style and type. - * The style must have a glyph metrics set. - * - * @param style the style - * - * @exception IllegalArgumentException
    - *
  • ERROR_NULL_ARGUMENT when the style or the glyph metrics are null
  • - *
- */ - public this (int type, StyleRange style) { - if (style is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - if (style.metrics is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.type = type; - this.style = style; +/** + * Create a new bullet with the specified style, and type ST.BULLET_DOT. + * The style must have a glyph metrics set. + * + * @param style the style + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT when the style or the glyph metrics are null
  • + *
+ */ +public this(StyleRange style) { + this(ST.BULLET_DOT, style); +} +/** + * Create a new bullet the specified style and type. + * The style must have a glyph metrics set. + * + * @param type the bullet type + * @param style the style + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT when the style or the glyph metrics are null
  • + *
+ */ +public this(int type, StyleRange style) { + if (style is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + if (style.metrics is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + this.type = type; + this.style = style; +} +void addIndices (int startLine, int lineCount) { + if (linesIndices is null) { + linesIndices = new int[lineCount]; + count = lineCount; + for (int i = 0; i < lineCount; i++) linesIndices[i] = startLine + i; + } else { + int modifyStart = 0; + while (modifyStart < count) { + if (startLine <= linesIndices[modifyStart]) break; + modifyStart++; + } + int modifyEnd = modifyStart; + while (modifyEnd < count) { + if (startLine + lineCount <= linesIndices[modifyEnd]) break; + modifyEnd++; + } + int newSize = modifyStart + lineCount + count - modifyEnd; + if (newSize > linesIndices.length) { + int[] newLinesIndices = new int[newSize]; + System.arraycopy(linesIndices, 0, newLinesIndices, 0, count); + linesIndices = newLinesIndices; + } + System.arraycopy(linesIndices, modifyEnd, linesIndices, modifyStart + lineCount, count - modifyEnd); + for (int i = 0; i < lineCount; i++) linesIndices[modifyStart + i] = startLine + i; + count = newSize; } - - void addIndices (int startLine, int lineCount) { - if (linesIndices is null) { - linesIndices = new int[lineCount]; - count = lineCount; - for (int i = 0; i < lineCount; i++) - linesIndices[i] = startLine + i; - } - else { - int modifyStart = 0; - while (modifyStart < count) { - if (startLine <= linesIndices[modifyStart]) - break; - modifyStart++; +} +int indexOf (int lineIndex) { + for (int i = 0; i < count; i++) { + if (linesIndices[i] is lineIndex) return i; + } + return -1; +} +public override hash_t toHash() { + return style.toHash() ^ type; +} +int[] removeIndices (int startLine, int replaceLineCount, int newLineCount, bool update) { + if (count is 0) return null; + if (startLine > linesIndices[count - 1]) return null; + int endLine = startLine + replaceLineCount; + int delta = newLineCount - replaceLineCount; + for (int i = 0; i < count; i++) { + int index = linesIndices[i]; + if (startLine <= index) { + int j = i; + while (j < count) { + if (linesIndices[j] >= endLine) break; + j++; } - int modifyEnd = modifyStart; - while (modifyEnd < count) { - if (startLine + lineCount <= linesIndices[modifyEnd]) - break; - modifyEnd++; + if (update) { + for (int k = j; k < count; k++) linesIndices[k] += delta; } - int newSize = modifyStart + lineCount + count - modifyEnd; - if (newSize > linesIndices.length) { - int[] newLinesIndices = new int[newSize]; - System.arraycopy(linesIndices, 0, newLinesIndices, 0, count); - linesIndices = newLinesIndices; - } - System.arraycopy(linesIndices, modifyEnd, linesIndices, modifyStart + lineCount, count - modifyEnd); - for (int i = 0; i < lineCount; i++) - linesIndices[modifyStart + i] = startLine + i; - count = newSize; + int[] redrawLines = new int[count - j]; + System.arraycopy(linesIndices, j, redrawLines, 0, count - j); + System.arraycopy(linesIndices, j, linesIndices, i, count - j); + count -= (j - i); + return redrawLines; } } - - int indexOf (int lineIndex) { - for (int i = 0; i < count; i++) { - if (linesIndices[i] is lineIndex) - return i; - } - return -1; - } - - public hash_t toHash () { - return style.toHash() ^ type; - } - - int[] removeIndices (int startLine, int replaceLineCount, int newLineCount, bool update) { - if (count is 0) - return null; - if (startLine > linesIndices[count - 1]) - return null; - int endLine = startLine + replaceLineCount; - int delta = newLineCount - replaceLineCount; - for (int i = 0; i < count; i++) { - int index = linesIndices[i]; - if (startLine <= index) { - int j = i; - while (j < count) { - if (linesIndices[j] >= endLine) - break; - j++; - } - if (update) { - for (int k = j; k < count; k++) - linesIndices[k] += delta; - } - int[] redrawLines = new int[count - j]; - System.arraycopy(linesIndices, j, redrawLines, 0, count - j); - System.arraycopy(linesIndices, j, linesIndices, i, count - j); - count -= (j - i); - return redrawLines; - } - } - for (int i = 0; i < count; i++) - linesIndices[i] += delta; - return null; - } - - int size () { - return count; - } + for (int i = 0; i < count; i++) linesIndices[i] += delta; + return null; } +int size() { + return count; +} +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/BusyIndicator.d --- a/dwt/custom/BusyIndicator.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/BusyIndicator.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,81 +7,82 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.BusyIndicator; + + import dwt.DWT; import dwt.graphics.Cursor; import dwt.widgets.Display; import dwt.widgets.Shell; - import dwt.dwthelper.Runnable; -import dwt.dwthelper.string; -import dwt.dwthelper.utils : Integer; +import dwt.dwthelper.utils; /** * Support for showing a Busy Cursor during a long running process. + * + * @see BusyIndicator snippets + * @see Sample code and further information */ public class BusyIndicator { static int nextBusyId = 1; - static final String BUSYID_NAME = "DWT BusyIndicator"; //$NON-NLS-1$ - static final String BUSY_CURSOR = "DWT BusyIndicator Cursor"; //$NON-NLS-1$ + static const String BUSYID_NAME = "DWT BusyIndicator"; //$NON-NLS-1$ + static const String BUSY_CURSOR = "DWT BusyIndicator Cursor"; //$NON-NLS-1$ - /** - * Runs the given 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
    - *
  • ERROR_NULL_ARGUMENT - if the runnable is null
  • - *
- */ +/** + * Runs the given 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
    + *
  • ERROR_NULL_ARGUMENT - if the runnable is null
  • + *
+ */ - public static void showWhile (Display display, Runnable runnable) { - if (runnable is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); +public static void showWhile(Display display, Runnable runnable) { + if (runnable is null) + DWT.error(DWT.ERROR_NULL_ARGUMENT); + if (display is null) { + display = Display.getCurrent(); if (display is null) { - display = Display.getCurrent(); - if (display is null) { - runnable.run(); - return; - } + runnable.run(); + return; } + } - Integer busyId = new Integer(nextBusyId); - nextBusyId++; - Cursor cursor = display.getSystemCursor(DWT.CURSOR_WAIT); - Shell[] shells = display.getShells(); + Integer busyId = new Integer(nextBusyId); + nextBusyId++; + Cursor cursor = display.getSystemCursor(DWT.CURSOR_WAIT); + Shell[] shells = display.getShells(); + for (int i = 0; i < shells.length; i++) { + Integer id = cast(Integer)shells[i].getData(BUSYID_NAME); + if (id is null) { + shells[i].setCursor(cursor); + shells[i].setData(BUSYID_NAME, busyId); + } + } + + try { + runnable.run(); + } finally { + shells = display.getShells(); for (int i = 0; i < shells.length; i++) { - Integer id = cast(Integer) shells[i].getData(BUSYID_NAME); - if (id is null) { - shells[i].setCursor(cursor); - shells[i].setData(BUSYID_NAME, busyId); - } - } - - try { - runnable.run(); - } - finally { - shells = display.getShells(); - for (int i = 0; i < shells.length; i++) { - Integer id = cast(Integer) shells[i].getData(BUSYID_NAME); - if (id is busyId) { - shells[i].setCursor(null); - shells[i].setData(BUSYID_NAME, null); - } + Integer id = cast(Integer)shells[i].getData(BUSYID_NAME); + if ( id !is null && id == busyId) { + shells[i].setCursor(null); + shells[i].setData(BUSYID_NAME, null); } } } } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CBanner.d --- a/dwt/custom/CBanner.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CBanner.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,13 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CBanner; + + import dwt.DWT; import dwt.DWTException; import dwt.graphics.Color; @@ -26,6 +27,10 @@ import dwt.widgets.Event; import dwt.widgets.Layout; import dwt.widgets.Listener; +import dwt.custom.CBannerLayout; + +import Math = tango.math.Math; + /** * Instances of this class implement a Composite that lays out its @@ -42,12 +47,14 @@ *
Styles:
*
NONE
*
Events:
- *
cast(None)
+ *
(None)
* *

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

- * + * + * @see Sample code and further information + * * @since 3.0 */ @@ -59,9 +66,9 @@ bool simple = true; - int[] curve = new int[0]; + int[] curve; int curveStart = 0; - Rectangle curveRect = new Rectangle(0, 0, 0, 0); + Rectangle curveRect; int curve_width = 5; int curve_indent = -2; @@ -82,506 +89,472 @@ 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. - *

- * - * @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
  • - *
- * - */ - public this (Composite parent, int style) { - super(parent, checkStyle(style)); - super.setLayout(new CBannerLayout()); - resizeCursor = new Cursor(getDisplay(), DWT.CURSOR_SIZEWE); + +/** + * 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
  • + *
+ * + */ +public this(Composite parent, int style) { + curveRect = new Rectangle(0, 0, 0, 0); + super(parent, checkStyle(style)); + super.setLayout(new CBannerLayout()); + resizeCursor = new Cursor(getDisplay(), DWT.CURSOR_SIZEWE); - Listener listener = new class Listener { - public void handleEvent (Event e) { - switch (e.type) { - case DWT.Dispose: - onDispose(); - break; - case DWT.MouseDown: - onMouseDown(e.x, e.y); - break; - case DWT.MouseExit: - onMouseExit(); - break; - case DWT.MouseMove: - onMouseMove(e.x, e.y); - break; - case DWT.MouseUp: - onMouseUp(); - break; - case DWT.Paint: - onPaint(e.gc); - break; - case DWT.Resize: - onResize(); - break; - } + Listener listener = new class() Listener { + public void handleEvent(Event e) { + switch (e.type) { + case DWT.Dispose: + onDispose(); break; + case DWT.MouseDown: + onMouseDown (e.x, e.y); break; + case DWT.MouseExit: + onMouseExit(); break; + case DWT.MouseMove: + onMouseMove(e.x, e.y); break; + case DWT.MouseUp: + onMouseUp(); break; + case DWT.Paint: + onPaint(e.gc); break; + case DWT.Resize: + onResize(); break; + default: } - }; - int[] events = new int[][DWT.Dispose , DWT.MouseDown , DWT.MouseExit , DWT.MouseMove , DWT.MouseUp , DWT.Paint , DWT.Resize]; - for (int i = 0; i < events.length; i++) { - addListener(events[i], listener); } + }; + int[] events = [DWT.Dispose, DWT.MouseDown, DWT.MouseExit, DWT.MouseMove, DWT.MouseUp, DWT.Paint, DWT.Resize]; + for (int i = 0; i < events.length; i++) { + addListener(events[i], listener); } +} +static int[] bezier(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int count) { + // The parametric equations for a Bezier curve for x[t] and y[t] where 0 <= t <=1 are: + // x[t] = x0+3(x1-x0)t+3(x0+x2-2x1)t^2+(x3-x0+3x1-3x2)t^3 + // y[t] = y0+3(y1-y0)t+3(y0+y2-2y1)t^2+(y3-y0+3y1-3y2)t^3 + double a0 = x0; + double a1 = 3*(x1 - x0); + double a2 = 3*(x0 + x2 - 2*x1); + double a3 = x3 - x0 + 3*x1 - 3*x2; + double b0 = y0; + double b1 = 3*(y1 - y0); + double b2 = 3*(y0 + y2 - 2*y1); + double b3 = y3 - y0 + 3*y1 - 3*y2; - static int[] bezier (int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int count) { - // The parametric equations for a Bezier curve for x[t] and y[t] where 0 <= t <=1 are: - // x[t] = x0+3(x1-x0)t+3(x0+x2-2x1)t^2+(x3-x0+3x1-3x2)t^3 - // y[t] = y0+3(y1-y0)t+3(y0+y2-2y1)t^2+(y3-y0+3y1-3y2)t^3 - double a0 = x0; - double a1 = 3 * (x1 - x0); - double a2 = 3 * (x0 + x2 - 2 * x1); - double a3 = x3 - x0 + 3 * x1 - 3 * x2; - double b0 = y0; - double b1 = 3 * (y1 - y0); - double b2 = 3 * (y0 + y2 - 2 * y1); - double b3 = y3 - y0 + 3 * y1 - 3 * y2; - - int[] polygon = new int[2 * count + 2]; - for (int i = 0; i <= count; i++) { - double t = cast(double) i / cast(double) count; - polygon[2 * i] = cast(int) (a0 + a1 * t + a2 * t * t + a3 * t * t * t); - polygon[2 * i + 1] = cast(int) (b0 + b1 * t + b2 * t * t + b3 * t * t * t); - } - return polygon; + int[] polygon = new int[2*count + 2]; + for (int i = 0; i <= count; i++) { + double t = cast(double)i / cast(double)count; + polygon[2*i] = cast(int)(a0 + a1*t + a2*t*t + a3*t*t*t); + polygon[2*i + 1] = cast(int)(b0 + b1*t + b2*t*t + b3*t*t*t); } + return polygon; +} +static int checkStyle (int style) { + return DWT.NONE; +} +/** +* Returns the Control that appears on the bottom side of the banner. +* +* @return the control that appears on the bottom side of the banner 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
  • +*
+* +* @since 3.0 +*/ +public Control getBottom() { + checkWidget(); + return bottom; +} +public override Rectangle getClientArea() { + return new Rectangle(0, 0, 0, 0); +} - static int checkStyle (int style) { - return DWT.NONE; - } - - /** - * Returns the Control that appears on the bottom side of the banner. - * - * @return the control that appears on the bottom side of the banner 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
  • - *
- * - * @since 3.0 - */ - public Control getBottom () { - checkWidget(); - return bottom; - } - - public Rectangle getClientArea () { - return new Rectangle(0, 0, 0, 0); - } +/** +* Returns the Control that appears on the left side of the banner. +* +* @return the control that appears on the left side of the banner 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
  • +*
+* +* @since 3.0 +*/ +public Control getLeft() { + checkWidget(); + return left; +} - /** - * Returns the Control that appears on the left side of the banner. - * - * @return the control that appears on the left side of the banner 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
  • - *
- * - * @since 3.0 - */ - public Control getLeft () { - checkWidget(); - return left; +/** +* Returns the Control that appears on the right side of the banner. +* +* @return the control that appears on the right side of the banner 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
  • +*
+* +* @since 3.0 +*/ +public Control getRight() { + checkWidget(); + return right; +} +/** + * Returns the minimum size of the control that appears on the right of the banner. + * + * @return the minimum size of the control that appears on the right of the banner + * + * @since 3.1 + */ +public Point getRightMinimumSize() { + checkWidget(); + return new Point(rightMinWidth, rightMinHeight); +} +/** + * Returns the width of the control that appears on the right of the banner. + * + * @return the width of the control that appears on the right of the banner + * + * @since 3.0 + */ +public int getRightWidth() { + checkWidget(); + if (right is null) return 0; + if (rightWidth is DWT.DEFAULT) { + Point size = right.computeSize(DWT.DEFAULT, DWT.DEFAULT, false); + return size.x; } - - /** - * Returns the Control that appears on the right side of the banner. - * - * @return the control that appears on the right side of the banner 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
  • - *
- * - * @since 3.0 - */ - public Control getRight () { - checkWidget(); - return right; + return rightWidth; +} +/** + * Returns 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; } - - /** - * Returns the minimum size of the control that appears on the right of the banner. - * - * @return the minimum size of the control that appears on the right of the banner - * - * @since 3.1 - */ - public Point getRightMinimumSize () { - checkWidget(); - return new Point(rightMinWidth, rightMinHeight); - } - - /** - * Returns the width of the control that appears on the right of the banner. - * - * @return the width of the control that appears on the right of the banner - * - * @since 3.0 - */ - public int getRightWidth () { - checkWidget(); - if (right is null) - return 0; - if (rightWidth is DWT.DEFAULT) { - Point size = right.computeSize(DWT.DEFAULT, DWT.DEFAULT, false); - return size.x; +} +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); } - return rightWidth; + layout(false); + return; } - - /** - * Returns 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; + if (curveRect.contains(x, y)) { + setCursor(resizeCursor); + } else { + setCursor(null); } - - void onDispose () { - if (resizeCursor !is null) - resizeCursor.dispose(); - resizeCursor = null; - left = null; - right = null; - bottom = 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); } - - void onMouseDown (int x, int y) { - if (curveRect.contains(x, y)) { - dragging = true; - rightDragDisplacement = curveStart - x + curve_width - curve_indent; - } + 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; - void onMouseExit () { - if (!dragging) - setCursor(null); - } + Color background = getBackground(); - 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 (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++]; } - if (curveRect.contains(x, y)) { - setCursor(resizeCursor); - } - else { - setCursor(null); - } - } + 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(); - void onMouseUp () { - dragging = false; + // 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); } - 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 border + gc.setForeground(border1); + gc.drawPolyline(line1); +} - // 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); +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
    +*
  • 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 bottom control was not created as a child of the receiver
  • +*
+* +* @since 3.0 +*/ +public void setBottom(Control control) { + checkWidget(); + if (control !is null && control.getParent() !is this) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); } - - /** - * 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
    - *
  • 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 bottom control was not created as a child of the receiver
  • - *
- * - * @since 3.0 - */ - public void setBottom (Control control) { - checkWidget(); - if (control !is null && control.getParent() !is this) { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (bottom !is null && !bottom.isDisposed()) { - Point size = bottom.getSize(); - bottom.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); - } - bottom = control; - layout(false); + if (bottom !is null && !bottom.isDisposed()) { + Point size = bottom.getSize(); + bottom.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); } - - /** - * 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; - } + bottom = control; + 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 override void setLayout (Layout layout) { + checkWidget(); + return; +} - /** - * Set the control that appears on the left side of the banner. - * The left control is optional. Setting the left 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 left 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 left control was not created as a child of the receiver
  • - *
- * - * @since 3.0 - */ - public void setLeft (Control control) { - checkWidget(); - if (control !is null && control.getParent() !is this) { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (left !is null && !left.isDisposed()) { - Point size = left.getSize(); - left.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); - } - left = control; - layout(false); +/** +* Set the control that appears on the left side of the banner. +* The left control is optional. Setting the left 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 left 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 left control was not created as a child of the receiver
  • +*
+* +* @since 3.0 +*/ +public void setLeft(Control control) { + checkWidget(); + if (control !is null && control.getParent() !is this) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (left !is null && !left.isDisposed()) { + Point size = left.getSize(); + left.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); } - - /** - * Set the control that appears on the right side of the banner. - * The right control is optional. Setting the right 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 right 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 right control was not created as a child of the receiver
  • - *
- * - * @since 3.0 - */ - public void setRight (Control control) { - checkWidget(); - if (control !is null && control.getParent() !is this) { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (right !is null && !right.isDisposed()) { - Point size = right.getSize(); - right.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); - } - right = control; - layout(false); + left = control; + layout(false); +} +/** +* Set the control that appears on the right side of the banner. +* The right control is optional. Setting the right 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 right 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 right control was not created as a child of the receiver
  • +*
+* +* @since 3.0 +*/ +public void setRight(Control control) { + checkWidget(); + if (control !is null && control.getParent() !is this) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (right !is null && !right.isDisposed()) { + Point size = right.getSize(); + right.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); } - - /** - * Set the minimum height of the control that appears on the right side of the banner. - * - * @param size the minimum size of the control on the right - * - * @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 size is null or the values of size are less than DWT.DEFAULT
  • - *
- * - * @since 3.1 - */ - public void setRightMinimumSize (Point size) { - checkWidget(); - if (size is null || size.x < DWT.DEFAULT || size.y < DWT.DEFAULT) - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - rightMinWidth = size.x; - rightMinHeight = size.y; + right = control; + layout(false); +} +/** + * Set the minimum height of the control that appears on the right side of the banner. + * + * @param size the minimum size of the control on the right + * + * @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 size is null or the values of size are less than DWT.DEFAULT
  • + *
+ * + * @since 3.1 + */ +public void setRightMinimumSize(Point size) { + checkWidget(); + if (size is null || size.x < DWT.DEFAULT || size.y < DWT.DEFAULT) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + rightMinWidth = size.x; + rightMinHeight = size.y; + layout(false); +} +/** + * Set the width of the control that appears on the right side of the banner. + * + * @param width the width of the control on the right + * + * @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 width is less than DWT.DEFAULT
  • + *
+ * + * @since 3.0 + */ +public void setRightWidth(int width) { + checkWidget(); + if (width < DWT.DEFAULT) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + rightWidth = width; + layout(false); +} +/** + * Sets the shape that the CBanner will use to render itself. + * + * @param simple true if the CBanner should render itself in a simple, traditional style + * + * @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 setSimple(bool simple) { + checkWidget(); + if (this.simple !is simple) { + this.simple = simple; + if (simple) { + curve_width = 5; + curve_indent = -2; + } else { + curve_width = 50; + curve_indent = 5; + } + updateCurve(getSize().y); layout(false); - } - - /** - * Set the width of the control that appears on the right side of the banner. - * - * @param width the width of the control on the right - * - * @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 width is less than DWT.DEFAULT
  • - *
- * - * @since 3.0 - */ - public void setRightWidth (int width) { - checkWidget(); - if (width < DWT.DEFAULT) - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - rightWidth = width; - layout(false); - } - - /** - * Sets the shape that the CBanner will use to render itself. - * - * @param simple true if the CBanner should render itself in a simple, traditional style - * - * @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 setSimple (bool simple) { - checkWidget(); - if (this.simple !is simple) { - this.simple = simple; - if (simple) { - curve_width = 5; - curve_indent = -2; - } - else { - curve_width = 50; - curve_indent = 5; - } - updateCurve(getSize().y); - layout(false); - redraw(); - } - } - - void updateCurve (int height) { - int h = height - BORDER_STRIPE; - if (simple) { - curve = new int[][0 , h , 1 , h , 2 , h - 1 , 3 , h - 2 , 3 , 2 , 4 , 1 , 5 , 0]; - } - else { - curve = bezier(0, h + 1, BEZIER_LEFT, h + 1, curve_width - BEZIER_RIGHT, 0, curve_width, 0, curve_width); - } + redraw(); } } +void updateCurve(int height) { + int h = height - BORDER_STRIPE; + if (simple) { + curve = [0,h, 1,h, 2,h-1, 3,h-2, + 3,2, 4,1, 5,0]; + } else { + curve = bezier(0, h+1, BEZIER_LEFT, h+1, + curve_width-BEZIER_RIGHT, 0, curve_width, 0, + curve_width); + } +} +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CBannerLayout.d --- a/dwt/custom/CBannerLayout.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CBannerLayout.d Tue Oct 07 16:29:55 2008 +0200 @@ -7,207 +7,193 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CBannerLayout; -import Math = tango.math.Math; import dwt.DWT; -import dwt.custom.CBanner; import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.widgets.Composite; import dwt.widgets.Control; import dwt.widgets.Layout; import dwt.widgets.Scrollable; +import dwt.custom.CBanner; +import dwt.custom.CLayoutData; + +import Math = tango.math.Math; /** * This class provides the layout for CBanner - * + * * @see CBanner */ class CBannerLayout : Layout { - protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache) { - CBanner banner = cast(CBanner) composite; - Control left = banner.left; - Control right = banner.right; - Control bottom = banner.bottom; - bool showCurve = left !is null && right !is null; - int height = hHint; - int width = wHint; +protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { + CBanner banner = cast(CBanner)composite; + Control left = banner.left; + Control right = banner.right; + Control bottom = banner.bottom; + bool showCurve = left !is null && right !is null; + int height = hHint; + int width = wHint; - // Calculate component sizes - Point bottomSize = new Point(0, 0); - if (bottom !is null) { - int trim = computeTrim(bottom); - int w = wHint is DWT.DEFAULT ? DWT.DEFAULT : Math.max(0, width - trim); - bottomSize = computeChildSize(bottom, w, DWT.DEFAULT, flushCache); - } - Point rightSize = new Point(0, 0); - if (right !is null) { - int trim = computeTrim(right); - int w = DWT.DEFAULT; - if (banner.rightWidth !is DWT.DEFAULT) { - w = banner.rightWidth - trim; - if (left !is null) { - w = Math.min(w, width - banner.curve_width + 2 * banner.curve_indent - CBanner.MIN_LEFT - trim); - } - w = Math.max(0, w); + // Calculate component sizes + Point bottomSize = new Point(0, 0); + if (bottom !is null) { + int trim = computeTrim(bottom); + int w = wHint is DWT.DEFAULT ? DWT.DEFAULT : Math.max(0, width - trim); + bottomSize = computeChildSize(bottom, w, DWT.DEFAULT, flushCache); + } + Point rightSize = new Point(0, 0); + if (right !is null) { + int trim = computeTrim(right); + int w = DWT.DEFAULT; + if (banner.rightWidth !is DWT.DEFAULT) { + w = banner.rightWidth - trim; + if (left !is null) { + w = Math.min(w, width - banner.curve_width + 2* banner.curve_indent - CBanner.MIN_LEFT - trim); } - rightSize = computeChildSize(right, w, DWT.DEFAULT, flushCache); - if (wHint !is DWT.DEFAULT) { - width -= rightSize.x + banner.curve_width - 2 * banner.curve_indent; - } + w = Math.max(0, w); } - Point leftSize = new Point(0, 0); - if (left !is null) { - int trim = computeTrim(left); - int w = wHint is DWT.DEFAULT ? DWT.DEFAULT : Math.max(0, width - trim); - leftSize = computeChildSize(left, w, DWT.DEFAULT, flushCache); - } - - // Add up sizes - width = leftSize.x + rightSize.x; - height = bottomSize.y; - if (bottom !is null && (left !is null || right !is null)) { - height += CBanner.BORDER_STRIPE + 2; + rightSize = computeChildSize(right, w, DWT.DEFAULT, flushCache); + if (wHint !is DWT.DEFAULT) { + width -= rightSize.x + banner.curve_width - 2* banner.curve_indent; } - if (left !is null) { - if (right is null) { - height += leftSize.y; - } - else { - height += Math.max(leftSize.y, banner.rightMinHeight is DWT.DEFAULT ? rightSize.y : banner.rightMinHeight); - } - } - else { - height += rightSize.y; - } - if (showCurve) { - width += banner.curve_width - 2 * banner.curve_indent; - height += CBanner.BORDER_TOP + CBanner.BORDER_BOTTOM + 2 * CBanner.BORDER_STRIPE; - } - - if (wHint !is DWT.DEFAULT) - width = wHint; - if (hHint !is DWT.DEFAULT) - height = hHint; - - return new Point(width, height); + } + Point leftSize = new Point(0, 0); + if (left !is null) { + int trim = computeTrim(left); + int w = wHint is DWT.DEFAULT ? DWT.DEFAULT : Math.max(0, width - trim); + leftSize = computeChildSize(left, w, DWT.DEFAULT, flushCache); } - Point computeChildSize (Control control, int wHint, int hHint, bool flushCache) { - Object data = control.getLayoutData(); - if (data is null || !(cast(CLayoutData) data)) { - data = new CLayoutData(); - control.setLayoutData(data); - } - return (cast(CLayoutData) data).computeSize(control, wHint, hHint, flushCache); + // Add up sizes + width = leftSize.x + rightSize.x; + height = bottomSize.y; + if (bottom !is null && (left !is null || right !is null)) { + height += CBanner.BORDER_STRIPE + 2; } - - int computeTrim (Control c) { - if (cast(Scrollable) c) { - Rectangle rect = (cast(Scrollable) c).computeTrim(0, 0, 0, 0); - return rect.width; + if (left !is null) { + if (right is null) { + height += leftSize.y; + } else { + height += Math.max(leftSize.y, banner.rightMinHeight is DWT.DEFAULT ? rightSize.y : banner.rightMinHeight); } - return c.getBorderWidth() * 2; + } else { + height += rightSize.y; + } + if (showCurve) { + width += banner.curve_width - 2*banner.curve_indent; + height += CBanner.BORDER_TOP + CBanner.BORDER_BOTTOM + 2*CBanner.BORDER_STRIPE; } - protected bool flushCache (Control control) { - Object data = control.getLayoutData(); - if (data !is null && cast(CLayoutData) data) - (cast(CLayoutData) data).flushCache(); - return true; + if (wHint !is DWT.DEFAULT) width = wHint; + if (hHint !is DWT.DEFAULT) height = hHint; + + return new Point(width, height); +} +Point computeChildSize(Control control, int wHint, int hHint, bool flushCache) { + Object data = control.getLayoutData(); + if (data is null || !( null !is cast(CLayoutData)data)) { + data = new CLayoutData(); + control.setLayoutData(data); + } + return (cast(CLayoutData)data).computeSize(control, wHint, hHint, flushCache); +} +int computeTrim(Control c) { + if ( auto s = cast(Scrollable)c) { + Rectangle rect = s.computeTrim (0, 0, 0, 0); + return rect.width; + } + return c.getBorderWidth () * 2; +} +protected override bool flushCache(Control control) { + Object data = control.getLayoutData(); + if ( auto ld = cast(CLayoutData)data ) ld.flushCache(); + return true; +} +protected override void layout(Composite composite, bool flushCache) { + CBanner banner = cast(CBanner)composite; + Control left = banner.left; + Control right = banner.right; + Control bottom = banner.bottom; + + Point size = banner.getSize(); + bool showCurve = left !is null && right !is null; + int width = size.x - 2*banner.getBorderWidth(); + int height = size.y - 2*banner.getBorderWidth(); + + Point bottomSize = new Point(0, 0); + if (bottom !is null) { + int trim = computeTrim(bottom); + int w = Math.max(0, width - trim); + bottomSize = computeChildSize(bottom, w, DWT.DEFAULT, flushCache); + height -= bottomSize.y + CBanner.BORDER_STRIPE + 2; + } + if (showCurve) height -= CBanner.BORDER_TOP + CBanner.BORDER_BOTTOM + 2*CBanner.BORDER_STRIPE; + height = Math.max(0, height); + Point rightSize = new Point(0,0); + if (right !is null) { + int trim = computeTrim(right); + int w = DWT.DEFAULT; + if (banner.rightWidth !is DWT.DEFAULT) { + w = banner.rightWidth - trim; + if (left !is null) { + w = Math.min(w, width - banner.curve_width + 2* banner.curve_indent - CBanner.MIN_LEFT - trim); + } + w = Math.max(0, w); + } + rightSize = computeChildSize(right, w, DWT.DEFAULT, flushCache); + width = width - (rightSize.x - banner.curve_indent + banner.curve_width - banner.curve_indent); + } + Point leftSize = new Point(0, 0); + if (left !is null) { + int trim = computeTrim(left); + int w = Math.max(0, width - trim); + leftSize = computeChildSize(left, w, DWT.DEFAULT, flushCache); } - protected void layout (Composite composite, bool flushCache) { - CBanner banner = cast(CBanner) composite; - Control left = banner.left; - Control right = banner.right; - Control bottom = banner.bottom; - - Point size = banner.getSize(); - bool showCurve = left !is null && right !is null; - int width = size.x - 2 * banner.getBorderWidth(); - int height = size.y - 2 * banner.getBorderWidth(); - - Point bottomSize = new Point(0, 0); - if (bottom !is null) { - int trim = computeTrim(bottom); - int w = Math.max(0, width - trim); - bottomSize = computeChildSize(bottom, w, DWT.DEFAULT, flushCache); - height -= bottomSize.y + CBanner.BORDER_STRIPE + 2; - } - if (showCurve) - height -= CBanner.BORDER_TOP + CBanner.BORDER_BOTTOM + 2 * CBanner.BORDER_STRIPE; - height = Math.max(0, height); - Point rightSize = new Point(0, 0); - if (right !is null) { - int trim = computeTrim(right); - int w = DWT.DEFAULT; - if (banner.rightWidth !is DWT.DEFAULT) { - w = banner.rightWidth - trim; - if (left !is null) { - w = Math.min(w, width - banner.curve_width + 2 * banner.curve_indent - CBanner.MIN_LEFT - trim); - } - w = Math.max(0, w); - } - rightSize = computeChildSize(right, w, DWT.DEFAULT, flushCache); - width = width - (rightSize.x - banner.curve_indent + banner.curve_width - banner.curve_indent); - } - Point leftSize = new Point(0, 0); + int x = 0; + int y = 0; + int oldStart = banner.curveStart; + Rectangle leftRect = null; + Rectangle rightRect = null; + Rectangle bottomRect = null; + if (bottom !is null) { + bottomRect = new Rectangle(x, y+size.y-bottomSize.y, bottomSize.x, bottomSize.y); + } + if (showCurve) y += CBanner.BORDER_TOP + CBanner.BORDER_STRIPE; + if(left !is null) { + leftRect = new Rectangle(x, y, leftSize.x, leftSize.y); + banner.curveStart = x + leftSize.x - banner.curve_indent; + x += leftSize.x - banner.curve_indent + banner.curve_width - banner.curve_indent; + } + if (right !is null) { if (left !is null) { - int trim = computeTrim(left); - int w = Math.max(0, width - trim); - leftSize = computeChildSize(left, w, DWT.DEFAULT, flushCache); + rightSize.y = Math.max(leftSize.y, banner.rightMinHeight is DWT.DEFAULT ? rightSize.y : banner.rightMinHeight); } - - int x = 0; - int y = 0; - int oldStart = banner.curveStart; - Rectangle leftRect = null; - Rectangle rightRect = null; - Rectangle bottomRect = null; - if (bottom !is null) { - bottomRect = new Rectangle(x, y + size.y - bottomSize.y, bottomSize.x, bottomSize.y); - } - if (showCurve) - y += CBanner.BORDER_TOP + CBanner.BORDER_STRIPE; - if (left !is null) { - leftRect = new Rectangle(x, y, leftSize.x, leftSize.y); - banner.curveStart = x + leftSize.x - banner.curve_indent; - x += leftSize.x - banner.curve_indent + banner.curve_width - banner.curve_indent; - } - if (right !is null) { - if (left !is null) { - rightSize.y = Math.max(leftSize.y, banner.rightMinHeight is DWT.DEFAULT ? rightSize.y : banner.rightMinHeight); - } - rightRect = new Rectangle(x, y, rightSize.x, rightSize.y); - } - if (banner.curveStart < oldStart) { - banner.redraw(banner.curveStart - CBanner.CURVE_TAIL, 0, oldStart + banner.curve_width - banner.curveStart + CBanner.CURVE_TAIL + 5, - size.y, false); - } - if (banner.curveStart > oldStart) { - banner.redraw(oldStart - CBanner.CURVE_TAIL, 0, banner.curveStart + banner.curve_width - oldStart + CBanner.CURVE_TAIL + 5, size.y, false); - } - /* - * The paint events must be flushed in order to make the curve draw smoothly - * while the user drags the divider. - * On Windows, it is necessary to flush the paints before the children are - * resized because otherwise the children (particularly toolbars) will flash. - */ - banner.update(); - banner.curveRect = new Rectangle(banner.curveStart, 0, banner.curve_width, size.y); - if (bottomRect !is null) - bottom.setBounds(bottomRect); - if (rightRect !is null) - right.setBounds(rightRect); - if (leftRect !is null) - left.setBounds(leftRect); + rightRect = new Rectangle(x, y, rightSize.x, rightSize.y); + } + if (banner.curveStart < oldStart) { + banner.redraw(banner.curveStart - CBanner.CURVE_TAIL, 0, oldStart + banner.curve_width - banner.curveStart + CBanner.CURVE_TAIL + 5, size.y, false); + } + if (banner.curveStart > oldStart) { + banner.redraw(oldStart - CBanner.CURVE_TAIL, 0, banner.curveStart + banner.curve_width - oldStart + CBanner.CURVE_TAIL + 5, size.y, false); } + /* + * The paint events must be flushed in order to make the curve draw smoothly + * while the user drags the divider. + * On Windows, it is necessary to flush the paints before the children are + * resized because otherwise the children (particularly toolbars) will flash. + */ + banner.update(); + banner.curveRect = new Rectangle(banner.curveStart, 0, banner.curve_width, size.y); + if (bottomRect !is null) bottom.setBounds(bottomRect); + if (rightRect !is null) right.setBounds(rightRect); + if (leftRect !is null) left.setBounds(leftRect); } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CCombo.d --- a/dwt/custom/CCombo.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CCombo.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,13 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CCombo; + + import dwt.DWT; import dwt.DWTException; import dwt.accessibility.ACC; @@ -46,7 +47,11 @@ import dwt.widgets.TypedListener; import dwt.widgets.Widget; +static import tango.text.convert.Utf; +static import tango.text.Unicode; +static import tango.text.convert.Format; import dwt.dwthelper.utils; +import dwt.dwthelper.Runnable; /** * The CCombo class represents a selectable user interface object @@ -57,7 +62,7 @@ * 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. + * 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. *

@@ -71,9 +76,14 @@ *
Events: *
DefaultSelection, Modify, Selection, Verify
* + * + * @see CCombo snippets + * @see DWT Example: CustomControlExample + * @see Sample code and further information */ -public final class CCombo : Composite -{ +public final class CCombo : Composite { + + alias Composite.computeSize computeSize; Text text; List list; @@ -85,2090 +95,1712 @@ Color foreground, background; Font font; - /** - * Constructs a new instance of this class given its parent - * and a style value describing its behavior and appearance. - *

- * The style value is either one of the style constants defined in - * class 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#READ_ONLY - * @see DWT#FLAT - * @see Widget#getStyle() - */ - public this (Composite parent, int style) - { - super(parent, style = checkStyle(style)); +/** + * 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#READ_ONLY + * @see DWT#FLAT + * @see Widget#getStyle() + */ +public this (Composite parent, int style) { + super (parent, style = checkStyle (style)); - int textStyle = DWT.SINGLE; - if ((style & DWT.READ_ONLY) !is 0) - textStyle |= DWT.READ_ONLY; - if ((style & DWT.FLAT) !is 0) - textStyle |= DWT.FLAT; - text = new Text(this, textStyle); - int arrowStyle = DWT.ARROW | DWT.DOWN; - if ((style & DWT.FLAT) !is 0) - arrowStyle |= DWT.FLAT; - arrow = new Button(this, arrowStyle); + int textStyle = DWT.SINGLE; + if ((style & DWT.READ_ONLY) !is 0) textStyle |= DWT.READ_ONLY; + if ((style & DWT.FLAT) !is 0) textStyle |= DWT.FLAT; + text = new Text (this, textStyle); + int arrowStyle = DWT.ARROW | DWT.DOWN; + if ((style & DWT.FLAT) !is 0) arrowStyle |= DWT.FLAT; + arrow = new Button (this, arrowStyle); - listener = new class Listener - { - public void handleEvent (Event event) - { - if (popup is event.widget) - { - popupEvent(event); - return; - } - if (text is event.widget) - { - textEvent(event); - return; - } - if (list is event.widget) - { - listEvent(event); - return; - } - if (arrow is event.widget) - { - arrowEvent(event); - return; - } - if (this is event.widget) - { - comboEvent(event); - return; - } - if (getShell() is event.widget) - { - getDisplay().asyncExec(new class Runnable - { - public void run () - { - if (isDisposed()) - return; - handleFocus(DWT.FocusOut); - } - }); - } + listener = new class() Listener { + public void handleEvent (Event event) { + if (popup is event.widget) { + popupEvent (event); + return; + } + if (text is event.widget) { + textEvent (event); + return; + } + if (list is event.widget) { + listEvent (event); + return; + } + if (arrow is event.widget) { + arrowEvent (event); + return; + } + if (this.outer is event.widget) { + comboEvent (event); + return; } - }; - filter = new class Listener - { - public void handleEvent (Event event) - { - Shell shell = (cast(Control) event.widget).getShell(); - if (shell is this.getShell()) - { - handleFocus(DWT.FocusOut); - } + if (getShell () is event.widget) { + getDisplay().asyncExec(new class() Runnable { + public void run() { + if (isDisposed()) return; + handleFocus (DWT.FocusOut); + } + }); } - }; - - int[] comboEvents = [DWT.Dispose, DWT.FocusIn, DWT.Move, DWT.Resize]; - for (int i = 0; i < comboEvents.length; i++) - this.addListener(comboEvents[i], listener); - - int[] textEvents = [DWT.DefaultSelection, DWT.KeyDown, DWT.KeyUp, - DWT.MenuDetect, DWT.Modify, DWT.MouseDown, DWT.MouseUp, - DWT.MouseDoubleClick, DWT.MouseWheel, DWT.Traverse, - DWT.FocusIn, DWT.Verify]; - for (int i = 0; i < textEvents.length; i++) - text.addListener(textEvents[i], listener); - - int[] arrowEvents = [DWT.MouseDown, DWT.MouseUp, DWT.Selection, - DWT.FocusIn]; - for (int i = 0; i < arrowEvents.length; i++) - arrow.addListener(arrowEvents[i], listener); + } + }; + filter = new class() Listener { + public void handleEvent(Event event) { + Shell shell = (cast(Control)event.widget).getShell (); + if (shell is this.outer.getShell ()) { + handleFocus (DWT.FocusOut); + } + } + }; - createPopup(null, -1); - initAccessible(); - } - - static int checkStyle (int style) - { - int - mask = DWT.BORDER | DWT.READ_ONLY | DWT.FLAT | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; - return DWT.NO_FOCUS | (style & mask); - } + int [] comboEvents = [DWT.Dispose, DWT.FocusIn, DWT.Move, DWT.Resize]; + for (int i=0; i - *
  • ERROR_NULL_ARGUMENT - if the String 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 #add(String,int) - */ - public void add (String str) - { - checkWidget(); - if (str is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - list.add(str); - } + int [] textEvents = [DWT.DefaultSelection, DWT.KeyDown, DWT.KeyUp, DWT.MenuDetect, DWT.Modify, DWT.MouseDown, DWT.MouseUp, DWT.MouseDoubleClick, DWT.MouseWheel, DWT.Traverse, DWT.FocusIn, DWT.Verify]; + for (int i=0; i - * Note: To add an item at the end of the list, use the - * result of calling getItemCount() as the - * index or use add(String). - *

    - * - * @param String the new item - * @param index the index for the item - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the String is null
    • - *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)
    • - *
    - * @exception 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 #add(String) - */ - public void add (String str, int index) - { - checkWidget(); - if (str is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - list.add(str, index); - } - - /** - * Adds the listener to the collection of listeners who will - * be notified when the receiver's text is modified, by sending - * it one of the messages defined in the ModifyListener - * interface. - * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception 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 ModifyListener - * @see #removeModifyListener - */ - public void addModifyListener (ModifyListener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - TypedListener typedListener = new TypedListener(listener); - addListener(DWT.Modify, typedListener); - } - - /** - * Adds the listener to the collection of listeners who will - * be notified when the user changes the receiver's selection, by sending - * it one of the messages defined in the SelectionListener - * interface. - *

    - * widgetSelected is called when the combo's list selection changes. - * widgetDefaultSelected is typically called when ENTER is pressed the combo's text area. - *

    - * - * @param listener the listener which should be notified when the user changes the receiver's selection - * - * @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 SelectionListener - * @see #removeSelectionListener - * @see SelectionEvent - */ - public void addSelectionListener (SelectionListener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - TypedListener typedListener = new TypedListener(listener); - addListener(DWT.Selection, typedListener); - addListener(DWT.DefaultSelection, typedListener); - } - - /** - * Adds the listener to the collection of listeners who will - * be notified when the receiver's text is verified, by sending - * it one of the messages defined in the VerifyListener - * interface. - * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception 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 VerifyListener - * @see #removeVerifyListener - * - * @since 3.3 - */ - public void addVerifyListener (VerifyListener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - TypedListener typedListener = new TypedListener(listener); - addListener(DWT.Verify, typedListener); - } - - void arrowEvent (Event event) - { - switch (event.type) - { - case DWT.FocusIn: - { - handleFocus(DWT.FocusIn); - break; - } - case DWT.MouseDown: - { - Event mouseEvent = new Event(); - mouseEvent.button = event.button; - mouseEvent.count = event.count; - mouseEvent.stateMask = event.stateMask; - mouseEvent.time = event.time; - mouseEvent.x = event.x; - mouseEvent.y = event.y; - notifyListeners(DWT.MouseDown, mouseEvent); - event.doit = mouseEvent.doit; - break; - } - case DWT.MouseUp: - { - Event mouseEvent = new Event(); - mouseEvent.button = event.button; - mouseEvent.count = event.count; - mouseEvent.stateMask = event.stateMask; - mouseEvent.time = event.time; - mouseEvent.x = event.x; - mouseEvent.y = event.y; - notifyListeners(DWT.MouseUp, mouseEvent); - event.doit = mouseEvent.doit; - break; - } - case DWT.Selection: - { - text.setFocus(); - dropDown(!isDropped()); - break; - } - - default: + createPopup(null, -1); + initAccessible(); +} +static int checkStyle (int style) { + int mask = DWT.BORDER | DWT.READ_ONLY | DWT.FLAT | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; + return DWT.NO_FOCUS | (style & mask); +} +/** + * Adds the argument to the end of the receiver's list. + * + * @param string the new item + * + * @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 #add(String,int) + */ +public void add (String string) { + checkWidget(); + // DWT extension: allow null for zero length string + //if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + list.add (string); +} +/** + * Adds the argument to the receiver's list at the given + * zero-relative index. + *

    + * Note: To add an item at the end of the list, use the + * result of calling getItemCount() as the + * index or use add(String). + *

    + * + * @param string the new item + * @param index the index for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (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
    • + *
    + * + * @see #add(String) + */ +public void add (String string, int index) { + checkWidget(); + // DWT extension: allow null for zero length string + //if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + list.add (string, index); +} +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is modified, by sending + * it one of the messages defined in the ModifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception 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 ModifyListener + * @see #removeModifyListener + */ +public void addModifyListener (ModifyListener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (DWT.Modify, typedListener); +} +/** + * Adds the listener to the collection of listeners who will + * be notified when the user changes the receiver's selection, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the combo's list selection changes. + * widgetDefaultSelected is typically called when ENTER is pressed the combo's text area. + *

    + * + * @param listener the listener which should be notified when the user changes the receiver's selection + * + * @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 SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (DWT.Selection,typedListener); + addListener (DWT.DefaultSelection,typedListener); +} +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is verified, by sending + * it one of the messages defined in the VerifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception 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 VerifyListener + * @see #removeVerifyListener + * + * @since 3.3 + */ +public void addVerifyListener (VerifyListener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (DWT.Verify,typedListener); +} +void arrowEvent (Event event) { + switch (event.type) { + case DWT.FocusIn: { + handleFocus (DWT.FocusIn); break; } - } - - /** - * Sets the selection in the receiver's text field to an empty - * selection starting just before the first character. If the - * text field is editable, this has the effect of placing the - * i-beam at the start of the text. - *

    - * Note: To clear the selected items in the receiver's list, - * use deselectAll(). - *

    - * - * @exception 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 #deselectAll - */ - public void clearSelection () - { - checkWidget(); - text.clearSelection(); - list.deselectAll(); - } - - void comboEvent (Event event) - { - switch (event.type) - { - case DWT.Dispose: - if (popup !is null && !popup.isDisposed()) - { - list.removeListener(DWT.Dispose, listener); - popup.dispose(); - } - Shell shell = getShell(); - shell.removeListener(DWT.Deactivate, listener); - Display display = getDisplay(); - display.removeFilter(DWT.FocusIn, filter); - popup = null; - text = null; - list = null; - arrow = null; + case DWT.MouseDown: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseDown, mouseEvent); + event.doit = mouseEvent.doit; break; - case DWT.FocusIn: - Control focusControl = getDisplay().getFocusControl(); - if (focusControl is arrow || focusControl is list) - return; - if (isDropped()) - { - list.setFocus(); - } - else - { - text.setFocus(); - } + } + case DWT.MouseUp: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseUp, mouseEvent); + event.doit = mouseEvent.doit; break; - case DWT.Move: - dropDown(false); - break; - case DWT.Resize: - internalLayout(false); - break; - - default: + } + case DWT.Selection: { + text.setFocus(); + dropDown (!isDropped ()); break; } + default: } - - public Point computeSize (int wHint, int hHint, bool changed) - { - checkWidget(); - int width = 0, height = 0; - String[] items = list.getItems(); - GC gc = new GC(text); - int spacer = gc.StringExtent(" ").x; //$NON-NLS-1$ - int textWidth = gc.StringExtent(text.getText()).x; - for (int i = 0; i < items.length; i++) - { - textWidth = Math.max(gc.StringExtent(items[i]).x, textWidth); - } - gc.dispose(); - Point textSize = text.computeSize(DWT.DEFAULT, DWT.DEFAULT, changed); - Point arrowSize = arrow.computeSize(DWT.DEFAULT, DWT.DEFAULT, changed); - Point listSize = list.computeSize(DWT.DEFAULT, DWT.DEFAULT, changed); - int borderWidth = getBorderWidth(); +} +/** + * Sets the selection in the receiver's text field to an empty + * selection starting just before the first character. If the + * text field is editable, this has the effect of placing the + * i-beam at the start of the text. + *

    + * Note: To clear the selected items in the receiver's list, + * use deselectAll(). + *

    + * + * @exception 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 #deselectAll + */ +public void clearSelection () { + checkWidget (); + text.clearSelection (); + list.deselectAll (); +} +void comboEvent (Event event) { + switch (event.type) { + case DWT.Dispose: + if (popup !is null && !popup.isDisposed ()) { + list.removeListener (DWT.Dispose, listener); + popup.dispose (); + } + Shell shell = getShell (); + shell.removeListener (DWT.Deactivate, listener); + Display display = getDisplay (); + display.removeFilter (DWT.FocusIn, filter); + popup = null; + text = null; + list = null; + arrow = null; + break; + case DWT.FocusIn: + Control focusControl = getDisplay ().getFocusControl (); + if (focusControl is arrow || focusControl is list) return; + if (isDropped()) { + list.setFocus(); + } else { + text.setFocus(); + } + break; + case DWT.Move: + dropDown (false); + break; + case DWT.Resize: + internalLayout (false); + break; + default: + } +} - height = Math.max(textSize.y, arrowSize.y); - width = Math.max( - textWidth + 2 * spacer + arrowSize.x + 2 * borderWidth, - listSize.x); - if (wHint !is DWT.DEFAULT) - width = wHint; - if (hHint !is DWT.DEFAULT) - height = hHint; - return new Point(width + 2 * borderWidth, height + 2 * borderWidth); +public override Point computeSize (int wHint, int hHint, bool changed) { + checkWidget (); + int width = 0, height = 0; + String[] items = list.getItems (); + GC gc = new GC (text); + int spacer = gc.stringExtent (" ").x; //$NON-NLS-1$ + int textWidth = gc.stringExtent (text.getText ()).x; + for (int i = 0; i < items.length; i++) { + textWidth = Math.max (gc.stringExtent (items[i]).x, textWidth); } - - /** - * Copies the selected text. - *

    - * The current selection is copied to 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.3 - */ - public void copy () - { - checkWidget(); - text.copy(); - } + gc.dispose (); + Point textSize = text.computeSize (DWT.DEFAULT, DWT.DEFAULT, changed); + Point arrowSize = arrow.computeSize (DWT.DEFAULT, DWT.DEFAULT, changed); + Point listSize = list.computeSize (DWT.DEFAULT, DWT.DEFAULT, changed); + int borderWidth = getBorderWidth (); - void createPopup (String[] items, int selectionIndex) - { - // create shell and list - popup = new Shell(getShell(), DWT.NO_TRIM | DWT.ON_TOP); - int style = getStyle(); - int listStyle = DWT.SINGLE | DWT.V_SCROLL; - if ((style & DWT.FLAT) !is 0) - listStyle |= DWT.FLAT; - if ((style & DWT.RIGHT_TO_LEFT) !is 0) - listStyle |= DWT.RIGHT_TO_LEFT; - if ((style & DWT.LEFT_TO_RIGHT) !is 0) - listStyle |= DWT.LEFT_TO_RIGHT; - list = new List(popup, listStyle); - if (font !is null) - list.setFont(font); - if (foreground !is null) - list.setForeground(foreground); - if (background !is null) - list.setBackground(background); + height = Math.max (textSize.y, arrowSize.y); + width = Math.max (textWidth + 2*spacer + arrowSize.x + 2*borderWidth, listSize.x); + if (wHint !is DWT.DEFAULT) width = wHint; + if (hHint !is DWT.DEFAULT) height = hHint; + return new Point (width + 2*borderWidth, height + 2*borderWidth); +} +/** + * Copies the selected text. + *

    + * The current selection is copied to 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.3 + */ +public void copy () { + checkWidget (); + text.copy (); +} +void createPopup(String[] items, int selectionIndex) { + // create shell and list + popup = new Shell (getShell (), DWT.NO_TRIM | DWT.ON_TOP); + int style = getStyle (); + int listStyle = DWT.SINGLE | DWT.V_SCROLL; + if ((style & DWT.FLAT) !is 0) listStyle |= DWT.FLAT; + if ((style & DWT.RIGHT_TO_LEFT) !is 0) listStyle |= DWT.RIGHT_TO_LEFT; + if ((style & DWT.LEFT_TO_RIGHT) !is 0) listStyle |= DWT.LEFT_TO_RIGHT; + list = new List (popup, listStyle); + if (font !is null) list.setFont (font); + if (foreground !is null) list.setForeground (foreground); + if (background !is null) list.setBackground (background); + + int [] popupEvents = [DWT.Close, DWT.Paint, DWT.Deactivate]; + for (int i=0; i + * The current selection is first copied to the + * clipboard and then deleted from the widget. + *

    + * + * @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.3 + */ +public void cut () { + checkWidget (); + text.cut (); +} +/** + * Deselects the item at the given zero-relative index in the receiver's + * list. If the item at the index was already deselected, it remains + * deselected. Indices that are out of range are ignored. + * + * @param index the index of the item to deselect + * + * @exception 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 deselect (int index) { + checkWidget (); + if (0 <= index && index < list.getItemCount () && + index is list.getSelectionIndex() && + text.getText().equals(list.getItem(index))) { + text.setText(""); //$NON-NLS-1$ + list.deselect (index); } - - /** - * Cuts the selected text. - *

    - * The current selection is first copied to the - * clipboard and then deleted from the widget. - *

    - * - * @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.3 - */ - public void cut () - { - checkWidget(); - text.cut(); +} +/** + * Deselects all selected items in the receiver's list. + *

    + * Note: To clear the selection in the receiver's text field, + * use clearSelection(). + *

    + * + * @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 #clearSelection + */ +public void deselectAll () { + checkWidget (); + text.setText(""); //$NON-NLS-1$ + list.deselectAll (); +} +void dropDown (bool drop) { + if (drop is isDropped () || !isVisible()) return; + if (!drop) { + popup.setVisible (false); + if (!isDisposed () && isFocusControl()) { + text.setFocus(); + } + return; } - /** - * Deselects the item at the given zero-relative index in the receiver's - * list. If the item at the index was already deselected, it remains - * deselected. Indices that are out of range are ignored. - * - * @param index the index of the item to deselect - * - * @exception 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 deselect (int index) - { - checkWidget(); - if (0 <= index && index < list.getItemCount() && index is list.getSelectionIndex() && text.getText().opEquals( - list.getItem(index))) - { - text.setText(""); //$NON-NLS-1$ - list.deselect(index); - } - } - - /** - * Deselects all selected items in the receiver's list. - *

    - * Note: To clear the selection in the receiver's text field, - * use clearSelection(). - *

    - * - * @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 #clearSelection - */ - public void deselectAll () - { - checkWidget(); - text.setText(""); //$NON-NLS-1$ - list.deselectAll(); - } - - void dropDown (bool drop) - { - if (drop is isDropped()) - return; - if (!drop) - { - popup.setVisible(false); - if (!isDisposed() && isFocusControl()) - { - text.setFocus(); - } - return; - } - - if (getShell() !is popup.getParent()) - { - String[] items = list.getItems(); - int selectionIndex = list.getSelectionIndex(); - list.removeListener(DWT.Dispose, listener); - popup.dispose(); - popup = null; - list = null; - createPopup(items, selectionIndex); - } - - Point size = getSize(); - int itemCount = list.getItemCount(); - itemCount = (itemCount is 0) ? visibleItemCount : Math.min( - visibleItemCount, itemCount); - int itemHeight = list.getItemHeight() * itemCount; - Point listSize = list.computeSize(DWT.DEFAULT, itemHeight, false); - list.setBounds(1, 1, Math.max(size.x - 2, listSize.x), listSize.y); - - int index = list.getSelectionIndex(); - if (index !is -1) - list.setTopIndex(index); - Display display = getDisplay(); - Rectangle listRect = list.getBounds(); - Rectangle parentRect = display.map(getParent(), null, getBounds()); - Point comboSize = getSize(); - Rectangle displayRect = getMonitor().getClientArea(); - int width = Math.max(comboSize.x, listRect.width + 2); - int height = listRect.height + 2; - int x = parentRect.x; - int y = parentRect.y + comboSize.y; - if (y + height > displayRect.y + displayRect.height) - y = parentRect.y - height; - if (x + width > displayRect.x + displayRect.width) - x = displayRect.x + displayRect.width - listRect.width; - popup.setBounds(x, y, width, height); - popup.setVisible(true); - if (isFocusControl()) - list.setFocus(); - } - - /* - * Return the lowercase of the first non-'&' character following - * an '&' character in the given String. If there are no '&' - * characters in the given String, return '\0'. - */ - char _findMnemonic (String str) - { - if (str is null) - return '\0'; - int index = 0; - int length = str.length(); - do - { - while (index < length && str.charAt(index) !is '&') - index++; - if (++index >= length) - return '\0'; - if (str.charAt(index) !is '&') - return CharacterToLower(string.charAt(index)); - index++; - } while (index < length); - return '\0'; - } - - /* - * Return the Label immediately preceding the receiver in the z-order, - * or null if none. - */ - Label getAssociatedLabel () - { - Control[] siblings = getParent().getChildren(); - for (int i = 0; i < siblings.length; i++) - { - if (siblings[i] is this) - { - if (i > 0 && cast(Label) (siblings[i - 1])) - { - return cast(Label) (siblings[i - 1]); - } - } - } - return null; - } - - public Control[] getChildren () - { - checkWidget(); - return new Control[0]; - } - - /** - * Gets the editable state. - * - * @return whether or not the receiver is editable - * - * @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 bool getEditable () - { - checkWidget(); - return text.getEditable(); - } - - /** - * Returns the item at the given, zero-relative index in the - * receiver's list. Throws an exception if the index is out - * of range. - * - * @param index the index of the item to return - * @return the item at the given index - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • - *
    - * @exception 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 getItem (int index) - { - checkWidget(); - return list.getItem(index); - } - - /** - * Returns the number of items contained in the receiver's list. - * - * @return the number of items - * - * @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 int getItemCount () - { - checkWidget(); - return list.getItemCount(); - } - - /** - * Returns the height of the area which would be used to - * display one of the items in the receiver's list. - * - * @return the height of one item - * - * @exception 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 int getItemHeight () - { - checkWidget(); - return list.getItemHeight(); - } - - /** - * Returns an array of Strings which are the items - * in the receiver's list. - *

    - * Note: This is not the actual structure used by the receiver - * to maintain its list of items, so modifying the array will - * not affect the receiver. - *

    - * - * @return the items in the receiver's list - * - * @exception 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[] getItems () - { - checkWidget(); - return list.getItems(); + if (getShell() !is popup.getParent ()) { + String[] items = list.getItems (); + int selectionIndex = list.getSelectionIndex (); + list.removeListener (DWT.Dispose, listener); + popup.dispose(); + popup = null; + list = null; + createPopup (items, selectionIndex); } - /** - * Returns true 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 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.4 - */ - public bool getListVisible () - { - checkWidget(); - return isDropped(); - } - - public Menu getMenu () - { - return text.getMenu(); - } - - /** - * Returns a Point 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
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - */ - public Point getSelection () - { - checkWidget(); - return text.getSelection(); - } - - /** - * Returns the zero-relative index of the item which is currently - * selected in the receiver's list, or -1 if no item is selected. - * - * @return the index of the selected item - * - * @exception 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 int getSelectionIndex () - { - checkWidget(); - return list.getSelectionIndex(); - } - - public int getStyle () - { - int style = super.getStyle(); - style &= ~DWT.READ_ONLY; - if (!text.getEditable()) - style |= DWT.READ_ONLY; - return style; - } - - /** - * Returns a String containing a copy of the contents of the - * receiver's text field. - * - * @return the receiver's text - * - * @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 getText () - { - checkWidget(); - return text.getText(); - } - - /** - * Returns the height of the receivers's text field. - * - * @return the text height - * - * @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 int getTextHeight () - { - checkWidget(); - return text.getLineHeight(); - } - - /** - * Returns the maximum number of characters that the receiver's - * text field is capable of holding. If this has not been changed - * by setTextLimit(), it will be the constant - * Combo.LIMIT. - * - * @return the text limit - * - * @exception 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 int getTextLimit () - { - checkWidget(); - return text.getTextLimit(); - } + Point size = getSize (); + int itemCount = list.getItemCount (); + itemCount = (itemCount is 0) ? visibleItemCount : Math.min(visibleItemCount, itemCount); + int itemHeight = list.getItemHeight () * itemCount; + Point listSize = list.computeSize (DWT.DEFAULT, itemHeight, false); + list.setBounds (1, 1, Math.max (size.x - 2, listSize.x), listSize.y); - /** - * Gets the number of items that are visible in the drop - * down portion of the receiver's list. - * - * @return the number of items that are visible - * - * @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 int getVisibleItemCount () - { - checkWidget(); - return visibleItemCount; - } - - void handleFocus (int type) - { - if (isDisposed()) - return; - switch (type) - { - case DWT.FocusIn: - { - if (hasFocus) - return; - if (getEditable()) - text.selectAll(); - hasFocus = true; - Shell shell = getShell(); - shell.removeListener(DWT.Deactivate, listener); - shell.addListener(DWT.Deactivate, listener); - Display display = getDisplay(); - display.removeFilter(DWT.FocusIn, filter); - display.addFilter(DWT.FocusIn, filter); - Event e = new Event(); - notifyListeners(DWT.FocusIn, e); - break; - } - case DWT.FocusOut: - { - if (!hasFocus) - return; - Control focusControl = getDisplay().getFocusControl(); - if (focusControl is arrow || focusControl is list || focusControl is text) - return; - hasFocus = false; - Shell shell = getShell(); - shell.removeListener(DWT.Deactivate, listener); - Display display = getDisplay(); - display.removeFilter(DWT.FocusIn, filter); - Event e = new Event(); - notifyListeners(DWT.FocusOut, e); - break; - } - - default: - break; + int index = list.getSelectionIndex (); + if (index !is -1) list.setTopIndex (index); + Display display = getDisplay (); + Rectangle listRect = list.getBounds (); + Rectangle parentRect = display.map (getParent (), null, getBounds ()); + Point comboSize = getSize (); + Rectangle displayRect = getMonitor ().getClientArea (); + int width = Math.max (comboSize.x, listRect.width + 2); + int height = listRect.height + 2; + int x = parentRect.x; + int y = parentRect.y + comboSize.y; + if (y + height > displayRect.y + displayRect.height) y = parentRect.y - height; + if (x + width > displayRect.x + displayRect.width) x = displayRect.x + displayRect.width - listRect.width; + popup.setBounds (x, y, width, height); + popup.setVisible (true); + if (isFocusControl()) list.setFocus (); +} +/* + * Return the lowercase of the first non-'&' character following + * an '&' character in the given string. If there are no '&' + * characters in the given string, return '\0'. + */ +dchar _findMnemonic (String string) { + if (string is null) return '\0'; + int index = 0; + int length = string.length; + do { + while (index < length && string[index] !is '&') index++; + if (++index >= length) return '\0'; + if (string[index] !is '&') { + dchar[1] d; uint ate; + auto d2 = tango.text.convert.Utf.toString32( string[ index .. Math.min( index +4, string.length )], d, &ate ); + auto d3 = tango.text.Unicode.toLower( d2, d2 ); + return d3[0]; } - } - - /** - * Searches the receiver's list starting at the first item - * (index 0) until an item is found that is equal to the - * argument, and returns the index of that item. If no item - * is found, returns -1. - * - * @param String the search item - * @return the index of the item - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the String 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
    • - *
    - */ - public int indexOf (String String) - { - checkWidget(); - if (String is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - return list.indexOf(String); - } - - /** - * Searches the receiver's list starting at the given, - * zero-relative index until an item is found that is equal - * to the argument, and returns the index of that item. If - * no item is found or the starting index is out of range, - * returns -1. - * - * @param String the search item - * @param start the zero-relative index at which to begin the search - * @return the index of the item - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the String is null
    • - *
    - * @exception 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 int indexOf (String String, int start) - { - checkWidget(); - if (String is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - return list.indexOf(String, start); - } - - void initAccessible () - { - AccessibleAdapter accessibleAdapter = new class AccessibleAdapter - { - public void getName (AccessibleEvent e) - { - String name = null; - Label label = getAssociatedLabel(); - if (label !is null) - { - name = stripMnemonic(label.getText()); - } - e.result = name; - } - - public void getKeyboardShortcut (AccessibleEvent e) - { - String shortcut = null; - Label label = getAssociatedLabel(); - if (label !is null) - { - String text = label.getText(); - if (text !is null) - { - char mnemonic = _findMnemonic(text); - if (mnemonic !is '\0') - { - shortcut = "Alt+" + mnemonic; //$NON-NLS-1$ + index++; + } while (index < length); + return '\0'; +} +/* + * Return the Label immediately preceding the receiver in the z-order, + * or null if none. + */ +Label getAssociatedLabel () { + Control[] siblings = getParent ().getChildren (); + for (int i = 0; i < siblings.length; i++) { + if (siblings [i] is this) { + if (i > 0 && ( null !is cast(Label)siblings [i-1] )) { + return cast(Label) siblings [i-1]; } } } - e.result = shortcut; + return null; +} +public override Control [] getChildren () { + checkWidget(); + return new Control [0]; +} +/** + * Gets the editable state. + * + * @return whether or not the receiver is editable + * + * @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 bool getEditable () { + checkWidget (); + return text.getEditable(); +} +/** + * Returns the item at the given, zero-relative index in the + * receiver's list. Throws an exception if the index is out + * of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception 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 getItem (int index) { + checkWidget(); + return list.getItem (index); +} +/** + * Returns the number of items contained in the receiver's list. + * + * @return the number of items + * + * @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 int getItemCount () { + checkWidget (); + return list.getItemCount (); +} +/** + * Returns the height of the area which would be used to + * display one of the items in the receiver's list. + * + * @return the height of one item + * + * @exception 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 int getItemHeight () { + checkWidget (); + return list.getItemHeight (); +} +/** + * Returns an array of Strings which are the items + * in the receiver's list. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver's list + * + * @exception 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 [] getItems () { + checkWidget (); + return list.getItems (); +} +/** + * Returns true 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 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.4 + */ +public bool getListVisible () { + checkWidget (); + return isDropped(); +} +public override Menu getMenu() { + return text.getMenu(); +} +/** + * Returns a Point 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
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSelection () { + checkWidget (); + return text.getSelection (); +} +/** + * Returns the zero-relative index of the item which is currently + * selected in the receiver's list, or -1 if no item is selected. + * + * @return the index of the selected item + * + * @exception 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 int getSelectionIndex () { + checkWidget (); + return list.getSelectionIndex (); +} +public override int getStyle () { + int style = super.getStyle (); + style &= ~DWT.READ_ONLY; + if (!text.getEditable()) style |= DWT.READ_ONLY; + return style; +} +/** + * Returns a string containing a copy of the contents of the + * receiver's text field. + * + * @return the receiver's text + * + * @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 getText () { + checkWidget (); + return text.getText (); +} +/** + * Returns the height of the receivers's text field. + * + * @return the text height + * + * @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 int getTextHeight () { + checkWidget (); + return text.getLineHeight (); +} +/** + * Returns the maximum number of characters that the receiver's + * text field is capable of holding. If this has not been changed + * by setTextLimit(), it will be the constant + * Combo.LIMIT. + * + * @return the text limit + * + * @exception 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 int getTextLimit () { + checkWidget (); + return text.getTextLimit (); +} +/** + * Gets the number of items that are visible in the drop + * down portion of the receiver's list. + * + * @return the number of items that are visible + * + * @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 int getVisibleItemCount () { + checkWidget (); + return visibleItemCount; +} +void handleFocus (int type) { + if (isDisposed ()) return; + switch (type) { + case DWT.FocusIn: { + if (hasFocus) return; + if (getEditable ()) text.selectAll (); + hasFocus = true; + Shell shell = getShell (); + shell.removeListener (DWT.Deactivate, listener); + shell.addListener (DWT.Deactivate, listener); + Display display = getDisplay (); + display.removeFilter (DWT.FocusIn, filter); + display.addFilter (DWT.FocusIn, filter); + Event e = new Event (); + notifyListeners (DWT.FocusIn, e); + break; + } + case DWT.FocusOut: { + if (!hasFocus) return; + Control focusControl = getDisplay ().getFocusControl (); + if (focusControl is arrow || focusControl is list || focusControl is text) return; + hasFocus = false; + Shell shell = getShell (); + shell.removeListener(DWT.Deactivate, listener); + Display display = getDisplay (); + display.removeFilter (DWT.FocusIn, filter); + Event e = new Event (); + notifyListeners (DWT.FocusOut, e); + break; + } + default: + } +} +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param string the search item + * @return the index of the item + * + * @exception 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 int indexOf (String string) { + checkWidget (); + // DWT extension: allow null for zero length string + //if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + return list.indexOf (string); +} +/** + * Searches the receiver's list starting at the given, + * zero-relative index until an item is found that is equal + * to the argument, and returns the index of that item. If + * no item is found or the starting index is out of range, + * returns -1. + * + * @param string the search item + * @param start the zero-relative index at which to begin the search + * @return the index of the item + * + * @exception 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 int indexOf (String string, int start) { + checkWidget (); + // DWT extension: allow null for zero length string + //if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + return list.indexOf (string, start); } -public void getHelp (AccessibleEvent e) -{ - e.result = getToolTipText(); -} -} ; - getAccessible().addAccessibleListener(accessibleAdapter); - text.getAccessible().addAccessibleListener(accessibleAdapter); - list.getAccessible().addAccessibleListener(accessibleAdapter); - - arrow.getAccessible().addAccessibleListener( - new class AccessibleAdapter - { - public void getName (AccessibleEvent e) - { - e.result = isDropped() ? DWT.getMessage("DWT_Close") : DWT.getMessage( - "DWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - public void getKeyboardShortcut (AccessibleEvent e) - { - e.result = "Alt+Down Arrow"; //$NON-NLS-1$ - } - - public void getHelp (AccessibleEvent e) - { - e.result = getToolTipText(); +void initAccessible() { + AccessibleAdapter accessibleAdapter = new class() AccessibleAdapter { + public void getName (AccessibleEvent e) { + String name = null; + Label label = getAssociatedLabel (); + if (label !is null) { + name = stripMnemonic (label.getText()); + } + e.result = name; + } + public void getKeyboardShortcut(AccessibleEvent e) { + String shortcut = null; + Label label = getAssociatedLabel (); + if (label !is null) { + String text = label.getText (); + if (text !is null) { + dchar mnemonic = _findMnemonic (text); + if (mnemonic !is '\0') { + shortcut = tango.text.convert.Format.Format( "Alt+{}", mnemonic ); //$NON-NLS-1$ } - }); - - getAccessible().addAccessibleTextListener(new class - AccessibleTextAdapter - { - public void getCaretOffset (AccessibleTextEvent e) - { - e.offset = text.getCaretPosition(); - } - - public void getSelectionRange (AccessibleTextEvent e) - { - Point sel = text.getSelection(); - e.offset = sel.x; - e.length = sel.y - sel.x; - } - }); - - getAccessible().addAccessibleControlListener(new class - AccessibleControlAdapter - { - public void getChildAtPoint (AccessibleControlEvent e) - { - Point testPoint = toControl(e.x, e.y); - if (getBounds().contains(testPoint)) - { - e.childID = ACC.CHILDID_SELF; } } - - public void getLocation (AccessibleControlEvent e) - { - Rectangle location = getBounds(); - Point pt = getParent().toDisplay(location.x, location.y); - e.x = pt.x; - e.y = pt.y; - e.width = location.width; - e.height = location.height; - } + e.result = shortcut; + } + public void getHelp (AccessibleEvent e) { + e.result = getToolTipText (); + } + }; + getAccessible ().addAccessibleListener (accessibleAdapter); + text.getAccessible ().addAccessibleListener (accessibleAdapter); + list.getAccessible ().addAccessibleListener (accessibleAdapter); - public void getChildCount (AccessibleControlEvent e) - { - e.detail = 0; - } + arrow.getAccessible ().addAccessibleListener (new class() AccessibleAdapter { + public void getName (AccessibleEvent e) { + e.result = isDropped () ? DWT.getMessage ("SWT_Close") : DWT.getMessage ("SWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$ + } + public void getKeyboardShortcut (AccessibleEvent e) { + e.result = "Alt+Down Arrow"; //$NON-NLS-1$ + } + public void getHelp (AccessibleEvent e) { + e.result = getToolTipText (); + } + }); - public void getRole (AccessibleControlEvent e) - { - e.detail = ACC.ROLE_COMBOBOX; - } - - public void getState (AccessibleControlEvent e) - { - e.detail = ACC.STATE_NORMAL; - } + getAccessible().addAccessibleTextListener (new class() AccessibleTextAdapter { + public void getCaretOffset (AccessibleTextEvent e) { + e.offset = text.getCaretPosition (); + } + public void getSelectionRange(AccessibleTextEvent e) { + Point sel = text.getSelection(); + e.offset = sel.x; + e.length = sel.y - sel.x; + } + }); - public void getValue (AccessibleControlEvent e) - { - e.result = getText(); + getAccessible().addAccessibleControlListener (new class() AccessibleControlAdapter { + public void getChildAtPoint (AccessibleControlEvent e) { + Point testPoint = toControl (e.x, e.y); + if (getBounds ().contains (testPoint)) { + e.childID = ACC.CHILDID_SELF; } - }); + } - text.getAccessible().addAccessibleControlListener(new class - AccessibleControlAdapter - { - public void getRole (AccessibleControlEvent e) - { - e.detail = text.getEditable() ? ACC.ROLE_TEXT : ACC.ROLE_LABEL; - } - }); + public void getLocation (AccessibleControlEvent e) { + Rectangle location = getBounds (); + Point pt = getParent().toDisplay (location.x, location.y); + e.x = pt.x; + e.y = pt.y; + e.width = location.width; + e.height = location.height; + } - arrow.getAccessible().addAccessibleControlListener( - new class AccessibleControlAdapter - { - public void getDefaultAction (AccessibleControlEvent e) - { - e.result = isDropped() ? DWT.getMessage("DWT_Close") : DWT.getMessage( - "DWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$ - } - }); - } + public void getChildCount (AccessibleControlEvent e) { + e.detail = 0; + } + + public void getRole (AccessibleControlEvent e) { + e.detail = ACC.ROLE_COMBOBOX; + } - bool isDropped () - { - return popup.getVisible(); - } + public void getState (AccessibleControlEvent e) { + e.detail = ACC.STATE_NORMAL; + } + + public void getValue (AccessibleControlEvent e) { + e.result = getText (); + } + }); + + text.getAccessible ().addAccessibleControlListener (new class() AccessibleControlAdapter { + public void getRole (AccessibleControlEvent e) { + e.detail = text.getEditable () ? ACC.ROLE_TEXT : ACC.ROLE_LABEL; + } + }); - public bool isFocusControl () - { - checkWidget(); - if (text.isFocusControl() || arrow.isFocusControl() || list.isFocusControl() || popup.isFocusControl()) - { - return true; + arrow.getAccessible ().addAccessibleControlListener (new class() AccessibleControlAdapter { + public void getDefaultAction (AccessibleControlEvent e) { + e.result = isDropped () ? DWT.getMessage ("SWT_Close") : DWT.getMessage ("SWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$ } - return super.isFocusControl(); - } - - void internalLayout (bool changed) - { - if (isDropped()) - dropDown(false); - Rectangle rect = getClientArea(); - int width = rect.width; - int height = rect.height; - Point arrowSize = arrow.computeSize(DWT.DEFAULT, height, changed); - text.setBounds(0, 0, width - arrowSize.x, height); - arrow.setBounds(width - arrowSize.x, 0, arrowSize.x, arrowSize.y); + }); +} +bool isDropped () { + return popup.getVisible (); +} +public override bool isFocusControl () { + checkWidget(); + if (text.isFocusControl () || arrow.isFocusControl () || list.isFocusControl () || popup.isFocusControl ()) { + return true; } - - void listEvent (Event event) - { - switch (event.type) - { - case DWT.Dispose: - if (getShell() !is popup.getParent()) - { - String[] items = list.getItems(); - int selectionIndex = list.getSelectionIndex(); - popup = null; - list = null; - createPopup(items, selectionIndex); - } + return super.isFocusControl (); +} +void internalLayout (bool changed) { + if (isDropped ()) dropDown (false); + Rectangle rect = getClientArea (); + int width = rect.width; + int height = rect.height; + Point arrowSize = arrow.computeSize (DWT.DEFAULT, height, changed); + text.setBounds (0, 0, width - arrowSize.x, height); + arrow.setBounds (width - arrowSize.x, 0, arrowSize.x, arrowSize.y); +} +void listEvent (Event event) { + switch (event.type) { + case DWT.Dispose: + if (getShell () !is popup.getParent ()) { + String[] items = list.getItems (); + int selectionIndex = list.getSelectionIndex (); + popup = null; + list = null; + createPopup (items, selectionIndex); + } + break; + case DWT.FocusIn: { + handleFocus (DWT.FocusIn); + break; + } + case DWT.MouseUp: { + if (event.button !is 1) return; + dropDown (false); + break; + } + case DWT.Selection: { + int index = list.getSelectionIndex (); + if (index is -1) return; + text.setText (list.getItem (index)); + text.selectAll (); + list.setSelection (index); + Event e = new Event (); + e.time = event.time; + e.stateMask = event.stateMask; + e.doit = event.doit; + notifyListeners (DWT.Selection, e); + event.doit = e.doit; break; - case DWT.FocusIn: - { - handleFocus(DWT.FocusIn); - break; - } - case DWT.MouseUp: - { - if (event.button !is 1) + } + case DWT.Traverse: { + switch (event.detail) { + case DWT.TRAVERSE_RETURN: + case DWT.TRAVERSE_ESCAPE: + case DWT.TRAVERSE_ARROW_PREVIOUS: + case DWT.TRAVERSE_ARROW_NEXT: + event.doit = false; + break; + case DWT.TRAVERSE_TAB_NEXT: + case DWT.TRAVERSE_TAB_PREVIOUS: + event.doit = text.traverse(event.detail); + event.detail = DWT.TRAVERSE_NONE; + if (event.doit) dropDown(false); return; - dropDown(false); - break; + default: } - case DWT.Selection: - { - int index = list.getSelectionIndex(); - if (index is -1) - return; - text.setText(list.getItem(index)); - text.selectAll(); - list.setSelection(index); - Event e = new Event(); + Event e = new Event (); + e.time = event.time; + e.detail = event.detail; + e.doit = event.doit; + e.character = event.character; + e.keyCode = event.keyCode; + notifyListeners (DWT.Traverse, e); + event.doit = e.doit; + event.detail = e.detail; + break; + } + case DWT.KeyUp: { + Event e = new Event (); + e.time = event.time; + e.character = event.character; + e.keyCode = event.keyCode; + e.stateMask = event.stateMask; + notifyListeners (DWT.KeyUp, e); + break; + } + case DWT.KeyDown: { + if (event.character is DWT.ESC) { + // Escape key cancels popup list + dropDown (false); + } + if ((event.stateMask & DWT.ALT) !is 0 && (event.keyCode is DWT.ARROW_UP || event.keyCode is DWT.ARROW_DOWN)) { + dropDown (false); + } + if (event.character is DWT.CR) { + // Enter causes default selection + dropDown (false); + Event e = new Event (); e.time = event.time; e.stateMask = event.stateMask; - e.doit = event.doit; - notifyListeners(DWT.Selection, e); - event.doit = e.doit; - break; + notifyListeners (DWT.DefaultSelection, e); + } + // At this point the widget may have been disposed. + // If so, do not continue. + if (isDisposed ()) break; + Event e = new Event(); + e.time = event.time; + e.character = event.character; + e.keyCode = event.keyCode; + e.stateMask = event.stateMask; + notifyListeners(DWT.KeyDown, e); + break; + + } + default: + } +} +/** + * Pastes text from clipboard. + *

    + * The selected text is deleted from the widget + * and new text inserted from 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.3 + */ +public void paste () { + checkWidget (); + text.paste (); +} +void popupEvent(Event event) { + switch (event.type) { + case DWT.Paint: + // draw black rectangle around list + Rectangle listRect = list.getBounds(); + Color black = getDisplay().getSystemColor(DWT.COLOR_BLACK); + event.gc.setForeground(black); + event.gc.drawRectangle(0, 0, listRect.width + 1, listRect.height + 1); + break; + case DWT.Close: + event.doit = false; + dropDown (false); + break; + case DWT.Deactivate: + /* + * Bug in GTK. When the arrow button is pressed the popup control receives a + * deactivate event and then the arrow button receives a selection event. If + * we hide the popup in the deactivate event, the selection event will show + * it again. To prevent the popup from showing again, we will let the selection + * event of the arrow button hide the popup. + * In Windows, hiding the popup during the deactivate causes the deactivate + * to be called twice and the selection event to be disappear. + */ + if (!"carbon".equals(DWT.getPlatform())) { + Point point = arrow.toControl(getDisplay().getCursorLocation()); + Point size = arrow.getSize(); + Rectangle rect = new Rectangle(0, 0, size.x, size.y); + if (!rect.contains(point)) dropDown (false); + } else { + dropDown(false); } - case DWT.Traverse: - { - switch (event.detail) - { - case DWT.TRAVERSE_RETURN: - case DWT.TRAVERSE_ESCAPE: - case DWT.TRAVERSE_ARROW_PREVIOUS: - case DWT.TRAVERSE_ARROW_NEXT: - event.doit = false; + break; + default: + } +} +public override void redraw () { + super.redraw(); + text.redraw(); + arrow.redraw(); + if (popup.isVisible()) list.redraw(); +} +public override void redraw (int x, int y, int width, int height, bool all) { + super.redraw(x, y, width, height, true); +} + +/** + * Removes the item from the receiver's list at the given + * zero-relative index. + * + * @param index the index for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception 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 remove (int index) { + checkWidget(); + list.remove (index); +} +/** + * Removes the items from the receiver's list which are + * between the given zero-relative start and end + * indices (inclusive). + * + * @param start the start of the range + * @param end the end of the range + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception 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 remove (int start, int end) { + checkWidget(); + list.remove (start, end); +} +/** + * Searches the receiver's list starting at the first item + * until an item is found that is equal to the argument, + * and removes that item from the list. + * + * @param string the item to remove + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the string is not found in the list
    • + *
    + * @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 remove (String string) { + checkWidget(); + // DWT extension: allow null for zero length string + //if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + list.remove (string); +} +/** + * Removes all of the items from the receiver's list and clear the + * contents of receiver's text field. + *

    + * @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 removeAll () { + checkWidget(); + text.setText (""); //$NON-NLS-1$ + list.removeAll (); +} +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's text is modified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception 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 ModifyListener + * @see #addModifyListener + */ +public void removeModifyListener (ModifyListener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + removeListener(DWT.Modify, listener); +} +/** + * Removes the listener from the collection of listeners who will + * be notified when the user changes the receiver's selection. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception 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 SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + removeListener(DWT.Selection, listener); + removeListener(DWT.DefaultSelection,listener); +} +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is verified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception 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 VerifyListener + * @see #addVerifyListener + * + * @since 3.3 + */ +public void removeVerifyListener (VerifyListener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + removeListener(DWT.Verify, listener); +} +/** + * Selects the item at the given zero-relative index in the receiver's + * list. If the item at the index was already selected, it remains + * selected. Indices that are out of range are ignored. + * + * @param index the index of the item to select + * + * @exception 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 select (int index) { + checkWidget(); + if (index is -1) { + list.deselectAll (); + text.setText (""); //$NON-NLS-1$ + return; + } + if (0 <= index && index < list.getItemCount()) { + if (index !is getSelectionIndex()) { + text.setText (list.getItem (index)); + text.selectAll (); + list.select (index); + list.showSelection (); + } + } +} +public override void setBackground (Color color) { + super.setBackground(color); + background = color; + if (text !is null) text.setBackground(color); + if (list !is null) list.setBackground(color); + if (arrow !is null) arrow.setBackground(color); +} +/** + * Sets the editable state. + * + * @param editable the new editable state + * + * @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 setEditable (bool editable) { + checkWidget (); + text.setEditable(editable); +} +public override void setEnabled (bool enabled) { + super.setEnabled(enabled); + if (popup !is null) popup.setVisible (false); + if (text !is null) text.setEnabled(enabled); + if (arrow !is null) arrow.setEnabled(enabled); +} +public override bool setFocus () { + checkWidget(); + if (!isEnabled () || !isVisible ()) return false; + if (isFocusControl ()) return true; + return text.setFocus (); +} +public override void setFont (Font font) { + super.setFont (font); + this.font = font; + text.setFont (font); + list.setFont (font); + internalLayout (true); +} +public override void setForeground (Color color) { + super.setForeground(color); + foreground = color; + if (text !is null) text.setForeground(color); + if (list !is null) list.setForeground(color); + if (arrow !is null) arrow.setForeground(color); +} +/** + * Sets the text of the item in the receiver's list at the given + * zero-relative index to the string argument. This is equivalent + * to remove'ing the old item at the index, and then + * add'ing the new item at that index. + * + * @param index the index for the item + * @param string the new text for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @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 setItem (int index, String string) { + checkWidget(); + list.setItem (index, string); +} +/** + * Sets the receiver's list to be the given array of items. + * + * @param items the array of items + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if an item in the items array 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
    • + *
    + */ +public void setItems (String [] items) { + checkWidget (); + list.setItems (items); + if (!text.getEditable ()) text.setText (""); //$NON-NLS-1$ +} +/** + * 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 override void setLayout (Layout layout) { + checkWidget (); + return; +} +/** + * Marks the receiver's list as visible if the argument is true, + * and marks it invisible otherwise. + *

    + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

    + * + * @param visible the new visibility state + * + * @exception 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.4 + */ +public void setListVisible (bool visible) { + checkWidget (); + dropDown(visible); +} +public override void setMenu(Menu menu) { + text.setMenu(menu); +} +/** + * Sets the selection in the receiver's text field to the + * range specified by the argument whose x coordinate is the + * start of the selection and whose y coordinate is the end + * of the selection. + * + * @param selection a point representing the new selection start and end + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception 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 setSelection (Point selection) { + checkWidget(); + if (selection is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + text.setSelection (selection.x, selection.y); +} + +/** + * Sets the contents of the receiver's text field to the + * given string. + *

    + * Note: The text field in a Combo is typically + * only capable of displaying a single line of text. Thus, + * setting the text to a string containing line breaks or + * other special characters will probably cause it to + * display incorrectly. + *

    + * + * @param string the new text + * + * @exception 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 setText (String string) { + checkWidget(); + // DWT extension: allow null for zero length string + //if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + int index = list.indexOf (string); + if (index is -1) { + list.deselectAll (); + text.setText (string); + return; + } + text.setText (string); + text.selectAll (); + list.setSelection (index); + list.showSelection (); +} +/** + * Sets the maximum number of characters that the receiver's + * text field is capable of holding to be the argument. + * + * @param limit new text limit + * + * @exception IllegalArgumentException
      + *
    • ERROR_CANNOT_BE_ZERO - if the limit is zero
    • + *
    + * @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 setTextLimit (int limit) { + checkWidget(); + text.setTextLimit (limit); +} + +public override void setToolTipText (String string) { + checkWidget(); + super.setToolTipText(string); + arrow.setToolTipText (string); + text.setToolTipText (string); +} + +public override void setVisible (bool visible) { + super.setVisible(visible); + /* + * At this point the widget may have been disposed in a FocusOut event. + * If so then do not continue. + */ + if (isDisposed ()) return; + // TEMPORARY CODE + if (popup is null || popup.isDisposed ()) return; + if (!visible) popup.setVisible (false); +} +/** + * Sets the number of items that are visible in the drop + * down portion of the receiver's list. + * + * @param count the new number of items to be visible + * + * @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 setVisibleItemCount (int count) { + checkWidget (); + if (count < 0) return; + visibleItemCount = count; +} +String stripMnemonic (String string) { + int index = 0; + int length_ = string.length; + do { + while ((index < length_) && (string[index] !is '&')) index++; + if (++index >= length_) return string; + if (string[index] !is '&') { + return string[0 .. index-1] ~ string[index .. length_]; + } + index++; + } while (index < length_); + return string; +} +void textEvent (Event event) { + switch (event.type) { + case DWT.FocusIn: { + handleFocus (DWT.FocusIn); + break; + } + case DWT.DefaultSelection: { + dropDown (false); + Event e = new Event (); + e.time = event.time; + e.stateMask = event.stateMask; + notifyListeners (DWT.DefaultSelection, e); + break; + } + case DWT.KeyDown: { + Event keyEvent = new Event (); + keyEvent.time = event.time; + keyEvent.character = event.character; + keyEvent.keyCode = event.keyCode; + keyEvent.stateMask = event.stateMask; + notifyListeners (DWT.KeyDown, keyEvent); + if (isDisposed ()) break; + event.doit = keyEvent.doit; + if (!event.doit) break; + if (event.keyCode is DWT.ARROW_UP || event.keyCode is DWT.ARROW_DOWN) { + event.doit = false; + if ((event.stateMask & DWT.ALT) !is 0) { + bool dropped = isDropped (); + text.selectAll (); + if (!dropped) setFocus (); + dropDown (!dropped); break; - case DWT.TRAVERSE_TAB_NEXT: - case DWT.TRAVERSE_TAB_PREVIOUS: - event.doit = text.traverse(event.detail); - event.detail = DWT.TRAVERSE_NONE; - if (event.doit) - dropDown(false); - return; } - Event e = new Event(); - e.time = event.time; - e.detail = event.detail; - e.doit = event.doit; - e.character = event.character; - e.keyCode = event.keyCode; - notifyListeners(DWT.Traverse, e); - event.doit = e.doit; - event.detail = e.detail; - break; - } - case DWT.KeyUp: - { - Event e = new Event(); - e.time = event.time; - e.character = event.character; - e.keyCode = event.keyCode; - e.stateMask = event.stateMask; - notifyListeners(DWT.KeyUp, e); - break; - } - case DWT.KeyDown: - { - if (event.character is DWT.ESC) - { - // Escape key cancels popup list - dropDown(false); + + int oldIndex = getSelectionIndex (); + if (event.keyCode is DWT.ARROW_UP) { + select (Math.max (oldIndex - 1, 0)); + } else { + select (Math.min (oldIndex + 1, getItemCount () - 1)); } - if ((event.stateMask & DWT.ALT) !is 0 && (event.keyCode is DWT.ARROW_UP || event.keyCode is DWT.ARROW_DOWN)) - { - dropDown(false); - } - if (event.character is DWT.CR) - { - // Enter causes default selection - dropDown(false); + if (oldIndex !is getSelectionIndex ()) { Event e = new Event(); e.time = event.time; e.stateMask = event.stateMask; - notifyListeners(DWT.DefaultSelection, e); + notifyListeners (DWT.Selection, e); } - // At this point the widget may have been disposed. - // If so, do not continue. - if (isDisposed()) - break; - Event e = new Event(); - e.time = event.time; - e.character = event.character; - e.keyCode = event.keyCode; - e.stateMask = event.stateMask; - notifyListeners(DWT.KeyDown, e); - break; - + if (isDisposed ()) break; } - default: + // Further work : Need to add support for incremental search in + // pop up list as characters typed in text widget + break; + } + case DWT.KeyUp: { + Event e = new Event (); + e.time = event.time; + e.character = event.character; + e.keyCode = event.keyCode; + e.stateMask = event.stateMask; + notifyListeners (DWT.KeyUp, e); + event.doit = e.doit; + break; + } + case DWT.MenuDetect: { + Event e = new Event (); + e.time = event.time; + notifyListeners (DWT.MenuDetect, e); + break; + } + case DWT.Modify: { + list.deselectAll (); + Event e = new Event (); + e.time = event.time; + notifyListeners (DWT.Modify, e); break; } - } - - /** - * Pastes text from clipboard. - *

    - * The selected text is deleted from the widget - * and new text inserted from 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.3 - */ - public void paste () - { - checkWidget(); - text.paste(); - } - - void popupEvent (Event event) - { - switch (event.type) - { - case DWT.Paint: - // draw black rectangle around list - Rectangle listRect = list.getBounds(); - Color black = getDisplay().getSystemColor(DWT.COLOR_BLACK); - event.gc.setForeground(black); - event.gc.drawRectangle(0, 0, listRect.width + 1, - listRect.height + 1); + case DWT.MouseDown: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseDown, mouseEvent); + if (isDisposed ()) break; + event.doit = mouseEvent.doit; + if (!event.doit) break; + if (event.button !is 1) return; + if (text.getEditable ()) return; + bool dropped = isDropped (); + text.selectAll (); + if (!dropped) setFocus (); + dropDown (!dropped); break; - case DWT.Close: - event.doit = false; - dropDown(false); - break; - case DWT.Deactivate: - /* - * Bug in GTK. When the arrow button is pressed the popup control receives a - * deactivate event and then the arrow button receives a selection event. If - * we hide the popup in the deactivate event, the selection event will show - * it again. To prevent the popup from showing again, we will let the selection - * event of the arrow button hide the popup. - * In Windows, hiding the popup during the deactivate causes the deactivate - * to be called twice and the selection event to be disappear. - */ - if (!"carbon".opEquals(DWT.getPlatform())) - { - Point point = arrow.toControl( - getDisplay().getCursorLocation()); - Point size = arrow.getSize(); - Rectangle rect = new Rectangle(0, 0, size.x, size.y); - if (!rect.contains(point)) - dropDown(false); - } - else - { - dropDown(false); - } - break; - - default: + } + case DWT.MouseUp: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseUp, mouseEvent); + if (isDisposed ()) break; + event.doit = mouseEvent.doit; + if (!event.doit) break; + if (event.button !is 1) return; + if (text.getEditable ()) return; + text.selectAll (); break; } - } - - public void redraw () - { - super.redraw(); - text.redraw(); - arrow.redraw(); - if (popup.isVisible()) - list.redraw(); - } - - public void redraw (int x, int y, int width, int height, bool all) - { - super.redraw(x, y, width, height, true); - } - - /** - * Removes the item from the receiver's list at the given - * zero-relative index. - * - * @param index the index for the item - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • - *
    - * @exception 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 remove (int index) - { - checkWidget(); - list.remove(index); - } - - /** - * Removes the items from the receiver's list which are - * between the given zero-relative start and end - * indices (inclusive). - * - * @param start the start of the range - * @param end the end of the range - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
    • - *
    - * @exception 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 remove (int start, int end) - { - checkWidget(); - list.remove(start, end); - } - - /** - * Searches the receiver's list starting at the first item - * until an item is found that is equal to the argument, - * and removes that item from the list. - * - * @param String the item to remove - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the String is null
    • - *
    • ERROR_INVALID_ARGUMENT - if the String is not found in the list
    • - *
    - * @exception 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 remove (String String) - { - checkWidget(); - if (String is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - list.remove(String); - } - - /** - * Removes all of the items from the receiver's list and clear the - * contents of receiver's text field. - *

    - * @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 removeAll () - { - checkWidget(); - text.setText(""); //$NON-NLS-1$ - list.removeAll(); - } - - /** - * Removes the listener from the collection of listeners who will - * be notified when the receiver's text is modified. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception 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 ModifyListener - * @see #addModifyListener - */ - public void removeModifyListener (ModifyListener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(DWT.Modify, listener); - } - - /** - * Removes the listener from the collection of listeners who will - * be notified when the user changes the receiver's selection. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception 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 SelectionListener - * @see #addSelectionListener - */ - public void removeSelectionListener (SelectionListener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(DWT.Selection, listener); - removeListener(DWT.DefaultSelection, listener); - } - - /** - * Removes the listener from the collection of listeners who will - * be notified when the control is verified. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception 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 VerifyListener - * @see #addVerifyListener - * - * @since 3.3 - */ - public void removeVerifyListener (VerifyListener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(DWT.Verify, listener); - } - - /** - * Selects the item at the given zero-relative index in the receiver's - * list. If the item at the index was already selected, it remains - * selected. Indices that are out of range are ignored. - * - * @param index the index of the item to select - * - * @exception 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 select (int index) - { - checkWidget(); - if (index is -1) - { - list.deselectAll(); - text.setText(""); //$NON-NLS-1$ - return; - } - if (0 <= index && index < list.getItemCount()) - { - if (index !is getSelectionIndex()) - { - text.setText(list.getItem(index)); - text.selectAll(); - list.select(index); - list.showSelection(); - } + case DWT.MouseDoubleClick: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseDoubleClick, mouseEvent); + break; } - } - - public void setBackground (Color color) - { - super.setBackground(color); - background = color; - if (text !is null) - text.setBackground(color); - if (list !is null) - list.setBackground(color); - if (arrow !is null) - arrow.setBackground(color); - } - - /** - * Sets the editable state. - * - * @param editable the new editable state - * - * @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 setEditable (bool editable) - { - checkWidget(); - text.setEditable(editable); - } - - public void setEnabled (bool enabled) - { - super.setEnabled(enabled); - if (popup !is null) - popup.setVisible(false); - if (text !is null) - text.setEnabled(enabled); - if (arrow !is null) - arrow.setEnabled(enabled); - } - - public bool setFocus () - { - checkWidget(); - if (!isEnabled() || !isVisible()) - return false; - if (isFocusControl()) - return true; - return text.setFocus(); - } - - public void setFont (Font font) - { - super.setFont(font); - this.font = font; - text.setFont(font); - list.setFont(font); - internalLayout(true); - } - - public void setForeground (Color color) - { - super.setForeground(color); - foreground = color; - if (text !is null) - text.setForeground(color); - if (list !is null) - list.setForeground(color); - if (arrow !is null) - arrow.setForeground(color); - } - - /** - * Sets the text of the item in the receiver's list at the given - * zero-relative index to the String argument. This is equivalent - * to remove'ing the old item at the index, and then - * add'ing the new item at that index. - * - * @param index the index for the item - * @param String the new text for the item - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • - *
    • ERROR_NULL_ARGUMENT - if the String is null
    • - *
    - * @exception 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 setItem (int index, String String) - { - checkWidget(); - list.setItem(index, String); - } - - /** - * Sets the receiver's list to be the given array of items. - * - * @param items the array of items - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the items array is null
    • - *
    • ERROR_INVALID_ARGUMENT - if an item in the items array is null
    • - *
    - * @exception 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 setItems (String[] items) - { - checkWidget(); - list.setItems(items); - if (!text.getEditable()) - text.setText(""); //$NON-NLS-1$ - } - - /** - * 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; - } - - /** - * Marks the receiver's list as visible if the argument is true, - * and marks it invisible otherwise. - *

    - * If one of the receiver's ancestors is not visible or some - * other condition makes the receiver not visible, marking - * it visible may not actually cause it to be displayed. - *

    - * - * @param visible the new visibility state - * - * @exception 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.4 - */ - public void setListVisible (bool visible) - { - checkWidget(); - dropDown(visible); - } - - public void setMenu (Menu menu) - { - text.setMenu(menu); - } - - /** - * Sets the selection in the receiver's text field to the - * range specified by the argument whose x coordinate is the - * start of the selection and whose y coordinate is the end - * of the selection. - * - * @param selection a point representing the new selection start and end - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the point is null
    • - *
    - * @exception 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 setSelection (Point selection) - { - checkWidget(); - if (selection is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - text.setSelection(selection.x, selection.y); - } - - /** - * Sets the contents of the receiver's text field to the - * given String. - *

    - * Note: The text field in a Combo is typically - * only capable of displaying a single line of text. Thus, - * setting the text to a String containing line breaks or - * other special characters will probably cause it to - * display incorrectly. - *

    - * - * @param String the new text - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the String is null
    • - *
    - * @exception 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 setText (String String) - { - checkWidget(); - if (String is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - int index = list.indexOf(String); - if (index is -1) - { - list.deselectAll(); - text.setText(String); - return; - } - text.setText(String); - text.selectAll(); - list.setSelection(index); - list.showSelection(); - } - - /** - * Sets the maximum number of characters that the receiver's - * text field is capable of holding to be the argument. - * - * @param limit new text limit - * - * @exception IllegalArgumentException
      - *
    • ERROR_CANNOT_BE_ZERO - if the limit is zero
    • - *
    - * @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 setTextLimit (int limit) - { - checkWidget(); - text.setTextLimit(limit); - } - - public void setToolTipText (String String) - { - checkWidget(); - super.setToolTipText(String); - arrow.setToolTipText(String); - text.setToolTipText(String); - } - - public void setVisible (bool visible) - { - super.setVisible(visible); - /* - * At this point the widget may have been disposed in a FocusOut event. - * If so then do not continue. - */ - if (isDisposed()) - return; - if (!visible) - popup.setVisible(false); - } - - /** - * Sets the number of items that are visible in the drop - * down portion of the receiver's list. - * - * @param count the new number of items to be visible - * - * @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 setVisibleItemCount (int count) - { - checkWidget(); - if (count < 0) - return; - visibleItemCount = count; - } - - String stripMnemonic (String String) - { - int index = 0; - int length = String.length(); - do - { - while ((index < length) && (String.charAt(index) !is '&')) - index++; - if (++index >= length) - return String; - if (String.charAt(index) !is '&') - { - return String.substring(0, index - 1) + String.substring(index, - length); + case DWT.MouseWheel: { + Event keyEvent = new Event (); + keyEvent.time = event.time; + keyEvent.keyCode = event.count > 0 ? DWT.ARROW_UP : DWT.ARROW_DOWN; + keyEvent.stateMask = event.stateMask; + notifyListeners (DWT.KeyDown, keyEvent); + if (isDisposed ()) break; + event.doit = keyEvent.doit; + if (!event.doit) break; + if (event.count !is 0) { + event.doit = false; + int oldIndex = getSelectionIndex (); + if (event.count > 0) { + select (Math.max (oldIndex - 1, 0)); + } else { + select (Math.min (oldIndex + 1, getItemCount () - 1)); + } + if (oldIndex !is getSelectionIndex ()) { + Event e = new Event(); + e.time = event.time; + e.stateMask = event.stateMask; + notifyListeners (DWT.Selection, e); + } + if (isDisposed ()) break; } - index++; - } while (index < length); - return String; - } - - void textEvent (Event event) - { - switch (event.type) - { - case DWT.FocusIn: - { - handleFocus(DWT.FocusIn); - break; - } - case DWT.DefaultSelection: - { - dropDown(false); - Event e = new Event(); - e.time = event.time; - e.stateMask = event.stateMask; - notifyListeners(DWT.DefaultSelection, e); - break; - } - case DWT.KeyDown: - { - Event keyEvent = new Event(); - keyEvent.time = event.time; - keyEvent.character = event.character; - keyEvent.keyCode = event.keyCode; - keyEvent.stateMask = event.stateMask; - notifyListeners(DWT.KeyDown, keyEvent); - if (isDisposed()) - break; - event.doit = keyEvent.doit; - if (!event.doit) - break; - if (event.keyCode is DWT.ARROW_UP || event.keyCode is DWT.ARROW_DOWN) - { - event.doit = false; - if ((event.stateMask & DWT.ALT) !is 0) - { - bool dropped = isDropped(); - text.selectAll(); - if (!dropped) - setFocus(); - dropDown(!dropped); - break; - } - - int oldIndex = getSelectionIndex(); - if (event.keyCode is DWT.ARROW_UP) - { - select(Math.max(oldIndex - 1, 0)); - } - else - { - select(Math.min(oldIndex + 1, getItemCount() - 1)); - } - if (oldIndex !is getSelectionIndex()) - { - Event e = new Event(); - e.time = event.time; - e.stateMask = event.stateMask; - notifyListeners(DWT.Selection, e); - } - if (isDisposed()) - break; - } - - // Further work : Need to add support for incremental search in - // pop up list as characters typed in text widget - break; - } - case DWT.KeyUp: - { - Event e = new Event(); - e.time = event.time; - e.character = event.character; - e.keyCode = event.keyCode; - e.stateMask = event.stateMask; - notifyListeners(DWT.KeyUp, e); - event.doit = e.doit; - break; - } - case DWT.MenuDetect: - { - Event e = new Event(); - e.time = event.time; - notifyListeners(DWT.MenuDetect, e); - break; - } - case DWT.Modify: - { - list.deselectAll(); - Event e = new Event(); - e.time = event.time; - notifyListeners(DWT.Modify, e); - break; - } - case DWT.MouseDown: - { - Event mouseEvent = new Event(); - mouseEvent.button = event.button; - mouseEvent.count = event.count; - mouseEvent.stateMask = event.stateMask; - mouseEvent.time = event.time; - mouseEvent.x = event.x; - mouseEvent.y = event.y; - notifyListeners(DWT.MouseDown, mouseEvent); - if (isDisposed()) - break; - event.doit = mouseEvent.doit; - if (!event.doit) - break; - if (event.button !is 1) - return; - if (text.getEditable()) - return; - bool dropped = isDropped(); - text.selectAll(); - if (!dropped) - setFocus(); - dropDown(!dropped); - break; - } - case DWT.MouseUp: - { - Event mouseEvent = new Event(); - mouseEvent.button = event.button; - mouseEvent.count = event.count; - mouseEvent.stateMask = event.stateMask; - mouseEvent.time = event.time; - mouseEvent.x = event.x; - mouseEvent.y = event.y; - notifyListeners(DWT.MouseUp, mouseEvent); - if (isDisposed()) - break; - event.doit = mouseEvent.doit; - if (!event.doit) - break; - if (event.button !is 1) - return; - if (text.getEditable()) - return; - text.selectAll(); - break; - } - case DWT.MouseDoubleClick: - { - Event mouseEvent = new Event(); - mouseEvent.button = event.button; - mouseEvent.count = event.count; - mouseEvent.stateMask = event.stateMask; - mouseEvent.time = event.time; - mouseEvent.x = event.x; - mouseEvent.y = event.y; - notifyListeners(DWT.MouseDoubleClick, mouseEvent); - break; - } - case DWT.MouseWheel: - { - Event keyEvent = new Event(); - keyEvent.time = event.time; - keyEvent.keyCode = event.count > 0 ? DWT.ARROW_UP : DWT.ARROW_DOWN; - keyEvent.stateMask = event.stateMask; - notifyListeners(DWT.KeyDown, keyEvent); - if (isDisposed()) - break; - event.doit = keyEvent.doit; - if (!event.doit) - break; - if (event.count !is 0) - { - event.doit = false; - int oldIndex = getSelectionIndex(); - if (event.count > 0) - { - select(Math.max(oldIndex - 1, 0)); - } - else - { - select(Math.min(oldIndex + 1, getItemCount() - 1)); - } - if (oldIndex !is getSelectionIndex()) - { - Event e = new Event(); - e.time = event.time; - e.stateMask = event.stateMask; - notifyListeners(DWT.Selection, e); - } - if (isDisposed()) - break; - } - break; - } - case DWT.Traverse: - { - switch (event.detail) - { - case DWT.TRAVERSE_ARROW_PREVIOUS: - case DWT.TRAVERSE_ARROW_NEXT: - // The enter causes default selection and - // the arrow keys are used to manipulate the list contents so - // do not use them for traversal. - event.doit = false; - break; - case DWT.TRAVERSE_TAB_PREVIOUS: - event.doit = traverse(DWT.TRAVERSE_TAB_PREVIOUS); - event.detail = DWT.TRAVERSE_NONE; - return; - } - Event e = new Event(); - e.time = event.time; - e.detail = event.detail; - e.doit = event.doit; - e.character = event.character; - e.keyCode = event.keyCode; - notifyListeners(DWT.Traverse, e); - event.doit = e.doit; - event.detail = e.detail; - break; - } - case DWT.Verify: - { - Event e = new Event(); - e.text = event.text; - e.start = event.start; - e.end = event.end; - e.character = event.character; - e.keyCode = event.keyCode; - e.stateMask = event.stateMask; - notifyListeners(DWT.Verify, e); - event.doit = e.doit; - break; - } - - default: break; } + case DWT.Traverse: { + switch (event.detail) { + case DWT.TRAVERSE_ARROW_PREVIOUS: + case DWT.TRAVERSE_ARROW_NEXT: + // The enter causes default selection and + // the arrow keys are used to manipulate the list contents so + // do not use them for traversal. + event.doit = false; + break; + case DWT.TRAVERSE_TAB_PREVIOUS: + event.doit = traverse(DWT.TRAVERSE_TAB_PREVIOUS); + event.detail = DWT.TRAVERSE_NONE; + return; + default: + } + Event e = new Event (); + e.time = event.time; + e.detail = event.detail; + e.doit = event.doit; + e.character = event.character; + e.keyCode = event.keyCode; + notifyListeners (DWT.Traverse, e); + event.doit = e.doit; + event.detail = e.detail; + break; + } + case DWT.Verify: { + Event e = new Event (); + e.text = event.text; + e.start = event.start; + e.end = event.end; + e.character = event.character; + e.keyCode = event.keyCode; + e.stateMask = event.stateMask; + notifyListeners (DWT.Verify, e); + event.doit = e.doit; + break; + } + default: } } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CLabel.d --- a/dwt/custom/CLabel.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CLabel.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,12 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CLabel; + import dwt.DWT; import dwt.DWTException; import dwt.accessibility.ACC; @@ -38,13 +38,15 @@ import dwt.widgets.Composite; import dwt.widgets.Control; import dwt.widgets.Display; +import dwt.dwthelper.utils; -import dwt.dwthelper.utils; +static import tango.text.Unicode; +static import tango.text.convert.Utf; /** * A Label which supports aligned text and/or an image and different border styles. *

    - * If there is not enough space a CLabel uses the following strategy to fit the + * 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
    @@ -59,22 +61,26 @@
      * 
    Events: *
    * - * + * *

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

    + * + * @see DWT Example: CustomControlExample + * @see Sample code and further information */ -public class CLabel : Canvas -{ +public class CLabel : Canvas { + + alias Canvas.computeSize computeSize; /** Gap between icon and text */ private static const int GAP = 5; /** Left and right margins */ private static const int INDENT = 3; - /** a String inserted in the middle of text that has been shortened */ + /** 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; + /** the alignment. Either CENTER, RIGHT, LEFT. Default is LEFT*/ + private int align_ = DWT.LEFT; private int hIndent = INDENT; private int vIndent = INDENT; /** the current text */ @@ -84,7 +90,7 @@ // 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 + // The appToolTip stores the tooltip set by the application. Control.tooltiptext // contains whatever tooltip is currently being displayed. private String appToolTipText; @@ -94,947 +100,750 @@ private bool gradientVertical; private Color background; - private static int - DRAW_FLAGS = DWT.DRAW_MNEMONIC | DWT.DRAW_TAB | DWT.DRAW_TRANSPARENT | DWT.DRAW_DELIMITER; + 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. - *

    - * - * @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#LEFT - * @see DWT#RIGHT - * @see DWT#CENTER - * @see DWT#SHADOW_IN - * @see DWT#SHADOW_OUT - * @see DWT#SHADOW_NONE - * @see #getStyle() - */ - public this (Composite parent, int style) - { - super(parent, checkStyle(style)); - if ((style & (DWT.CENTER | DWT.RIGHT)) is 0) - style |= DWT.LEFT; - if ((style & DWT.CENTER) !is 0) - alignn = DWT.CENTER; - if ((style & DWT.RIGHT) !is 0) - alignn = DWT.RIGHT; - if ((style & DWT.LEFT) !is 0) - alignn = DWT.LEFT; +/** + * 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#LEFT + * @see DWT#RIGHT + * @see DWT#CENTER + * @see DWT#SHADOW_IN + * @see DWT#SHADOW_OUT + * @see DWT#SHADOW_NONE + * @see #getStyle() + */ +public this(Composite parent, int style) { + super(parent, checkStyle(style)); + if ((style & (DWT.CENTER | DWT.RIGHT)) is 0) style |= DWT.LEFT; + if ((style & DWT.CENTER) !is 0) align_ = DWT.CENTER; + if ((style & DWT.RIGHT) !is 0) align_ = DWT.RIGHT; + if ((style & DWT.LEFT) !is 0) align_ = DWT.LEFT; - addPaintListener(new class PaintListener - { - public void paintControl (PaintEvent event) - { - onPaint(event); - } - }); + addPaintListener(new class() PaintListener{ + public void paintControl(PaintEvent event) { + onPaint(event); + } + }); - addDisposeListener(new class DisposeListener - { - public void widgetDisposed (DisposeEvent event) - { - onDispose(event); + addDisposeListener(new class() DisposeListener{ + public void widgetDisposed(DisposeEvent event) { + onDispose(event); + } + }); + + addTraverseListener(new class() TraverseListener { + public void keyTraversed(TraverseEvent event) { + if (event.detail is DWT.TRAVERSE_MNEMONIC) { + onMnemonic(event); } - }); + } + }); + + initAccessible(); - addTraverseListener(new class TraverseListener - { - public void keyTraversed (TraverseEvent event) - { - if (event.detail is DWT.TRAVERSE_MNEMONIC) - { - onMnemonic(event); - } - } - }); - - initAccessible(); - - } +} +/** + * Check the style bits to ensure that no invalid styles are applied. + */ +private static int checkStyle (int style) { + if ((style & DWT.BORDER) !is 0) style |= DWT.SHADOW_IN; + int mask = DWT.SHADOW_IN | DWT.SHADOW_OUT | DWT.SHADOW_NONE | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; + style = style & mask; + return style |= DWT.NO_FOCUS | DWT.DOUBLE_BUFFERED; +} - /** - * Check the style bits to ensure that no invalid styles are applied. - */ - private static int checkStyle (int style) - { - if ((style & DWT.BORDER) !is 0) - style |= DWT.SHADOW_IN; - int - mask = DWT.SHADOW_IN | DWT.SHADOW_OUT | DWT.SHADOW_NONE | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; - style = style & mask; - return style |= DWT.NO_FOCUS | DWT.DOUBLE_BUFFERED; - } - - //protected void checkSubclass () { - // String name = getClass().getName (); - // String validName = CLabel.class.getName(); - // if (!validName.opEquals(name)) { - // DWT.error (DWT.ERROR_INVALID_SUBCLASS); - // } - //} +//protected void checkSubclass () { +// String name = getClass().getName (); +// String validName = CLabel.class.getName(); +// if (!validName.equals(name)) { +// DWT.error (DWT.ERROR_INVALID_SUBCLASS); +// } +//} - public Point computeSize (int wHint, int hHint, bool changed) - { - checkWidget(); - Point e = getTotalSize(image, text); - if (wHint is DWT.DEFAULT) - { - e.x += 2 * hIndent; - } - else - { - e.x = wHint; - } - if (hHint is DWT.DEFAULT) - { - e.y += 2 * vIndent; - } - else - { - e.y = hHint; - } - return e; +public override Point computeSize(int wHint, int hHint, bool changed) { + checkWidget(); + Point e = getTotalSize(image, text); + if (wHint is DWT.DEFAULT){ + e.x += 2*hIndent; + } else { + e.x = wHint; } + if (hHint is DWT.DEFAULT) { + e.y += 2*vIndent; + } else { + e.y = hHint; + } + return e; +} +/** + * Draw a rectangle in the given colors. + */ +private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) { + gc.setForeground(bottomright); + gc.drawLine(x+w, y, x+w, y+h); + gc.drawLine(x, y+h, x+w, y+h); - /** - * Draw a rectangle in the given colors. - */ - private void drawBevelRect (GC gc, int x, int y, int w, int h, - Color topleft, Color bottomright) - { - gc.setForeground(bottomright); - gc.drawLine(x + w, y, x + w, y + h); - gc.drawLine(x, y + h, x + w, y + h); - - gc.setForeground(topleft); - gc.drawLine(x, y, x + w - 1, y); - gc.drawLine(x, y, x, y + h - 1); - } + gc.setForeground(topleft); + gc.drawLine(x, y, x+w-1, y); + gc.drawLine(x, y, x, y+h-1); +} +/* + * Return the lowercase of the first non-'&' character following + * an '&' character in the given string. If there are no '&' + * characters in the given string, return '\0'. + */ +dchar _findMnemonic (String string) { + if (string is null) return '\0'; + int index = 0; + int length = string.length; + do { + while (index < length && string[index] !is '&') index++; + if (++index >= length) return '\0'; + if (string[index] !is '&') { + dchar[1] tmp; uint ate; + dchar[] tmp2 = tango.text.convert.Utf.toString32( string[index .. Math.min( index + 4, string.length ) ], tmp, &ate ); + assert( tmp2.length == 1 ); + return tango.text.Unicode.toLower( tmp2 )[0]; + } + index++; + } while (index < length); + return '\0'; +} +/** + * Returns the alignment. + * The alignment style (LEFT, CENTER or RIGHT) is returned. + * + * @return DWT.LEFT, DWT.RIGHT or DWT.CENTER + */ +public int getAlignment() { + //checkWidget(); + return align_; +} +/** + * Return the CLabel's image or 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); - /* - * Return the lowercase of the first non-'&' character following - * an '&' character in the given String. If there are no '&' - * characters in the given String, return '\0'. - */ - char _findMnemonic (String str) - { - if (str is null) - return '\0'; - int index = 0; - int length = str.length(); - do - { - while (index < length && str.charAt(index) !is '&') - index++; - if (++index >= length) - return '\0'; - if (str.charAt(index) !is '&') - return CharacterToLower(str.charAt(index)); - index++; - } while (index < length); - return '\0'; - } - - /** - * Returns the alignnment. - * The alignnment style (LEFT, CENTER or RIGHT) is returned. - * - * @return DWT.LEFT, DWT.RIGHT or DWT.CENTER - */ - public int getAlignment () - { - //checkWidget(); - return alignn; + if (image !is null) { + Rectangle r = image.getBounds(); + size.x += r.width; + size.y += r.height; } - /** - * Return the CLabel's image or null. - * - * @return the image of the label or null - */ - public Image getImage () - { - //checkWidget(); - return image; + GC gc = new GC(this); + if (text !is null && text.length > 0) { + Point e = gc.textExtent(text, DRAW_FLAGS); + size.x += e.x; + size.y = Math.max(size.y, e.y); + if (image !is null) size.x += GAP; + } else { + size.y = Math.max(size.y, gc.getFontMetrics().getHeight()); } + gc.dispose(); + + return size; +} +public override int getStyle () { + int style = super.getStyle(); + switch (align_) { + case DWT.RIGHT: style |= DWT.RIGHT; break; + case DWT.CENTER: style |= DWT.CENTER; break; + case DWT.LEFT: style |= DWT.LEFT; break; + default: + } + return style; +} - /** - * Compute the minimum size. - */ - private Point getTotalSize (Image image, String text) - { - Point size = new Point(0, 0); +/** + * Return the Label's text. + * + * @return the text of the label or null + */ +public String getText() { + //checkWidget(); + return text; +} +public override String getToolTipText () { + checkWidget(); + return appToolTipText; +} +private void initAccessible() { + Accessible accessible = getAccessible(); + accessible.addAccessibleListener(new class() AccessibleAdapter { + public void getName(AccessibleEvent e) { + e.result = getText(); + } - if (image !is null) - { - Rectangle r = image.getBounds(); - size.x += r.width; - size.y += r.height; + public void getHelp(AccessibleEvent e) { + e.result = getToolTipText(); + } + + public void getKeyboardShortcut(AccessibleEvent e) { + dchar mnemonic = _findMnemonic(this.outer.text); + if (mnemonic !is '\0') { + dchar[1] d; + d[0] = mnemonic; + e.result = "Alt+" ~ tango.text.convert.Utf.toString(d); //$NON-NLS-1$ + } + } + }); + + accessible.addAccessibleControlListener(new class() AccessibleControlAdapter { + public void getChildAtPoint(AccessibleControlEvent e) { + e.childID = ACC.CHILDID_SELF; } - 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; + 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; } - 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; + public void getChildCount(AccessibleControlEvent e) { + e.detail = 0; } - return style; - } + + public void getRole(AccessibleControlEvent e) { + e.detail = ACC.ROLE_LABEL; + } - /** - * 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$ + public void getState(AccessibleControlEvent e) { + e.detail = ACC.STATE_READONLY; + } + }); +} +void onDispose(DisposeEvent event) { + gradientColors = null; + gradientPercents = null; + backgroundImage = null; + text = null; + image = null; + appToolTipText = null; +} +void onMnemonic(TraverseEvent event) { + dchar mnemonic = _findMnemonic(text); + if (mnemonic is '\0') return; + dchar[1] d; uint ate; + auto r = tango.text.convert.Utf.toString32( [event.character][], d, &ate ); + if (tango.text.Unicode.toLower(r)[0] !is mnemonic) return; + Composite control = this.getParent(); + while (control !is null) { + Control [] children = control.getChildren(); + int index = 0; + while (index < children.length) { + if (children [index] is this) break; + index++; + } + index++; + if (index < children.length) { + if (children [index].setFocus ()) { + event.doit = true; + event.detail = DWT.TRAVERSE_NONE; } } - } ); - - accessible.addAccessibleControlListener(new class - AccessibleControlAdapter - { - public void getChildAtPoint (AccessibleControlEvent e) - { - e.childID = ACC.CHILDID_SELF; - } + control = control.getParent(); + } +} - 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 onPaint(PaintEvent event) { + Rectangle rect = getClientArea(); + if (rect.width is 0 || rect.height is 0) return; - 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(); + 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; } } - 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); - 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); + // 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); } } - else - { - super.setToolTipText(appToolTipText); + if (appToolTipText is null) { + super.setToolTipText(text); } - - // 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; - } + } else { + super.setToolTipText(appToolTipText); + } - // 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); + // determine horizontal position + int x = rect.x + hIndent; + if (align_ is DWT.CENTER) { + x = (rect.width - extent.x)/2; + } + if (align_ 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; } - 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; - } + xPos += imageRect.width; + } + } else if (gradientColors !is null) { + // draw a gradient behind the text + final Color oldBackground = gc.getBackground(); + if (gradientColors.length is 1) { + if (gradientColors[0] !is null) gc.setBackground(gradientColors[0]); + gc.fillRectangle(0, 0, rect.width, rect.height); + } else { + final Color oldForeground = gc.getForeground(); + Color lastColor = gradientColors[0]; + if (lastColor is null) lastColor = oldBackground; + int pos = 0; + for (int i = 0; i < gradientPercents.length; ++i) { + gc.setForeground(lastColor); + lastColor = gradientColors[i + 1]; + if (lastColor is null) lastColor = oldBackground; + gc.setBackground(lastColor); + if (gradientVertical) { + final int gradientHeight = (gradientPercents[i] * rect.height / 100) - pos; + gc.fillGradientRectangle(0, pos, rect.width, gradientHeight, true); + pos += gradientHeight; + } else { + final int gradientWidth = (gradientPercents[i] * rect.width / 100) - pos; + gc.fillGradientRectangle(pos, 0, gradientWidth, rect.height, false); + pos += gradientWidth; } - if (gradientVertical && pos < rect.height) - { - gc.setBackground(getBackground()); - gc.fillRectangle(0, pos, rect.width, rect.height - pos); - } - if (!gradientVertical && pos < rect.width) - { - gc.setBackground(getBackground()); - gc.fillRectangle(pos, 0, rect.width - pos, rect.height); - } - gc.setForeground(oldForeground); + } + if (gradientVertical && pos < rect.height) { + gc.setBackground(getBackground()); + gc.fillRectangle(0, pos, rect.width, rect.height - pos); } - gc.setBackground(oldBackground); + if (!gradientVertical && pos < rect.width) { + gc.setBackground(getBackground()); + gc.fillRectangle(pos, 0, rect.width - pos, rect.height); + } + gc.setForeground(oldForeground); } - 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(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 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 image + if (img !is null) { + Rectangle imageRect = img.getBounds(); + gc.drawImage(img, 0, 0, imageRect.width, imageRect.height, + x, (rect.height-imageRect.height)/2, imageRect.width, imageRect.height); + x += imageRect.width + GAP; + extent.x -= imageRect.width + GAP; + } + // draw the text + if (lines !is null) { + int lineHeight = gc.getFontMetrics().getHeight(); + int textHeight = lines.length * lineHeight; + int lineY = Math.max(vIndent, rect.y + (rect.height - textHeight) / 2); + gc.setForeground(getForeground()); + for (int i = 0; i < lines.length; i++) { + int lineX = x; + if (lines.length > 1) { + if (align_ is DWT.CENTER) { + int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x; + lineX = x + Math.max(0, (extent.x - lineWidth) / 2); + } + if (align_ 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; } - // 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 alignment of the CLabel. + * Use the values LEFT, CENTER and RIGHT to align image and text within the available space. + * + * @param align the alignment style of LEFT, RIGHT or CENTER + * + * @exception 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 value of align is not one of DWT.LEFT, DWT.RIGHT or DWT.CENTER
    • + *
    + */ +public void setAlignment(int align_) { + checkWidget(); + if (align_ !is DWT.LEFT && align_ !is DWT.RIGHT && align_ !is DWT.CENTER) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (this.align_ !is align_) { + this.align_ = align_; + redraw(); + } +} + +public override void setBackground (Color color) { + super.setBackground (color); + // Are these settings the same as before? + if (backgroundImage is null && + gradientColors is null && + gradientPercents is null) { + if (color is null) { + if (background is null) return; + } else { + if (color ==/*eq*/ background) return; + } + } + background = color; + backgroundImage = null; + gradientColors = null; + gradientPercents = null; + redraw (); +} + +/** + * Specify a gradient of colours to be drawn in the background of the CLabel. + *

    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
      + *
    • 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 values of colors and percents are not consistent
    • + *
    + */ +public void setBackground(Color[] colors, int[] percents) { + setBackground(colors, percents, false); +} +/** + * Specify a gradient of colours to be drawn in the background of the CLabel. + *

    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
      + *
    • 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 values of colors and percents are not consistent
    • + *
    + * + * @since 3.0 + */ +public void setBackground(Color[] colors, int[] percents, bool vertical) { + checkWidget(); + if (colors !is null) { + if (percents is null || percents.length !is colors.length - 1) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (getDisplay().getDepth() < 15) { + // Don't use gradients on low color displays + colors = [colors[colors.length - 1]]; + percents = null; + } + for (int i = 0; i < percents.length; i++) { + if (percents[i] < 0 || percents[i] > 100) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (i > 0 && percents[i] < percents[i-1]) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); } } } - /** - * 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
      - *
    • 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 value of alignn is not one of DWT.LEFT, DWT.RIGHT or DWT.CENTER
    • - *
    - */ - public void setAlignment (int alignn) - { - checkWidget(); - if (alignn !is DWT.LEFT && alignn !is DWT.RIGHT && alignn !is DWT.CENTER) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (this.alignn !is alignn) - { - this.alignn = alignn; - redraw(); - } - } - - public void setBackground (Color color) - { - super.setBackground(color); - // Are these settings the same as before? - if (backgroundImage is null && gradientColors is null && gradientPercents is null) - { - if (color is null) - { - if (background is null) - return; - } - else - { - if (color.opEquals(background)) - return; + // Are these settings the same as before? + final Color background = getBackground(); + if (backgroundImage is null) { + if ((gradientColors !is null) && (colors !is null) && + (gradientColors.length is colors.length)) { + bool same = false; + for (int i = 0; i < gradientColors.length; i++) { + same = (gradientColors[i] is colors[i]) || + ((gradientColors[i] is null) && (colors[i] is background)) || + ((gradientColors[i] is background) && (colors[i] is null)); + if (!same) break; } - } - background = color; - backgroundImage = null; - gradientColors = null; - gradientPercents = null; - redraw(); - } - - /** - * Specify a gradient of colours to be drawn in the background of the CLabel. - *

    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
      - *
    • 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 values of colors and percents are not consistent
    • - *
    - */ - public void setBackground (Color[] colors, int[] percents) - { - setBackground(colors, percents, false); - } - - /** - * Specify a gradient of colours to be drawn in the background of the CLabel. - *

    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
      - *
    • 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 values of colors and percents are not consistent
    • - *
    - * - * @since 3.0 - */ - public void setBackground (Color[] colors, int[] percents, bool vertical) - { - checkWidget(); - if (colors !is null) - { - if (percents is null || percents.length !is colors.length - 1) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (getDisplay().getDepth() < 15) - { - // Don't use gradients on low color displays - colors = new Color[][colors[colors.length - 1]]; - percents = new int[][]; - } - for (int i = 0; i < percents.length; i++) - { - if (percents[i] < 0 || percents[i] > 100) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (i > 0 && percents[i] < percents[i - 1]) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); + if (same) { + for (int i = 0; i < gradientPercents.length; i++) { + same = gradientPercents[i] is percents[i]; + if (!same) break; } } + if (same && this.gradientVertical is vertical) return; } + } else { + backgroundImage = null; + } + // Store the new settings + if (colors is null) { + gradientColors = null; + gradientPercents = null; + gradientVertical = false; + } else { + gradientColors = new Color[colors.length]; + for (int i = 0; i < colors.length; ++i) + gradientColors[i] = (colors[i] !is null) ? colors[i] : background; + gradientPercents = new int[percents.length]; + for (int i = 0; i < percents.length; ++i) + gradientPercents[i] = percents[i]; + gradientVertical = vertical; + } + // Refresh with the new settings + redraw(); +} +/** + * Set the image to be drawn in the background of the label. + * + * @param image the image to be drawn in the background + * + * @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 setBackground(Image image) { + checkWidget(); + if (image is backgroundImage) return; + if (image !is null) { + gradientColors = null; + gradientPercents = null; + } + backgroundImage = image; + redraw(); - // Are these settings the same as before? - const Color background = getBackground(); - if (backgroundImage is null) - { - if ((gradientColors !is null) && (colors !is null) && (gradientColors.length is colors.length)) - { - bool same = false; - for (int i = 0; i < gradientColors.length; i++) - { - same = (gradientColors[i] is colors[i]) || ((gradientColors[i] is null) && (colors[i] is background)) || ((gradientColors[i] is background) && (colors[i] is null)); - if (!same) - break; - } - if (same) - { - for (int i = 0; i < gradientPercents.length; i++) - { - same = gradientPercents[i] is percents[i]; - if (!same) - break; - } - } - if (same && this.gradientVertical is vertical) - return; - } - } - else - { - backgroundImage = null; - } - // Store the new settings - if (colors is null) - { - gradientColors = null; - gradientPercents = null; - gradientVertical = false; - } - else - { - gradientColors = new Color[colors.length]; - for (int i = 0; i < colors.length; ++i) - gradientColors[i] = (colors[i] !is null) ? colors[i] : background; - gradientPercents = new int[percents.length]; - for (int i = 0; i < percents.length; ++i) - gradientPercents[i] = percents[i]; - gradientVertical = vertical; - } - // Refresh with the new settings +} +public override void setFont(Font font) { + super.setFont(font); + redraw(); +} +/** + * Set the label's Image. + * The value null clears it. + * + * @param image the image to be displayed in the label 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 setImage(Image image) { + checkWidget(); + if (image !is this.image) { + this.image = image; redraw(); } - - /** - * Set the image to be drawn in the background of the label. - * - * @param image the image to be drawn in the background - * - * @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 setBackground (Image image) - { - checkWidget(); - if (image is backgroundImage) - return; - if (image !is null) - { - gradientColors = null; - gradientPercents = null; - } - backgroundImage = image; - redraw(); - - } - - public void setFont (Font font) - { - super.setFont(font); +} +/** + * Set the label's text. + * The value null clears it. + * + * @param text the text to be displayed in the label 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 setText(String text) { + checkWidget(); + if (text is null) text = ""; //$NON-NLS-1$ + if ( text !=/*eq*/ this.text) { + this.text = text; redraw(); } - - /** - * Set the label's Image. - * The value null clears it. - * - * @param image the image to be displayed in the label 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 setImage (Image image) - { - checkWidget(); - if (image !is this.image) - { - this.image = image; - redraw(); +} +public override void setToolTipText (String string) { + super.setToolTipText (string); + appToolTipText = super.getToolTipText(); +} +/** + * Shorten the given text t so that its length doesn't exceed + * the given width. The default implementation replaces characters in the + * center of the original string with an ellipsis ("..."). + * Override if you need a different strategy. + * + * @param gc the gc to use for text measurement + * @param t the text to shorten + * @param width the width to shorten the text to, in pixels + * @return the shortened text + */ +protected String shortenText(GC gc, String t, int width) { + if (t is null) return null; + int w = gc.textExtent(ELLIPSIS, DRAW_FLAGS).x; + if (width<=w) return t; + int l = t.length; + int max = l/2; + int min = 0; + int mid = (max+min)/2 - 1; + if (mid <= 0) return t; + TextLayout layout = new TextLayout (getDisplay()); + layout.setText(t); + mid = validateOffset(layout, mid); + while (min < mid && mid < max) { + String s1 = t[0 .. mid].dup; + String s2 = t.substring(validateOffset(layout, l-mid), l); + int l1 = gc.textExtent(s1, DRAW_FLAGS).x; + int l2 = gc.textExtent(s2, DRAW_FLAGS).x; + if (l1+w+l2 > width) { + max = mid; + mid = validateOffset(layout, (max+min)/2); + } else if (l1+w+l2 < width) { + min = mid; + mid = validateOffset(layout, (max+min)/2); + } else { + min = max; } } - - /** - * Set the label's text. - * The value null clears it. - * - * @param text the text to be displayed in the label 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 setText (String text) - { - checkWidget(); - if (text is null) - text = ""; //$NON-NLS-1$ - if (!text.opEquals(this.text)) - { - this.text = text; - redraw(); + 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 = tango.text.Util.locate( text, '\n', start); + if (pos is text.length ) { + lines[lines.length - 1] = text[start .. $ ]; + } else { + bool crlf = (pos > 0) && (text[ pos - 1 ] is '\r'); + lines[lines.length - 1] = text[ start .. pos - (crlf ? 1 : 0)]; + start = pos + 1; + String[] newLines = new String[lines.length+1]; + System.arraycopy(lines, 0, newLines, 0, lines.length); + lines = newLines; } - } - - public void setToolTipText (String String) - { - super.setToolTipText(String); - appToolTipText = super.getToolTipText(); - } - - /** - * Shorten the given text 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; - } + } while (pos !is text.length); + return lines; } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CLayoutData.d --- a/dwt/custom/CLayoutData.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CLayoutData.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * 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 @@ -7,12 +7,12 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CLayoutData; + import dwt.DWT; import dwt.graphics.Point; import dwt.widgets.Control; @@ -22,29 +22,27 @@ int defaultWidth = -1, defaultHeight = -1; int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1; - Point computeSize (Control control, int wHint, int hHint, bool flushCache) { - if (flushCache) - flushCache(); - if (wHint is DWT.DEFAULT && hHint is DWT.DEFAULT) { - if (defaultWidth is -1 || defaultHeight is -1) { - Point size = control.computeSize(wHint, hHint, flushCache); - defaultWidth = size.x; - defaultHeight = size.y; - } - return new Point(defaultWidth, defaultHeight); +Point computeSize (Control control, int wHint, int hHint, bool flushCache_) { + if (flushCache_) flushCache(); + if (wHint is DWT.DEFAULT && hHint is DWT.DEFAULT) { + if (defaultWidth is -1 || defaultHeight is -1) { + Point size = control.computeSize (wHint, hHint, flushCache_); + defaultWidth = size.x; + defaultHeight = size.y; } - if (currentWidth is -1 || currentHeight is -1 || wHint !is currentWhint || hHint !is currentHhint) { - Point size = control.computeSize(wHint, hHint, flushCache); - currentWhint = wHint; - currentHhint = hHint; - currentWidth = size.x; - currentHeight = size.y; - } - return new Point(currentWidth, currentHeight); + return new Point(defaultWidth, defaultHeight); } - - void flushCache () { - defaultWidth = defaultHeight = -1; - currentWidth = currentHeight = -1; + if (currentWidth is -1 || currentHeight is -1 || wHint !is currentWhint || hHint !is currentHhint) { + Point size = control.computeSize (wHint, hHint, flushCache_); + currentWhint = wHint; + currentHhint = hHint; + currentWidth = size.x; + currentHeight = size.y; } + return new Point(currentWidth, currentHeight); } +void flushCache () { + defaultWidth = defaultHeight = -1; + currentWidth = currentHeight = -1; +} +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CTabFolder.d --- a/dwt/custom/CTabFolder.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CTabFolder.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,9 +7,8 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CTabFolder; @@ -21,9 +20,6 @@ import dwt.accessibility.AccessibleControlAdapter; import dwt.accessibility.AccessibleControlEvent; import dwt.accessibility.AccessibleEvent; -import dwt.custom.CTabFolderListener; -import dwt.custom.CTabFolder2Listener; -import dwt.custom.CTabItem; import dwt.events.SelectionAdapter; import dwt.events.SelectionEvent; import dwt.events.SelectionListener; @@ -45,9 +41,18 @@ import dwt.widgets.Menu; import dwt.widgets.MenuItem; import dwt.widgets.TypedListener; +import dwt.custom.CTabItem; +import dwt.custom.CTabFolder2Listener; +import dwt.custom.CTabFolderListener; +import dwt.custom.CTabFolderLayout; +import dwt.custom.CTabFolderEvent; + +import dwt.dwthelper.utils; +import tango.util.Convert; +static import tango.text.convert.Utf; /** - * + * * Instances of this class implement the notebook user interface * metaphor. It allows the user to select a notebook page from * set of pages. @@ -68,15 +73,18 @@ *
    "CTabFolder2"
    * *

    - * Note: Only one of the styles TOP and BOTTOM + * Note: Only one of the styles TOP and BOTTOM * may be specified. *

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

    + * + * @see CTabFolder, CTabItem snippets + * @see DWT Example: CustomControlExample + * @see Sample code and further information */ -public class CTabFolder : Composite -{ +public class CTabFolder : Composite { /** * marginWidth specifies the number of pixels of horizontal margin @@ -94,43 +102,43 @@ public int marginHeight = 0; /** - * A multiple of the tab height that specifies the minimum width to which a tab + * 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); + public static RGB borderInsideRGB; /** * Color of middle line of drop shadow border. - * + * * NOTE This field is badly named and can not be fixed for backwards compatibility. * It should be capitalized. - * + * * @deprecated drop shadow border is no longer drawn in 3.0 */ - public static RGB borderMiddleRGB = new RGB(143, 141, 138); + public static RGB borderMiddleRGB; /** * Color of outermost line of drop shadow border. - * + * * NOTE This field is badly named and can not be fixed for backwards compatibility. * It should be capitalized. - * + * * @deprecated drop shadow border is no longer drawn in 3.0 */ - public static RGB borderOutsideRGB = new RGB(171, 168, 165); + public static RGB borderOutsideRGB; /* sizing, positioning */ int xClient, yClient; @@ -142,17 +150,17 @@ int minChars = 20; /* item management */ - CTabItem items[] = new CTabItem[0]; + CTabItem items[]; int firstIndex = -1; // index of the left most visible tab. int selectedIndex = -1; - int[] priority = new int[0]; + int[] priority; bool mru = false; Listener listener; /* External Listener management */ - CTabFolder2Listener[] folderListeners = new CTabFolder2Listener[0]; + CTabFolder2Listener[] folderListeners; // support for deprecated listener mechanism - CTabFolderListener[] tabListeners = new CTabFolderListener[0]; + CTabFolderListener[] tabListeners; /* Selected item appearance */ Image selectionBgImage; @@ -160,17 +168,17 @@ int[] selectionGradientPercents; bool selectionGradientVertical; Color selectionForeground; - Color selectionBackground; //selection fade end + Color selectionBackground; //selection fade end Color selectionFadeStart; - Color selectionHighlightGradientBegin = null; //null is no highlight + 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 + Color[] selectionHighlightGradientColorsCache = null; //null is a legal value, check on access /* Unselected item appearance */ Image bgImage; @@ -185,23 +193,23 @@ bool showClose = false; bool showUnselectedClose = true; - Rectangle chevronRect = new Rectangle(0, 0, 0, 0); + Rectangle chevronRect; int chevronImageState = NORMAL; bool showChevron = false; Menu showMenu; bool showMin = false; - Rectangle minRect = new Rectangle(0, 0, 0, 0); + Rectangle minRect; bool minimized = false; int minImageState = NORMAL; bool showMax = false; - Rectangle maxRect = new Rectangle(0, 0, 0, 0); + Rectangle maxRect; bool maximized = false; int maxImageState = NORMAL; Control topRight; - Rectangle topRightRect = new Rectangle(0, 0, 0, 0); + Rectangle topRightRect; int topRightAlignment = DWT.RIGHT; // borders and shapes @@ -219,7 +227,7 @@ int curveWidth = 0; int curveIndent = 0; - // when disposing CTabFolder, don't try to layout the items or + // when disposing CTabFolder, don't try to layout the items or // change the selection as each child is destroyed. bool inDispose = false; @@ -228,53 +236,36 @@ Point oldSize; Font oldFont; - // internal constants + // 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]; + static const int[] TOP_LEFT_CORNER = [0,6, 1,5, 1,4, 4,1, 5,1, 6,0]; - // TOP_LEFT_CORNER_HILITE is laid out in reverse (ie. top to bottom) - // so can fade in same direction as right swoop curve - static const int[] - TOP_LEFT_CORNER_HILITE = new int[][5 , 2 , 4 , 2 , 3 , 3 , 2 , 4 , 2 , 5 , 1 , 6]; + //TOP_LEFT_CORNER_HILITE is laid out in reverse (ie. top to bottom) + //so can fade in same direction as right swoop curve + static const int[] TOP_LEFT_CORNER_HILITE = [5,2, 4,2, 3,3, 2,4, 2,5, 1,6]; - static const int[] - TOP_RIGHT_CORNER = 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[] TOP_RIGHT_CORNER = [-6,0, -5,1, -4,1, -1,4, -1,5, 0,6]; + static const int[] BOTTOM_LEFT_CORNER = [0,-6, 1,-5, 1,-4, 4,-1, 5,-1, 6,0]; + static const int[] BOTTOM_RIGHT_CORNER = [-6,0, -5,-1, -4,-1, -1,-4, -1,-5, 0,-6]; - static const int[] - SIMPLE_TOP_LEFT_CORNER = 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[] SIMPLE_TOP_LEFT_CORNER = [0,2, 1,1, 2,0]; + static const int[] SIMPLE_TOP_RIGHT_CORNER = [-2,0, -1,1, 0,2]; + static const int[] SIMPLE_BOTTOM_LEFT_CORNER = [0,-2, 1,-1, 2,0]; + static const int[] SIMPLE_BOTTOM_RIGHT_CORNER = [-2,0, -1,-1, 0,-2]; + static const int[] SIMPLE_UNSELECTED_INNER_CORNER = [0,0]; - static const int[] - TOP_LEFT_CORNER_BORDERLESS = 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[] TOP_LEFT_CORNER_BORDERLESS = [0,6, 1,5, 1,4, 4,1, 5,1, 6,0]; + static const int[] TOP_RIGHT_CORNER_BORDERLESS = [-7,0, -6,1, -5,1, -2,4, -2,5, -1,6]; + static const int[] BOTTOM_LEFT_CORNER_BORDERLESS = [0,-6, 1,-6, 1,-5, 2,-4, 4,-2, 5,-1, 6,-1, 6,0]; + static const int[] BOTTOM_RIGHT_CORNER_BORDERLESS = [-7,0, -7,-1, -6,-1, -5,-2, -3,-4, -2,-5, -2,-6, -1,-6]; - static const int[] - SIMPLE_TOP_LEFT_CORNER_BORDERLESS = 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[] SIMPLE_TOP_LEFT_CORNER_BORDERLESS = [0,2, 1,1, 2,0]; + static const int[] SIMPLE_TOP_RIGHT_CORNER_BORDERLESS= [-3,0, -2,1, -1,2]; + static const int[] SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS = [0,-3, 1,-2, 2,-1, 3,0]; + static const int[] SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS = [-4,0, -3,-1, -2,-2, -1,-3]; static const int SELECTION_FOREGROUND = DWT.COLOR_LIST_FOREGROUND; static const int SELECTION_BACKGROUND = DWT.COLOR_LIST_BACKGROUND; @@ -288,2414 +279,2013 @@ 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 RGB CLOSE_FILL; static const int CHEVRON_CHILD_ID = 0; static const int MINIMIZE_CHILD_ID = 1; static const int MAXIMIZE_CHILD_ID = 2; static const int EXTRA_CHILD_ID_COUNT = 3; - /** - * 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#TOP - * @see DWT#BOTTOM - * @see DWT#FLAT - * @see DWT#BORDER - * @see DWT#SINGLE - * @see DWT#MULTI - * @see #getStyle() - */ - public this (Composite parent, int style) - { - super(parent, checkStyle(parent, style)); - super.setLayout(new CTabFolderLayout()); - int style2 = super.getStyle(); - oldFont = getFont(); - onBottom = (style2 & DWT.BOTTOM) !is 0; - showClose = (style2 & DWT.CLOSE) !is 0; - // showMin = (style2 & DWT.MIN) !is 0; - conflicts with DWT.TOP - // showMax = (style2 & DWT.MAX) !is 0; - conflicts with DWT.BOTTOM - single = (style2 & DWT.SINGLE) !is 0; - borderLeft = borderRight = (style & DWT.BORDER) !is 0 ? 1 : 0; - borderTop = onBottom ? borderLeft : 0; - borderBottom = onBottom ? 0 : borderLeft; - highlight_header = (style & DWT.FLAT) !is 0 ? 1 : 3; - highlight_margin = (style & DWT.FLAT) !is 0 ? 0 : 2; - //set up default colors - Display display = getDisplay(); - selectionForeground = display.getSystemColor(SELECTION_FOREGROUND); - selectionBackground = display.getSystemColor(SELECTION_BACKGROUND); - borderColor = display.getSystemColor(BORDER1_COLOR); - updateTabHeight(false); - - initAccessible(); - - // Add all listeners - listener = new class Listener - { - public void handleEvent (Event event) - { - switch (event.type) - { - case DWT.Dispose: - onDispose(event); - break; - case DWT.DragDetect: - onDragDetect(event); - break; - case DWT.FocusIn: - onFocus(event); - break; - case DWT.FocusOut: - onFocus(event); - break; - case DWT.KeyDown: - onKeyDown(event); - break; - case DWT.MouseDoubleClick: - onMouseDoubleClick(event); - break; - case DWT.MouseDown: - onMouse(event); - break; - case DWT.MouseEnter: - onMouse(event); - break; - case DWT.MouseExit: - onMouse(event); - break; - case DWT.MouseMove: - onMouse(event); - break; - case DWT.MouseUp: - onMouse(event); - break; - case DWT.Paint: - onPaint(event); - break; - case DWT.Resize: - onResize(); - break; - case DWT.Traverse: - onTraverse(event); - break; - } - } - }; - - int[] - folderEvents = new int[][DWT.Dispose , DWT.DragDetect , DWT.FocusIn , DWT.FocusOut , DWT.KeyDown , DWT.MouseDoubleClick , DWT.MouseDown , DWT.MouseEnter , DWT.MouseExit , DWT.MouseMove , DWT.MouseUp , DWT.Paint , DWT.Resize , DWT.Traverse]; - for (int i = 0; i < folderEvents.length; i++) - { - addListener(folderEvents[i], listener); - } - } - - static int checkStyle (Composite parent, int style) - { - int - mask = DWT.CLOSE | DWT.TOP | DWT.BOTTOM | DWT.FLAT | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT | DWT.SINGLE | DWT.MULTI; - style = style & mask; - // TOP and BOTTOM are mutually exclusive. - // TOP is the default - if ((style & DWT.TOP) !is 0) - style = style & ~DWT.BOTTOM; - // SINGLE and MULTI are mutually exclusive. - // MULTI is the default - if ((style & DWT.MULTI) !is 0) - style = style & ~DWT.SINGLE; - // reduce the flash by not redrawing the entire area on a Resize event - style |= DWT.NO_REDRAW_RESIZE; - //TEMPORARY CODE - /* - * The default background on carbon and some GTK themes is not a solid color - * but a texture. To show the correct default background, we must allow - * the operating system to draw it and therefore, we can not use the - * NO_BACKGROUND style. The NO_BACKGROUND style is not required on platforms - * that use double buffering which is true in both of these cases. - */ - String platform = DWT.getPlatform(); - if ("carbon".opEquals(platform) || "gtk".opEquals(platform)) - return style; //$NON-NLS-1$ //$NON-NLS-2$ - - //TEMPORARY CODE - /* - * In Right To Left orientation on Windows, all GC calls that use a brush are drawing - * offset by one pixel. This results in some parts of the CTabFolder not drawing correctly. - * To alleviate some of the appearance problems, allow the OS to draw the background. - * This does not draw correctly but the result is less obviously wrong. - */ - if ((style & DWT.RIGHT_TO_LEFT) !is 0) - return style; - if ((parent.getStyle() & DWT.MIRRORED) !is 0 && (style & DWT.LEFT_TO_RIGHT) is 0) - return style; - - return style | DWT.NO_BACKGROUND; - } - - static void fillRegion (GC gc, Region region) - { - // NOTE: region passed in to this function will be modified - Region clipping = new Region(); - gc.getClipping(clipping); - region.intersect(clipping); - gc.setClipping(region); - gc.fillRectangle(region.getBounds()); - gc.setClipping(clipping); - clipping.dispose(); - } - - /** - * - * Adds the listener to the collection of listeners who will - * be notified when a tab item is closed, minimized, maximized, - * restored, or to show the list of items that are not - * currently visible. - * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - * - * @see CTabFolder2Listener - * @see #removeCTabFolder2Listener(CTabFolder2Listener) - * - * @since 3.0 - */ - public void addCTabFolder2Listener (CTabFolder2Listener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - // add to array - CTabFolder2Listener[] - newListeners = new CTabFolder2Listener[folderListeners.length + 1]; - System.arraycopy(folderListeners, 0, newListeners, 0, - folderListeners.length); - folderListeners = newListeners; - folderListeners[folderListeners.length - 1] = listener; - } +static this(){ + borderInsideRGB = new RGB (132, 130, 132); + borderMiddleRGB = new RGB (143, 141, 138); + borderOutsideRGB = new RGB (171, 168, 165); + CLOSE_FILL = new RGB(252, 160, 160); +} - /** - * Adds the listener to the collection of listeners who will - * be notified when a tab item is closed. - * - * @param listener the listener which should be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - * - * @see CTabFolderListener - * @see #removeCTabFolderListener(CTabFolderListener) - * - * @deprecated use addCTabFolder2Listener(CTabFolder2Listener) - */ - public void addCTabFolderListener (CTabFolderListener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - // add to array - CTabFolderListener[] - newTabListeners = new CTabFolderListener[tabListeners.length + 1]; - System.arraycopy(tabListeners, 0, newTabListeners, 0, - tabListeners.length); - tabListeners = newTabListeners; - tabListeners[tabListeners.length - 1] = listener; - // display close button to be backwards compatible - if (!showClose) - { - showClose = true; - updateItems(); - redraw(); - } - } - - /** - * Adds the listener to the collection of listeners who will - * be notified when the user changes the receiver's selection, by sending - * it one of the messages defined in the SelectionListener - * interface. - *

    - * widgetSelected is called when the user changes the selected tab. - * widgetDefaultSelected is not called. - *

    - * - * @param listener the listener which should be notified when the user changes the receiver's selection - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception 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 SelectionListener - * @see #removeSelectionListener - * @see SelectionEvent - */ - public void addSelectionListener (SelectionListener listener) - { - checkWidget(); - if (listener is null) - { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } - TypedListener typedListener = new TypedListener(listener); - addListener(DWT.Selection, typedListener); - addListener(DWT.DefaultSelection, typedListener); - } +/** + * 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#TOP + * @see DWT#BOTTOM + * @see DWT#FLAT + * @see DWT#BORDER + * @see DWT#SINGLE + * @see DWT#MULTI + * @see #getStyle() + */ +public this(Composite parent, int style) { + chevronRect = new Rectangle(0, 0, 0, 0); + minRect = new Rectangle(0, 0, 0, 0); + maxRect = new Rectangle(0, 0, 0, 0); + topRightRect = new Rectangle(0, 0, 0, 0); + super(parent, checkStyle (parent, style)); + super.setLayout(new CTabFolderLayout()); + int style2 = super.getStyle(); + oldFont = getFont(); + onBottom = (style2 & DWT.BOTTOM) !is 0; + showClose = (style2 & DWT.CLOSE) !is 0; +// showMin = (style2 & DWT.MIN) !is 0; - conflicts with DWT.TOP +// showMax = (style2 & DWT.MAX) !is 0; - conflicts with DWT.BOTTOM + single = (style2 & DWT.SINGLE) !is 0; + borderLeft = borderRight = (style & DWT.BORDER) !is 0 ? 1 : 0; + borderTop = onBottom ? borderLeft : 0; + borderBottom = onBottom ? 0 : borderLeft; + highlight_header = (style & DWT.FLAT) !is 0 ? 1 : 3; + highlight_margin = (style & DWT.FLAT) !is 0 ? 0 : 2; + //set up default colors + Display display = getDisplay(); + selectionForeground = display.getSystemColor(SELECTION_FOREGROUND); + selectionBackground = display.getSystemColor(SELECTION_BACKGROUND); + borderColor = display.getSystemColor(BORDER1_COLOR); + updateTabHeight(false); - void antialias (int[] shape, RGB lineRGB, RGB innerRGB, RGB outerRGB, GC gc) - { - // Don't perform anti-aliasing on Mac and WPF because the platform - // already does it. The simple style also does not require anti-aliasing. - if (simple || "carbon".opEquals(DWT.getPlatform()) || "wpf".opEquals( - DWT.getPlatform())) - return; //$NON-NLS-1$ - // Don't perform anti-aliasing on low resolution displays - if (getDisplay().getDepth() < 15) - return; - if (outerRGB !is null) - { - int index = 0; - bool left = true; - int oldY = onBottom ? 0 : getSize().y; - int[] outer = new int[shape.length]; - for (int i = 0; i < shape.length / 2; i++) - { - if (left && (index + 3 < shape.length)) - { - left = onBottom ? oldY <= shape[index + 3] : oldY >= shape[index + 3]; - oldY = shape[index + 1]; - } - outer[index] = shape[index++] + (left ? -1 : +1); - outer[index] = shape[index++]; - } - RGB from = lineRGB; - RGB to = outerRGB; - int red = from.red + 2 * (to.red - from.red) / 3; - int green = from.green + 2 * (to.green - from.green) / 3; - int blue = from.blue + 2 * (to.blue - from.blue) / 3; - Color color = new Color(getDisplay(), red, green, blue); - gc.setForeground(color); - gc.drawPolyline(outer); - color.dispose(); - } - if (innerRGB !is null) - { - int[] inner = new int[shape.length]; - int index = 0; - bool left = true; - int oldY = onBottom ? 0 : getSize().y; - for (int i = 0; i < shape.length / 2; i++) - { - if (left && (index + 3 < shape.length)) - { - left = onBottom ? oldY <= shape[index + 3] : oldY >= shape[index + 3]; - oldY = shape[index + 1]; - } - inner[index] = shape[index++] + (left ? +1 : -1); - inner[index] = shape[index++]; - } - RGB from = lineRGB; - RGB to = innerRGB; - int red = from.red + 2 * (to.red - from.red) / 3; - int green = from.green + 2 * (to.green - from.green) / 3; - int blue = from.blue + 2 * (to.blue - from.blue) / 3; - Color color = new Color(getDisplay(), red, green, blue); - gc.setForeground(color); - gc.drawPolyline(inner); - color.dispose(); - } - } - - public Rectangle computeTrim (int x, int y, int width, int height) - { - checkWidget(); - int trimX = x - marginWidth - highlight_margin - borderLeft; - int - trimWidth = width + borderLeft + borderRight + 2 * marginWidth + 2 * highlight_margin; - if (minimized) - { - int - trimY = onBottom ? y - borderTop : y - highlight_header - tabHeight - borderTop; - int - trimHeight = borderTop + borderBottom + tabHeight + highlight_header; - return new Rectangle(trimX, trimY, trimWidth, trimHeight); - } - else - { - int - trimY = onBottom ? y - marginHeight - highlight_margin - borderTop : y - marginHeight - highlight_header - tabHeight - borderTop; - int - trimHeight = height + borderTop + borderBottom + 2 * marginHeight + tabHeight + highlight_header + highlight_margin; - return new Rectangle(trimX, trimY, trimWidth, trimHeight); - } - } + initAccessible(); - void createItem (CTabItem item, int index) - { - if (0 > index || index > getItemCount()) - DWT.error(DWT.ERROR_INVALID_RANGE); - item.parent = this; - CTabItem[] newItems = new CTabItem[items.length + 1]; - System.arraycopy(items, 0, newItems, 0, index); - newItems[index] = item; - System.arraycopy(items, index, newItems, index + 1, - items.length - index); - items = newItems; - if (selectedIndex >= index) - selectedIndex++; - int[] newPriority = new int[priority.length + 1]; - int next = 0, priorityIndex = priority.length; - for (int i = 0; i < priority.length; i++) - { - if (!mru && priority[i] is index) - { - priorityIndex = next++; - } - newPriority[next++] = priority[i] >= index ? priority[i] + 1 : priority[i]; - } - newPriority[priorityIndex] = index; - priority = newPriority; - - if (items.length is 1) - { - if (!updateTabHeight(false)) - updateItems(); - redraw(); - } - else - { - updateItems(); - redrawTabs(); - } - } - - void destroyItem (CTabItem item) - { - if (inDispose) - return; - int index = indexOf(item); - if (index is -1) - return; - - if (items.length is 1) - { - items = new CTabItem[0]; - priority = new int[0]; - firstIndex = -1; - selectedIndex = -1; - - Control control = item.getControl(); - if (control !is null && !control.isDisposed()) - { - control.setVisible(false); - } - setToolTipText(null); - setButtonBounds(); - redraw(); - return; - } - - CTabItem[] newItems = new CTabItem[items.length - 1]; - System.arraycopy(items, 0, newItems, 0, index); - System.arraycopy(items, index + 1, newItems, index, - items.length - index - 1); - items = newItems; - - int[] newPriority = new int[priority.length - 1]; - int next = 0; - for (int i = 0; i < priority.length; i++) - { - if (priority[i] is index) - continue; - newPriority[next++] = priority[i] > index ? priority[i] - 1 : priority[i]; - } - priority = newPriority; - - // move the selection if this item is selected - if (selectedIndex is index) - { - Control control = item.getControl(); - selectedIndex = -1; - int nextSelection = mru ? priority[0] : Math.max(0, index - 1); - setSelection(nextSelection, true); - if (control !is null && !control.isDisposed()) - { - control.setVisible(false); + // Add all listeners + listener = new class() Listener { + public void handleEvent(Event event) { + switch (event.type) { + case DWT.Dispose: onDispose(event); break; + case DWT.DragDetect: onDragDetect(event); break; + case DWT.FocusIn: onFocus(event); break; + case DWT.FocusOut: onFocus(event); break; + case DWT.KeyDown: onKeyDown(event); break; + case DWT.MouseDoubleClick: onMouseDoubleClick(event); break; + case DWT.MouseDown: onMouse(event); break; + case DWT.MouseEnter: onMouse(event); break; + case DWT.MouseExit: onMouse(event); break; + case DWT.MouseMove: onMouse(event); break; + case DWT.MouseUp: onMouse(event); break; + case DWT.Paint: onPaint(event); break; + case DWT.Resize: onResize(); break; + case DWT.Traverse: onTraverse(event); break; + default: } } - else if (selectedIndex > index) - { - selectedIndex--; + }; + + int[] folderEvents = [ + DWT.Dispose, + DWT.DragDetect, + DWT.FocusIn, + DWT.FocusOut, + DWT.KeyDown, + DWT.MouseDoubleClick, + DWT.MouseDown, + DWT.MouseEnter, + DWT.MouseExit, + DWT.MouseMove, + DWT.MouseUp, + DWT.Paint, + DWT.Resize, + DWT.Traverse, + ]; + for (int i = 0; i < folderEvents.length; i++) { + addListener(folderEvents[i], listener); + } +} +static int checkStyle (Composite parent, int style) { + int mask = DWT.CLOSE | DWT.TOP | DWT.BOTTOM | DWT.FLAT | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT | DWT.SINGLE | DWT.MULTI; + style = style & mask; + // TOP and BOTTOM are mutually exclusive. + // TOP is the default + if ((style & DWT.TOP) !is 0) style = style & ~DWT.BOTTOM; + // SINGLE and MULTI are mutually exclusive. + // MULTI is the default + if ((style & DWT.MULTI) !is 0) style = style & ~DWT.SINGLE; + // reduce the flash by not redrawing the entire area on a Resize event + style |= DWT.NO_REDRAW_RESIZE; + //TEMPORARY CODE + /* + * The default background on carbon and some GTK themes is not a solid color + * but a texture. To show the correct default background, we must allow + * the operating system to draw it and therefore, we can not use the + * NO_BACKGROUND style. The NO_BACKGROUND style is not required on platforms + * that use double buffering which is true in both of these cases. + */ + String platform = DWT.getPlatform(); + if ("carbon"==platform || "gtk"==platform) return style; //$NON-NLS-1$ //$NON-NLS-2$ + + //TEMPORARY CODE + /* + * In Right To Left orientation on Windows, all GC calls that use a brush are drawing + * offset by one pixel. This results in some parts of the CTabFolder not drawing correctly. + * To alleviate some of the appearance problems, allow the OS to draw the background. + * This does not draw correctly but the result is less obviously wrong. + */ + if ((style & DWT.RIGHT_TO_LEFT) !is 0) return style; + if ((parent.getStyle() & DWT.MIRRORED) !is 0 && (style & DWT.LEFT_TO_RIGHT) is 0) return style; + + return style | DWT.NO_BACKGROUND; +} +static void fillRegion(GC gc, Region region) { + // NOTE: region passed in to this function will be modified + Region clipping = new Region(); + gc.getClipping(clipping); + region.intersect(clipping); + gc.setClipping(region); + gc.fillRectangle(region.getBounds()); + gc.setClipping(clipping); + clipping.dispose(); +} +/** + * + * Adds the listener to the collection of listeners who will + * be notified when a tab item is closed, minimized, maximized, + * restored, or to show the list of items that are not + * currently visible. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + * + * @see CTabFolder2Listener + * @see #removeCTabFolder2Listener(CTabFolder2Listener) + * + * @since 3.0 + */ +public void addCTabFolder2Listener(CTabFolder2Listener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + // add to array + CTabFolder2Listener[] newListeners = new CTabFolder2Listener[folderListeners.length + 1]; + SimpleType!(CTabFolder2Listener).arraycopy(folderListeners, 0, newListeners, 0, folderListeners.length); + folderListeners = newListeners; + folderListeners[folderListeners.length - 1] = listener; +} +/** + * Adds the listener to the collection of listeners who will + * be notified when a tab item is closed. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + * + * @see CTabFolderListener + * @see #removeCTabFolderListener(CTabFolderListener) + * + * @deprecated use addCTabFolder2Listener(CTabFolder2Listener) + */ +public void addCTabFolderListener(CTabFolderListener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + // add to array + CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length + 1]; + SimpleType!(CTabFolderListener).arraycopy(tabListeners, 0, newTabListeners, 0, tabListeners.length); + tabListeners = newTabListeners; + tabListeners[tabListeners.length - 1] = listener; + // display close button to be backwards compatible + if (!showClose) { + showClose = true; + updateItems(); + redraw(); + } +} +/** + * Adds the listener to the collection of listeners who will + * be notified when the user changes the receiver's selection, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the user changes the selected tab. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified when the user changes the receiver's selection + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception 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 SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener is null) { + DWT.error(DWT.ERROR_NULL_ARGUMENT); + } + TypedListener typedListener = new TypedListener(listener); + addListener(DWT.Selection, typedListener); + addListener(DWT.DefaultSelection, typedListener); +} +void antialias (int[] shape, RGB lineRGB, RGB innerRGB, RGB outerRGB, GC gc){ + // Don't perform anti-aliasing on Mac and WPF because the platform + // already does it. The simple style also does not require anti-aliasing. + if (simple || "carbon".equals(DWT.getPlatform()) || "wpf".equals(DWT.getPlatform())) return; //$NON-NLS-1$ + // Don't perform anti-aliasing on low resolution displays + if (getDisplay().getDepth() < 15) return; + if (outerRGB !is null) { + int index = 0; + bool left = true; + int oldY = onBottom ? 0 : getSize().y; + int[] outer = new int[shape.length]; + for (int i = 0; i < shape.length/2; i++) { + if (left && (index + 3 < shape.length)) { + left = onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3]; + oldY = shape[index+1]; + } + outer[index] = shape[index] + (left ? -1 : +1); + index++; + outer[index] = shape[index]; + index++; } + RGB from = lineRGB; + RGB to = outerRGB; + int red = from.red + 2*(to.red - from.red)/3; + int green = from.green + 2*(to.green - from.green)/3; + int blue = from.blue + 2*(to.blue - from.blue)/3; + Color color = new Color(getDisplay(), red, green, blue); + gc.setForeground(color); + gc.drawPolyline(outer); + color.dispose(); + } + if (innerRGB !is null) { + int[] inner = new int[shape.length]; + int index = 0; + bool left = true; + int oldY = onBottom ? 0 : getSize().y; + for (int i = 0; i < shape.length/2; i++) { + if (left && (index + 3 < shape.length)) { + left = onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3]; + oldY = shape[index+1]; + } + inner[index] = shape[index] + (left ? +1 : -1); + index++; + inner[index] = shape[index]; + index++; + } + RGB from = lineRGB; + RGB to = innerRGB; + int red = from.red + 2*(to.red - from.red)/3; + int green = from.green + 2*(to.green - from.green)/3; + int blue = from.blue + 2*(to.blue - from.blue)/3; + Color color = new Color(getDisplay(), red, green, blue); + gc.setForeground(color); + gc.drawPolyline(inner); + color.dispose(); + } +} +public override Rectangle computeTrim (int x, int y, int width, int height) { + checkWidget(); + int trimX = x - marginWidth - highlight_margin - borderLeft; + int trimWidth = width + borderLeft + borderRight + 2*marginWidth + 2*highlight_margin; + if (minimized) { + int trimY = onBottom ? y - borderTop : y - highlight_header - tabHeight - borderTop; + int trimHeight = borderTop + borderBottom + tabHeight + highlight_header; + return new Rectangle (trimX, trimY, trimWidth, trimHeight); + } else { + int trimY = onBottom ? y - marginHeight - highlight_margin - borderTop: y - marginHeight - highlight_header - tabHeight - borderTop; + int trimHeight = height + borderTop + borderBottom + 2*marginHeight + tabHeight + highlight_header + highlight_margin; + return new Rectangle (trimX, trimY, trimWidth, trimHeight); + } +} +void createItem (CTabItem item, int index) { + if (0 > index || index > getItemCount ())DWT.error (DWT.ERROR_INVALID_RANGE); + item.parent = this; + CTabItem[] newItems = new CTabItem [items.length + 1]; + System.arraycopy(items, 0, newItems, 0, index); + newItems[index] = item; + System.arraycopy(items, index, newItems, index + 1, items.length - index); + items = newItems; + if (selectedIndex >= index) selectedIndex ++; + int[] newPriority = new int[priority.length + 1]; + int next = 0, priorityIndex = priority.length; + for (int i = 0; i < priority.length; i++) { + if (!mru && priority[i] is index) { + priorityIndex = next++; + } + newPriority[next++] = priority[i] >= index ? priority[i] + 1 : priority[i]; + } + newPriority[priorityIndex] = index; + priority = newPriority; + if (items.length is 1) { + if (!updateTabHeight(false)) updateItems(); + redraw(); + } else { updateItems(); redrawTabs(); } +} +void destroyItem (CTabItem item) { + if (inDispose) return; + int index = indexOf(item); + if (index is -1) return; - void drawBackground (GC gc, int[] shape, bool selected) - { - Color - defaultBackground = selected ? selectionBackground : getBackground(); - Image image = selected ? selectionBgImage : bgImage; - Color[] colors = selected ? selectionGradientColors : gradientColors; - int[] - percents = selected ? selectionGradientPercents : gradientPercents; - bool vertical = selected ? selectionGradientVertical : gradientVertical; - Point size = getSize(); - int width = size.x; - int height = tabHeight + highlight_header; - int x = 0; - if (borderLeft > 0) - { - x += 1; - width -= 2; + if (items.length is 1) { + items = new CTabItem[0]; + priority = new int[0]; + firstIndex = -1; + selectedIndex = -1; + + Control control = item.getControl(); + if (control !is null && !control.isDisposed()) { + control.setVisible(false); } - int y = onBottom ? size.y - borderBottom - height : borderTop; - drawBackground(gc, shape, x, y, width, height, defaultBackground, - image, colors, percents, vertical); + setToolTipText(null); + setButtonBounds(); + redraw(); + return; + } + + CTabItem[] newItems = new CTabItem [items.length - 1]; + System.arraycopy(items, 0, newItems, 0, index); + System.arraycopy(items, index + 1, newItems, index, items.length - index - 1); + items = newItems; + + int[] newPriority = new int[priority.length - 1]; + int next = 0; + for (int i = 0; i < priority.length; i++) { + if (priority [i] is index) continue; + newPriority[next++] = priority[i] > index ? priority[i] - 1 : priority [i]; + } + priority = newPriority; + + // move the selection if this item is selected + if (selectedIndex is index) { + Control control = item.getControl(); + selectedIndex = -1; + int nextSelection = mru ? priority[0] : Math.max(0, index - 1); + setSelection(nextSelection, true); + if (control !is null && !control.isDisposed()) { + control.setVisible(false); + } + } else if (selectedIndex > index) { + selectedIndex --; } - void drawBackground (GC gc, int[] shape, int x, int y, int width, - int height, Color defaultBackground, Image image, Color[] colors, - int[] percents, bool vertical) - { - Region clipping = new Region(); - gc.getClipping(clipping); - Region region = new Region(); - region.add(shape); - region.intersect(clipping); - gc.setClipping(region); + updateItems(); + redrawTabs(); +} +void drawBackground(GC gc, int[] shape, bool selected) { + Color defaultBackground = selected ? selectionBackground : getBackground(); + Image image = selected ? selectionBgImage : bgImage; + Color[] colors = selected ? selectionGradientColors : gradientColors; + int[] percents = selected ? selectionGradientPercents : gradientPercents; + bool vertical = selected ? selectionGradientVertical : gradientVertical; + Point size = getSize(); + int width = size.x; + int height = tabHeight + highlight_header; + int x = 0; + if (borderLeft > 0) { + x += 1; width -= 2; + } + int y = onBottom ? size.y - borderBottom - height : borderTop; + drawBackground(gc, shape, x, y, width, height, defaultBackground, image, colors, percents, vertical); +} +void drawBackground(GC gc, int[] shape, int x, int y, int width, int height, Color defaultBackground, Image image, Color[] colors, int[] percents, bool vertical) { + Region clipping = new Region(); + gc.getClipping(clipping); + Region region = new Region(); + region.add(shape); + region.intersect(clipping); + gc.setClipping(region); - if (image !is null) - { - // draw the background image in shape - gc.setBackground(defaultBackground); + if (image !is null) { + // draw the background image in shape + gc.setBackground(defaultBackground); + gc.fillRectangle(x, y, width, height); + Rectangle imageRect = image.getBounds(); + gc.drawImage(image, imageRect.x, imageRect.y, imageRect.width, imageRect.height, x, y, width, height); + } else if (colors !is null) { + // draw gradient + if (colors.length is 1) { + Color background = colors[0] !is null ? colors[0] : defaultBackground; + gc.setBackground(background); gc.fillRectangle(x, y, width, height); - Rectangle imageRect = image.getBounds(); - gc.drawImage(image, imageRect.x, imageRect.y, imageRect.width, - imageRect.height, x, y, width, height); - } - else if (colors !is null) - { - // draw gradient - if (colors.length is 1) - { - Color - background = colors[0] !is null ? colors[0] : defaultBackground; - gc.setBackground(background); - gc.fillRectangle(x, y, width, height); - } - else - { - if (vertical) - { - if (onBottom) - { - int pos = 0; - if (percents[percents.length - 1] < 100) - { - pos = percents[percents.length - 1] * height / 100; - gc.setBackground(defaultBackground); - gc.fillRectangle(x, y, width, pos); - } - Color lastColor = colors[colors.length - 1]; - if (lastColor is null) - lastColor = defaultBackground; - for (int i = percents.length - 1; i >= 0; i--) - { - gc.setForeground(lastColor); - lastColor = colors[i]; - if (lastColor is null) - lastColor = defaultBackground; - gc.setBackground(lastColor); - int gradientHeight = percents[i] * height / 100; - gc.fillGradientRectangle(x, y + pos, width, - gradientHeight, true); - pos += gradientHeight; - } + } else { + if (vertical) { + if (onBottom) { + int pos = 0; + if (percents[percents.length - 1] < 100) { + pos = percents[percents.length - 1] * height / 100; + gc.setBackground(defaultBackground); + gc.fillRectangle(x, y, width, pos); } - else - { - Color lastColor = colors[0]; - if (lastColor is null) - lastColor = defaultBackground; - int pos = 0; - for (int i = 0; i < percents.length; i++) - { - gc.setForeground(lastColor); - lastColor = colors[i + 1]; - if (lastColor is null) - lastColor = defaultBackground; - gc.setBackground(lastColor); - int gradientHeight = percents[i] * height / 100; - gc.fillGradientRectangle(x, y + pos, width, - gradientHeight, true); - pos += gradientHeight; - } - if (pos < height) - { - gc.setBackground(defaultBackground); - gc.fillRectangle(x, pos, width, height - pos + 1); - } + Color lastColor = colors[colors.length-1]; + if (lastColor is null) lastColor = defaultBackground; + for (int i = percents.length-1; i >= 0; i--) { + gc.setForeground(lastColor); + lastColor = colors[i]; + if (lastColor is null) lastColor = defaultBackground; + gc.setBackground(lastColor); + int gradientHeight = percents[i] * height / 100; + gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true); + pos += gradientHeight; + } + } else { + Color lastColor = colors[0]; + if (lastColor is null) lastColor = defaultBackground; + int pos = 0; + for (int i = 0; i < percents.length; i++) { + gc.setForeground(lastColor); + lastColor = colors[i + 1]; + if (lastColor is null) lastColor = defaultBackground; + gc.setBackground(lastColor); + int gradientHeight = percents[i] * height / 100; + gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true); + pos += gradientHeight; + } + if (pos < height) { + gc.setBackground(defaultBackground); + gc.fillRectangle(x, pos, width, height-pos+1); } } - else - { //horizontal gradient - y = 0; - height = getSize().y; - Color lastColor = colors[0]; - if (lastColor is null) - lastColor = defaultBackground; - int pos = 0; - for (int i = 0; i < percents.length; ++i) - { - gc.setForeground(lastColor); - lastColor = colors[i + 1]; - if (lastColor is null) - lastColor = defaultBackground; - gc.setBackground(lastColor); - int gradientWidth = (percents[i] * width / 100) - pos; - gc.fillGradientRectangle(x + pos, y, gradientWidth, - height, false); - pos += gradientWidth; - } - if (pos < width) - { - gc.setBackground(defaultBackground); - gc.fillRectangle(x + pos, y, width - pos, height); - } + } else { //horizontal gradient + y = 0; + height = getSize().y; + Color lastColor = colors[0]; + if (lastColor is null) lastColor = defaultBackground; + int pos = 0; + for (int i = 0; i < percents.length; ++i) { + gc.setForeground(lastColor); + lastColor = colors[i + 1]; + if (lastColor is null) lastColor = defaultBackground; + gc.setBackground(lastColor); + int gradientWidth = (percents[i] * width / 100) - pos; + gc.fillGradientRectangle(x+pos, y, gradientWidth, height, false); + pos += gradientWidth; + } + if (pos < width) { + gc.setBackground(defaultBackground); + gc.fillRectangle(x+pos, y, width-pos, height); } } } - else - { - // draw a solid background using default background in shape - if ((getStyle() & DWT.NO_BACKGROUND) !is 0 || !defaultBackground.opEquals( - getBackground())) - { - gc.setBackground(defaultBackground); - gc.fillRectangle(x, y, width, height); + } else { + // draw a solid background using default background in shape + if ((getStyle() & DWT.NO_BACKGROUND) !is 0 || defaultBackground!=getBackground()) { + gc.setBackground(defaultBackground); + gc.fillRectangle(x, y, width, height); + } + } + gc.setClipping(clipping); + clipping.dispose(); + region.dispose(); +} +void drawBody(Event event) { + GC gc = event.gc; + Point size = getSize(); + + // fill in body + if (!minimized){ + int width = size.x - borderLeft - borderRight - 2*highlight_margin; + int height = size.y - borderTop - borderBottom - tabHeight - highlight_header - highlight_margin; + // Draw highlight margin + if (highlight_margin > 0) { + int[] shape = null; + if (onBottom) { + int x1 = borderLeft; + int y1 = borderTop; + int x2 = size.x - borderRight; + int y2 = size.y - borderBottom - tabHeight - highlight_header; + shape = [x1,y1, x2,y1, x2,y2, x2-highlight_margin,y2, + x2-highlight_margin, y1+highlight_margin, x1+highlight_margin,y1+highlight_margin, + x1+highlight_margin,y2, x1,y2]; + } else { + int x1 = borderLeft; + int y1 = borderTop + tabHeight + highlight_header; + int x2 = size.x - borderRight; + int y2 = size.y - borderBottom; + shape = [x1,y1, x1+highlight_margin,y1, x1+highlight_margin,y2-highlight_margin, + x2-highlight_margin,y2-highlight_margin, x2-highlight_margin,y1, + x2,y1, x2,y2, x1,y2]; + } + // If horizontal gradient, show gradient across the whole area + if (selectedIndex !is -1 && selectionGradientColors !is null && selectionGradientColors.length > 1 && !selectionGradientVertical) { + drawBackground(gc, shape, true); + } else if (selectedIndex is -1 && gradientColors !is null && gradientColors.length > 1 && !gradientVertical) { + drawBackground(gc, shape, false); + } else { + gc.setBackground(selectedIndex is -1 ? getBackground() : selectionBackground); + gc.fillPolygon(shape); } } - gc.setClipping(clipping); - clipping.dispose(); - region.dispose(); - } - - void drawBody (Event event) - { - GC gc = event.gc; - Point size = getSize(); - - // fill in body - if (!minimized) - { - int - width = size.x - borderLeft - borderRight - 2 * highlight_margin; - int - height = size.y - borderTop - borderBottom - tabHeight - highlight_header - highlight_margin; - // Draw highlight margin - if (highlight_margin > 0) - { - int[] shape = null; - if (onBottom) - { - int x1 = borderLeft; - int y1 = borderTop; - int x2 = size.x - borderRight; - int - y2 = size.y - borderBottom - tabHeight - highlight_header; - shape = new int[][x1 , y1 , x2 , y1 , x2 , y2 , x2 - highlight_margin , y2 , x2 - highlight_margin , y1 + highlight_margin , x1 + highlight_margin , y1 + highlight_margin , x1 + highlight_margin , y2 , x1 , y2]; - } - else - { - int x1 = borderLeft; - int y1 = borderTop + tabHeight + highlight_header; - int x2 = size.x - borderRight; - int y2 = size.y - borderBottom; - shape = new int[][x1 , y1 , x1 + highlight_margin , y1 , x1 + highlight_margin , y2 - highlight_margin , x2 - highlight_margin , y2 - highlight_margin , x2 - highlight_margin , y1 , x2 , y1 , x2 , y2 , x1 , y2]; - } - // If horizontal gradient, show gradient across the whole area - if (selectedIndex !is -1 && selectionGradientColors !is null && selectionGradientColors.length > 1 && !selectionGradientVertical) - { - drawBackground(gc, shape, true); - } - else if (selectedIndex is -1 && gradientColors !is null && gradientColors.length > 1 && !gradientVertical) - { - drawBackground(gc, shape, false); - } - else - { - gc.setBackground( - selectedIndex is -1 ? getBackground() : selectionBackground); - gc.fillPolygon(shape); - } - } - //Draw client area - if ((getStyle() & DWT.NO_BACKGROUND) !is 0) - { - gc.setBackground(getBackground()); - gc.fillRectangle(xClient - marginWidth, yClient - marginHeight, - width, height); - } + //Draw client area + if ((getStyle() & DWT.NO_BACKGROUND) !is 0) { + gc.setBackground(getBackground()); + gc.fillRectangle(xClient - marginWidth, yClient - marginHeight, width, height); } - else - { - if ((getStyle() & DWT.NO_BACKGROUND) !is 0) - { - int - height = borderTop + tabHeight + highlight_header + borderBottom; - if (size.y > height) - { - gc.setBackground(getParent().getBackground()); - gc.fillRectangle(0, height, size.x, size.y - height); - } - } - } - - //draw 1 pixel border around outside - if (borderLeft > 0) - { - gc.setForeground(borderColor); - int x1 = borderLeft - 1; - int x2 = size.x - borderRight; - int y1 = onBottom ? borderTop - 1 : borderTop + tabHeight; - int - y2 = onBottom ? size.y - tabHeight - borderBottom - 1 : size.y - borderBottom; - gc.drawLine(x1, y1, x1, y2); // left - gc.drawLine(x2, y1, x2, y2); // right - if (onBottom) - { - gc.drawLine(x1, y1, x2, y1); // top - } - else - { - gc.drawLine(x1, y2, x2, y2); // bottom + } else { + if ((getStyle() & DWT.NO_BACKGROUND) !is 0) { + int height = borderTop + tabHeight + highlight_header + borderBottom; + if (size.y > height) { + gc.setBackground(getParent().getBackground()); + gc.fillRectangle(0, height, size.x, size.y - height); } } } - void drawChevron (GC gc) - { - if (chevronRect.width is 0 || chevronRect.height is 0) - return; - // draw chevron (10x7) - Display display = getDisplay(); - Point dpi = display.getDPI(); - int fontHeight = 72 * 10 / dpi.y; - FontData fd = getFont().getFontData()[0]; - fd.setHeight(fontHeight); - Font f = new Font(display, fd); - int fHeight = f.getFontData()[0].getHeight() * dpi.y / 72; - int indent = Math.max(2, (chevronRect.height - fHeight - 4) / 2); - int x = chevronRect.x + 2; - int y = chevronRect.y + indent; - int count; - if (single) - { - count = selectedIndex is -1 ? items.length : items.length - 1; + //draw 1 pixel border around outside + if (borderLeft > 0) { + gc.setForeground(borderColor); + int x1 = borderLeft - 1; + int x2 = size.x - borderRight; + int y1 = onBottom ? borderTop - 1 : borderTop + tabHeight; + int y2 = onBottom ? size.y - tabHeight - borderBottom - 1 : size.y - borderBottom; + gc.drawLine(x1, y1, x1, y2); // left + gc.drawLine(x2, y1, x2, y2); // right + if (onBottom) { + gc.drawLine(x1, y1, x2, y1); // top + } else { + gc.drawLine(x1, y2, x2, y2); // bottom + } + } +} + +void drawChevron(GC gc) { + if (chevronRect.width is 0 || chevronRect.height is 0) return; + // draw chevron (10x7) + Display display = getDisplay(); + Point dpi = display.getDPI(); + int fontHeight = 72 * 10 / dpi.y; + FontData fd = getFont().getFontData()[0]; + fd.setHeight(fontHeight); + Font f = new Font(display, fd); + int fHeight = f.getFontData()[0].getHeight() * dpi.y / 72; + int indent = Math.max(2, (chevronRect.height - fHeight - 4) /2); + int x = chevronRect.x + 2; + int y = chevronRect.y + indent; + int count; + if (single) { + count = selectedIndex is -1 ? items.length : items.length - 1; + } else { + int showCount = 0; + while (showCount < priority.length && items[priority[showCount]].showing) { + showCount++; + } + count = items.length - showCount; + } + String chevronString = count > 99 ? "99+" : to!(String)(count); //$NON-NLS-1$ + switch (chevronImageState) { + case NORMAL: { + Color chevronBorder = single ? getSelectionForeground() : getForeground(); + gc.setForeground(chevronBorder); + gc.setFont(f); + gc.drawLine(x,y, x+2,y+2); + gc.drawLine(x+2,y+2, x,y+4); + gc.drawLine(x+1,y, x+3,y+2); + gc.drawLine(x+3,y+2, x+1,y+4); + gc.drawLine(x+4,y, x+6,y+2); + gc.drawLine(x+6,y+2, x+5,y+4); + gc.drawLine(x+5,y, x+7,y+2); + gc.drawLine(x+7,y+2, x+4,y+4); + gc.drawString(chevronString, x+7, y+3, true); + break; } - else - { - int showCount = 0; - while (showCount < priority.length && items[priority[showCount]].showing) - { - showCount++; + case HOT: { + gc.setForeground(display.getSystemColor(BUTTON_BORDER)); + gc.setBackground(display.getSystemColor(BUTTON_FILL)); + gc.setFont(f); + gc.fillRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, 6, 6); + gc.drawRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width - 1, chevronRect.height - 1, 6, 6); + gc.drawLine(x,y, x+2,y+2); + gc.drawLine(x+2,y+2, x,y+4); + gc.drawLine(x+1,y, x+3,y+2); + gc.drawLine(x+3,y+2, x+1,y+4); + gc.drawLine(x+4,y, x+6,y+2); + gc.drawLine(x+6,y+2, x+5,y+4); + gc.drawLine(x+5,y, x+7,y+2); + gc.drawLine(x+7,y+2, x+4,y+4); + gc.drawString(chevronString, x+7, y+3, true); + break; + } + case SELECTED: { + gc.setForeground(display.getSystemColor(BUTTON_BORDER)); + gc.setBackground(display.getSystemColor(BUTTON_FILL)); + gc.setFont(f); + gc.fillRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, 6, 6); + gc.drawRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width - 1, chevronRect.height - 1, 6, 6); + gc.drawLine(x+1,y+1, x+3,y+3); + gc.drawLine(x+3,y+3, x+1,y+5); + gc.drawLine(x+2,y+1, x+4,y+3); + gc.drawLine(x+4,y+3, x+2,y+5); + gc.drawLine(x+5,y+1, x+7,y+3); + gc.drawLine(x+7,y+3, x+6,y+5); + gc.drawLine(x+6,y+1, x+8,y+3); + gc.drawLine(x+8,y+3, x+5,y+5); + gc.drawString(chevronString, x+8, y+4, true); + break; + } + default: + } + f.dispose(); +} +void drawMaximize(GC gc) { + if (maxRect.width is 0 || maxRect.height is 0) return; + Display display = getDisplay(); + // 5x4 or 7x9 + int x = maxRect.x + (CTabFolder.BUTTON_SIZE - 10)/2; + int y = maxRect.y + 3; + + gc.setForeground(display.getSystemColor(BUTTON_BORDER)); + gc.setBackground(display.getSystemColor(BUTTON_FILL)); + + switch (maxImageState) { + case NORMAL: { + if (!maximized) { + gc.fillRectangle(x, y, 9, 9); + gc.drawRectangle(x, y, 9, 9); + gc.drawLine(x+1, y+2, x+8, y+2); + } else { + gc.fillRectangle(x, y+3, 5, 4); + gc.fillRectangle(x+2, y, 5, 4); + gc.drawRectangle(x, y+3, 5, 4); + gc.drawRectangle(x+2, y, 5, 4); + gc.drawLine(x+3, y+1, x+6, y+1); + gc.drawLine(x+1, y+4, x+4, y+4); } - count = items.length - showCount; + break; } - String chevronString = count > 99 ? "99+" : String.valueOf(count); //$NON-NLS-1$ - switch (chevronImageState) - { - case NORMAL: - { - Color - chevronBorder = single ? getSelectionForeground() : getForeground(); - gc.setForeground(chevronBorder); - gc.setFont(f); - gc.drawLine(x, y, x + 2, y + 2); - gc.drawLine(x + 2, y + 2, x, y + 4); - gc.drawLine(x + 1, y, x + 3, y + 2); - gc.drawLine(x + 3, y + 2, x + 1, y + 4); - gc.drawLine(x + 4, y, x + 6, y + 2); - gc.drawLine(x + 6, y + 2, x + 5, y + 4); - gc.drawLine(x + 5, y, x + 7, y + 2); - gc.drawLine(x + 7, y + 2, x + 4, y + 4); - gc.drawString(chevronString, x + 7, y + 3, true); - break; + case HOT: { + gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, maxRect.height, 6, 6); + gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, maxRect.height - 1, 6, 6); + if (!maximized) { + gc.fillRectangle(x, y, 9, 9); + gc.drawRectangle(x, y, 9, 9); + gc.drawLine(x+1, y+2, x+8, y+2); + } else { + gc.fillRectangle(x, y+3, 5, 4); + gc.fillRectangle(x+2, y, 5, 4); + gc.drawRectangle(x, y+3, 5, 4); + gc.drawRectangle(x+2, y, 5, 4); + gc.drawLine(x+3, y+1, x+6, y+1); + gc.drawLine(x+1, y+4, x+4, y+4); + } + break; + } + case SELECTED: { + gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, maxRect.height, 6, 6); + gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, maxRect.height - 1, 6, 6); + if (!maximized) { + gc.fillRectangle(x+1, y+1, 9, 9); + gc.drawRectangle(x+1, y+1, 9, 9); + gc.drawLine(x+2, y+3, x+9, y+3); + } else { + gc.fillRectangle(x+1, y+4, 5, 4); + gc.fillRectangle(x+3, y+1, 5, 4); + gc.drawRectangle(x+1, y+4, 5, 4); + gc.drawRectangle(x+3, y+1, 5, 4); + gc.drawLine(x+4, y+2, x+7, y+2); + gc.drawLine(x+2, y+5, x+5, y+5); + } + break; + } + default: + } +} +void drawMinimize(GC gc) { + if (minRect.width is 0 || minRect.height is 0) return; + Display display = getDisplay(); + // 5x4 or 9x3 + int x = minRect.x + (BUTTON_SIZE - 10)/2; + int y = minRect.y + 3; + + gc.setForeground(display.getSystemColor(BUTTON_BORDER)); + gc.setBackground(display.getSystemColor(BUTTON_FILL)); + + switch (minImageState) { + case NORMAL: { + if (!minimized) { + gc.fillRectangle(x, y, 9, 3); + gc.drawRectangle(x, y, 9, 3); + } else { + gc.fillRectangle(x, y+3, 5, 4); + gc.fillRectangle(x+2, y, 5, 4); + gc.drawRectangle(x, y+3, 5, 4); + gc.drawRectangle(x+2, y, 5, 4); + gc.drawLine(x+3, y+1, x+6, y+1); + gc.drawLine(x+1, y+4, x+4, y+4); } - case HOT: - { - gc.setForeground(display.getSystemColor(BUTTON_BORDER)); - gc.setBackground(display.getSystemColor(BUTTON_FILL)); - gc.setFont(f); - gc.fillRoundRectangle(chevronRect.x, chevronRect.y, - chevronRect.width, chevronRect.height, 6, 6); - gc.drawRoundRectangle(chevronRect.x, chevronRect.y, - chevronRect.width - 1, chevronRect.height - 1, 6, 6); - gc.drawLine(x, y, x + 2, y + 2); - gc.drawLine(x + 2, y + 2, x, y + 4); - gc.drawLine(x + 1, y, x + 3, y + 2); - gc.drawLine(x + 3, y + 2, x + 1, y + 4); - gc.drawLine(x + 4, y, x + 6, y + 2); - gc.drawLine(x + 6, y + 2, x + 5, y + 4); - gc.drawLine(x + 5, y, x + 7, y + 2); - gc.drawLine(x + 7, y + 2, x + 4, y + 4); - gc.drawString(chevronString, x + 7, y + 3, true); - break; + break; + } + case HOT: { + gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, minRect.height, 6, 6); + gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, minRect.height - 1, 6, 6); + if (!minimized) { + gc.fillRectangle(x, y, 9, 3); + gc.drawRectangle(x, y, 9, 3); + } else { + gc.fillRectangle(x, y+3, 5, 4); + gc.fillRectangle(x+2, y, 5, 4); + gc.drawRectangle(x, y+3, 5, 4); + gc.drawRectangle(x+2, y, 5, 4); + gc.drawLine(x+3, y+1, x+6, y+1); + gc.drawLine(x+1, y+4, x+4, y+4); + } + break; + } + case SELECTED: { + gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, minRect.height, 6, 6); + gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, minRect.height - 1, 6, 6); + if (!minimized) { + gc.fillRectangle(x+1, y+1, 9, 3); + gc.drawRectangle(x+1, y+1, 9, 3); + } else { + gc.fillRectangle(x+1, y+4, 5, 4); + gc.fillRectangle(x+3, y+1, 5, 4); + gc.drawRectangle(x+1, y+4, 5, 4); + gc.drawRectangle(x+3, y+1, 5, 4); + gc.drawLine(x+4, y+2, x+7, y+2); + gc.drawLine(x+2, y+5, x+5, y+5); } - case SELECTED: - { - gc.setForeground(display.getSystemColor(BUTTON_BORDER)); - gc.setBackground(display.getSystemColor(BUTTON_FILL)); - gc.setFont(f); - gc.fillRoundRectangle(chevronRect.x, chevronRect.y, - chevronRect.width, chevronRect.height, 6, 6); - gc.drawRoundRectangle(chevronRect.x, chevronRect.y, - chevronRect.width - 1, chevronRect.height - 1, 6, 6); - gc.drawLine(x + 1, y + 1, x + 3, y + 3); - gc.drawLine(x + 3, y + 3, x + 1, y + 5); - gc.drawLine(x + 2, y + 1, x + 4, y + 3); - gc.drawLine(x + 4, y + 3, x + 2, y + 5); - gc.drawLine(x + 5, y + 1, x + 7, y + 3); - gc.drawLine(x + 7, y + 3, x + 6, y + 5); - gc.drawLine(x + 6, y + 1, x + 8, y + 3); - gc.drawLine(x + 8, y + 3, x + 5, y + 5); - gc.drawString(chevronString, x + 8, y + 4, true); - break; - } + break; } - f.dispose(); + default: + } +} +void drawTabArea(Event event) { + GC gc = event.gc; + Point size = getSize(); + int[] shape = null; + + if (tabHeight is 0) { + int style = getStyle(); + if ((style & DWT.FLAT) !is 0 && (style & DWT.BORDER) is 0) return; + int x1 = borderLeft - 1; + int x2 = size.x - borderRight; + int y1 = onBottom ? size.y - borderBottom - highlight_header - 1 : borderTop + highlight_header; + int y2 = onBottom ? size.y - borderBottom : borderTop; + if (borderLeft > 0 && onBottom) y2 -= 1; + + shape = [x1, y1, x1,y2, x2,y2, x2,y1]; + + // If horizontal gradient, show gradient across the whole area + if (selectedIndex !is -1 && selectionGradientColors !is null && selectionGradientColors.length > 1 && !selectionGradientVertical) { + drawBackground(gc, shape, true); + } else if (selectedIndex is -1 && gradientColors !is null && gradientColors.length > 1 && !gradientVertical) { + drawBackground(gc, shape, false); + } else { + gc.setBackground(selectedIndex is -1 ? getBackground() : selectionBackground); + gc.fillPolygon(shape); + } + + //draw 1 pixel border + if (borderLeft > 0) { + gc.setForeground(borderColor); + gc.drawPolyline(shape); + } + return; } - void drawMaximize (GC gc) - { - if (maxRect.width is 0 || maxRect.height is 0) - return; - Display display = getDisplay(); - // 5x4 or 7x9 - int x = maxRect.x + (CTabFolder.BUTTON_SIZE - 10) / 2; - int y = maxRect.y + 3; - - gc.setForeground(display.getSystemColor(BUTTON_BORDER)); - gc.setBackground(display.getSystemColor(BUTTON_FILL)); + int x = Math.max(0, borderLeft - 1); + int y = onBottom ? size.y - borderBottom - tabHeight : borderTop; + int width = size.x - borderLeft - borderRight + 1; + int height = tabHeight - 1; - switch (maxImageState) - { - case NORMAL: - { - if (!maximized) - { - gc.fillRectangle(x, y, 9, 9); - gc.drawRectangle(x, y, 9, 9); - gc.drawLine(x + 1, y + 2, x + 8, y + 2); - } - else - { - gc.fillRectangle(x, y + 3, 5, 4); - gc.fillRectangle(x + 2, y, 5, 4); - gc.drawRectangle(x, y + 3, 5, 4); - gc.drawRectangle(x + 2, y, 5, 4); - gc.drawLine(x + 3, y + 1, x + 6, y + 1); - gc.drawLine(x + 1, y + 4, x + 4, y + 4); - } - break; - } - case HOT: - { - gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, - maxRect.height, 6, 6); - gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, - maxRect.height - 1, 6, 6); - if (!maximized) - { - gc.fillRectangle(x, y, 9, 9); - gc.drawRectangle(x, y, 9, 9); - gc.drawLine(x + 1, y + 2, x + 8, y + 2); - } - else - { - gc.fillRectangle(x, y + 3, 5, 4); - gc.fillRectangle(x + 2, y, 5, 4); - gc.drawRectangle(x, y + 3, 5, 4); - gc.drawRectangle(x + 2, y, 5, 4); - gc.drawLine(x + 3, y + 1, x + 6, y + 1); - gc.drawLine(x + 1, y + 4, x + 4, y + 4); - } - break; - } - case SELECTED: - { - gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, - maxRect.height, 6, 6); - gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, - maxRect.height - 1, 6, 6); - if (!maximized) - { - gc.fillRectangle(x + 1, y + 1, 9, 9); - gc.drawRectangle(x + 1, y + 1, 9, 9); - gc.drawLine(x + 2, y + 3, x + 9, y + 3); - } - else - { - gc.fillRectangle(x + 1, y + 4, 5, 4); - gc.fillRectangle(x + 3, y + 1, 5, 4); - gc.drawRectangle(x + 1, y + 4, 5, 4); - gc.drawRectangle(x + 3, y + 1, 5, 4); - gc.drawLine(x + 4, y + 2, x + 7, y + 2); - gc.drawLine(x + 2, y + 5, x + 5, y + 5); - } - break; - } + // Draw Tab Header + if (onBottom) { + int[] left, right; + if ((getStyle() & DWT.BORDER) !is 0) { + left = simple ? SIMPLE_BOTTOM_LEFT_CORNER : BOTTOM_LEFT_CORNER; + right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER : BOTTOM_RIGHT_CORNER; + } else { + left = simple ? SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS : BOTTOM_LEFT_CORNER_BORDERLESS; + right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS : BOTTOM_RIGHT_CORNER_BORDERLESS; + } + shape = new int[left.length + right.length + 4]; + int index = 0; + shape[index++] = x; + shape[index++] = y-highlight_header; + for (int i = 0; i < left.length/2; i++) { + shape[index++] = x+left[2*i]; + shape[index++] = y+height+left[2*i+1]; + if (borderLeft is 0) shape[index-1] += 1; + } + for (int i = 0; i < right.length/2; i++) { + shape[index++] = x+width+right[2*i]; + shape[index++] = y+height+right[2*i+1]; + if (borderLeft is 0) shape[index-1] += 1; } + shape[index++] = x+width; + shape[index++] = y-highlight_header; + } else { + int[] left, right; + if ((getStyle() & DWT.BORDER) !is 0) { + left = simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER; + right = simple ? SIMPLE_TOP_RIGHT_CORNER : TOP_RIGHT_CORNER; + } else { + left = simple ? SIMPLE_TOP_LEFT_CORNER_BORDERLESS : TOP_LEFT_CORNER_BORDERLESS; + right = simple ? SIMPLE_TOP_RIGHT_CORNER_BORDERLESS : TOP_RIGHT_CORNER_BORDERLESS; + } + shape = new int[left.length + right.length + 4]; + int index = 0; + shape[index++] = x; + shape[index++] = y+height+highlight_header + 1; + for (int i = 0; i < left.length/2; i++) { + shape[index++] = x+left[2*i]; + shape[index++] = y+left[2*i+1]; + } + for (int i = 0; i < right.length/2; i++) { + shape[index++] = x+width+right[2*i]; + shape[index++] = y+right[2*i+1]; + } + shape[index++] = x+width; + shape[index++] = y+height+highlight_header + 1; } + // Fill in background + bool bkSelected = single && selectedIndex !is -1; + drawBackground(gc, shape, bkSelected); + // Fill in parent background for non-rectangular shape + Region r = new Region(); + r.add(new Rectangle(x, y, width + 1, height + 1)); + r.subtract(shape); + gc.setBackground(getParent().getBackground()); + fillRegion(gc, r); + r.dispose(); - void drawMinimize (GC gc) - { - if (minRect.width is 0 || minRect.height is 0) - return; - Display display = getDisplay(); - // 5x4 or 9x3 - int x = minRect.x + (BUTTON_SIZE - 10) / 2; - int y = minRect.y + 3; - - gc.setForeground(display.getSystemColor(BUTTON_BORDER)); - gc.setBackground(display.getSystemColor(BUTTON_FILL)); - - switch (minImageState) - { - case NORMAL: - { - if (!minimized) - { - gc.fillRectangle(x, y, 9, 3); - gc.drawRectangle(x, y, 9, 3); - } - else - { - gc.fillRectangle(x, y + 3, 5, 4); - gc.fillRectangle(x + 2, y, 5, 4); - gc.drawRectangle(x, y + 3, 5, 4); - gc.drawRectangle(x + 2, y, 5, 4); - gc.drawLine(x + 3, y + 1, x + 6, y + 1); - gc.drawLine(x + 1, y + 4, x + 4, y + 4); - } - break; - } - case HOT: - { - gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, - minRect.height, 6, 6); - gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, - minRect.height - 1, 6, 6); - if (!minimized) - { - gc.fillRectangle(x, y, 9, 3); - gc.drawRectangle(x, y, 9, 3); - } - else - { - gc.fillRectangle(x, y + 3, 5, 4); - gc.fillRectangle(x + 2, y, 5, 4); - gc.drawRectangle(x, y + 3, 5, 4); - gc.drawRectangle(x + 2, y, 5, 4); - gc.drawLine(x + 3, y + 1, x + 6, y + 1); - gc.drawLine(x + 1, y + 4, x + 4, y + 4); - } - break; - } - case SELECTED: - { - gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, - minRect.height, 6, 6); - gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, - minRect.height - 1, 6, 6); - if (!minimized) - { - gc.fillRectangle(x + 1, y + 1, 9, 3); - gc.drawRectangle(x + 1, y + 1, 9, 3); - } - else - { - gc.fillRectangle(x + 1, y + 4, 5, 4); - gc.fillRectangle(x + 3, y + 1, 5, 4); - gc.drawRectangle(x + 1, y + 4, 5, 4); - gc.drawRectangle(x + 3, y + 1, 5, 4); - gc.drawLine(x + 4, y + 2, x + 7, y + 2); - gc.drawLine(x + 2, y + 5, x + 5, y + 5); - } - break; + // Draw the unselected tabs. + if (!single) { + for (int i=0; i < items.length; i++) { + if (i !is selectedIndex && event.getBounds().intersects(items[i].getBounds())) { + items[i].onPaint(gc, false); } } } - void drawTabArea (Event event) - { - GC gc = event.gc; - Point size = getSize(); - int[] shape = null; - - if (tabHeight is 0) - { - int style = getStyle(); - if ((style & DWT.FLAT) !is 0 && (style & DWT.BORDER) is 0) - return; - int x1 = borderLeft - 1; - int x2 = size.x - borderRight; - int - y1 = onBottom ? size.y - borderBottom - highlight_header - 1 : borderTop + highlight_header; - int y2 = onBottom ? size.y - borderBottom : borderTop; - if (borderLeft > 0 && onBottom) - y2 -= 1; - - shape = new int[][x1 , y1 , x1 , y2 , x2 , y2 , x2 , y1]; - - // If horizontal gradient, show gradient across the whole area - if (selectedIndex !is -1 && selectionGradientColors !is null && selectionGradientColors.length > 1 && !selectionGradientVertical) - { - drawBackground(gc, shape, true); - } - else if (selectedIndex is -1 && gradientColors !is null && gradientColors.length > 1 && !gradientVertical) - { - drawBackground(gc, shape, false); - } - else - { - gc.setBackground( - selectedIndex is -1 ? getBackground() : selectionBackground); - gc.fillPolygon(shape); - } - - //draw 1 pixel border - if (borderLeft > 0) - { - gc.setForeground(borderColor); - gc.drawPolyline(shape); - } - return; - } - - int x = Math.max(0, borderLeft - 1); - int y = onBottom ? size.y - borderBottom - tabHeight : borderTop; - int width = size.x - borderLeft - borderRight + 1; - int height = tabHeight - 1; - - // Draw Tab Header - if (onBottom) - { - int[] left, right; - if ((getStyle() & DWT.BORDER) !is 0) - { - left = simple ? SIMPLE_BOTTOM_LEFT_CORNER : BOTTOM_LEFT_CORNER; - right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER : BOTTOM_RIGHT_CORNER; - } - else - { - left = simple ? SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS : BOTTOM_LEFT_CORNER_BORDERLESS; - right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS : BOTTOM_RIGHT_CORNER_BORDERLESS; - } - shape = new int[left.length + right.length + 4]; - int index = 0; - shape[index++] = x; - shape[index++] = y - highlight_header; - for (int i = 0; i < left.length / 2; i++) - { - shape[index++] = x + left[2 * i]; - shape[index++] = y + height + left[2 * i + 1]; - if (borderLeft is 0) - shape[index - 1] += 1; - } - for (int i = 0; i < right.length / 2; i++) - { - shape[index++] = x + width + right[2 * i]; - shape[index++] = y + height + right[2 * i + 1]; - if (borderLeft is 0) - shape[index - 1] += 1; - } - shape[index++] = x + width; - shape[index++] = y - highlight_header; - } - else - { - int[] left, right; - if ((getStyle() & DWT.BORDER) !is 0) - { - left = simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER; - right = simple ? SIMPLE_TOP_RIGHT_CORNER : TOP_RIGHT_CORNER; - } - else - { - left = simple ? SIMPLE_TOP_LEFT_CORNER_BORDERLESS : TOP_LEFT_CORNER_BORDERLESS; - right = simple ? SIMPLE_TOP_RIGHT_CORNER_BORDERLESS : TOP_RIGHT_CORNER_BORDERLESS; - } - shape = new int[left.length + right.length + 4]; - int index = 0; - shape[index++] = x; - shape[index++] = y + height + highlight_header + 1; - for (int i = 0; i < left.length / 2; i++) - { - shape[index++] = x + left[2 * i]; - shape[index++] = y + left[2 * i + 1]; - } - for (int i = 0; i < right.length / 2; i++) - { - shape[index++] = x + width + right[2 * i]; - shape[index++] = y + right[2 * i + 1]; - } - shape[index++] = x + width; - shape[index++] = y + height + highlight_header + 1; - } - // Fill in background - bool bkSelected = single && selectedIndex !is -1; - drawBackground(gc, shape, bkSelected); - // Fill in parent background for non-rectangular shape - Region r = new Region(); - r.add(new Rectangle(x, y, width + 1, height + 1)); - r.subtract(shape); - gc.setBackground(getParent().getBackground()); - fillRegion(gc, r); - r.dispose(); - - // Draw the unselected tabs. - if (!single) - { - for (int i = 0; i < items.length; i++) - { - if (i !is selectedIndex && event.getBounds().intersects( - items[i].getBounds())) - { - items[i].onPaint(gc, false); - } - } - } - - // Draw selected tab - if (selectedIndex !is -1) - { - CTabItem item = items[selectedIndex]; - item.onPaint(gc, true); - } - else - { - // if no selected tab - draw line across bottom of all tabs - int x1 = borderLeft; - int - y1 = (onBottom) ? size.y - borderBottom - tabHeight - 1 : borderTop + tabHeight; - int x2 = size.x - borderRight; - gc.setForeground(borderColor); - gc.drawLine(x1, y1, x2, y1); - } - - // Draw Buttons - drawChevron(gc); - drawMinimize(gc); - drawMaximize(gc); - - // Draw border line - if (borderLeft > 0) - { - RGB outside = getParent().getBackground().getRGB(); - antialias(shape, borderColor.getRGB(), null, outside, gc); - gc.setForeground(borderColor); - gc.drawPolyline(shape); - } - } - - /** - * Returns true if the receiver's border is visible. - * - * @return the receiver's border visibility state - * - * @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 bool getBorderVisible () - { - checkWidget(); - return borderLeft is 1; - } - - public Rectangle getClientArea () - { - checkWidget(); - if (minimized) - return new Rectangle(xClient, yClient, 0, 0); - Point size = getSize(); - int - width = size.x - borderLeft - borderRight - 2 * marginWidth - 2 * highlight_margin; - int - height = size.y - borderTop - borderBottom - 2 * marginHeight - highlight_margin - highlight_header; - height -= tabHeight; - return new Rectangle(xClient, yClient, width, height); - } - - /** - * Return the tab that is located at the specified index. - * - * @param index the index of the tab item - * @return the item at the specified index - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_RANGE - if the index is out of range
    • - *
    - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public CTabItem getItem (int index) - { - //checkWidget(); - if (index < 0 || index >= items.length) - DWT.error(DWT.ERROR_INVALID_RANGE); - return items[index]; - } - - /** - * Gets the item at a point in the widget. - * - * @param pt the point in coordinates relative to the CTabFolder - * @return the item at a point or null - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public CTabItem getItem (Point pt) - { - //checkWidget(); - if (items.length is 0) - return null; - Point size = getSize(); - if (size.x <= borderLeft + borderRight) - return null; - if (showChevron && chevronRect.contains(pt)) - return null; - for (int i = 0; i < priority.length; i++) - { - CTabItem item = items[priority[i]]; - Rectangle rect = item.getBounds(); - if (rect.contains(pt)) - return item; - } - return null; - } - - /** - * Return the number of tabs in the folder. - * - * @return the number of tabs in the folder - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public int getItemCount () - { - //checkWidget(); - return items.length; - } - - /** - * Return the tab items. - * - * @return the tab items - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public CTabItem[] getItems () - { - //checkWidget(); - CTabItem[] tabItems = new CTabItem[items.length]; - System.arraycopy(items, 0, tabItems, 0, items.length); - return tabItems; - } - - /* - * Return the lowercase of the first non-'&' character following - * an '&' character in the given String. If there are no '&' - * characters in the given String, return '\0'. - */ - char _findMnemonic (String String) - { - if (String is null) - return '\0'; - int index = 0; - int length = String.length(); - do - { - while (index < length && String.charAt(index) !is '&') - index++; - if (++index >= length) - return '\0'; - if (String.charAt(index) !is '&') - return Character.toLowerCase(String.charAt(index)); - index++; - } while (index < length); - return '\0'; - } - - String stripMnemonic (String String) - { - int index = 0; - int length = String.length(); - do - { - while ((index < length) && (String.charAt(index) !is '&')) - index++; - if (++index >= length) - return String; - if (String.charAt(index) !is '&') - { - return String.substring(0, index - 1) + String.substring(index, - length); - } - index++; - } while (index < length); - return String; - } - - /** - * Returns true if the receiver is minimized. - * - * @return the receiver's minimized state - * - * @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 bool getMinimized () - { - checkWidget(); - return minimized; + // Draw selected tab + if (selectedIndex !is -1) { + CTabItem item = items[selectedIndex]; + item.onPaint(gc, true); + } else { + // if no selected tab - draw line across bottom of all tabs + int x1 = borderLeft; + int y1 = (onBottom) ? size.y - borderBottom - tabHeight - 1 : borderTop + tabHeight; + int x2 = size.x - borderRight; + gc.setForeground(borderColor); + gc.drawLine(x1, y1, x2, y1); } - /** - * Returns true if the minimize button - * is visible. - * - * @return the visibility of the minimized button - * - * @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 bool getMinimizeVisible () - { - checkWidget(); - return showMin; - } - - /** - * Returns the number of characters that will - * appear in a fully compressed tab. - * - * @return number of characters that will appear in a fully compressed tab - * - * @since 3.0 - */ - public int getMinimumCharacters () - { - checkWidget(); - return minChars; - } - - /** - * Returns true if the receiver is maximized. - *

    - * - * @return the receiver's maximized state - * - * @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 bool getMaximized () - { - checkWidget(); - return maximized; - } - - /** - * Returns true if the maximize button - * is visible. - * - * @return the visibility of the maximized button - * - * @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 bool getMaximizeVisible () - { - checkWidget(); - return showMax; - } - - /** - * Returns 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 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 bool getMRUVisible () - { - checkWidget(); - return mru; - } - - int getRightItemEdge () - { - int x = getSize().x - borderRight - 3; - if (showMin) - x -= BUTTON_SIZE; - if (showMax) - x -= BUTTON_SIZE; - if (showChevron) - x -= 3 * BUTTON_SIZE / 2; - if (topRight !is null && topRightAlignment !is DWT.FILL) - { - Point rightSize = topRight.computeSize(DWT.DEFAULT, DWT.DEFAULT); - x -= rightSize.x + 3; - } - return Math.max(0, x); - } - - /** - * Return the selected tab item, or null if there is no selection. - * - * @return the selected tab item, or null if none has been selected - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public CTabItem getSelection () - { - //checkWidget(); - if (selectedIndex is -1) - return null; - return items[selectedIndex]; - } - - /** - * Returns the receiver's selection background color. - * - * @return the selection background color of the receiver - * - * @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 Color getSelectionBackground () - { - checkWidget(); - return selectionBackground; - } - - /** - * Returns the receiver's selection foreground color. - * - * @return the selection foreground color of the receiver - * - * @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 Color getSelectionForeground () - { - checkWidget(); - return selectionForeground; - } + // Draw Buttons + drawChevron(gc); + drawMinimize(gc); + drawMaximize(gc); - /** - * Return the index of the selected tab item, or -1 if there - * is no selection. - * - * @return the index of the selected tab item or -1 - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public int getSelectionIndex () - { - //checkWidget(); - return selectedIndex; + // Draw border line + if (borderLeft > 0) { + RGB outside = getParent().getBackground().getRGB(); + antialias(shape, borderColor.getRGB(), null, outside, gc); + gc.setForeground(borderColor); + gc.drawPolyline(shape); } - - /** - * Returns true 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; +} +/** + * Returns true if the receiver's border is visible. + * + * @return the receiver's border visibility state + * + * @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 bool getBorderVisible() { + checkWidget(); + return borderLeft is 1; +} +public override Rectangle getClientArea() { + checkWidget(); + if (minimized) return new Rectangle(xClient, yClient, 0, 0); + Point size = getSize(); + int width = size.x - borderLeft - borderRight - 2*marginWidth - 2*highlight_margin; + int height = size.y - borderTop - borderBottom - 2*marginHeight - highlight_margin - highlight_header; + height -= tabHeight; + return new Rectangle(xClient, yClient, width, height); +} +/** + * Return the tab that is located at the specified index. + * + * @param index the index of the tab item + * @return the item at the specified index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is out of range
    • + *
    + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public CTabItem getItem (int index) { + //checkWidget(); + if (index < 0 || index >= items.length) + DWT.error(DWT.ERROR_INVALID_RANGE); + return items [index]; +} +/** + * Gets the item at a point in the widget. + * + * @param pt the point in coordinates relative to the CTabFolder + * @return the item at a point or null + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public CTabItem getItem (Point pt) { + //checkWidget(); + if (items.length is 0) return null; + Point size = getSize(); + if (size.x <= borderLeft + borderRight) return null; + if (showChevron && chevronRect.contains(pt)) return null; + for (int i = 0; i < priority.length; i++) { + CTabItem item = items[priority[i]]; + Rectangle rect = item.getBounds(); + if (rect.contains(pt)) return item; } - - 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; + return null; +} +/** + * Return the number of tabs in the folder. + * + * @return the number of tabs in the folder + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public int getItemCount(){ + //checkWidget(); + return items.length; +} +/** + * Return the tab items. + * + * @return the tab items + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public CTabItem [] getItems() { + //checkWidget(); + CTabItem[] tabItems = new CTabItem [items.length]; + System.arraycopy(items, 0, tabItems, 0, items.length); + return tabItems; +} +/* + * Return the lowercase of the first non-'&' character following + * an '&' character in the given string. If there are no '&' + * characters in the given string, return '\0'. + */ +dchar _findMnemonic (String string) { + if (string is null) return '\0'; + int index = 0; + int length_ = string.length; + do { + while (index < length_ && string[index] !is '&') index++; + if (++index >= length_) return '\0'; + if (string[index] !is '&') return CharacterFirstToLower(string[index..$]); + index++; + } while (index < length_); + return '\0'; +} +String stripMnemonic (String string) { + int index = 0; + int length_ = string.length; + do { + while ((index < length_) && (string[index] !is '&')) index++; + if (++index >= length_) return string; + if (string[index] !is '&') { + return string.substring(0, index-1) ~ string.substring(index, length_); + } + index++; + } while (index < length_); + return string; +} +/** + * Returns true if the receiver is minimized. + * + * @return the receiver's minimized state + * + * @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 bool getMinimized() { + checkWidget(); + return minimized; +} +/** + * Returns true if the minimize button + * is visible. + * + * @return the visibility of the minimized button + * + * @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 bool getMinimizeVisible() { + checkWidget(); + return showMin; +} +/** + * Returns the number of characters that will + * appear in a fully compressed tab. + * + * @return number of characters that will appear in a fully compressed tab + * + * @since 3.0 + */ +public int getMinimumCharacters() { + checkWidget(); + return minChars; +} +/** + * Returns true if the receiver is maximized. + *

    + * + * @return the receiver's maximized state + * + * @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 bool getMaximized() { + checkWidget(); + return maximized; +} +/** + * Returns true if the maximize button + * is visible. + * + * @return the visibility of the maximized button + * + * @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 bool getMaximizeVisible() { + checkWidget(); + return showMax; +} +/** + * Returns 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 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 bool getMRUVisible() { + checkWidget(); + return mru; +} +int getRightItemEdge (){ + int x = getSize().x - borderRight - 3; + if (showMin) x -= BUTTON_SIZE; + if (showMax) x -= BUTTON_SIZE; + if (showChevron) x -= 3*BUTTON_SIZE/2; + if (topRight !is null && topRightAlignment !is DWT.FILL) { + Point rightSize = topRight.computeSize(DWT.DEFAULT, DWT.DEFAULT); + x -= rightSize.x + 3; } - - /** - * Returns the height of the tab - * - * @return the height of the tab - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public int getTabHeight () - { - checkWidget(); - if (fixedTabHeight !is DWT.DEFAULT) - return fixedTabHeight; - return tabHeight - 1; // -1 for line drawn across top of tab - } - - /** - * Returns the position of the tab. Possible values are DWT.TOP or DWT.BOTTOM. - * - * @return the position of the tab - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public int getTabPosition () - { - checkWidget(); - return onBottom ? DWT.BOTTOM : DWT.TOP; - } + return Math.max(0, x); +} +/** + * Return the selected tab item, or null if there is no selection. + * + * @return the selected tab item, or null if none has been selected + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public CTabItem getSelection() { + //checkWidget(); + if (selectedIndex is -1) return null; + return items[selectedIndex]; +} +/** + * Returns the receiver's selection background color. + * + * @return the selection background color of the receiver + * + * @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 Color getSelectionBackground() { + checkWidget(); + return selectionBackground; +} +/** + * Returns the receiver's selection foreground color. + * + * @return the selection foreground color of the receiver + * + * @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 Color getSelectionForeground() { + checkWidget(); + return selectionForeground; +} +/** + * Return the index of the selected tab item, or -1 if there + * is no selection. + * + * @return the index of the selected tab item or -1 + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public int getSelectionIndex() { + //checkWidget(); + return selectedIndex; +} +/** + * Returns true 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; +} - /** - * Returns the control in the top right corner of the tab folder. - * 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 tab folder or null - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - * - * @since 2.1 - */ - public Control getTopRight () - { - checkWidget(); - return topRight; - } - - /** - * Returns 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; +public override 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
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public int getTabHeight(){ + checkWidget(); + if (fixedTabHeight !is DWT.DEFAULT) return fixedTabHeight; + return tabHeight - 1; // -1 for line drawn across top of tab +} +/** + * Returns the position of the tab. Possible values are DWT.TOP or DWT.BOTTOM. + * + * @return the position of the tab + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public int getTabPosition(){ + checkWidget(); + return onBottom ? DWT.BOTTOM : DWT.TOP; +} +/** + * Returns the control in the top right corner of the tab folder. + * 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 tab folder or null + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + * + * @since 2.1 + */ +public Control getTopRight() { + checkWidget(); + return topRight; +} +/** + * Returns 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
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public int indexOf(CTabItem item) { + checkWidget(); + if (item is null) { + DWT.error(DWT.ERROR_NULL_ARGUMENT); } - - /** - * 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
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public int indexOf (CTabItem item) - { - checkWidget(); - if (item is null) - { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } - for (int i = 0; i < items.length; i++) - { - if (items[i] is item) - return i; - } - return -1; + for (int i = 0; i < items.length; i++) { + if (items[i] is item) return i; } - - void initAccessible () - { - const Accessible accessible = getAccessible(); - accessible.addAccessibleListener(new class AccessibleAdapter - { - public void getName (AccessibleEvent e) - { - String name = null; - int childID = e.childID; - if (childID >= 0 && childID < items.length) - { - name = stripMnemonic(items[childID].getText()); - } - else if (childID is items.length + CHEVRON_CHILD_ID) - { - name = DWT.getMessage("DWT_ShowList"); //$NON-NLS-1$ - } - else if (childID is items.length + MINIMIZE_CHILD_ID) - { - name = minimized ? DWT.getMessage("DWT_Restore") : DWT.getMessage( - "DWT_Minimize"); //$NON-NLS-1$ //$NON-NLS-2$ - } - else if (childID is items.length + MAXIMIZE_CHILD_ID) - { - name = maximized ? DWT.getMessage("DWT_Restore") : DWT.getMessage( - "DWT_Maximize"); //$NON-NLS-1$ //$NON-NLS-2$ + return -1; +} +void initAccessible() { + Accessible accessible = getAccessible(); + accessible.addAccessibleListener(new class() AccessibleAdapter { + public void getName(AccessibleEvent e) { + String name = null; + int childID = e.childID; + if (childID >= 0 && childID < items.length) { + name = stripMnemonic(items[childID].getText()); + } else if (childID is items.length + CHEVRON_CHILD_ID) { + name = DWT.getMessage("SWT_ShowList"); //$NON-NLS-1$ + } else if (childID is items.length + MINIMIZE_CHILD_ID) { + name = minimized ? DWT.getMessage("SWT_Restore") : DWT.getMessage("SWT_Minimize"); //$NON-NLS-1$ //$NON-NLS-2$ + } else if (childID is items.length + MAXIMIZE_CHILD_ID) { + name = maximized ? DWT.getMessage("SWT_Restore") : DWT.getMessage("SWT_Maximize"); //$NON-NLS-1$ //$NON-NLS-2$ } e.result = name; } - public void getHelp (AccessibleEvent e) - { + public void getHelp(AccessibleEvent e) { String help = null; int childID = e.childID; - if (childID is ACC.CHILDID_SELF) - { + if (childID is ACC.CHILDID_SELF) { help = getToolTipText(); - } - else if (childID >= 0 && childID < items.length) - { + } else if (childID >= 0 && childID < items.length) { help = items[childID].getToolTipText(); } e.result = help; } - public void getKeyboardShortcut (AccessibleEvent e) - { + public void getKeyboardShortcut(AccessibleEvent e) { String shortcut = null; int childID = e.childID; - if (childID >= 0 && childID < items.length) - { + if (childID >= 0 && childID < items.length) { String text = items[childID].getText(); - if (text !is null) - { - char mnemonic = _findMnemonic(text); - if (mnemonic !is '\0') - { - shortcut = "Alt+" + mnemonic; //$NON-NLS-1$ + if (text !is null) { + dchar mnemonic = _findMnemonic(text); + if (mnemonic !is '\0') { + shortcut = "Alt+"~tango.text.convert.Utf.toString([mnemonic]); //$NON-NLS-1$ } } } e.result = shortcut; } - } ); - - accessible.addAccessibleControlListener( - new class AccessibleControlAdapter - { - public void getChildAtPoint (AccessibleControlEvent e) - { - Point testPoint = toControl(e.x, e.y); - int childID = ACC.CHILDID_NONE; - for (int i = 0; i < items.length; i++) - { - if (items[i].getBounds().contains(testPoint)) - { - childID = i; - break; - } - } - if (childID is ACC.CHILDID_NONE) - { - if (showChevron && chevronRect.contains(testPoint)) - { - childID = items.length + CHEVRON_CHILD_ID; - } - else if (showMin && minRect.contains(testPoint)) - { - childID = items.length + MINIMIZE_CHILD_ID; - } - else if (showMax && maxRect.contains(testPoint)) - { - childID = items.length + MAXIMIZE_CHILD_ID; - } - else - { - Rectangle location = getBounds(); - location.height = location.height - getClientArea().height; - if (location.contains(testPoint)) - { - childID = ACC.CHILDID_SELF; - } - } - } - e.childID = childID; - } - - public void getLocation (AccessibleControlEvent e) - { - Rectangle location = null; - Point pt = null; - int childID = e.childID; - if (childID is ACC.CHILDID_SELF) - { - location = getBounds(); - pt = getParent().toDisplay(location.x, location.y); - } - else - { - if (childID >= 0 && childID < items.length && items[childID].isShowing()) - { - location = items[childID].getBounds(); - } - else if (showChevron && childID is items.length + CHEVRON_CHILD_ID) - { - location = chevronRect; - } - else if (showMin && childID is items.length + MINIMIZE_CHILD_ID) - { - location = minRect; - } - else if (showMax && childID is items.length + MAXIMIZE_CHILD_ID) - { - location = maxRect; - } - if (location !is null) - { - pt = toDisplay(location.x, location.y); - } - } - if (location !is null && pt !is null) - { - e.x = pt.x; - e.y = pt.y; - e.width = location.width; - e.height = location.height; - } - } - - public void getChildCount (AccessibleControlEvent e) - { - e.detail = items.length + EXTRA_CHILD_ID_COUNT; - } - - public void getDefaultAction (AccessibleControlEvent e) - { - String action = null; - int childID = e.childID; - if (childID >= 0 && childID < items.length) - { - action = DWT.getMessage("DWT_Switch"); //$NON-NLS-1$ - } - if (childID >= items.length && childID < items.length + EXTRA_CHILD_ID_COUNT) - { - action = DWT.getMessage("DWT_Press"); //$NON-NLS-1$ - } - e.result = action; - } + }); - public void getFocus (AccessibleControlEvent e) - { - int childID = ACC.CHILDID_NONE; - if (isFocusControl()) - { - if (selectedIndex is -1) - { - childID = ACC.CHILDID_SELF; - } - else - { - childID = selectedIndex; - } - } - e.childID = childID; - } - - public void getRole (AccessibleControlEvent e) - { - int role = 0; - int childID = e.childID; - if (childID is ACC.CHILDID_SELF) - { - role = ACC.ROLE_TABFOLDER; - } - else if (childID >= 0 && childID < items.length) - { - role = ACC.ROLE_TABITEM; - } - else if (childID >= items.length && childID < items.length + EXTRA_CHILD_ID_COUNT) - { - role = ACC.ROLE_PUSHBUTTON; - } - e.detail = role; - } - - public void getSelection (AccessibleControlEvent e) - { - e.childID = (selectedIndex is -1) ? ACC.CHILDID_NONE : selectedIndex; - } - - public void getState (AccessibleControlEvent e) - { - int state = 0; - int childID = e.childID; - if (childID is ACC.CHILDID_SELF) - { - state = ACC.STATE_NORMAL; - } - else if (childID >= 0 && childID < items.length) - { - state = ACC.STATE_SELECTABLE; - if (isFocusControl()) - { - state |= ACC.STATE_FOCUSABLE; - } - if (selectedIndex is childID) - { - state |= ACC.STATE_SELECTED; - if (isFocusControl()) - { - state |= ACC.STATE_FOCUSED; - } - } - } - else if (childID is items.length + CHEVRON_CHILD_ID) - { - state = showChevron ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE; - } - else if (childID is items.length + MINIMIZE_CHILD_ID) - { - state = showMin ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE; - } - else if (childID is items.length + MAXIMIZE_CHILD_ID) - { - state = showMax ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE; - } - e.detail = state; - } - - public void getChildren (AccessibleControlEvent e) - { - int childIdCount = items.length + EXTRA_CHILD_ID_COUNT; - Object[] children = new Object[childIdCount]; - for (int i = 0; i < childIdCount; i++) - { - children[i] = new Integer(i); - } - e.children = children; - } - }); - - addListener(DWT.Selection, new class(accessible) Listener - { - - Accessible accessible; - - this (Accessible accessible) - { - this.accessible = accessible; + accessible.addAccessibleControlListener(new class() AccessibleControlAdapter { + public void getChildAtPoint(AccessibleControlEvent e) { + Point testPoint = toControl(e.x, e.y); + int childID = ACC.CHILDID_NONE; + for (int i = 0; i < items.length; i++) { + if (items[i].getBounds().contains(testPoint)) { + childID = i; + break; + } } - - public void handleEvent (Event event) - { - if (isFocusControl()) - { - if (selectedIndex is -1) - { - accessible.setFocus(ACC.CHILDID_SELF); - } - else - { - accessible.setFocus(selectedIndex); + if (childID is ACC.CHILDID_NONE) { + if (showChevron && chevronRect.contains(testPoint)) { + childID = items.length + CHEVRON_CHILD_ID; + } else if (showMin && minRect.contains(testPoint)) { + childID = items.length + MINIMIZE_CHILD_ID; + } else if (showMax && maxRect.contains(testPoint)) { + childID = items.length + MAXIMIZE_CHILD_ID; + } else { + Rectangle location = getBounds(); + location.height = location.height - getClientArea().height; + if (location.contains(testPoint)) { + childID = ACC.CHILDID_SELF; } } } - }); - - addListener(DWT.FocusIn, new class(accessible) Listener - { + e.childID = childID; + } - Accessible accessible; - - this (Accessible accessible) - { - this.accessible = accessible; + public void getLocation(AccessibleControlEvent e) { + Rectangle location = null; + Point pt = null; + int childID = e.childID; + if (childID is ACC.CHILDID_SELF) { + location = getBounds(); + pt = getParent().toDisplay(location.x, location.y); + } else { + if (childID >= 0 && childID < items.length && items[childID].isShowing()) { + location = items[childID].getBounds(); + } else if (showChevron && childID is items.length + CHEVRON_CHILD_ID) { + location = chevronRect; + } else if (showMin && childID is items.length + MINIMIZE_CHILD_ID) { + location = minRect; + } else if (showMax && childID is items.length + MAXIMIZE_CHILD_ID) { + location = maxRect; + } + if (location !is null) { + pt = toDisplay(location.x, location.y); + } } + if (location !is null && pt !is null) { + e.x = pt.x; + e.y = pt.y; + e.width = location.width; + e.height = location.height; + } + } - public void handleEvent (Event event) - { - if (selectedIndex is -1) - { - accessible.setFocus(ACC.CHILDID_SELF); - } - else - { - accessible.setFocus(selectedIndex); + public void getChildCount(AccessibleControlEvent e) { + e.detail = items.length + EXTRA_CHILD_ID_COUNT; + } + + public void getDefaultAction(AccessibleControlEvent e) { + String action = null; + int childID = e.childID; + if (childID >= 0 && childID < items.length) { + action = DWT.getMessage ("SWT_Switch"); //$NON-NLS-1$ + } + if (childID >= items.length && childID < items.length + EXTRA_CHILD_ID_COUNT) { + action = DWT.getMessage ("SWT_Press"); //$NON-NLS-1$ + } + e.result = action; + } + + public void getFocus(AccessibleControlEvent e) { + int childID = ACC.CHILDID_NONE; + if (isFocusControl()) { + if (selectedIndex is -1) { + childID = ACC.CHILDID_SELF; + } else { + childID = selectedIndex; } } - }); - } + e.childID = childID; + } + + public void getRole(AccessibleControlEvent e) { + int role = 0; + int childID = e.childID; + if (childID is ACC.CHILDID_SELF) { + role = ACC.ROLE_TABFOLDER; + } else if (childID >= 0 && childID < items.length) { + role = ACC.ROLE_TABITEM; + } else if (childID >= items.length && childID < items.length + EXTRA_CHILD_ID_COUNT) { + role = ACC.ROLE_PUSHBUTTON; + } + e.detail = role; + } + + public void getSelection(AccessibleControlEvent e) { + e.childID = (selectedIndex is -1) ? ACC.CHILDID_NONE : selectedIndex; + } + + public void getState(AccessibleControlEvent e) { + int state = 0; + int childID = e.childID; + if (childID is ACC.CHILDID_SELF) { + state = ACC.STATE_NORMAL; + } else if (childID >= 0 && childID < items.length) { + state = ACC.STATE_SELECTABLE; + if (isFocusControl()) { + state |= ACC.STATE_FOCUSABLE; + } + if (selectedIndex is childID) { + state |= ACC.STATE_SELECTED; + if (isFocusControl()) { + state |= ACC.STATE_FOCUSED; + } + } + } else if (childID is items.length + CHEVRON_CHILD_ID) { + state = showChevron ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE; + } else if (childID is items.length + MINIMIZE_CHILD_ID) { + state = showMin ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE; + } else if (childID is items.length + MAXIMIZE_CHILD_ID) { + state = showMax ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE; + } + e.detail = state; + } + + public void getChildren(AccessibleControlEvent e) { + int childIdCount = items.length + EXTRA_CHILD_ID_COUNT; + Object[] children = new Object[childIdCount]; + for (int i = 0; i < childIdCount; i++) { + children[i] = new Integer(i); + } + e.children = children; + } + }); - void onKeyDown (Event event) - { - switch (event.keyCode) - { - case DWT.ARROW_LEFT: - case DWT.ARROW_RIGHT: - int count = items.length; - if (count is 0) - return; - if (selectedIndex is -1) - return; - int - leadKey = (getStyle() & DWT.RIGHT_TO_LEFT) !is 0 ? DWT.ARROW_RIGHT : DWT.ARROW_LEFT; - int offset = event.keyCode is leadKey ? -1 : 1; - int index; - if (!mru) - { - index = selectedIndex + offset; + addListener(DWT.Selection, new class(accessible) Listener { + Accessible acc; + this( Accessible a ){ + this.acc = a; + } + public void handleEvent(Event event) { + if (isFocusControl()) { + if (selectedIndex is -1) { + acc.setFocus(ACC.CHILDID_SELF); + } else { + acc.setFocus(selectedIndex); } - else - { - int[] visible = new int[items.length]; - int idx = 0; - int current = -1; - for (int i = 0; i < items.length; i++) - { - if (items[i].showing) - { - if (i is selectedIndex) - current = idx; - visible[idx++] = i; + } + } + }); + + addListener(DWT.FocusIn, new class(accessible) Listener { + Accessible acc; + this( Accessible a ){ this.acc = a; } + public void handleEvent(Event event) { + if (selectedIndex is -1) { + acc.setFocus(ACC.CHILDID_SELF); + } else { + acc.setFocus(selectedIndex); + } + } + }); +} + +void onKeyDown (Event event) { + switch (event.keyCode) { + case DWT.ARROW_LEFT: + case DWT.ARROW_RIGHT: + int count = items.length; + if (count is 0) return; + if (selectedIndex is -1) return; + int leadKey = (getStyle() & DWT.RIGHT_TO_LEFT) !is 0 ? DWT.ARROW_RIGHT : DWT.ARROW_LEFT; + int offset = event.keyCode is leadKey ? -1 : 1; + int index; + if (!mru) { + index = selectedIndex + offset; + } else { + int[] visible = new int[items.length]; + int idx = 0; + int current = -1; + for (int i = 0; i < items.length; i++) { + if (items[i].showing) { + if (i is selectedIndex) current = idx; + visible [idx++] = i; + } + } + if (current + offset >= 0 && current + offset < idx){ + index = visible [current + offset]; + } else { + if (showChevron) { + CTabFolderEvent e = new CTabFolderEvent(this); + e.widget = this; + e.time = event.time; + e.x = chevronRect.x; + e.y = chevronRect.y; + e.width = chevronRect.width; + e.height = chevronRect.height; + e.doit = true; + for (int i = 0; i < folderListeners.length; i++) { + folderListeners[i].showList(e); + } + if (e.doit && !isDisposed()) { + showList(chevronRect); } } - if (current + offset >= 0 && current + offset < idx) - { - index = visible[current + offset]; - } - else - { - if (showChevron) - { - CTabFolderEvent e = new CTabFolderEvent(this); - e.widget = this; - e.time = event.time; - e.x = chevronRect.x; - e.y = chevronRect.y; - e.width = chevronRect.width; - e.height = chevronRect.height; - e.doit = true; - for (int i = 0; i < folderListeners.length; i++) - { - folderListeners[i].showList(e); - } - if (e.doit && !isDisposed()) - { - showList(chevronRect); - } - } - return; - } + return; } - if (index < 0 || index >= count) - return; - setSelection(index, true); - forceFocus(); + } + if (index < 0 || index >= count) return; + setSelection (index, true); + forceFocus(); + default: + } +} +void onDispose(Event event) { + removeListener(DWT.Dispose, listener); + notifyListeners(DWT.Dispose, event); + event.type = DWT.None; + /* + * Usually when an item is disposed, destroyItem will change the size of the items array, + * reset the bounds of all the tabs and manage the widget associated with the tab. + * Since the whole folder 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; + + if (showMenu !is null && !showMenu.isDisposed()) { + showMenu.dispose(); + showMenu = null; + } + int length = items.length; + for (int i = 0; i < length; i++) { + if (items[i] !is null) { + items[i].dispose(); } } - void onDispose (Event event) - { - removeListener(DWT.Dispose, listener); - notifyListeners(DWT.Dispose, event); - event.type = DWT.None; - /* - * Usually when an item is disposed, destroyItem will change the size of the items array, - * reset the bounds of all the tabs and manage the widget associated with the tab. - * Since the whole folder 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; + selectionGradientColors = null; + selectionGradientPercents = null; + selectionBgImage = null; - if (showMenu !is null && !showMenu.isDisposed()) - { - showMenu.dispose(); - showMenu = null; - } - int length = items.length; - for (int i = 0; i < length; i++) - { - if (items[i] !is null) - { - items[i].dispose(); + selectionBackground = null; + selectionForeground = null; + disposeSelectionHighlightGradientColors(); +} +void onDragDetect(Event event) { + bool consume = false; + if (chevronRect.contains(event.x, event.y) || + minRect.contains(event.x, event.y) || + maxRect.contains(event.x, event.y)){ + consume = true; + } else { + for (int i = 0; i < items.length; i++) { + if (items[i].closeRect.contains(event.x, event.y)) { + consume = true; + break; } } - - selectionGradientColors = null; - selectionGradientPercents = null; - selectionBgImage = null; - - selectionBackground = null; - selectionForeground = null; - disposeSelectionHighlightGradientColors(); + } + if (consume) { + event.type = DWT.None; } - - void onDragDetect (Event event) - { - bool consume = false; - if (chevronRect.contains(event.x, event.y) || minRect.contains(event.x, - event.y) || maxRect.contains(event.x, event.y)) - { - consume = true; - } - else - { - for (int i = 0; i < items.length; i++) - { - if (items[i].closeRect.contains(event.x, event.y)) - { - consume = true; - break; +} +void onFocus(Event event) { + checkWidget(); + if (selectedIndex >= 0) { + redraw(); + } else { + setSelection(0, true); + } +} +bool onMnemonic (Event event) { + auto key = event.character; + for (int i = 0; i < items.length; i++) { + if (items[i] !is null) { + auto mnemonic = _findMnemonic (items[i].getText ()); + if (mnemonic !is '\0') { + if ( CharacterToLower(key) is mnemonic) { + setSelection(i, true); + return true; } } } - if (consume) - { - event.type = DWT.None; - } } - - void onFocus (Event event) - { - checkWidget(); - if (selectedIndex >= 0) - { - redraw(); - } - else - { - setSelection(0, true); + return false; +} +void onMouseDoubleClick(Event event) { + if (event.button !is 1 || + (event.stateMask & DWT.BUTTON2) !is 0 || + (event.stateMask & DWT.BUTTON3) !is 0) return; + Event e = new Event(); + e.item = getItem(new Point(event.x, event.y)); + if (e.item !is null) { + notifyListeners(DWT.DefaultSelection, e); + } +} +void onMouse(Event event) { + int x = event.x, y = event.y; + switch (event.type) { + case DWT.MouseEnter: { + setToolTipText(null); + break; } - } - - bool onMnemonic (Event event) - { - char key = event.character; - for (int i = 0; i < items.length; i++) - { - if (items[i] !is null) - { - char mnemonic = _findMnemonic(items[i].getText()); - if (mnemonic !is '\0') - { - if (Character.toLowerCase(key) is mnemonic) - { - setSelection(i, true); - return true; + case DWT.MouseExit: { + if (minImageState !is NORMAL) { + minImageState = NORMAL; + redraw(minRect.x, minRect.y, minRect.width, minRect.height, false); + } + if (maxImageState !is NORMAL) { + maxImageState = NORMAL; + redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false); + } + if (chevronImageState !is NORMAL) { + chevronImageState = NORMAL; + redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false); + } + for (int i=0; i= 0 && current + offset < idx){ + index = visible [current + offset]; + } else { + if (showChevron) { CTabFolderEvent e = new CTabFolderEvent(this); e.widget = this; e.time = event.time; @@ -2704,2391 +2294,1788 @@ e.width = chevronRect.width; e.height = chevronRect.height; e.doit = true; - for (int i = 0; i < folderListeners.length; i++) - { + for (int i = 0; i < folderListeners.length; i++) { folderListeners[i].showList(e); } - if (e.doit && !isDisposed()) - { + if (e.doit && !isDisposed()) { showList(chevronRect); } - return; - } - if (minRect.contains(x, y)) - { - bool selected = minImageState is SELECTED; - minImageState = HOT; - redraw(minRect.x, minRect.y, minRect.width, minRect.height, - false); - if (!selected) - return; - CTabFolderEvent e = new CTabFolderEvent(this); - e.widget = this; - e.time = event.time; - for (int i = 0; i < folderListeners.length; i++) - { - if (minimized) - { - folderListeners[i].restore(e); - } - else - { - folderListeners[i].minimize(e); - } - } - return; - } - if (maxRect.contains(x, y)) - { - bool selected = maxImageState is SELECTED; - maxImageState = HOT; - redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, - false); - if (!selected) - return; - CTabFolderEvent e = new CTabFolderEvent(this); - e.widget = this; - e.time = event.time; - for (int i = 0; i < folderListeners.length; i++) - { - if (maximized) - { - folderListeners[i].restore(e); - } - else - { - folderListeners[i].maximize(e); - } - } - return; - } - CTabItem item = null; - if (single) - { - if (selectedIndex !is -1) - { - Rectangle bounds = items[selectedIndex].getBounds(); - if (bounds.contains(x, y)) - { - item = items[selectedIndex]; - } - } } - else - { - for (int i = 0; i < items.length; i++) - { - Rectangle bounds = items[i].getBounds(); - if (bounds.contains(x, y)) - { - item = items[i]; - } - } - } - if (item !is null) - { - if (item.closeRect.contains(x, y)) - { - bool selected = item.closeImageState is SELECTED; - item.closeImageState = HOT; - redraw(item.closeRect.x, item.closeRect.y, - item.closeRect.width, item.closeRect.height, - false); - if (!selected) - return; - CTabFolderEvent e = new CTabFolderEvent(this); - e.widget = this; - e.time = event.time; - e.item = item; - e.doit = true; - for (int j = 0; j < folderListeners.length; j++) - { - CTabFolder2Listener listener = folderListeners[j]; - listener.close(e); - } - for (int j = 0; j < tabListeners.length; j++) - { - CTabFolderListener listener = tabListeners[j]; - listener.itemClosed(e); - } - if (e.doit) - item.dispose(); - if (!isDisposed() && item.isDisposed()) - { - Display display = getDisplay(); - Point pt = display.getCursorLocation(); - pt = display.map(null, this, pt.x, pt.y); - CTabItem nextItem = getItem(pt); - if (nextItem !is null) - { - if (nextItem.closeRect.contains(pt)) - { - if (nextItem.closeImageState !is SELECTED && nextItem.closeImageState !is HOT) - { - nextItem.closeImageState = HOT; - redraw(nextItem.closeRect.x, - nextItem.closeRect.y, - nextItem.closeRect.width, - nextItem.closeRect.height, - false); - } - } - else - { - if (nextItem.closeImageState !is NORMAL) - { - nextItem.closeImageState = NORMAL; - redraw(nextItem.closeRect.x, - nextItem.closeRect.y, - nextItem.closeRect.width, - nextItem.closeRect.height, - false); - } - } - } - } - return; - } - } + return true; } } } + setSelection (index, true); + return true; +} +void onPaint(Event event) { + if (inDispose) return; + Font font = getFont(); + if (oldFont is null || oldFont!=font) { + // handle case where default font changes + oldFont = font; + if (!updateTabHeight(false)) { + updateItems(); + redraw(); + return; + } + } - bool onPageTraversal (Event event) - { - int count = items.length; - if (count is 0) - return false; - int index = selectedIndex; - if (index is -1) - { - index = 0; - } - else - { - int offset = (event.detail is DWT.TRAVERSE_PAGE_NEXT) ? 1 : -1; - if (!mru) - { - index = (selectedIndex + offset + count) % count; - } - else - { - int[] visible = new int[items.length]; - int idx = 0; - int current = -1; - for (int i = 0; i < items.length; i++) - { - if (items[i].showing) - { - if (i is selectedIndex) - current = idx; - visible[idx++] = i; - } - } - if (current + offset >= 0 && current + offset < idx) - { - index = visible[current + offset]; - } - else - { - if (showChevron) - { - CTabFolderEvent e = new CTabFolderEvent(this); - e.widget = this; - e.time = event.time; - e.x = chevronRect.x; - e.y = chevronRect.y; - e.width = chevronRect.width; - e.height = chevronRect.height; - e.doit = true; - for (int i = 0; i < folderListeners.length; i++) - { - folderListeners[i].showList(e); - } - if (e.doit && !isDisposed()) - { - showList(chevronRect); - } - } - return true; - } - } - } - setSelection(index, true); - return true; - } + GC gc = event.gc; + Font gcFont = gc.getFont(); + Color gcBackground = gc.getBackground(); + Color gcForeground = gc.getForeground(); + +// 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); +//} + + drawBody(event); - void onPaint (Event event) - { - if (inDispose) - return; - Font font = getFont(); - if (oldFont is null || !oldFont.opEquals(font)) - { - // handle case where default font changes - oldFont = font; - if (!updateTabHeight(false)) - { - updateItems(); - redraw(); - return; - } - } + gc.setFont(gcFont); + gc.setForeground(gcForeground); + gc.setBackground(gcBackground); + + drawTabArea(event); + + gc.setFont(gcFont); + gc.setForeground(gcForeground); + gc.setBackground(gcBackground); +} + +void onResize() { + if (updateItems()) redrawTabs(); - GC gc = event.gc; - Font gcFont = gc.getFont(); - Color gcBackground = gc.getBackground(); - Color gcForeground = gc.getForeground(); - - // 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); - //} - - drawBody(event); - - gc.setFont(gcFont); - gc.setForeground(gcForeground); - gc.setBackground(gcBackground); - - drawTabArea(event); - - gc.setFont(gcFont); - gc.setForeground(gcForeground); - gc.setBackground(gcBackground); - } - - void onResize () - { - if (updateItems()) - redrawTabs(); - - Point size = getSize(); - if (oldSize is null) - { + Point size = getSize(); + if (oldSize is null) { + redraw(); + } else { + if (onBottom && size.y !is oldSize.y) { redraw(); + } else { + int x1 = Math.min(size.x, oldSize.x); + if (size.x !is oldSize.x) x1 -= borderRight + highlight_margin + 2; + if (!simple) x1 -= 5; // rounded top right corner + int y1 = Math.min(size.y, oldSize.y); + if (size.y !is oldSize.y) y1 -= borderBottom + highlight_margin; + int x2 = Math.max(size.x, oldSize.x); + int y2 = Math.max(size.y, oldSize.y); + redraw(0, y1, x2, y2 - y1, false); + redraw(x1, 0, x2 - x1, y2, false); } - else - { - if (onBottom && size.y !is oldSize.y) - { - redraw(); - } - else - { - int x1 = Math.min(size.x, oldSize.x); - if (size.x !is oldSize.x) - x1 -= borderRight + highlight_margin + 2; - if (!simple) - x1 -= 5; // rounded top right corner - int y1 = Math.min(size.y, oldSize.y); - if (size.y !is oldSize.y) - y1 -= borderBottom + highlight_margin; - int x2 = Math.max(size.x, oldSize.x); - int y2 = Math.max(size.y, oldSize.y); - redraw(0, y1, x2, y2 - y1, false); - redraw(x1, 0, x2 - x1, y2, false); - } - } - oldSize = size; + } + oldSize = size; +} +void onTraverse (Event event) { + switch (event.detail) { + case DWT.TRAVERSE_ESCAPE: + case DWT.TRAVERSE_RETURN: + case DWT.TRAVERSE_TAB_NEXT: + case DWT.TRAVERSE_TAB_PREVIOUS: + Control focusControl = getDisplay().getFocusControl(); + if (focusControl is this) event.doit = true; + break; + case DWT.TRAVERSE_MNEMONIC: + event.doit = onMnemonic(event); + if (event.doit) event.detail = DWT.TRAVERSE_NONE; + break; + case DWT.TRAVERSE_PAGE_NEXT: + case DWT.TRAVERSE_PAGE_PREVIOUS: + event.doit = onPageTraversal(event); + event.detail = DWT.TRAVERSE_NONE; + break; + default: } - - void onTraverse (Event event) - { - switch (event.detail) - { - case DWT.TRAVERSE_ESCAPE: - case DWT.TRAVERSE_RETURN: - case DWT.TRAVERSE_TAB_NEXT: - case DWT.TRAVERSE_TAB_PREVIOUS: - Control focusControl = getDisplay().getFocusControl(); - if (focusControl is this) - event.doit = true; - break; - case DWT.TRAVERSE_MNEMONIC: - event.doit = onMnemonic(event); - if (event.doit) - event.detail = DWT.TRAVERSE_NONE; - break; - case DWT.TRAVERSE_PAGE_NEXT: - case DWT.TRAVERSE_PAGE_PREVIOUS: - event.doit = onPageTraversal(event); - event.detail = DWT.TRAVERSE_NONE; +} +void redrawTabs() { + Point size = getSize(); + if (onBottom) { + redraw(0, size.y - borderBottom - tabHeight - highlight_header - 1, size.x, borderBottom + tabHeight + highlight_header + 1, false); + } else { + redraw(0, 0, size.x, borderTop + tabHeight + highlight_header + 1, false); + } +} +/** + * Removes the listener. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + * + * @see #addCTabFolder2Listener(CTabFolder2Listener) + * + * @since 3.0 + */ +public void removeCTabFolder2Listener(CTabFolder2Listener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + if (folderListeners.length is 0) return; + int index = -1; + for (int i = 0; i < folderListeners.length; i++) { + if (listener is folderListeners[i]){ + index = i; break; } } - - void redrawTabs () - { - Point size = getSize(); - if (onBottom) - { - redraw(0, size.y - borderBottom - tabHeight - highlight_header - 1, - size.x, borderBottom + tabHeight + highlight_header + 1, - false); + if (index is -1) return; + if (folderListeners.length is 1) { + folderListeners = new CTabFolder2Listener[0]; + return; + } + CTabFolder2Listener[] newTabListeners = new CTabFolder2Listener[folderListeners.length - 1]; + SimpleType!(CTabFolder2Listener).arraycopy(folderListeners, 0, newTabListeners, 0, index); + SimpleType!(CTabFolder2Listener).arraycopy(folderListeners, index + 1, newTabListeners, index, folderListeners.length - index - 1); + folderListeners = newTabListeners; +} +/** + * Removes the listener. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + * + * @deprecated see removeCTabFolderCloseListener(CTabFolderListener) + */ +public void removeCTabFolderListener(CTabFolderListener listener) { + checkWidget(); + if (listener is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + if (tabListeners.length is 0) return; + int index = -1; + for (int i = 0; i < tabListeners.length; i++) { + if (listener is tabListeners[i]){ + index = i; + break; } - else - { - redraw(0, 0, size.x, borderTop + tabHeight + highlight_header + 1, - false); + } + if (index is -1) return; + if (tabListeners.length is 1) { + tabListeners = new CTabFolderListener[0]; + return; + } + CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length - 1]; + SimpleType!(CTabFolderListener).arraycopy(tabListeners, 0, newTabListeners, 0, index); + SimpleType!(CTabFolderListener).arraycopy(tabListeners, index + 1, newTabListeners, index, tabListeners.length - index - 1); + tabListeners = newTabListeners; +} +/** + * Removes the listener from the collection of listeners who will + * be notified when the user changes the receiver's selection. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception 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 SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener is null) { + DWT.error(DWT.ERROR_NULL_ARGUMENT); + } + removeListener(DWT.Selection, listener); + removeListener(DWT.DefaultSelection, listener); +} +public override void setBackground (Color color) { + super.setBackground(color); + redraw(); +} +/** + * Specify a gradient of colours to be drawn in the background of the unselected tabs. + * For example to draw a gradient that varies from dark blue to blue and then to + * white, use the following call to setBackground: + *
    + *  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
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + * + * @since 3.0 + */ +void setBackground(Color[] colors, int[] percents) { + setBackground(colors, percents, false); +} +/** + * Specify a gradient of colours to be drawn in the background of the unselected tab. + * For example to draw a vertical gradient that varies from dark blue to blue and then to + * white, use the following call to setBackground: + *
    + *  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
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + * + * @since 3.0 + */ +void setBackground(Color[] colors, int[] percents, bool vertical) { + checkWidget(); + if (colors !is null) { + if (percents is null || percents.length !is colors.length - 1) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + for (int i = 0; i < percents.length; i++) { + if (percents[i] < 0 || percents[i] > 100) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (i > 0 && percents[i] < percents[i-1]) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + } + if (getDisplay().getDepth() < 15) { + // Don't use gradients on low color displays + colors = [colors[colors.length - 1]]; + percents = null; } } - /** - * Removes the listener. - * - * @param listener the listener - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - * - * @see #addCTabFolder2Listener(CTabFolder2Listener) - * - * @since 3.0 - */ - public void removeCTabFolder2Listener (CTabFolder2Listener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - if (folderListeners.length is 0) - return; - int index = -1; - for (int i = 0; i < folderListeners.length; i++) - { - if (listener is folderListeners[i]) - { - index = i; - break; + // Are these settings the same as before? + if (bgImage is null) { + if ((gradientColors !is null) && (colors !is null) && + (gradientColors.length is colors.length)) { + bool same = false; + for (int i = 0; i < gradientColors.length; i++) { + if (gradientColors[i] is null) { + same = colors[i] is null; + } else { + same = cast(bool)(gradientColors[i]==colors[i]); + } + if (!same) break; } - } - if (index is -1) - return; - if (folderListeners.length is 1) - { - folderListeners = new CTabFolder2Listener[0]; - return; - } - CTabFolder2Listener[] - newTabListeners = new CTabFolder2Listener[folderListeners.length - 1]; - System.arraycopy(folderListeners, 0, newTabListeners, 0, index); - System.arraycopy(folderListeners, index + 1, newTabListeners, index, - folderListeners.length - index - 1); - folderListeners = newTabListeners; - } - - /** - * Removes the listener. - * - * @param listener the listener - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - * - * @deprecated see removeCTabFolderCloseListener(CTabFolderListener) - */ - public void removeCTabFolderListener (CTabFolderListener listener) - { - checkWidget(); - if (listener is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - if (tabListeners.length is 0) - return; - int index = -1; - for (int i = 0; i < tabListeners.length; i++) - { - if (listener is tabListeners[i]) - { - index = i; - break; + if (same) { + for (int i = 0; i < gradientPercents.length; i++) { + same = gradientPercents[i] is percents[i]; + if (!same) break; + } } - } - if (index is -1) - return; - if (tabListeners.length is 1) - { - tabListeners = new CTabFolderListener[0]; - return; - } - CTabFolderListener[] - newTabListeners = new CTabFolderListener[tabListeners.length - 1]; - System.arraycopy(tabListeners, 0, newTabListeners, 0, index); - System.arraycopy(tabListeners, index + 1, newTabListeners, index, - tabListeners.length - index - 1); - tabListeners = newTabListeners; - } - - /** - * Removes the listener from the collection of listeners who will - * be notified when the user changes the receiver's selection. - * - * @param listener the listener which should no longer be notified - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • - *
    - * @exception 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 SelectionListener - * @see #addSelectionListener - */ - public void removeSelectionListener (SelectionListener listener) - { - checkWidget(); - if (listener is null) - { - DWT.error(DWT.ERROR_NULL_ARGUMENT); + if (same && this.gradientVertical is vertical) return; } - removeListener(DWT.Selection, listener); - removeListener(DWT.DefaultSelection, listener); - } - - public void setBackground (Color color) - { - super.setBackground(color); - redraw(); + } else { + bgImage = null; } - - /** - * Specify a gradient of colours to be drawn in the background of the unselected tabs. - * For example to draw a gradient that varies from dark blue to blue and then to - * white, use the following call to setBackground: - *
    -     *  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
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - * - * @since 3.0 - */ - void setBackground (Color[] colors, int[] percents) - { - setBackground(colors, percents, false); + // Store the new settings + if (colors is null) { + gradientColors = null; + gradientPercents = null; + gradientVertical = false; + setBackground(cast(Color)null); + } else { + gradientColors = new Color[colors.length]; + for (int i = 0; i < colors.length; ++i) { + gradientColors[i] = colors[i]; + } + gradientPercents = new int[percents.length]; + for (int i = 0; i < percents.length; ++i) { + gradientPercents[i] = percents[i]; + } + gradientVertical = vertical; + setBackground(gradientColors[gradientColors.length-1]); } - /** - * Specify a gradient of colours to be drawn in the background of the unselected tab. - * For example to draw a vertical gradient that varies from dark blue to blue and then to - * white, use the following call to setBackground: - *
    -     *  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
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - * - * @since 3.0 - */ - void setBackground (Color[] colors, int[] percents, bool vertical) - { - checkWidget(); - if (colors !is null) - { - if (percents is null || percents.length !is colors.length - 1) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - for (int i = 0; i < percents.length; i++) - { - if (percents[i] < 0 || percents[i] > 100) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (i > 0 && percents[i] < percents[i - 1]) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - } - if (getDisplay().getDepth() < 15) - { - // Don't use gradients on low color displays - colors = new Color[][colors[colors.length - 1]]; - percents = new int[][]; - } - } + // Refresh with the new settings + redraw(); +} - // Are these settings the same as before? - if (bgImage is null) - { - if ((gradientColors !is null) && (colors !is null) && (gradientColors.length is colors.length)) - { - bool same = false; - for (int i = 0; i < gradientColors.length; i++) - { - if (gradientColors[i] is null) - { - same = colors[i] is null; - } - else - { - same = gradientColors[i].opEquals(colors[i]); - } - if (!same) - break; - } - if (same) - { - for (int i = 0; i < gradientPercents.length; i++) - { - same = gradientPercents[i] is percents[i]; - if (!same) - break; - } - } - if (same && this.gradientVertical is vertical) - return; - } - } - else - { - bgImage = null; - } - // Store the new settings - if (colors is null) - { - gradientColors = null; - gradientPercents = null; - gradientVertical = false; - setBackground(cast(Color) null); - } - else - { - gradientColors = new Color[colors.length]; - for (int i = 0; i < colors.length; ++i) - { - gradientColors[i] = colors[i]; - } - gradientPercents = new int[percents.length]; - for (int i = 0; i < percents.length; ++i) - { - gradientPercents[i] = percents[i]; - } - gradientVertical = vertical; - setBackground(gradientColors[gradientColors.length - 1]); - } - - // Refresh with the new settings - redraw(); +/** + * Set the image to be drawn in the background of the unselected tab. Image + * is stretched or compressed to cover entire unselected tab area. + * + * @param image the image to be drawn in the background + * + * @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 + */ +void setBackground(Image image) { + checkWidget(); + if (image is bgImage) return; + if (image !is null) { + gradientColors = null; + gradientPercents = null; + } + bgImage = image; + redraw(); +} +/** + * Toggle the visibility of the border + * + * @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 ((borderLeft is 1) is show) return; + borderLeft = borderRight = show ? 1 : 0; + borderTop = onBottom ? borderLeft : 0; + borderBottom = onBottom ? 0 : borderLeft; + Rectangle rectBefore = getClientArea(); + updateItems(); + Rectangle rectAfter = getClientArea(); + if (rectBefore!=rectAfter) { + notifyListeners(DWT.Resize, new Event()); + } + redraw(); +} +void setButtonBounds() { + Point size = getSize(); + int oldX, oldY, oldWidth, oldHeight; + // max button + oldX = maxRect.x; + oldY = maxRect.y; + oldWidth = maxRect.width; + oldHeight = maxRect.height; + maxRect.x = maxRect.y = maxRect.width = maxRect.height = 0; + if (showMax) { + maxRect.x = size.x - borderRight - BUTTON_SIZE - 3; + if (borderRight > 0) maxRect.x += 1; + maxRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2; + maxRect.width = BUTTON_SIZE; + maxRect.height = BUTTON_SIZE; + } + if (oldX !is maxRect.x || oldWidth !is maxRect.width || + oldY !is maxRect.y || oldHeight !is maxRect.height) { + int left = Math.min(oldX, maxRect.x); + int right = Math.max(oldX + oldWidth, maxRect.x + maxRect.width); + int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1; + redraw(left, top, right - left, tabHeight, false); } - /** - * Set the image to be drawn in the background of the unselected tab. Image - * is stretched or compressed to cover entire unselected tab area. - * - * @param image the image to be drawn in the background - * - * @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 - */ - void setBackground (Image image) - { - checkWidget(); - if (image is bgImage) - return; - if (image !is null) - { - gradientColors = null; - gradientPercents = null; - } - bgImage = image; - redraw(); + // min button + oldX = minRect.x; + oldY = minRect.y; + oldWidth = minRect.width; + oldHeight = minRect.height; + minRect.x = minRect.y = minRect.width = minRect.height = 0; + if (showMin) { + minRect.x = size.x - borderRight - maxRect.width - BUTTON_SIZE - 3; + if (borderRight > 0) minRect.x += 1; + minRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2; + minRect.width = BUTTON_SIZE; + minRect.height = BUTTON_SIZE; } - - /** - * Toggle the visibility of the border - * - * @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 ((borderLeft is 1) is show) - return; - borderLeft = borderRight = show ? 1 : 0; - borderTop = onBottom ? borderLeft : 0; - borderBottom = onBottom ? 0 : borderLeft; - Rectangle rectBefore = getClientArea(); - updateItems(); - Rectangle rectAfter = getClientArea(); - if (!rectBefore.opEquals(rectAfter)) - { - notifyListeners(DWT.Resize, new Event()); - } - redraw(); + if (oldX !is minRect.x || oldWidth !is minRect.width || + oldY !is minRect.y || oldHeight !is minRect.height) { + int left = Math.min(oldX, minRect.x); + int right = Math.max(oldX + oldWidth, minRect.x + minRect.width); + int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1; + redraw(left, top, right - left, tabHeight, false); } - void setButtonBounds () - { - Point size = getSize(); - int oldX, oldY, oldWidth, oldHeight; - // max button - oldX = maxRect.x; - oldY = maxRect.y; - oldWidth = maxRect.width; - oldHeight = maxRect.height; - maxRect.x = maxRect.y = maxRect.width = maxRect.height = 0; - if (showMax) - { - maxRect.x = size.x - borderRight - BUTTON_SIZE - 3; - if (borderRight > 0) - maxRect.x += 1; - maxRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE) / 2 : borderTop + (tabHeight - BUTTON_SIZE) / 2; - maxRect.width = BUTTON_SIZE; - maxRect.height = BUTTON_SIZE; - } - if (oldX !is maxRect.x || oldWidth !is maxRect.width || oldY !is maxRect.y || oldHeight !is maxRect.height) - { - int left = Math.min(oldX, maxRect.x); - int right = Math.max(oldX + oldWidth, maxRect.x + maxRect.width); - int - top = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1; - redraw(left, top, right - left, tabHeight, false); - } - - // min button - oldX = minRect.x; - oldY = minRect.y; - oldWidth = minRect.width; - oldHeight = minRect.height; - minRect.x = minRect.y = minRect.width = minRect.height = 0; - if (showMin) - { - minRect.x = size.x - borderRight - maxRect.width - BUTTON_SIZE - 3; - if (borderRight > 0) - minRect.x += 1; - minRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE) / 2 : borderTop + (tabHeight - BUTTON_SIZE) / 2; - minRect.width = BUTTON_SIZE; - minRect.height = BUTTON_SIZE; - } - if (oldX !is minRect.x || oldWidth !is minRect.width || oldY !is minRect.y || oldHeight !is minRect.height) - { - int left = Math.min(oldX, minRect.x); - int right = Math.max(oldX + oldWidth, minRect.x + minRect.width); - int - top = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1; - redraw(left, top, right - left, tabHeight, false); - } - - // top right control - oldX = topRightRect.x; - oldY = topRightRect.y; - oldWidth = topRightRect.width; - oldHeight = topRightRect.height; - topRightRect.x = topRightRect.y = topRightRect.width = topRightRect.height = 0; - if (topRight !is null) - { - switch (topRightAlignment) - { - case DWT.FILL: - { - int - rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width; - if (!simple && borderRight > 0 && !showMax && !showMin) - rightEdge -= 2; - if (single) - { - if (items.length is 0 || selectedIndex is -1) - { - topRightRect.x = borderLeft + 3; - topRightRect.width = rightEdge - topRightRect.x; - } - else - { - // fill size is 0 if item compressed - CTabItem item = items[selectedIndex]; - if (item.x + item.width + 7 + 3 * BUTTON_SIZE / 2 >= rightEdge) - break; - topRightRect.x = item.x + item.width + 7 + 3 * BUTTON_SIZE / 2; - topRightRect.width = rightEdge - topRightRect.x; - } + // top right control + oldX = topRightRect.x; + oldY = topRightRect.y; + oldWidth = topRightRect.width; + oldHeight = topRightRect.height; + topRightRect.x = topRightRect.y = topRightRect.width = topRightRect.height = 0; + if (topRight !is null) { + switch (topRightAlignment) { + case DWT.FILL: { + int rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width; + if (!simple && borderRight > 0 && !showMax && !showMin) rightEdge -= 2; + if (single) { + if (items.length is 0 || selectedIndex is -1) { + topRightRect.x = borderLeft + 3; + topRightRect.width = rightEdge - topRightRect.x; + } else { + // fill size is 0 if item compressed + CTabItem item = items[selectedIndex]; + if (item.x + item.width + 7 + 3*BUTTON_SIZE/2 >= rightEdge) break; + topRightRect.x = item.x + item.width + 7 + 3*BUTTON_SIZE/2; + topRightRect.width = rightEdge - topRightRect.x; } - else - { - // fill size is 0 if chevron showing - if (showChevron) - break; - if (items.length is 0) - { - topRightRect.x = borderLeft + 3; - } - else - { - CTabItem item = items[items.length - 1]; - topRightRect.x = item.x + item.width; - if (!simple && items.length - 1 is selectedIndex) - topRightRect.x += curveWidth - curveIndent; - } - topRightRect.width = Math.max(0, - rightEdge - topRightRect.x); + } else { + // fill size is 0 if chevron showing + if (showChevron) break; + if (items.length is 0) { + topRightRect.x = borderLeft + 3; + } else { + CTabItem item = items[items.length - 1]; + topRightRect.x = item.x + item.width; + if (!simple && items.length - 1 is selectedIndex) topRightRect.x += curveWidth - curveIndent; } - topRightRect.y = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1; - topRightRect.height = tabHeight - 1; - break; + topRightRect.width = Math.max(0, rightEdge - topRightRect.x); } - case DWT.RIGHT: - { - Point topRightSize = topRight.computeSize(DWT.DEFAULT, - tabHeight, false); - int - rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width; - if (!simple && borderRight > 0 && !showMax && !showMin) - rightEdge -= 2; - topRightRect.x = rightEdge - topRightSize.x; - topRightRect.width = topRightSize.x; - topRightRect.y = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1; - topRightRect.height = tabHeight - 1; - } + topRightRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1; + topRightRect.height = tabHeight - 1; + break; } - topRight.setBounds(topRightRect); - } - if (oldX !is topRightRect.x || oldWidth !is topRightRect.width || oldY !is topRightRect.y || oldHeight !is topRightRect.height) - { - int left = Math.min(oldX, topRightRect.x); - int right = Math.max(oldX + oldWidth, - topRightRect.x + topRightRect.width); - int - top = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1; - redraw(left, top, right - left, tabHeight, false); - } - - // chevron button - oldX = chevronRect.x; - oldY = chevronRect.y; - oldWidth = chevronRect.width; - oldHeight = chevronRect.height; - chevronRect.x = chevronRect.y = chevronRect.height = chevronRect.width = 0; - if (single) - { - if (selectedIndex is -1 || items.length > 1) - { - chevronRect.width = 3 * BUTTON_SIZE / 2; - chevronRect.height = BUTTON_SIZE; - chevronRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - chevronRect.height) / 2 : borderTop + (tabHeight - chevronRect.height) / 2; - if (selectedIndex is -1) - { - chevronRect.x = size.x - borderRight - 3 - minRect.width - maxRect.width - topRightRect.width - chevronRect.width; - } - else - { - CTabItem item = items[selectedIndex]; - int - w = size.x - borderRight - 3 - minRect.width - maxRect.width - chevronRect.width; - if (topRightRect.width > 0) - w -= topRightRect.width + 3; - chevronRect.x = Math.min(item.x + item.width + 3, w); - } - if (borderRight > 0) - chevronRect.x += 1; + case DWT.RIGHT: { + Point topRightSize = topRight.computeSize(DWT.DEFAULT, tabHeight, false); + int rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width; + if (!simple && borderRight > 0 && !showMax && !showMin) rightEdge -= 2; + topRightRect.x = rightEdge - topRightSize.x; + topRightRect.width = topRightSize.x; + topRightRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1; + topRightRect.height = tabHeight - 1; } + default: } - else - { - if (showChevron) - { - chevronRect.width = 3 * BUTTON_SIZE / 2; - chevronRect.height = BUTTON_SIZE; - int i = 0, lastIndex = -1; - while (i < priority.length && items[priority[i]].showing) - { - lastIndex = Math.max(lastIndex, priority[i++]); - } - if (lastIndex is -1) - lastIndex = firstIndex; - CTabItem lastItem = items[lastIndex]; - int w = lastItem.x + lastItem.width + 3; - if (!simple && lastIndex is selectedIndex) - w += curveWidth - 2 * curveIndent; - chevronRect.x = Math.min(w, getRightItemEdge()); - chevronRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - chevronRect.height) / 2 : borderTop + (tabHeight - chevronRect.height) / 2; - } - } - if (oldX !is chevronRect.x || oldWidth !is chevronRect.width || oldY !is chevronRect.y || oldHeight !is chevronRect.height) - { - int left = Math.min(oldX, chevronRect.x); - int right = Math.max(oldX + oldWidth, - chevronRect.x + chevronRect.width); - int - top = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1; - redraw(left, top, right - left, tabHeight, false); - } + topRight.setBounds(topRightRect); } - - public void setFont (Font font) - { - checkWidget(); - if (font !is null && font.opEquals(getFont())) - return; - super.setFont(font); - oldFont = getFont(); - if (!updateTabHeight(false)) - { - updateItems(); - redraw(); - } - } - - public void setForeground (Color color) - { - super.setForeground(color); - redraw(); - } - - /** - * Display an insert marker before or after the specified tab item. - * - * A value of null will clear the mark. - * - * @param item the item with which the mark is associated or null - * - * @param after true if the mark should be displayed after the specified item - * - * @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 setInsertMark (CTabItem item, bool after) - { - checkWidget(); + if (oldX !is topRightRect.x || oldWidth !is topRightRect.width || + oldY !is topRightRect.y || oldHeight !is topRightRect.height) { + int left = Math.min(oldX, topRightRect.x); + int right = Math.max(oldX + oldWidth, topRightRect.x + topRightRect.width); + int top = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1; + redraw(left, top, right - left, tabHeight, false); } - /** - * Display an insert marker before or after the specified tab item. - * - * A value of -1 will clear the mark. - * - * @param index the index of the item with which the mark is associated or null - * - * @param after true if the mark should be displayed after the specified item - * - * @exception IllegalArgumentException
      - *
    - * - * @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 setInsertMark (int index, bool after) - { - checkWidget(); - if (index < -1 || index >= getItemCount()) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); + // chevron button + oldX = chevronRect.x; + oldY = chevronRect.y; + oldWidth = chevronRect.width; + oldHeight = chevronRect.height; + chevronRect.x = chevronRect.y = chevronRect.height = chevronRect.width = 0; + if (single) { + if (selectedIndex is -1 || items.length > 1) { + chevronRect.width = 3*BUTTON_SIZE/2; + chevronRect.height = BUTTON_SIZE; + chevronRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - chevronRect.height)/2 : borderTop + (tabHeight - chevronRect.height)/2; + if (selectedIndex is -1) { + chevronRect.x = size.x - borderRight - 3 - minRect.width - maxRect.width - topRightRect.width - chevronRect.width; + } else { + CTabItem item = items[selectedIndex]; + int w = size.x - borderRight - 3 - minRect.width - maxRect.width - chevronRect.width; + if (topRightRect.width > 0) w -= topRightRect.width + 3; + chevronRect.x = Math.min(item.x + item.width + 3, w); + } + if (borderRight > 0) chevronRect.x += 1; + } + } else { + if (showChevron) { + chevronRect.width = 3*BUTTON_SIZE/2; + chevronRect.height = BUTTON_SIZE; + int i = 0, lastIndex = -1; + while (i < priority.length && items[priority[i]].showing) { + lastIndex = Math.max(lastIndex, priority[i++]); + } + if (lastIndex is -1) lastIndex = firstIndex; + CTabItem lastItem = items[lastIndex]; + int w = lastItem.x + lastItem.width + 3; + if (!simple && lastIndex is selectedIndex) w += curveWidth - 2*curveIndent; + chevronRect.x = Math.min(w, getRightItemEdge()); + chevronRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - chevronRect.height)/2 : borderTop + (tabHeight - chevronRect.height)/2; } } - - bool setItemLocation () - { - bool changed = false; - if (items.length is 0) - return false; - Point size = getSize(); - int y = onBottom ? Math.max(borderBottom, - size.y - borderBottom - tabHeight) : borderTop; - if (single) - { - int defaultX = getDisplay().getBounds().width + 10; // off screen - for (int i = 0; i < items.length; i++) - { - CTabItem item = items[i]; - if (i is selectedIndex) - { - firstIndex = selectedIndex; - int oldX = item.x, oldY = item.y; - item.x = borderLeft; - item.y = y; - item.showing = true; - if (showClose || item.showClose) - { - item.closeRect.x = borderLeft + CTabItem.LEFT_MARGIN; - item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE) / 2 : borderTop + (tabHeight - BUTTON_SIZE) / 2; - } - if (item.x !is oldX || item.y !is oldY) - changed = true; - } - else - { - item.x = defaultX; - item.showing = false; + if (oldX !is chevronRect.x || oldWidth !is chevronRect.width || + oldY !is chevronRect.y || oldHeight !is chevronRect.height) { + int left = Math.min(oldX, chevronRect.x); + int right = Math.max(oldX + oldWidth, chevronRect.x + chevronRect.width); + int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1; + redraw(left, top, right - left, tabHeight, false); + } +} +public override void setFont(Font font) { + checkWidget(); + if (font !is null && font==getFont()) return; + super.setFont(font); + oldFont = getFont(); + if (!updateTabHeight(false)) { + updateItems(); + redraw(); + } +} +public override void setForeground (Color color) { + super.setForeground(color); + redraw(); +} +/** + * Display an insert marker before or after the specified tab item. + * + * A value of null will clear the mark. + * + * @param item the item with which the mark is associated or null + * + * @param after true if the mark should be displayed after the specified item + * + * @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 setInsertMark(CTabItem item, bool after) { + checkWidget(); +} +/** + * Display an insert marker before or after the specified tab item. + * + * A value of -1 will clear the mark. + * + * @param index the index of the item with which the mark is associated or null + * + * @param after true if the mark should be displayed after the specified item + * + * @exception IllegalArgumentException
      + *
    + * + * @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 setInsertMark(int index, bool after) { + checkWidget(); + if (index < -1 || index >= getItemCount()) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } +} +bool setItemLocation() { + bool changed = false; + if (items.length is 0) return false; + Point size = getSize(); + int y = onBottom ? Math.max(borderBottom, size.y - borderBottom - tabHeight) : borderTop; + if (single) { + int defaultX = getDisplay().getBounds().width + 10; // off screen + for (int i = 0; i < items.length; i++) { + CTabItem item = items[i]; + if (i is selectedIndex) { + firstIndex = selectedIndex; + int oldX = item.x, oldY = item.y; + item.x = borderLeft; + item.y = y; + item.showing = true; + if (showClose || item.showClose) { + item.closeRect.x = borderLeft + CTabItem.LEFT_MARGIN; + item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2; } - } - } - else - { - int rightItemEdge = getRightItemEdge(); - int maxWidth = rightItemEdge - borderLeft; - int width = 0; - for (int i = 0; i < priority.length; i++) - { - CTabItem item = items[priority[i]]; - width += item.width; - item.showing = i is 0 ? true : item.width > 0 && width <= maxWidth; - if (!simple && priority[i] is selectedIndex) - width += curveWidth - 2 * curveIndent; - } - int x = 0; - int defaultX = getDisplay().getBounds().width + 10; // off screen - firstIndex = items.length - 1; - for (int i = 0; i < items.length; i++) - { - CTabItem item = items[i]; - if (!item.showing) - { - if (item.x !is defaultX) - changed = true; - item.x = defaultX; - } - else - { - firstIndex = Math.min(firstIndex, i); - if (item.x !is x || item.y !is y) - changed = true; - item.x = x; - item.y = y; - if (i is selectedIndex) - { - int edge = Math.min(item.x + item.width, rightItemEdge); - item.closeRect.x = edge - CTabItem.RIGHT_MARGIN - BUTTON_SIZE; - } - else - { - item.closeRect.x = item.x + item.width - CTabItem.RIGHT_MARGIN - BUTTON_SIZE; - } - item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE) / 2 : borderTop + (tabHeight - BUTTON_SIZE) / 2; - x = x + item.width; - if (!simple && i is selectedIndex) - x += curveWidth - 2 * curveIndent; - } + if (item.x !is oldX || item.y !is oldY) changed = true; + } else { + item.x = defaultX; + item.showing = false; } } - return changed; - } - - bool setItemSize () - { - bool changed = false; - if (isDisposed()) - return changed; - Point size = getSize(); - if (size.x <= 0 || size.y <= 0) - return changed; - xClient = borderLeft + marginWidth + highlight_margin; - if (onBottom) - { - yClient = borderTop + highlight_margin + marginHeight; - } - else - { - yClient = borderTop + tabHeight + highlight_header + marginHeight; + } else { + int rightItemEdge = getRightItemEdge(); + int maxWidth = rightItemEdge - borderLeft; + int width = 0; + for (int i = 0; i < priority.length; i++) { + CTabItem item = items[priority[i]]; + width += item.width; + item.showing = i is 0 ? true : item.width > 0 && width <= maxWidth; + if (!simple && priority[i] is selectedIndex) width += curveWidth - 2*curveIndent; } - showChevron = false; - if (single) - { - showChevron = true; - if (selectedIndex !is -1) - { - CTabItem tab = items[selectedIndex]; - GC gc = new GC(this); - int width = tab.preferredWidth(gc, true, false); - gc.dispose(); - width = Math.min(width, getRightItemEdge() - borderLeft); - if (tab.height !is tabHeight || tab.width !is width) - { - changed = true; - tab.shortenedText = null; - tab.shortenedTextWidth = 0; - tab.height = tabHeight; - tab.width = width; - tab.closeRect.width = tab.closeRect.height = 0; - if (showClose || tab.showClose) - { - tab.closeRect.width = BUTTON_SIZE; - tab.closeRect.height = BUTTON_SIZE; - } + int x = 0; + int defaultX = getDisplay().getBounds().width + 10; // off screen + firstIndex = items.length - 1; + for (int i = 0; i < items.length; i++) { + CTabItem item = items[i]; + if (!item.showing) { + if (item.x !is defaultX) changed = true; + item.x = defaultX; + } else { + firstIndex = Math.min(firstIndex, i); + if (item.x !is x || item.y !is y) changed = true; + item.x = x; + item.y = y; + if (i is selectedIndex) { + int edge = Math.min(item.x + item.width, rightItemEdge); + item.closeRect.x = edge - CTabItem.RIGHT_MARGIN - BUTTON_SIZE; + } else { + item.closeRect.x = item.x + item.width - CTabItem.RIGHT_MARGIN - BUTTON_SIZE; } - } - return changed; - } - - if (items.length is 0) - return changed; - - int[] widths; - GC gc = new GC(this); - int tabAreaWidth = size.x - borderLeft - borderRight - 3; - if (showMin) - tabAreaWidth -= BUTTON_SIZE; - if (showMax) - tabAreaWidth -= BUTTON_SIZE; - if (topRightAlignment is DWT.RIGHT && topRight !is null) - { - Point rightSize = topRight.computeSize(DWT.DEFAULT, DWT.DEFAULT, - false); - tabAreaWidth -= rightSize.x + 3; - } - if (!simple) - tabAreaWidth -= curveWidth - 2 * curveIndent; - tabAreaWidth = Math.max(0, tabAreaWidth); - - // First, try the minimum tab size at full compression. - int minWidth = 0; - int[] minWidths = new int[items.length]; - for (int i = 0; i < priority.length; i++) - { - int index = priority[i]; - minWidths[index] = items[index].preferredWidth(gc, - index is selectedIndex, true); - minWidth += minWidths[index]; - if (minWidth > tabAreaWidth) - break; - } - if (minWidth > tabAreaWidth) - { - // full compression required and a chevron - showChevron = items.length > 1; - if (showChevron) - tabAreaWidth -= 3 * BUTTON_SIZE / 2; - widths = minWidths; - int index = selectedIndex !is -1 ? selectedIndex : 0; - if (tabAreaWidth < widths[index]) - { - widths[index] = Math.max(0, tabAreaWidth); + item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2; + x = x + item.width; + if (!simple && i is selectedIndex) x += curveWidth - 2*curveIndent; } } - else - { - int maxWidth = 0; - int[] maxWidths = new int[items.length]; - for (int i = 0; i < items.length; i++) - { - maxWidths[i] = items[i].preferredWidth(gc, i is selectedIndex, - false); - maxWidth += maxWidths[i]; - } - if (maxWidth <= tabAreaWidth) - { - // no compression required - widths = maxWidths; - } - else - { - // determine compression for each item - int extra = (tabAreaWidth - minWidth) / items.length; - while (true) - { - int large = 0, totalWidth = 0; - for (int i = 0; i < items.length; i++) - { - if (maxWidths[i] > minWidths[i] + extra) - { - totalWidth += minWidths[i] + extra; - large++; - } - else - { - totalWidth += maxWidths[i]; - } - } - if (totalWidth >= tabAreaWidth) - { - extra--; - break; - } - if (large is 0 || tabAreaWidth - totalWidth < large) - break; - extra++; - } - widths = new int[items.length]; - for (int i = 0; i < items.length; i++) - { - widths[i] = Math.min(maxWidths[i], minWidths[i] + extra); - } - } - } - gc.dispose(); - - for (int i = 0; i < items.length; i++) - { - CTabItem tab = items[i]; - int width = widths[i]; - if (tab.height !is tabHeight || tab.width !is width) - { + } + return changed; +} +bool setItemSize() { + bool changed = false; + if (isDisposed()) return changed; + Point size = getSize(); + if (size.x <= 0 || size.y <= 0) return changed; + xClient = borderLeft + marginWidth + highlight_margin; + if (onBottom) { + yClient = borderTop + highlight_margin + marginHeight; + } else { + yClient = borderTop + tabHeight + highlight_header + marginHeight; + } + showChevron = false; + if (single) { + showChevron = true; + if (selectedIndex !is -1) { + CTabItem tab = items[selectedIndex]; + GC gc = new GC(this); + int width = tab.preferredWidth(gc, true, false); + gc.dispose(); + width = Math.min(width, getRightItemEdge() - borderLeft); + if (tab.height !is tabHeight || tab.width !is width) { changed = true; tab.shortenedText = null; tab.shortenedTextWidth = 0; tab.height = tabHeight; tab.width = width; tab.closeRect.width = tab.closeRect.height = 0; - if (showClose || tab.showClose) - { - if (i is selectedIndex || showUnselectedClose) - { - tab.closeRect.width = BUTTON_SIZE; - tab.closeRect.height = BUTTON_SIZE; - } + if (showClose || tab.showClose) { + tab.closeRect.width = BUTTON_SIZE; + tab.closeRect.height = BUTTON_SIZE; } } } return changed; } - /** - * Marks the receiver's maximize button as visible if the argument is true, - * and marks it invisible otherwise. - * - * @param visible the new visibility state - * - * @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 setMaximizeVisible (bool visible) - { - checkWidget(); - if (showMax is visible) - return; - // display maximize button - showMax = visible; - updateItems(); - redraw(); + if (items.length is 0) return changed; + + int[] widths; + GC gc = new GC(this); + int tabAreaWidth = size.x - borderLeft - borderRight - 3; + if (showMin) tabAreaWidth -= BUTTON_SIZE; + if (showMax) tabAreaWidth -= BUTTON_SIZE; + if (topRightAlignment is DWT.RIGHT && topRight !is null) { + Point rightSize = topRight.computeSize(DWT.DEFAULT, DWT.DEFAULT, false); + tabAreaWidth -= rightSize.x + 3; + } + if (!simple) tabAreaWidth -= curveWidth - 2*curveIndent; + tabAreaWidth = Math.max(0, tabAreaWidth); + + // First, try the minimum tab size at full compression. + int minWidth = 0; + int[] minWidths = new int[items.length]; + for (int i = 0; i < priority.length; i++) { + int index = priority[i]; + minWidths[index] = items[index].preferredWidth(gc, index is selectedIndex, true); + minWidth += minWidths[index]; + if (minWidth > tabAreaWidth) break; + } + if (minWidth > tabAreaWidth) { + // full compression required and a chevron + showChevron = items.length > 1; + if (showChevron) tabAreaWidth -= 3*BUTTON_SIZE/2; + widths = minWidths; + int index = selectedIndex !is -1 ? selectedIndex : 0; + if (tabAreaWidth < widths[index]) { + widths[index] = Math.max(0, tabAreaWidth); + } + } else { + int maxWidth = 0; + int[] maxWidths = new int[items.length]; + for (int i = 0; i < items.length; i++) { + maxWidths[i] = items[i].preferredWidth(gc, i is selectedIndex, false); + maxWidth += maxWidths[i]; + } + if (maxWidth <= tabAreaWidth) { + // no compression required + widths = maxWidths; + } else { + // determine compression for each item + int extra = (tabAreaWidth - minWidth) / items.length; + while (true) { + int large = 0, totalWidth = 0; + for (int i = 0 ; i < items.length; i++) { + if (maxWidths[i] > minWidths[i] + extra) { + totalWidth += minWidths[i] + extra; + large++; + } else { + totalWidth += maxWidths[i]; + } + } + if (totalWidth >= tabAreaWidth) { + extra--; + break; + } + if (large is 0 || tabAreaWidth - totalWidth < large) break; + extra++; + } + widths = new int[items.length]; + for (int i = 0; i < items.length; i++) { + widths[i] = Math.min(maxWidths[i], minWidths[i] + extra); + } + } + } + gc.dispose(); + + for (int i = 0; i < items.length; i++) { + CTabItem tab = items[i]; + int width = widths[i]; + if (tab.height !is tabHeight || tab.width !is width) { + changed = true; + tab.shortenedText = null; + tab.shortenedTextWidth = 0; + tab.height = tabHeight; + tab.width = width; + tab.closeRect.width = tab.closeRect.height = 0; + if (showClose || tab.showClose) { + if (i is selectedIndex || showUnselectedClose) { + tab.closeRect.width = BUTTON_SIZE; + tab.closeRect.height = BUTTON_SIZE; + } + } + } } + return changed; +} +/** + * Marks the receiver's maximize button as visible if the argument is true, + * and marks it invisible otherwise. + * + * @param visible the new visibility state + * + * @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 setMaximizeVisible(bool visible) { + checkWidget(); + if (showMax is visible) return; + // display maximize button + showMax = visible; + updateItems(); + redraw(); +} +/** + * 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 override void setLayout (Layout layout) { + checkWidget(); + return; +} +/** + * Sets the maximized state of the receiver. + * + * @param maximize the new maximized state + * + * @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 setMaximized(bool maximize) { + checkWidget (); + if (this.maximized is maximize) return; + if (maximize && this.minimized) setMinimized(false); + this.maximized = maximize; + redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false); +} +/** + * Marks the receiver's minimize button as visible if the argument is true, + * and marks it invisible otherwise. + * + * @param visible the new visibility state + * + * @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 setMinimizeVisible(bool visible) { + checkWidget(); + if (showMin is visible) return; + // display minimize button + showMin = visible; + updateItems(); + redraw(); +} +/** + * Sets the minimized state of the receiver. + * + * @param minimize the new minimized state + * + * @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 setMinimized(bool minimize) { + checkWidget (); + if (this.minimized is minimize) return; + if (minimize && this.maximized) setMaximized(false); + this.minimized = minimize; + redraw(minRect.x, minRect.y, minRect.width, minRect.height, 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(); +/** + * Sets the minimum number of characters that will + * be displayed in a fully compressed tab. + * + * @param count the minimum number of characters that will be displayed in a fully compressed tab + * + * @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_RANGE - if the count is less than zero
    • + *
    + * + * @since 3.0 + */ +public void setMinimumCharacters(int count) { + checkWidget (); + if (count < 0) DWT.error(DWT.ERROR_INVALID_RANGE); + if (minChars is count) return; + minChars = count; + if (updateItems()) redrawTabs(); +} + +/** + * 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).

    + * + * @param show the new visibility state + * + * @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 setMRUVisible(bool show) { + checkWidget(); + if (mru is show) return; + mru = show; + if (!mru) { + int idx = firstIndex; + int next = 0; + for (int i = firstIndex; i < items.length; i++) { + priority[next++] = i; + } + for (int i = 0; i < idx; i++) { + priority[next++] = i; + } + if (updateItems()) redrawTabs(); + } +} +/** + * Set the selection to the tab at the specified item. + * + * @param item the tab item to be selected + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item 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 setSelection(CTabItem item) { + checkWidget(); + if (item is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + int index = indexOf(item); + setSelection(index); +} +/** + * Set the selection to the tab at the specified index. + * + * @param index the index of the tab item to be selected + * + * @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 setSelection(int index) { + checkWidget(); + if (index < 0 || index >= items.length) return; + CTabItem selection = items[index]; + if (selectedIndex is index) { + showItem(selection); return; } - /** - * Sets the maximized state of the receiver. - * - * @param maximize the new maximized state - * - * @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 setMaximized (bool maximize) - { - checkWidget(); - if (this.maximized is maximize) - return; - if (maximize && this.minimized) - setMinimized(false); - this.maximized = maximize; - redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false); + int oldIndex = selectedIndex; + selectedIndex = index; + if (oldIndex !is -1) { + items[oldIndex].closeImageState = NONE; } + selection.closeImageState = NORMAL; + selection.showing = false; - /** - * Marks the receiver's minimize button as visible if the argument is true, - * and marks it invisible otherwise. - * - * @param visible the new visibility state - * - * @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 setMinimizeVisible (bool visible) - { - checkWidget(); - if (showMin is visible) - return; - // display minimize button - showMin = visible; - updateItems(); - redraw(); + Control newControl = selection.control; + Control oldControl = null; + if (oldIndex !is -1) { + oldControl = items[oldIndex].control; } - /** - * Sets the minimized state of the receiver. - * - * @param minimize the new minimized state - * - * @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 setMinimized (bool minimize) - { - checkWidget(); - if (this.minimized is minimize) - return; - if (minimize && this.maximized) - setMaximized(false); - this.minimized = minimize; - redraw(minRect.x, minRect.y, minRect.width, minRect.height, false); + if (newControl !is oldControl) { + if (newControl !is null && !newControl.isDisposed()) { + newControl.setBounds(getClientArea()); + newControl.setVisible(true); + } + if (oldControl !is null && !oldControl.isDisposed()) { + oldControl.setVisible(false); + } + } + showItem(selection); + redraw(); +} +void setSelection(int index, bool notify) { + int oldSelectedIndex = selectedIndex; + setSelection(index); + if (notify && selectedIndex !is oldSelectedIndex && selectedIndex !is -1) { + Event event = new Event(); + event.item = getItem(selectedIndex); + notifyListeners(DWT.Selection, event); + } +} +/** + * Sets the receiver's selection background color to the color specified + * by the argument, or to the default system color for the control + * if the argument is null. + * + * @param color the new color (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    + * @exception 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 setSelectionBackground (Color color) { + checkWidget(); + setSelectionHighlightGradientColor(null); + if (selectionBackground is color) return; + if (color is null) color = getDisplay().getSystemColor(SELECTION_BACKGROUND); + selectionBackground = color; + if (selectedIndex > -1) redraw(); +} +/** + * Specify a gradient of colours to be draw in the background of the selected tab. + * For example to draw a gradient that varies from dark blue to blue and then to + * white, use the following call to setBackground: + *
    + *  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
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + */ +public void setSelectionBackground(Color[] colors, int[] percents) { + setSelectionBackground(colors, percents, false); +} +/** + * Specify a gradient of colours to be draw in the background of the selected tab. + * For example to draw a vertical gradient that varies from dark blue to blue and then to + * white, use the following call to setBackground: + *
    + *  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
      + *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • + *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • + *
    + * + * @since 3.0 + */ +public void setSelectionBackground(Color[] colors, int[] percents, bool vertical) { + checkWidget(); + int colorsLength; + Color highlightBeginColor = null; //null is no highlight + + if (colors !is null) { + //The colors array can optionally have an extra entry which describes the highlight top color + //Thus its either one or two larger than the percents array + if (percents is null || + ! ((percents.length is colors.length - 1) || (percents.length is colors.length - 2))){ + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + for (int i = 0; i < percents.length; i++) { + if (percents[i] < 0 || percents[i] > 100) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (i > 0 && percents[i] < percents[i-1]) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + } + //If the colors is exactly two more than percents then last is highlight + //Keep track of *real* colorsLength (minus the highlight) + if(percents.length is colors.length - 2) { + highlightBeginColor = colors[colors.length - 1]; + colorsLength = colors.length - 1; + } else { + colorsLength = colors.length; + } + if (getDisplay().getDepth() < 15) { + // Don't use gradients on low color displays + colors = [colors[colorsLength - 1]]; + colorsLength = colors.length; + percents = null; + } + } else { + colorsLength = 0; } - /** - * Sets the minimum number of characters that will - * be displayed in a fully compressed tab. - * - * @param count the minimum number of characters that will be displayed in a fully compressed tab - * - * @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_RANGE - if the count is less than zero
    • - *
    - * - * @since 3.0 - */ - public void setMinimumCharacters (int count) - { - checkWidget(); - if (count < 0) - DWT.error(DWT.ERROR_INVALID_RANGE); - if (minChars is count) - return; - minChars = count; - if (updateItems()) - redrawTabs(); + // Are these settings the same as before? + if (selectionBgImage is null) { + if ((selectionGradientColors !is null) && (colors !is null) && + (selectionGradientColors.length is colorsLength)) { + bool same = false; + for (int i = 0; i < selectionGradientColors.length; i++) { + if (selectionGradientColors[i] is null) { + same = colors[i] is null; + } else { + same = cast(bool)(selectionGradientColors[i]==colors[i]); + } + if (!same) break; + } + if (same) { + for (int i = 0; i < selectionGradientPercents.length; i++) { + same = selectionGradientPercents[i] is percents[i]; + if (!same) break; + } + } + if (same && this.selectionGradientVertical is vertical) return; + } + } else { + selectionBgImage = null; + } + // Store the new settings + if (colors is null) { + selectionGradientColors = null; + selectionGradientPercents = null; + selectionGradientVertical = false; + setSelectionBackground(cast(Color)null); + setSelectionHighlightGradientColor(null); + } else { + selectionGradientColors = new Color[colorsLength]; + for (int i = 0; i < colorsLength; ++i) { + selectionGradientColors[i] = colors[i]; + } + selectionGradientPercents = new int[percents.length]; + for (int i = 0; i < percents.length; ++i) { + selectionGradientPercents[i] = percents[i]; + } + selectionGradientVertical = vertical; + setSelectionBackground(selectionGradientColors[selectionGradientColors.length-1]); + setSelectionHighlightGradientColor(highlightBeginColor); } - /** - * 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).

    - * - * @param show the new visibility state - * - * @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 setMRUVisible (bool show) - { - checkWidget(); - if (mru is show) - return; - mru = show; - if (!mru) - { - int idx = firstIndex; - int next = 0; - for (int i = firstIndex; i < items.length; i++) - { - priority[next++] = i; + // Refresh with the new settings + if (selectedIndex > -1) redraw(); +} + +/* + * Set the color for the highlight start for selected tabs. + * Update the cache of highlight gradient colors if required. + */ + +void setSelectionHighlightGradientColor(Color start) { + //Set to null to match all the early return cases. + //For early returns, don't realloc the cache, we may get a cache hit next time we're given the highlight + selectionHighlightGradientBegin = null; + + if(start is null) + return; + + //don't bother on low colour + if (getDisplay().getDepth() < 15) + return; + + //don't bother if we don't have a background gradient + if(selectionGradientColors.length < 2) + return; + + //OK we know its a valid gradient now + selectionHighlightGradientBegin = start; + + if(! isSelectionHighlightColorsCacheHit(start)) + createSelectionHighlightGradientColors(start); //if no cache hit then compute new ones +} + +/* + * Return true if given start color, the cache of highlight colors we have + * would match the highlight colors we'd compute. + */ +bool isSelectionHighlightColorsCacheHit(Color start) { + + if(selectionHighlightGradientColorsCache is null) + return false; + + //this case should never happen but check to be safe before accessing array indexes + if(selectionHighlightGradientColorsCache.length < 2) + return false; + + Color highlightBegin = selectionHighlightGradientColorsCache[0]; + Color highlightEnd = selectionHighlightGradientColorsCache[selectionHighlightGradientColorsCache.length - 1]; + + if( highlightBegin!=start) + return false; + + //Compare number of colours we have vs. we'd compute + if(selectionHighlightGradientColorsCache.length !is tabHeight) + return false; + + //Compare existing highlight end to what it would be (selectionBackground) + if( highlightEnd!=selectionBackground) + return false; + + return true; +} + +/** + * Set the image to be drawn in the background of the selected tab. Image + * is stretched or compressed to cover entire selection tab area. + * + * @param image the image to be drawn in the background + * + * @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 setSelectionBackground(Image image) { + checkWidget(); + setSelectionHighlightGradientColor(null); + if (image is selectionBgImage) return; + if (image !is null) { + selectionGradientColors = null; + selectionGradientPercents = null; + disposeSelectionHighlightGradientColors(); + } + selectionBgImage = image; + if (selectedIndex > -1) redraw(); +} +/** + * Set the foreground color of the selected tab. + * + * @param color the color of the text displayed in the selected tab + * + * @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 setSelectionForeground (Color color) { + checkWidget(); + if (selectionForeground is color) return; + if (color is null) color = getDisplay().getSystemColor(SELECTION_FOREGROUND); + selectionForeground = color; + if (selectedIndex > -1) redraw(); +} + +/* + * Allocate colors for the highlight line. + * Colours will be a gradual blend ranging from to. + * Blend length will be tab height. + * Recompute this if tab height changes. + * Could remain null if there'd be no gradient (start=end or low colour display) + */ +void createSelectionHighlightGradientColors(Color start) { + disposeSelectionHighlightGradientColors(); //dispose if existing + + if(start is null) //shouldn't happen but just to be safe + return; + + //alloc colours for entire height to ensure it matches wherever we stop drawing + int fadeGradientSize = tabHeight; + + RGB from = start.getRGB(); + RGB to = selectionBackground.getRGB(); + + selectionHighlightGradientColorsCache = new Color[fadeGradientSize]; + int denom = fadeGradientSize - 1; + + for (int i = 0; i < fadeGradientSize; i++) { + int propFrom = denom - i; + int propTo = i; + int red = (to.red * propTo + from.red * propFrom) / denom; + int green = (to.green * propTo + from.green * propFrom) / denom; + int blue = (to.blue * propTo + from.blue * propFrom) / denom; + selectionHighlightGradientColorsCache[i] = new Color(getDisplay(), red, green, blue); + } +} + +void disposeSelectionHighlightGradientColors() { + if(selectionHighlightGradientColorsCache is null) + return; + for (int i = 0; i < selectionHighlightGradientColorsCache.length; i++) { + selectionHighlightGradientColorsCache[i].dispose(); + } + selectionHighlightGradientColorsCache = null; +} + +/* + * Return the gradient start color for selected tabs, which is the start of the tab fade + * (end is selectionBackground). + */ +Color getSelectionBackgroundGradientBegin() { + if (selectionGradientColors is null) + return getSelectionBackground(); + if (selectionGradientColors.length is 0) + return getSelectionBackground(); + return selectionGradientColors[0]; +} + +/** + * Sets the shape that the CTabFolder will use to render itself. + * + * @param simple true if the CTabFolder should render itself in a simple, traditional style + * + * @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 setSimple(bool simple) { + checkWidget(); + if (this.simple !is simple) { + this.simple = simple; + Rectangle rectBefore = getClientArea(); + updateItems(); + Rectangle rectAfter = getClientArea(); + if (rectBefore!=rectAfter) { + notifyListeners(DWT.Resize, new Event()); + } + redraw(); + } +} +/** + * Sets the number of tabs that the CTabFolder should display + * + * @param single true if only the selected tab should be displayed otherwise, multiple tabs will be shown. + * + * @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 setSingle(bool single) { + checkWidget(); + if (this.single !is single) { + this.single = single; + if (!single) { + for (int i = 0; i < items.length; i++) { + if (i !is selectedIndex && items[i].closeImageState is NORMAL) { + items[i].closeImageState = NONE; + } } - for (int i = 0; i < idx; i++) - { - priority[next++] = i; - } - if (updateItems()) - redrawTabs(); + } + Rectangle rectBefore = getClientArea(); + updateItems(); + Rectangle rectAfter = getClientArea(); + if (rectBefore!=rectAfter) { + notifyListeners(DWT.Resize, new Event()); + } + redraw(); + } +} +/** + * Specify a fixed height for the tab items. If no height is specified, + * the default height is the height of the text or the image, whichever + * is greater. Specifying a height of -1 will revert to the default height. + * + * @param height the pixel value of the height or -1 + * + * @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 called with a height of less than 0
    • + *
    + */ +public void setTabHeight(int height) { + checkWidget(); + if (height < -1) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + fixedTabHeight = height; + updateTabHeight(false); +} +/** + * Specify whether the tabs should appear along the top of the folder + * or along the bottom of the folder. + * + * @param position DWT.TOP for tabs along the top or DWT.BOTTOM for tabs along the bottom + * + * @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 position value is not either DWT.TOP or DWT.BOTTOM
    • + *
    + * + * @since 3.0 + */ +public void setTabPosition(int position) { + checkWidget(); + if (position !is DWT.TOP && position !is DWT.BOTTOM) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (onBottom !is (position is DWT.BOTTOM)) { + onBottom = position is DWT.BOTTOM; + borderTop = onBottom ? borderLeft : 0; + borderBottom = onBottom ? 0 : borderRight; + updateTabHeight(true); + Rectangle rectBefore = getClientArea(); + updateItems(); + Rectangle rectAfter = getClientArea(); + if (rectBefore!=rectAfter) { + notifyListeners(DWT.Resize, new Event()); + } + redraw(); + } +} +/** + * Set the control that appears in the top right corner of the tab folder. + * Typically this is a close button or a composite with a Menu and close button. + * The topRight control is optional. Setting the top right control to null will + * remove it from the tab folder. + * + * @param control 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 CTabFolder
    • + *
    + * + * @since 2.1 + */ +public void setTopRight(Control control) { + setTopRight(control, DWT.RIGHT); +} +/** + * Set the control that appears in the top right corner of the tab folder. + * Typically this is a close button or a composite with a Menu and close button. + * The topRight control is optional. Setting the top right control to null + * will remove it from the tab folder. + *

    + * 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. + *

    + * + * @param control the control to be displayed in the top right corner or null + * @param alignment DWT.RIGHT or DWT.FILL + * + * @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 CTabFolder
    • + *
    + * + * @since 3.0 + */ +public void setTopRight(Control control, int alignment) { + checkWidget(); + if (alignment !is DWT.RIGHT && alignment !is DWT.FILL) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + if (control !is null && control.getParent() !is this) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + topRight = control; + topRightAlignment = alignment; + if (updateItems()) redraw(); +} +/** + * Specify whether the close button appears + * when the user hovers over an unselected tabs. + * + * @param visible true makes the close button appear + * + * @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 setUnselectedCloseVisible(bool visible) { + checkWidget(); + if (showUnselectedClose is visible) return; + // display close button when mouse hovers + showUnselectedClose = visible; + updateItems(); + redraw(); +} +/** + * Specify whether the image appears on unselected tabs. + * + * @param visible true makes the image appear + * + * @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 setUnselectedImageVisible(bool visible) { + checkWidget(); + if (showUnselectedImage is visible) return; + // display image on unselected items + showUnselectedImage = visible; + updateItems(); + redraw(); +} +/** + * Shows the item. If the item is already showing in the receiver, + * this method simply returns. Otherwise, the items are scrolled until + * the item is visible. + * + * @param item the item to be shown + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the item is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • + *
    + * @exception 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 CTabFolder#showSelection() + * + * @since 2.0 + */ +public void showItem (CTabItem item) { + checkWidget(); + if (item is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + int index = indexOf(item); + if (index is -1) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + int idx = -1; + for (int i = 0; i < priority.length; i++) { + if (priority[i] is index) { + idx = i; + break; } } - - /** - * Set the selection to the tab at the specified item. - * - * @param item the tab item to be selected - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the listener 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 setSelection (CTabItem item) - { - checkWidget(); - if (item is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - int index = indexOf(item); - setSelection(index); + if (mru) { + // move to front of mru order + int[] newPriority = new int[priority.length]; + System.arraycopy(priority, 0, newPriority, 1, idx); + System.arraycopy(priority, idx+1, newPriority, idx+1, priority.length - idx - 1); + newPriority[0] = index; + priority = newPriority; + } + if (item.isShowing()) return; + updateItems(index); + redrawTabs(); +} +void showList (Rectangle rect) { + if (items.length is 0 || !showChevron) return; + if (showMenu is null || showMenu.isDisposed()) { + showMenu = new Menu(this); + } else { + MenuItem[] items = showMenu.getItems(); + for (int i = 0; i < items.length; i++) { + items[i].dispose(); + } } + static const String id = "CTabFolder_showList_Index"; //$NON-NLS-1$ + for (int i = 0; i < items.length; i++) { + CTabItem tab = items[i]; + if (tab.showing) continue; + MenuItem item = new MenuItem(showMenu, DWT.NONE); + item.setText(tab.getText()); + item.setImage(tab.getImage()); + item.setData(id, tab); + item.addSelectionListener(new class() SelectionAdapter { + public void widgetSelected(SelectionEvent e) { + MenuItem menuItem = cast(MenuItem)e.widget; + int index = indexOf(cast(CTabItem)menuItem.getData(id)); + this.outer.setSelection(index, true); + } + }); + } + int x = rect.x; + int y = rect.y + rect.height; + Point location = getDisplay().map(this, null, x, y); + showMenu.setLocation(location.x, location.y); + showMenu.setVisible(true); +} +/** + * Shows the selection. If the selection is already showing in the receiver, + * this method simply returns. Otherwise, the items are scrolled until + * the selection is visible. + * + * @exception 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 CTabFolder#showItem(CTabItem) + * + * @since 2.0 + */ +public void showSelection () { + checkWidget (); + if (selectedIndex !is -1) { + showItem(getSelection()); + } +} - /** - * Set the selection to the tab at the specified index. - * - * @param index the index of the tab item to be selected - * - * @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 setSelection (int index) - { - checkWidget(); - if (index < 0 || index >= items.length) - return; - CTabItem selection = items[index]; - if (selectedIndex is index) - { - showItem(selection); - return; - } +void _setToolTipText (int x, int y) { + String oldTip = getToolTipText(); + String newTip = _getToolTip(x, y); + if (newTip is null || newTip!=oldTip) { + setToolTipText(newTip); + } +} - int oldIndex = selectedIndex; - selectedIndex = index; - if (oldIndex !is -1) - { - items[oldIndex].closeImageState = NONE; - } - selection.closeImageState = NORMAL; - selection.showing = false; +bool updateItems() { + return updateItems(selectedIndex); +} - Control newControl = selection.control; - Control oldControl = null; - if (oldIndex !is -1) - { - oldControl = items[oldIndex].control; - } - - if (newControl !is oldControl) - { - if (newControl !is null && !newControl.isDisposed()) - { - newControl.setBounds(getClientArea()); - newControl.setVisible(true); +bool updateItems(int showIndex) { + if (!single && !mru && showIndex !is -1) { + // make sure selected item will be showing + int firstIndex = showIndex; + if (priority[0] < showIndex) { + int maxWidth = getRightItemEdge() - borderLeft; + if (!simple) maxWidth -= curveWidth - 2*curveIndent; + int width = 0; + int[] widths = new int[items.length]; + GC gc = new GC(this); + for (int i = priority[0]; i <= showIndex; i++) { + widths[i] = items[i].preferredWidth(gc, i is selectedIndex, true); + width += widths[i]; + if (width > maxWidth) break; } - if (oldControl !is null && !oldControl.isDisposed()) - { - oldControl.setVisible(false); + if (width > maxWidth) { + width = 0; + for (int i = showIndex; i >= 0; i--) { + if (widths[i] is 0) widths[i] = items[i].preferredWidth(gc, i is selectedIndex, true); + width += widths[i]; + if (width > maxWidth) break; + firstIndex = i; + } + } else { + firstIndex = priority[0]; + for (int i = showIndex + 1; i < items.length; i++) { + widths[i] = items[i].preferredWidth(gc, i is selectedIndex, true); + width += widths[i]; + if (width >= maxWidth) break; + } + if (width < maxWidth) { + for (int i = priority[0] - 1; i >= 0; i--) { + if (widths[i] is 0) widths[i] = items[i].preferredWidth(gc, i is selectedIndex, true); + width += widths[i]; + if (width > maxWidth) break; + firstIndex = i; + } + } } + gc.dispose(); } - showItem(selection); - redraw(); - } - - void setSelection (int index, bool notify) - { - int oldSelectedIndex = selectedIndex; - setSelection(index); - if (notify && selectedIndex !is oldSelectedIndex && selectedIndex !is -1) - { - Event event = new Event(); - event.item = getItem(selectedIndex); - notifyListeners(DWT.Selection, event); + if (firstIndex !is priority[0]) { + int index = 0; + for (int i = firstIndex; i < items.length; i++) { + priority[index++] = i; + } + for (int i = 0; i < firstIndex; i++) { + priority[index++] = i; + } } } - /** - * Sets the receiver's selection background color to the color specified - * by the argument, or to the default system color for the control - * if the argument is null. - * - * @param color the new color (or null) - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • - *
    - * @exception 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 setSelectionBackground (Color color) - { - checkWidget(); - setSelectionHighlightGradientColor(null); - if (selectionBackground is color) - return; - if (color is null) - color = getDisplay().getSystemColor(SELECTION_BACKGROUND); - selectionBackground = color; - if (selectedIndex > -1) - redraw(); - } - - /** - * Specify a gradient of colours to be draw in the background of the selected tab. - * For example to draw a gradient that varies from dark blue to blue and then to - * white, use the following call to setBackground: - *
    -     *  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
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - */ - public void setSelectionBackground (Color[] colors, int[] percents) - { - setSelectionBackground(colors, percents, false); + bool oldShowChevron = showChevron; + bool changed = setItemSize(); + changed |= setItemLocation(); + setButtonBounds(); + changed |= showChevron !is oldShowChevron; + if (changed && getToolTipText() !is null) { + Point pt = getDisplay().getCursorLocation(); + pt = toControl(pt); + _setToolTipText(pt.x, pt.y); } - - /** - * Specify a gradient of colours to be draw in the background of the selected tab. - * For example to draw a vertical gradient that varies from dark blue to blue and then to - * white, use the following call to setBackground: - *
    -     *  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
      - *
    • ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
    • - *
    • ERROR_WIDGET_DISPOSED when the widget has been disposed
    • - *
    - * - * @since 3.0 - */ - public void setSelectionBackground (Color[] colors, int[] percents, - bool vertical) - { - checkWidget(); - int colorsLength; - Color highlightBeginColor = null; //null is no highlight - - if (colors !is null) - { - //The colors array can optionally have an extra entry which describes the highlight top color - //Thus its either one or two larger than the percents array - if (percents is null || !((percents.length is colors.length - 1) || (percents.length is colors.length - 2))) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - for (int i = 0; i < percents.length; i++) - { - if (percents[i] < 0 || percents[i] > 100) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (i > 0 && percents[i] < percents[i - 1]) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - } - //If the colors is exactly two more than percents then last is highlight - //Keep track of *real* colorsLength (minus the highlight) - if (percents.length is colors.length - 2) - { - highlightBeginColor = colors[colors.length - 1]; - colorsLength = colors.length - 1; - } - else - { - colorsLength = colors.length; - } - if (getDisplay().getDepth() < 15) - { - // Don't use gradients on low color displays - colors = new Color[][colors[colorsLength - 1]]; - colorsLength = colors.length; - percents = new int[][]; - } - } - else - { - colorsLength = 0; - } - - // Are these settings the same as before? - if (selectionBgImage is null) - { - if ((selectionGradientColors !is null) && (colors !is null) && (selectionGradientColors.length is colorsLength)) - { - bool same = false; - for (int i = 0; i < selectionGradientColors.length; i++) - { - if (selectionGradientColors[i] is null) - { - same = colors[i] is null; - } - else - { - same = selectionGradientColors[i].opEquals(colors[i]); - } - if (!same) - break; - } - if (same) - { - for (int i = 0; i < selectionGradientPercents.length; i++) - { - same = selectionGradientPercents[i] is percents[i]; - if (!same) - break; - } - } - if (same && this.selectionGradientVertical is vertical) - return; + return changed; +} +bool updateTabHeight(bool force){ + int style = getStyle(); + if (fixedTabHeight is 0 && (style & DWT.FLAT) !is 0 && (style & DWT.BORDER) is 0) highlight_header = 0; + int oldHeight = tabHeight; + if (fixedTabHeight !is DWT.DEFAULT) { + tabHeight = fixedTabHeight is 0 ? 0 : fixedTabHeight + 1; // +1 for line drawn across top of tab + } else { + int tempHeight = 0; + GC gc = new GC(this); + if (items.length is 0) { + tempHeight = gc.textExtent("Default", CTabItem.FLAGS).y + CTabItem.TOP_MARGIN + CTabItem.BOTTOM_MARGIN; //$NON-NLS-1$ + } else { + for (int i=0; i < items.length; i++) { + tempHeight = Math.max(tempHeight, items[i].preferredHeight(gc)); } } - else - { - selectionBgImage = null; - } - // Store the new settings - if (colors is null) - { - selectionGradientColors = null; - selectionGradientPercents = null; - selectionGradientVertical = false; - setSelectionBackground(cast(Color) null); - setSelectionHighlightGradientColor(null); - } - else - { - selectionGradientColors = new Color[colorsLength]; - for (int i = 0; i < colorsLength; ++i) - { - selectionGradientColors[i] = colors[i]; - } - selectionGradientPercents = new int[percents.length]; - for (int i = 0; i < percents.length; ++i) - { - selectionGradientPercents[i] = percents[i]; - } - selectionGradientVertical = vertical; - setSelectionBackground( - selectionGradientColors[selectionGradientColors.length - 1]); - setSelectionHighlightGradientColor(highlightBeginColor); - } - - // Refresh with the new settings - if (selectedIndex > -1) - redraw(); - } - - /* - * Set the color for the highlight start for selected tabs. - * Update the cache of highlight gradient colors if required. - */ - - void setSelectionHighlightGradientColor (Color start) - { - //Set to null to match all the early return cases. - //For early returns, don't realloc the cache, we may get a cache hit next time we're given the highlight - selectionHighlightGradientBegin = null; - - if (start is null) - return; - - //don't bother on low colour - if (getDisplay().getDepth() < 15) - return; - - //don't bother if we don't have a background gradient - if (selectionGradientColors.length < 2) - return; - - //OK we know its a valid gradient now - selectionHighlightGradientBegin = start; - - if (!isSelectionHighlightColorsCacheHit(start)) - createSelectionHighlightGradientColors(start); //if no cache hit then compute new ones + gc.dispose(); + tabHeight = tempHeight; } - - /* - * Return true if given start color, the cache of highlight colors we have - * would match the highlight colors we'd compute. - */ - bool isSelectionHighlightColorsCacheHit (Color start) - { - - if (selectionHighlightGradientColorsCache is null) - return false; - - //this case should never happen but check to be safe before accessing array indexes - if (selectionHighlightGradientColorsCache.length < 2) - return false; - - Color highlightBegin = selectionHighlightGradientColorsCache[0]; - Color - highlightEnd = selectionHighlightGradientColorsCache[selectionHighlightGradientColorsCache.length - 1]; - - if (!highlightBegin.opEquals(start)) - return false; - - //Compare number of colours we have vs. we'd compute - if (selectionHighlightGradientColorsCache.length !is tabHeight) - return false; - - //Compare existing highlight end to what it would be (selectionBackground) - if (!highlightEnd.opEquals(selectionBackground)) - return false; - - return true; - } - - /** - * Set the image to be drawn in the background of the selected tab. Image - * is stretched or compressed to cover entire selection tab area. - * - * @param image the image to be drawn in the background - * - * @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 setSelectionBackground (Image image) - { - checkWidget(); - setSelectionHighlightGradientColor(null); - if (image is selectionBgImage) - return; - if (image !is null) - { - selectionGradientColors = null; - selectionGradientPercents = null; - disposeSelectionHighlightGradientColors(); - } - selectionBgImage = image; - if (selectedIndex > -1) - redraw(); - } - - /** - * Set the foreground color of the selected tab. - * - * @param color the color of the text displayed in the selected tab - * - * @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 setSelectionForeground (Color color) - { - checkWidget(); - if (selectionForeground is color) - return; - if (color is null) - color = getDisplay().getSystemColor(SELECTION_FOREGROUND); - selectionForeground = color; - if (selectedIndex > -1) - redraw(); - } - - /* - * Allocate colors for the highlight line. - * Colours will be a gradual blend ranging from to. - * Blend length will be tab height. - * Recompute this if tab height changes. - * Could remain null if there'd be no gradient (start=end or low colour display) - */ - void createSelectionHighlightGradientColors (Color start) - { - disposeSelectionHighlightGradientColors(); //dispose if existing - - if (start is null) - //shouldn't happen but just to be safe - return; - - //alloc colours for entire height to ensure it matches wherever we stop drawing - int fadeGradientSize = tabHeight; - - RGB from = start.getRGB(); - RGB to = selectionBackground.getRGB(); - - selectionHighlightGradientColorsCache = new Color[fadeGradientSize]; - int denom = fadeGradientSize - 1; + if (!force && tabHeight is oldHeight) return false; - for (int i = 0; i < fadeGradientSize; i++) - { - int propFrom = denom - i; - int propTo = i; - int red = (to.red * propTo + from.red * propFrom) / denom; - int green = (to.green * propTo + from.green * propFrom) / denom; - int blue = (to.blue * propTo + from.blue * propFrom) / denom; - selectionHighlightGradientColorsCache[i] = new Color(getDisplay(), - red, green, blue); - } - } - - void disposeSelectionHighlightGradientColors () - { - if (selectionHighlightGradientColorsCache is null) - return; - for (int i = 0; i < selectionHighlightGradientColorsCache.length; i++) - { - selectionHighlightGradientColorsCache[i].dispose(); - } - selectionHighlightGradientColorsCache = null; - } - - /* - * Return the gradient start color for selected tabs, which is the start of the tab fade - * (end is selectionBackground). - */ - Color getSelectionBackgroundGradientBegin () - { - if (selectionGradientColors is null) - return getSelectionBackground(); - if (selectionGradientColors.length is 0) - return getSelectionBackground(); - return selectionGradientColors[0]; - } - - /** - * Sets the shape that the CTabFolder will use to render itself. - * - * @param simple true if the CTabFolder should render itself in a simple, traditional style - * - * @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 setSimple (bool simple) - { - checkWidget(); - if (this.simple !is simple) - { - this.simple = simple; - Rectangle rectBefore = getClientArea(); - updateItems(); - Rectangle rectAfter = getClientArea(); - if (!rectBefore.opEquals(rectAfter)) - { - notifyListeners(DWT.Resize, new Event()); - } - redraw(); - } - } - - /** - * Sets the number of tabs that the CTabFolder should display - * - * @param single true if only the selected tab should be displayed otherwise, multiple tabs will be shown. - * - * @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 setSingle (bool single) - { - checkWidget(); - if (this.single !is single) - { - this.single = single; - if (!single) - { - for (int i = 0; i < items.length; i++) - { - if (i !is selectedIndex && items[i].closeImageState is NORMAL) - { - items[i].closeImageState = NONE; - } - } - } - Rectangle rectBefore = getClientArea(); - updateItems(); - Rectangle rectAfter = getClientArea(); - if (!rectBefore.opEquals(rectAfter)) - { - notifyListeners(DWT.Resize, new Event()); - } - redraw(); - } - } - - /** - * Specify a fixed height for the tab items. If no height is specified, - * the default height is the height of the text or the image, whichever - * is greater. Specifying a height of -1 will revert to the default height. - * - * @param height the pixel value of the height or -1 - * - * @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 called with a height of less than 0
    • - *
    - */ - public void setTabHeight (int height) - { - checkWidget(); - if (height < -1) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - fixedTabHeight = height; - updateTabHeight(false); - } - - /** - * Specify whether the tabs should appear along the top of the folder - * or along the bottom of the folder. - * - * @param position DWT.TOP for tabs along the top or DWT.BOTTOM for tabs along the bottom - * - * @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 position value is not either DWT.TOP or DWT.BOTTOM
    • - *
    - * - * @since 3.0 - */ - public void setTabPosition (int position) - { - checkWidget(); - if (position !is DWT.TOP && position !is DWT.BOTTOM) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (onBottom !is (position is DWT.BOTTOM)) - { - onBottom = position is DWT.BOTTOM; - borderTop = onBottom ? borderLeft : 0; - borderBottom = onBottom ? 0 : borderRight; - updateTabHeight(true); - Rectangle rectBefore = getClientArea(); - updateItems(); - Rectangle rectAfter = getClientArea(); - if (!rectBefore.opEquals(rectAfter)) - { - notifyListeners(DWT.Resize, new Event()); - } - redraw(); - } - } - - /** - * Set the control that appears in the top right corner of the tab folder. - * Typically this is a close button or a composite with a Menu and close button. - * The topRight control is optional. Setting the top right control to null will - * remove it from the tab folder. - * - * @param control 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 CTabFolder
    • - *
    - * - * @since 2.1 - */ - public void setTopRight (Control control) - { - setTopRight(control, DWT.RIGHT); - } + oldSize = null; + if (onBottom) { + int d = tabHeight - 12; + curve = [0,13+d, 0,12+d, 2,12+d, 3,11+d, 5,11+d, 6,10+d, 7,10+d, 9,8+d, 10,8+d, + 11,7+d, 11+d,7, + 12+d,6, 13+d,6, 15+d,4, 16+d,4, 17+d,3, 19+d,3, 20+d,2, 22+d,2, 23+d,1]; + curveWidth = 26+d; + curveIndent = curveWidth/3; + } else { + int d = tabHeight - 12; + curve = [0,0, 0,1, 2,1, 3,2, 5,2, 6,3, 7,3, 9,5, 10,5, + 11,6, 11+d,6+d, + 12+d,7+d, 13+d,7+d, 15+d,9+d, 16+d,9+d, 17+d,10+d, 19+d,10+d, 20+d,11+d, 22+d,11+d, 23+d,12+d]; + curveWidth = 26+d; + curveIndent = curveWidth/3; - /** - * Set the control that appears in the top right corner of the tab folder. - * Typically this is a close button or a composite with a Menu and close button. - * The topRight control is optional. Setting the top right control to null - * will remove it from the tab folder. - *

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

    - * - * @param control the control to be displayed in the top right corner or null - * @param alignment DWT.RIGHT or DWT.FILL - * - * @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 CTabFolder
    • - *
    - * - * @since 3.0 - */ - public void setTopRight (Control control, int alignment) - { - checkWidget(); - if (alignment !is DWT.RIGHT && alignment !is DWT.FILL) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - if (control !is null && control.getParent() !is this) - { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - topRight = control; - topRightAlignment = alignment; - if (updateItems()) - redraw(); - } - - /** - * Specify whether the close button appears - * when the user hovers over an unselected tabs. - * - * @param visible true makes the close button appear - * - * @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 setUnselectedCloseVisible (bool visible) - { - checkWidget(); - if (showUnselectedClose is visible) - return; - // display close button when mouse hovers - showUnselectedClose = visible; - updateItems(); - redraw(); - } - - /** - * Specify whether the image appears on unselected tabs. - * - * @param visible true makes the image appear - * - * @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 setUnselectedImageVisible (bool visible) - { - checkWidget(); - if (showUnselectedImage is visible) - return; - // display image on unselected items - showUnselectedImage = visible; - updateItems(); - redraw(); - } - - /** - * Shows the item. If the item is already showing in the receiver, - * this method simply returns. Otherwise, the items are scrolled until - * the item is visible. - * - * @param item the item to be shown - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the item is null
    • - *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • - *
    - * @exception 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 CTabFolder#showSelection() - * - * @since 2.0 - */ - public void showItem (CTabItem item) - { - checkWidget(); - if (item is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - if (item.isDisposed()) - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - int index = indexOf(item); - if (index is -1) - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - int idx = -1; - for (int i = 0; i < priority.length; i++) - { - if (priority[i] is index) - { - idx = i; - break; - } - } - if (mru) - { - // move to front of mru order - int[] newPriority = new int[priority.length]; - System.arraycopy(priority, 0, newPriority, 1, idx); - System.arraycopy(priority, idx + 1, newPriority, idx + 1, - priority.length - idx - 1); - newPriority[0] = index; - priority = newPriority; - } - if (item.isShowing()) - return; - updateItems(index); - redrawTabs(); - } - - void showList (Rectangle rect) - { - if (items.length is 0 || !showChevron) - return; - if (showMenu is null || showMenu.isDisposed()) - { - showMenu = new Menu(this); - } - else - { - MenuItem[] items = showMenu.getItems(); - for (int i = 0; i < items.length; i++) - { - items[i].dispose(); - } - } - const String id = "CTabFolder_showList_Index"; //$NON-NLS-1$ - for (int i = 0; i < items.length; i++) - { - CTabItem tab = items[i]; - if (tab.showing) - continue; - MenuItem item = new MenuItem(showMenu, DWT.NONE); - item.setText(tab.getText()); - item.setImage(tab.getImage()); - item.setData(id, tab); - item.addSelectionListener(new class SelectionAdapter - { - public void widgetSelected (SelectionEvent e) - { - MenuItem menuItem = cast(MenuItem) e.widget; - int index = indexOf(cast(CTabItem) menuItem.getData(id)); - this.setSelection(index, true); - } - }); - } - int x = rect.x; - int y = rect.y + rect.height; - Point location = getDisplay().map(this, null, x, y); - showMenu.setLocation(location.x, location.y); - showMenu.setVisible(true); - } + //this could be static but since values depend on curve, better to keep in one place + topCurveHighlightStart = [ + 0, 2, 1, 2, 2, 2, + 3, 3, 4, 3, 5, 3, + 6, 4, 7, 4, + 8, 5, + 9, 6, 10, 6]; - /** - * Shows the selection. If the selection is already showing in the receiver, - * this method simply returns. Otherwise, the items are scrolled until - * the selection is visible. - * - * @exception 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 CTabFolder#showItem(CTabItem) - * - * @since 2.0 - */ - public void showSelection () - { - checkWidget(); - if (selectedIndex !is -1) - { - showItem(getSelection()); - } - } - - void _setToolTipText (int x, int y) - { - String oldTip = getToolTipText(); - String newTip = _getToolTip(x, y); - if (newTip is null || !newTip.opEquals(oldTip)) - { - setToolTipText(newTip); - } - } - - bool updateItems () - { - return updateItems(selectedIndex); + //also, by adding in 'd' here we save some math cost when drawing the curve + topCurveHighlightEnd = [ + 10+d, 6+d, + 11+d, 7+d, + 12+d, 8+d, 13+d, 8+d, + 14+d, 9+d, + 15+d, 10+d, 16+d, 10+d, + 17+d, 11+d, 18+d, 11+d, 19+d, 11+d, + 20+d, 12+d, 21+d, 12+d, 22+d, 12+d ]; } - - bool updateItems (int showIndex) - { - if (!single && !mru && showIndex !is -1) - { - // make sure selected item will be showing - int firstIndex = showIndex; - if (priority[0] < showIndex) - { - int maxWidth = getRightItemEdge() - borderLeft; - if (!simple) - maxWidth -= curveWidth - 2 * curveIndent; - int width = 0; - int[] widths = new int[items.length]; - GC gc = new GC(this); - for (int i = priority[0]; i <= showIndex; i++) - { - widths[i] = items[i].preferredWidth(gc, i is selectedIndex, - true); - width += widths[i]; - if (width > maxWidth) - break; - } - if (width > maxWidth) - { - width = 0; - for (int i = showIndex; i >= 0; i--) - { - if (widths[i] is 0) - widths[i] = items[i].preferredWidth(gc, - i is selectedIndex, true); - width += widths[i]; - if (width > maxWidth) - break; - firstIndex = i; - } - } - else - { - firstIndex = priority[0]; - for (int i = showIndex + 1; i < items.length; i++) - { - widths[i] = items[i].preferredWidth(gc, - i is selectedIndex, true); - width += widths[i]; - if (width >= maxWidth) - break; - } - if (width < maxWidth) - { - for (int i = priority[0] - 1; i >= 0; i--) - { - if (widths[i] is 0) - widths[i] = items[i].preferredWidth(gc, - i is selectedIndex, true); - width += widths[i]; - if (width > maxWidth) - break; - firstIndex = i; - } - } - } - gc.dispose(); - } - if (firstIndex !is priority[0]) - { - int index = 0; - for (int i = firstIndex; i < items.length; i++) - { - priority[index++] = i; - } - for (int i = 0; i < firstIndex; i++) - { - priority[index++] = i; - } - } - } - - bool oldShowChevron = showChevron; - bool changed = setItemSize(); - changed |= setItemLocation(); - setButtonBounds(); - changed |= showChevron !is oldShowChevron; - if (changed && getToolTipText() !is null) - { - Point pt = getDisplay().getCursorLocation(); - pt = toControl(pt); - _setToolTipText(pt.x, pt.y); - } - return changed; + notifyListeners(DWT.Resize, new Event()); + return true; +} +String _getToolTip(int x, int y) { + if (showMin && minRect.contains(x, y)) return minimized ? DWT.getMessage("SWT_Restore") : DWT.getMessage("SWT_Minimize"); //$NON-NLS-1$ //$NON-NLS-2$ + if (showMax && maxRect.contains(x, y)) return maximized ? DWT.getMessage("SWT_Restore") : DWT.getMessage("SWT_Maximize"); //$NON-NLS-1$ //$NON-NLS-2$ + if (showChevron && chevronRect.contains(x, y)) return DWT.getMessage("SWT_ShowList"); //$NON-NLS-1$ + CTabItem item = getItem(new Point (x, y)); + if (item is null) return null; + if (!item.showing) return null; + if ((showClose || item.showClose) && item.closeRect.contains(x, y)) { + return DWT.getMessage("SWT_Close"); //$NON-NLS-1$ } - - bool updateTabHeight (bool force) - { - int style = getStyle(); - if (fixedTabHeight is 0 && (style & DWT.FLAT) !is 0 && (style & DWT.BORDER) is 0) - highlight_header = 0; - int oldHeight = tabHeight; - if (fixedTabHeight !is DWT.DEFAULT) - { - tabHeight = fixedTabHeight is 0 ? 0 : fixedTabHeight + 1; // +1 for line drawn across top of tab - } - else - { - int tempHeight = 0; - GC gc = new GC(this); - if (items.length is 0) - { - tempHeight = gc.textExtent("Default", CTabItem.FLAGS).y + CTabItem.TOP_MARGIN + CTabItem.BOTTOM_MARGIN; //$NON-NLS-1$ - } - else - { - for (int i = 0; i < items.length; i++) - { - tempHeight = Math.max(tempHeight, items[i].preferredHeight( - gc)); - } - } - gc.dispose(); - tabHeight = tempHeight; - } - if (!force && tabHeight is oldHeight) - return false; - - oldSize = null; - if (onBottom) - { - int d = tabHeight - 12; - curve = new int[][0 , 13 + d , 0 , 12 + d , 2 , 12 + d , 3 , 11 + d , 5 , 11 + d , 6 , 10 + d , 7 , 10 + d , 9 , 8 + d , 10 , 8 + d , 11 , 7 + d , 11 + d , 7 , 12 + d , 6 , 13 + d , 6 , 15 + d , 4 , 16 + d , 4 , 17 + d , 3 , 19 + d , 3 , 20 + d , 2 , 22 + d , 2 , 23 + d , 1]; - curveWidth = 26 + d; - curveIndent = curveWidth / 3; - } - else - { - int d = tabHeight - 12; - curve = new int[][0 , 0 , 0 , 1 , 2 , 1 , 3 , 2 , 5 , 2 , 6 , 3 , 7 , 3 , 9 , 5 , 10 , 5 , 11 , 6 , 11 + d , 6 + d , 12 + d , 7 + d , 13 + d , 7 + d , 15 + d , 9 + d , 16 + d , 9 + d , 17 + d , 10 + d , 19 + d , 10 + d , 20 + d , 11 + d , 22 + d , 11 + d , 23 + d , 12 + d]; - curveWidth = 26 + d; - curveIndent = curveWidth / 3; - - //this could be static but since values depend on curve, better to keep in one place - topCurveHighlightStart = new int[][0 , 2 , 1 , 2 , 2 , 2 , 3 , 3 , 4 , 3 , 5 , 3 , 6 , 4 , 7 , 4 , 8 , 5 , 9 , 6 , 10 , 6]; - - //also, by adding in 'd' here we save some math cost when drawing the curve - topCurveHighlightEnd = new int[][10 + d , 6 + d , 11 + d , 7 + d , 12 + d , 8 + d , 13 + d , 8 + d , 14 + d , 9 + d , 15 + d , 10 + d , 16 + d , 10 + d , 17 + d , 11 + d , 18 + d , 11 + d , 19 + d , 11 + d , 20 + d , 12 + d , 21 + d , 12 + d , 22 + d , 12 + d]; - } - notifyListeners(DWT.Resize, new Event()); - return true; - } - - String _getToolTip (int x, int y) - { - if (showMin && minRect.contains(x, y)) - return minimized ? DWT.getMessage("DWT_Restore") : DWT.getMessage( - "DWT_Minimize"); //$NON-NLS-1$ //$NON-NLS-2$ - if (showMax && maxRect.contains(x, y)) - return maximized ? DWT.getMessage("DWT_Restore") : DWT.getMessage( - "DWT_Maximize"); //$NON-NLS-1$ //$NON-NLS-2$ - if (showChevron && chevronRect.contains(x, y)) - return DWT.getMessage("DWT_ShowList"); //$NON-NLS-1$ - CTabItem item = getItem(new Point(x, y)); - if (item is null) - return null; - if (!item.showing) - return null; - if ((showClose || item.showClose) && item.closeRect.contains(x, y)) - { - return DWT.getMessage("DWT_Close"); //$NON-NLS-1$ - } - return item.getToolTipText(); - } + return item.getToolTipText(); } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CTabFolder2Adapter.d --- a/dwt/custom/CTabFolder2Adapter.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CTabFolder2Adapter.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,10 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CTabFolder2Adapter; - import dwt.custom.CTabFolder2Listener; import dwt.custom.CTabFolderEvent; @@ -20,74 +18,70 @@ * This adapter class provides default implementations for the * methods described by the CTabFolder2Listener interface. *

    - * Classes that wish to dealF with CTabFolderEvents can + * Classes that wish to deal with CTabFolderEvents can * extend this class and override only the methods which they are * interested in. *

    * * @see CTabFolder2Listener * @see CTabFolderEvent - * + * @see Sample code and further information + * * @since 3.0 */ public class CTabFolder2Adapter : CTabFolder2Listener { - /** - * Sent when the user clicks on the close button of an item in the CTabFolder. The item being closed is specified - * in the event.item field. Setting the event.doit field to false will stop the CTabItem from closing. - * When the CTabItem is closed, it is disposed. The contents of the CTabItem (see CTabItem#setControl) will be - * made not visible when the CTabItem is closed. - *

    - * 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 close button of an item in the CTabFolder. The item being closed is specified + * in the event.item field. Setting the event.doit field to false will stop the CTabItem from closing. + * When the CTabItem is closed, it is disposed. The contents of the CTabItem (see CTabItem#setControl) will be + * made not visible when the CTabItem is closed. + *

    + * 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 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 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 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) { - } +/** + * 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 fbe68c33eeee -r 6337764516f1 dwt/custom/CTabFolder2Listener.d --- a/dwt/custom/CTabFolder2Listener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CTabFolder2Listener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * 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 @@ -7,18 +7,20 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CTabFolder2Listener; +import dwt.internal.DWTEventListener; import dwt.custom.CTabFolderEvent; -import dwt.internal.DWTEventListener; + +import tango.core.Traits; +import tango.core.Tuple; /** * Classes which implement this interface provide methods - * that deal with the events that are generated by the CTabFolder + * that deal with the events that are generated by the CTabFolder * control. *

    * After creating an instance of a class that : @@ -31,86 +33,163 @@ * * @see CTabFolder2Adapter * @see CTabFolderEvent - * + * * @since 3.0 */ public interface CTabFolder2Listener : DWTEventListener { + public enum { + MINIMIZE, + MAXIMIZE, + SHOWLIST, + RESTORE, + CLOSE + } - /** - * Sent when the user clicks on the close button of an item in the CTabFolder. - * The item being closed is specified in the event.item field. - * Setting the event.doit field to false will stop the CTabItem from closing. - * When the CTabItem is closed, it is disposed. The contents of the - * CTabItem (see CTabItem.setControl) will be made not visible when - * the CTabItem is closed. - * - * @param event an event indicating the item being closed - */ - public void close (CTabFolderEvent event); +/** + * Sent when the user clicks on the close button of an item in the CTabFolder. + * The item being closed is specified in the event.item field. + * Setting the event.doit field to false will stop the CTabItem from closing. + * When the CTabItem is closed, it is disposed. The contents of the + * CTabItem (see CTabItem.setControl) will be made not visible when + * the CTabItem is closed. + * + * @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 state of the CTabFolder does not change automatically - it + * is up to the application to change the state of the CTabFolder + * in response to this event using CTabFolder.setMinimized(true). + * + * @param event an event containing information about the minimize + * + * @see CTabFolder#getMinimized() + * @see CTabFolder#setMinimized(bool) + * @see CTabFolder#setMinimizeVisible(bool) + */ +public void minimize(CTabFolderEvent event); - /** - * Sent when the user clicks on the minimize button of a CTabFolder. - * The state of the CTabFolder does not change automatically - it - * is up to the application to change the state of the CTabFolder - * in response to this event using CTabFolder.setMinimized(true). - * - * @param event an event containing information about the minimize - * - * @see CTabFolder#getMinimized() - * @see CTabFolder#setMinimized(bool) - * @see CTabFolder#setMinimizeVisible(bool) - */ - public void minimize (CTabFolderEvent event); +/** + * Sent when the user clicks on the maximize button of a CTabFolder. + * The state of the CTabFolder does not change automatically - it + * is up to the application to change the state of the CTabFolder + * in response to this event using CTabFolder.setMaximized(true). + * + * @param event an event containing information about the maximize + * + * @see CTabFolder#getMaximized() + * @see CTabFolder#setMaximized(bool) + * @see CTabFolder#setMaximizeVisible(bool) + */ +public void maximize(CTabFolderEvent event); + +/** + * Sent when the user clicks on the restore button of a CTabFolder. + * This event is sent either to restore the CTabFolder from the + * minimized state or from the maximized state. To determine + * which restore is requested, use CTabFolder.getMinimized() or + * CTabFolder.getMaximized() to determine the current state. + * The state of the CTabFolder does not change automatically - it + * is up to the application to change the state of the CTabFolder + * in response to this event using CTabFolder.setMaximized(false) + * or CTabFolder.setMinimized(false). + * + * @param event an event containing information about the restore + * + * @see CTabFolder#getMinimized() + * @see CTabFolder#getMaximized() + * @see CTabFolder#setMinimized(bool) + * @see CTabFolder#setMinimizeVisible(bool) + * @see CTabFolder#setMaximized(bool) + * @see CTabFolder#setMaximizeVisible(bool) + */ +public void restore(CTabFolderEvent event); - /** - * Sent when the user clicks on the maximize button of a CTabFolder. - * The state of the CTabFolder does not change automatically - it - * is up to the application to change the state of the CTabFolder - * in response to this event using CTabFolder.setMaximized(true). - * - * @param event an event containing information about the maximize - * - * @see CTabFolder#getMaximized() - * @see CTabFolder#setMaximized(bool) - * @see CTabFolder#setMaximizeVisible(bool) - */ - public void maximize (CTabFolderEvent event); +/** + * Sent when the user clicks on the chevron button of the CTabFolder. + * A chevron appears in the CTabFolder when there are more tabs + * than can be displayed at the current widget size. To select a + * tab that is not currently visible, the user clicks on the + * chevron and selects a tab item from a list. By default, the + * CTabFolder provides a list of all the items that are not currently + * visible, however, the application can provide its own list by setting + * the event.doit field to false and displaying a selection list. + * + * @param event an event containing information about the show list + * + * @see CTabFolder#setSelection(CTabItem) + */ +public void showList(CTabFolderEvent event); +} + + + +/// Helper class for the dgListener template function +private class _DgCTabFolder2ListenerT(Dg,T...) : CTabFolder2Listener { + + alias ParameterTupleOf!(Dg) DgArgs; + static assert( is(DgArgs == Tuple!(CTabFolderEvent,T)), + "Delegate args not correct: "~DgArgs.stringof~" vs. (Event,"~T.stringof~")" ); + + Dg dg; + T t; + int type; + + private this( int type, Dg dg, T t ){ + this.type = type; + this.dg = dg; + static if( T.length > 0 ){ + this.t = t; + } + } - /** - * Sent when the user clicks on the restore button of a CTabFolder. - * This event is sent either to restore the CTabFolder from the - * minimized state or from the maximized state. To determine - * which restore is requested, use CTabFolder.getMinimized() or - * CTabFolder.getMaximized() to determine the current state. - * The state of the CTabFolder does not change automatically - it - * is up to the application to change the state of the CTabFolder - * in response to this event using CTabFolder.setMaximized(false) - * or CTabFolder.setMinimized(false). - * - * @param event an event containing information about the restore - * - * @see CTabFolder#getMinimized() - * @see CTabFolder#getMaximized() - * @see CTabFolder#setMinimized(bool) - * @see CTabFolder#setMinimizeVisible(bool) - * @see CTabFolder#setMaximized(bool) - * @see CTabFolder#setMaximizeVisible(bool) - */ - public void restore (CTabFolderEvent event); + void itemClosed( CTabFolderEvent e ){ + dg(e,t); + } + public void close(CTabFolderEvent e){ + if( type is CTabFolder2Listener.CLOSE ){ + dg(e,t); + } + } + public void minimize(CTabFolderEvent e){ + if( type is CTabFolder2Listener.MINIMIZE ){ + dg(e,t); + } + } + public void maximize(CTabFolderEvent e){ + if( type is CTabFolder2Listener.MAXIMIZE ){ + dg(e,t); + } + } + public void restore(CTabFolderEvent e){ + if( type is CTabFolder2Listener.RESTORE ){ + dg(e,t); + } + } + public void showList(CTabFolderEvent e){ + if( type is CTabFolder2Listener.SHOWLIST ){ + dg(e,t); + } + } +} - /** - * Sent when the user clicks on the chevron button of the CTabFolder. - * A chevron appears in the CTabFolder when there are more tabs - * than can be displayed at the current widget size. To select a - * tab that is not currently visible, the user clicks on the - * chevron and selects a tab item from a list. By default, the - * CTabFolder provides a list of all the items that are not currently - * visible, however, the application can provide its own list by setting - * the event.doit field to 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); +/++ + + dgListener creates a class implementing the Listener interface and delegating the call to + + handleEvent to the users delegate. This template function will store also additional parameters. + + + + Examle of usage: + + --- + + void handleTextEvent ( Event e, int inset ) { + + // ... + + } + + text.addListener (DWT.FocusOut, dgListener( &handleTextEvent, inset )); + + --- + +/ +CTabFolder2Listener dgCTabFolder2Listener( Dg, T... )( int type, Dg dg, T args ){ + return new _DgCTabFolder2ListenerT!( Dg, T )( type, dg, args ); } + + + diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CTabFolderAdapter.d --- a/dwt/custom/CTabFolderAdapter.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CTabFolderAdapter.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,16 +7,22 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CTabFolderAdapter; - import dwt.custom.CTabFolderEvent; import dwt.custom.CTabFolderListener; + +/** + * This adapter class provides a default implementation for the + * method described by the CTabFolderListener interface. + * + * @see CTabFolderListener + * @see CTabFolderEvent + * @see Sample code and further information + */ public class CTabFolderAdapter : CTabFolderListener { - public void itemClosed (CTabFolderEvent event) { - } + public void itemClosed(CTabFolderEvent event){} } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CTabFolderEvent.d --- a/dwt/custom/CTabFolderEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CTabFolderEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,19 +7,24 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CTabFolderEvent; +import dwt.dwthelper.utils; + + + import dwt.events.TypedEvent; import dwt.widgets.Widget; -import dwt.dwthelper.utils; +import tango.util.Convert; /** - * + * This event is sent when an event is generated in the CTabFolder. + * + * @see Sample code and further information */ public class CTabFolderEvent : TypedEvent { /** @@ -37,52 +42,58 @@ /** * 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); - } +/** + * 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 + "}"; - } +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the event + */ +public override String toString() { + String string = super.toString (); + return string[0.. $ - 1] // remove trailing '}' + ~ " item=" ~ to!(String)(item) + ~ " doit=" ~ to!(String)(doit) + ~ " x=" ~ to!(String)(x) + ~ " y=" ~ to!(String)(y) + ~ " width=" ~ to!(String)(width) + ~ " height=" ~ to!(String)(height) + ~ "}"; } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CTabFolderLayout.d --- a/dwt/custom/CTabFolderLayout.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CTabFolderLayout.d Tue Oct 07 16:29:55 2008 +0200 @@ -7,97 +7,85 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CTabFolderLayout; -import Math = tango.math.Math; +import dwt.dwthelper.utils; import dwt.DWT; -import dwt.custom.CTabFolder; -import dwt.custom.CTabItem; import dwt.graphics.GC; import dwt.graphics.Point; import dwt.widgets.Composite; import dwt.widgets.Control; import dwt.widgets.Layout; +import dwt.custom.CTabFolder; +import dwt.custom.CTabItem; /** * This class provides the layout for CTabFolder - * + * * @see CTabFolder */ class CTabFolderLayout : Layout { - protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache) { - CTabFolder folder = cast(CTabFolder) composite; - CTabItem[] items = folder.items; - // preferred width of tab area to show all tabs - int tabW = 0; - GC gc = new GC(folder); - for (int i = 0; i < items.length; i++) { - if (folder.single) { - tabW = Math.max(tabW, items[i].preferredWidth(gc, true, false)); - } - else { - tabW += items[i].preferredWidth(gc, i is folder.selectedIndex, false); - } - } - gc.dispose(); - tabW += 3; - if (folder.showMax) - tabW += CTabFolder.BUTTON_SIZE; - if (folder.showMin) - tabW += CTabFolder.BUTTON_SIZE; - if (folder.single) - tabW += 3 * CTabFolder.BUTTON_SIZE / 2; //chevron - if (folder.topRight !is null) { - Point pt = folder.topRight.computeSize(DWT.DEFAULT, folder.tabHeight, flushCache); - tabW += 3 + pt.x; +protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { + CTabFolder folder = cast(CTabFolder)composite; + CTabItem[] items = folder.items; + // preferred width of tab area to show all tabs + int tabW = 0; + GC gc = new GC(folder); + for (int i = 0; i < items.length; i++) { + if (folder.single) { + tabW = Math.max(tabW, items[i].preferredWidth(gc, true, false)); + } else { + tabW += items[i].preferredWidth(gc, i is folder.selectedIndex, false); } - if (!folder.single && !folder.simple) - tabW += folder.curveWidth - 2 * folder.curveIndent; + } + gc.dispose(); + tabW += 3; + if (folder.showMax) tabW += CTabFolder.BUTTON_SIZE; + if (folder.showMin) tabW += CTabFolder.BUTTON_SIZE; + if (folder.single) tabW += 3*CTabFolder.BUTTON_SIZE/2; //chevron + if (folder.topRight !is null) { + Point pt = folder.topRight.computeSize(DWT.DEFAULT, folder.tabHeight, flushCache); + tabW += 3 + pt.x; + } + if (!folder.single && !folder.simple) tabW += folder.curveWidth - 2*folder.curveIndent; - int controlW = 0; - int controlH = 0; - // preferred size of controls in tab items - for (int i = 0; i < items.length; i++) { - Control control = items[i].getControl(); - if (control !is null && !control.isDisposed()) { - Point size = control.computeSize(wHint, hHint, flushCache); - controlW = Math.max(controlW, size.x); - controlH = Math.max(controlH, size.y); - } + int controlW = 0; + int controlH = 0; + // preferred size of controls in tab items + for (int i = 0; i < items.length; i++) { + Control control = items[i].getControl(); + if (control !is null && !control.isDisposed()){ + Point size = control.computeSize (wHint, hHint, flushCache); + controlW = Math.max (controlW, size.x); + controlH = Math.max (controlH, size.y); } - - int minWidth = Math.max(tabW, controlW); - int minHeight = (folder.minimized) ? 0 : controlH; - if (minWidth is 0) - minWidth = CTabFolder.DEFAULT_WIDTH; - if (minHeight is 0) - minHeight = CTabFolder.DEFAULT_HEIGHT; - - if (wHint !is DWT.DEFAULT) - minWidth = wHint; - if (hHint !is DWT.DEFAULT) - minHeight = hHint; - - return new Point(minWidth, minHeight); } - protected bool flushCache (Control control) { - return true; - } + int minWidth = Math.max(tabW, controlW); + int minHeight = (folder.minimized) ? 0 : controlH; + if (minWidth is 0) minWidth = CTabFolder.DEFAULT_WIDTH; + if (minHeight is 0) minHeight = CTabFolder.DEFAULT_HEIGHT; + + if (wHint !is DWT.DEFAULT) minWidth = wHint; + if (hHint !is DWT.DEFAULT) minHeight = hHint; - protected void layout (Composite composite, bool flushCache) { - CTabFolder folder = cast(CTabFolder) composite; - // resize content - if (folder.selectedIndex !is -1) { - Control control = folder.items[folder.selectedIndex].getControl(); - if (control !is null && !control.isDisposed()) { - control.setBounds(folder.getClientArea()); - } + return new Point (minWidth, minHeight); +} +protected override bool flushCache(Control control) { + return true; +} +protected override void layout(Composite composite, bool flushCache) { + CTabFolder folder = cast(CTabFolder)composite; + // resize content + if (folder.selectedIndex !is -1) { + Control control = folder.items[folder.selectedIndex].getControl(); + if (control !is null && !control.isDisposed()) { + control.setBounds(folder.getClientArea()); } } } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CTabFolderListener.d --- a/dwt/custom/CTabFolderListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CTabFolderListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * 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 @@ -7,14 +7,16 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.CTabFolderListener; +import dwt.internal.DWTEventListener; import dwt.custom.CTabFolderEvent; -import dwt.internal.DWTEventListener; + +import tango.core.Traits; +import tango.core.Tuple; /** * Classes which implement this interface provide a method @@ -31,15 +33,58 @@ */ public interface CTabFolderListener : DWTEventListener { - /** - * Sent when the user clicks on the close button of an item in the CTabFolder. The item being closed is specified - * in the event.item field. Setting the event.doit field to false will stop the CTabItem from closing. - * When the CTabItem is closed, it is disposed. The contents of the CTabItem (see CTabItem.setControl) will be - * made not visible when the CTabItem is closed. - * - * @param event an event indicating the item being closed - * - * @see CTabItem#setControl - */ - public void itemClosed (CTabFolderEvent event); +/** + * Sent when the user clicks on the close button of an item in the CTabFolder. The item being closed is specified + * in the event.item field. Setting the event.doit field to false will stop the CTabItem from closing. + * When the CTabItem is closed, it is disposed. The contents of the CTabItem (see CTabItem.setControl) will be + * made not visible when the CTabItem is closed. + * + * @param event an event indicating the item being closed + * + * @see CTabItem#setControl + */ +public void itemClosed(CTabFolderEvent event); } + + + +/// Helper class for the dgListener template function +private class _DgCTabFolderListenerT(Dg,T...) : CTabFolderListener { + + alias ParameterTupleOf!(Dg) DgArgs; + static assert( is(DgArgs == Tuple!(CTabFolderEvent,T)), + "Delegate args not correct" ); + + Dg dg; + T t; + + private this( Dg dg, T t ){ + this.dg = dg; + static if( T.length > 0 ){ + this.t = t; + } + } + + void itemClosed( CTabFolderEvent e ){ + dg(e,t); + } +} + +/++ + + dgListener creates a class implementing the Listener interface and delegating the call to + + handleEvent to the users delegate. This template function will store also additional parameters. + + + + Examle of usage: + + --- + + void handleTextEvent (Event e, int inset ) { + + // ... + + } + + text.addListener (DWT.FocusOut, dgListener( &handleTextEvent, inset )); + + --- + +/ +CTabFolderListener dgCTabFolderListener( Dg, T... )( Dg dg, T args ){ + return new _DgCTabFolderListenerT!( Dg, T )( dg, args ); +} + + + diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/CTabItem.d --- a/dwt/custom/CTabItem.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/CTabItem.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,15 +7,17 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.CTabItem; + +import dwt.dwthelper.utils; + + import dwt.DWT; import dwt.DWTException; -import dwt.custom.CTabFolder; import dwt.graphics.Color; import dwt.graphics.Font; import dwt.graphics.GC; @@ -28,13 +30,12 @@ import dwt.widgets.Display; import dwt.widgets.Item; import dwt.widgets.Widget; - -import dwt.dwthelper.utils; +import dwt.custom.CTabFolder; /** * Instances of this class represent a selectable user interface object * that represent a page in a notebook widget. - * + * *

    *
    Styles:
    *
    DWT.CLOSE
    @@ -44,10 +45,13 @@ *

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

    + * + * @see CTabFolder, CTabItem snippets + * @see Sample code and further information */ public class CTabItem : Item { CTabFolder parent; - int x, y, width, height = 0; + int x,y,width,height = 0; Control control; // the tab page String toolTipText; @@ -58,7 +62,7 @@ Font font; Image disabledImage; - Rectangle closeRect = new Rectangle(0, 0, 0, 0); + Rectangle closeRect; int closeImageState = CTabFolder.NONE; bool showClose = false; bool showing = false; @@ -72,1061 +76,998 @@ 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 a CTabFolder) 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. - *

    - * - * @param parent a CTabFolder which will be the parent of the new instance (cannot be null) - * @param style the style of control to construct - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • - *
    - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • - *
    - * - * @see DWT - * @see Widget#getStyle() - */ - public this (CTabFolder parent, int style) { - this(parent, style, parent.getItemCount()); - } +/** + * Constructs a new instance of this class given its parent + * (which must be a CTabFolder) 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. + *

    + * + * @param parent a CTabFolder which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    + * + * @see DWT + * @see Widget#getStyle() + */ +public this (CTabFolder parent, int style) { + this(parent, style, parent.getItemCount()); +} +/** + * Constructs a new instance of this class given its parent + * (which must be a 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. + *

    + * + * @param parent a CTabFolder which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    + * + * @see DWT + * @see Widget#getStyle() + */ +public this (CTabFolder parent, int style, int index) { + closeRect = new Rectangle(0, 0, 0, 0); + super (parent, style); + showClose = (style & DWT.CLOSE) !is 0; + parent.createItem (this, index); +} + +/* + * Return whether to use ellipses or just truncate labels + */ +bool useEllipses() { + return parent.simple; +} + +String shortenText(GC gc, String text, int width) { + return useEllipses() + ? shortenText(gc, text, width, ELLIPSIS) + : shortenText(gc, text, width, ""); //$NON-NLS-1$ +} - /** - * Constructs a new instance of this class given its parent - * (which must be a 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. - *

    - * - * @param parent a CTabFolder which will be the parent of the new instance (cannot be null) - * @param style the style of control to construct - * @param index the zero-relative index to store the receiver in its parent - * - * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • - *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • - *
    - * @exception DWTException
      - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • - *
    - * - * @see DWT - * @see Widget#getStyle() - */ - public this (CTabFolder parent, int style, int index) { - super(parent, style); - showClose = (style & DWT.CLOSE) !is 0; - parent.createItem(this, index); +String shortenText(GC gc, String text, int width, String ellipses) { + if (gc.textExtent(text, FLAGS).x <= width) return text; + int ellipseWidth = gc.textExtent(ellipses, FLAGS).x; + int length = text.length; + TextLayout layout = new TextLayout(getDisplay()); + layout.setText(text); + int end = layout.getPreviousOffset(length, DWT.MOVEMENT_CLUSTER); + while (end > 0) { + text = text[ 0 .. end ]; + int l = gc.textExtent(text, FLAGS).x; + if (l + ellipseWidth <= width) { + break; + } + end = layout.getPreviousOffset(end, DWT.MOVEMENT_CLUSTER); } + layout.dispose(); + return end is 0 ? text.substring(0, 1) : text ~ ellipses; +} - /* - * Return whether to use ellipses or just truncate labels - */ - bool useEllipses () { - return parent.simple; +public override void dispose() { + if (isDisposed ()) return; + //if (!isValidThread ()) error (DWT.ERROR_THREAD_INVALID_ACCESS); + parent.destroyItem(this); + super.dispose(); + parent = null; + control = null; + toolTipText = null; + shortenedText = null; + font = null; +} +void drawClose(GC gc) { + if (closeRect.width is 0 || closeRect.height is 0) return; + Display display = getDisplay(); + + // draw X 9x9 + int indent = Math.max(1, (CTabFolder.BUTTON_SIZE-9)/2); + int x = closeRect.x + indent; + int y = closeRect.y + indent; + y += parent.onBottom ? -1 : 1; + + Color closeBorder = display.getSystemColor(CTabFolder.BUTTON_BORDER); + switch (closeImageState) { + case CTabFolder.NORMAL: { + int[] shape = [x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y, + x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9, + x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9, + x,y+7, x+2,y+5, x+2,y+4, x,y+2]; + gc.setBackground(display.getSystemColor(CTabFolder.BUTTON_FILL)); + gc.fillPolygon(shape); + gc.setForeground(closeBorder); + gc.drawPolygon(shape); + break; + } + case CTabFolder.HOT: { + int[] shape = [x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y, + x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9, + x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9, + x,y+7, x+2,y+5, x+2,y+4, x,y+2]; + Color fill = new Color(display, CTabFolder.CLOSE_FILL); + gc.setBackground(fill); + gc.fillPolygon(shape); + fill.dispose(); + gc.setForeground(closeBorder); + gc.drawPolygon(shape); + break; + } + case CTabFolder.SELECTED: { + int[] shape = [x+1,y+1, x+3,y+1, x+5,y+3, x+6,y+3, x+8,y+1, x+10,y+1, + x+10,y+3, x+8,y+5, x+8,y+6, x+10,y+8, x+10,y+10, + x+8,y+10, x+6,y+8, x+5,y+8, x+3,y+10, x+1,y+10, + x+1,y+8, x+3,y+6, x+3,y+5, x+1,y+3]; + Color fill = new Color(display, CTabFolder.CLOSE_FILL); + gc.setBackground(fill); + gc.fillPolygon(shape); + fill.dispose(); + gc.setForeground(closeBorder); + gc.drawPolygon(shape); + break; + } + case CTabFolder.NONE: { + int[] shape = [x,y, x+10,y, x+10,y+10, x,y+10]; + if (parent.gradientColors !is null && !parent.gradientVertical) { + parent.drawBackground(gc, shape, false); + } else { + Color defaultBackground = parent.getBackground(); + Image image = parent.bgImage; + Color[] colors = parent.gradientColors; + int[] percents = parent.gradientPercents; + bool vertical = parent.gradientVertical; + parent.drawBackground(gc, shape, x, y, 10, 10, defaultBackground, image, colors, percents, vertical); + } + break; + } + default: } +} +void drawSelected(GC gc ) { + Point size = parent.getSize(); + int rightEdge = Math.min (x + width, parent.getRightItemEdge()); - String shortenText (GC gc, String text, int width) { - return useEllipses() ? shortenText(gc, text, width, ELLIPSIS) : shortenText(gc, text, width, ""); //$NON-NLS-1$ + // Draw selection border across all tabs + int xx = parent.borderLeft; + int yy = parent.onBottom ? size.y - parent.borderBottom - parent.tabHeight - parent.highlight_header : parent.borderTop + parent.tabHeight + 1; + int ww = size.x - parent.borderLeft - parent.borderRight; + int hh = parent.highlight_header - 1; + int[] shape = [xx,yy, xx+ww,yy, xx+ww,yy+hh, xx,yy+hh]; + if (parent.selectionGradientColors !is null && !parent.selectionGradientVertical) { + parent.drawBackground(gc, shape, true); + } else { + gc.setBackground(parent.selectionBackground); + gc.fillRectangle(xx, yy, ww, hh); } - String shortenText (GC gc, String text, int width, String ellipses) { - if (gc.textExtent(text, FLAGS).x <= width) - return text; - int ellipseWidth = gc.textExtent(ellipses, FLAGS).x; - int length = text.length; - TextLayout layout = new TextLayout(getDisplay()); - layout.setText(text); - int end = layout.getPreviousOffset(length, DWT.MOVEMENT_CLUSTER); - while (end > 0) { - text = text.substring(0, end); - int l = gc.textExtent(text, FLAGS).x; - if (l + ellipseWidth <= width) { - break; - } - end = layout.getPreviousOffset(end, DWT.MOVEMENT_CLUSTER); + if (parent.single) { + if (!showing) return; + } else { + // if selected tab scrolled out of view or partially out of view + // just draw bottom line + if (!showing){ + int x1 = Math.max(0, parent.borderLeft - 1); + int y1 = (parent.onBottom) ? y - 1 : y + height; + int x2 = size.x - parent.borderRight; + gc.setForeground(CTabFolder.borderColor); + gc.drawLine(x1, y1, x2, y1); + return; } - layout.dispose(); - return end is 0 ? text.substring(0, 1) : text + ellipses; - } + + // draw selected tab background and outline + shape = null; + if (this.parent.onBottom) { + int[] left = parent.simple ? CTabFolder.SIMPLE_BOTTOM_LEFT_CORNER : CTabFolder.BOTTOM_LEFT_CORNER; + int[] right = parent.simple ? CTabFolder.SIMPLE_BOTTOM_RIGHT_CORNER : parent.curve; + if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { + left = [x, y+height]; + } + shape = new int[left.length+right.length+8]; + int index = 0; + shape[index++] = x; // first point repeated here because below we reuse shape to draw outline + shape[index++] = y - 1; + shape[index++] = x; + shape[index++] = y - 1; + for (int i = 0; i < left.length/2; i++) { + shape[index++] = x + left[2*i]; + shape[index++] = y + height + left[2*i+1] - 1; + } + for (int i = 0; i < right.length/2; i++) { + shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - parent.curveIndent + right[2*i]; + shape[index++] = parent.simple ? y + height + right[2*i+1] - 1 : y + right[2*i+1] - 2; + } + shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; + shape[index++] = y - 1; + shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; + shape[index++] = y - 1; + } else { + int[] left = parent.simple ? CTabFolder.SIMPLE_TOP_LEFT_CORNER : CTabFolder.TOP_LEFT_CORNER; + int[] right = parent.simple ? CTabFolder.SIMPLE_TOP_RIGHT_CORNER : parent.curve; + if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { + left = [x, y]; + } + shape = new int[left.length+right.length+8]; + int index = 0; + shape[index++] = x; // first point repeated here because below we reuse shape to draw outline + shape[index++] = y + height + 1; + shape[index++] = x; + shape[index++] = y + height + 1; + for (int i = 0; i < left.length/2; i++) { + shape[index++] = x + left[2*i]; + shape[index++] = y + left[2*i+1]; + } + for (int i = 0; i < right.length/2; i++) { + shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - parent.curveIndent + right[2*i]; + shape[index++] = y + right[2*i+1]; + } + shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; + shape[index++] = y + height + 1; + shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; + shape[index++] = y + height + 1; + } - public void dispose () { - if (isDisposed()) - return; - //if (!isValidThread ()) error (DWT.ERROR_THREAD_INVALID_ACCESS); - parent.destroyItem(this); - super.dispose(); - parent = null; - control = null; - toolTipText = null; - shortenedText = null; - font = null; + Rectangle clipping = gc.getClipping(); + Rectangle bounds = getBounds(); + bounds.height += 1; + if (parent.onBottom) bounds.y -= 1; + bool tabInPaint = clipping.intersects(bounds); + + if (tabInPaint) { + // fill in tab background + if (parent.selectionGradientColors !is null && !parent.selectionGradientVertical) { + parent.drawBackground(gc, shape, true); + } else { + Color defaultBackground = parent.selectionBackground; + Image image = parent.selectionBgImage; + Color[] colors = parent.selectionGradientColors; + int[] percents = parent.selectionGradientPercents; + bool vertical = parent.selectionGradientVertical; + xx = x; + yy = parent.onBottom ? y -1 : y + 1; + ww = width; + hh = height; + if (!parent.single && !parent.simple) ww += parent.curveWidth - parent.curveIndent; + parent.drawBackground(gc, shape, xx, yy, ww, hh, defaultBackground, image, colors, percents, vertical); + } + } + + //Highlight MUST be drawn before the outline so that outline can cover it in the right spots (start of swoop) + //otherwise the curve looks jagged + drawHighlight(gc, rightEdge); + + // draw outline + shape[0] = Math.max(0, parent.borderLeft - 1); + if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { + shape[1] = parent.onBottom ? y + height - 1 : y; + shape[5] = shape[3] = shape[1]; + } + shape[shape.length - 2] = size.x - parent.borderRight + 1; + for (int i = 0; i < shape.length/2; i++) { + if (shape[2*i + 1] is y + height + 1) shape[2*i + 1] -= 1; + } + RGB inside = parent.selectionBackground.getRGB(); + if (parent.selectionBgImage !is null || + (parent.selectionGradientColors !is null && parent.selectionGradientColors.length > 1)) { + inside = null; + } + RGB outside = parent.getBackground().getRGB(); + if (parent.bgImage !is null || + (parent.gradientColors !is null && parent.gradientColors.length > 1)) { + outside = null; + } + parent.antialias(shape, CTabFolder.borderColor.getRGB(), inside, outside, gc); + gc.setForeground(CTabFolder.borderColor); + gc.drawPolyline(shape); + + if (!tabInPaint) return; } - void drawClose (GC gc) { - if (closeRect.width is 0 || closeRect.height is 0) - return; - Display display = getDisplay(); - - // draw X 9x9 - int indent = Math.max(1, (CTabFolder.BUTTON_SIZE - 9) / 2); - int x = closeRect.x + indent; - int y = closeRect.y + indent; - y += parent.onBottom ? -1 : 1; - - Color closeBorder = display.getSystemColor(CTabFolder.BUTTON_BORDER); - switch (closeImageState) { - case CTabFolder.NORMAL: { - int[] shape = new int[] - { - x , y , x + 2 , y , x + 4 , y + 2 , x + 5 , y + 2 , x + 7 , y , x + 9 , y , x + 9 , y + 2 , x + 7 , y + 4 , x + 7 , y + 5 , x + 9 , y + 7 , x + 9 , y + 9 , x + 7 , y + 9 , x + 5 , y + 7 , x + 4 , y + 7 , x + 2 , y + 9 , x , y + 9 , x , y + 7 , x + 2 , y + 5 , x + 2 , y + 4 , x , y + 2 - }; - gc.setBackground(display.getSystemColor(CTabFolder.BUTTON_FILL)); - gc.fillPolygon(shape); - gc.setForeground(closeBorder); - gc.drawPolygon(shape); - break; - } - case CTabFolder.HOT: { - int[] shape = new int[] - { - x , y , x + 2 , y , x + 4 , y + 2 , x + 5 , y + 2 , x + 7 , y , x + 9 , y , x + 9 , y + 2 , x + 7 , y + 4 , x + 7 , y + 5 , x + 9 , y + 7 , x + 9 , y + 9 , x + 7 , y + 9 , x + 5 , y + 7 , x + 4 , y + 7 , x + 2 , y + 9 , x , y + 9 , x , y + 7 , x + 2 , y + 5 , x + 2 , y + 4 , x , y + 2 - }; - Color fill = new Color(display, CTabFolder.CLOSE_FILL); - gc.setBackground(fill); - gc.fillPolygon(shape); - fill.dispose(); - gc.setForeground(closeBorder); - gc.drawPolygon(shape); - break; - } - case CTabFolder.SELECTED: { - int[] shape = new int[] - { - x + 1 , y + 1 , x + 3 , y + 1 , x + 5 , y + 3 , x + 6 , y + 3 , x + 8 , y + 1 , x + 10 , y + 1 , x + 10 , y + 3 , x + 8 , y + 5 , x + 8 , y + 6 , x + 10 , y + 8 , x + 10 , y + 10 , x + 8 , y + 10 , x + 6 , y + 8 , x + 5 , y + 8 , x + 3 , y + 10 , x + 1 , y + 10 , x + 1 , y + 8 , x + 3 , y + 6 , x + 3 , y + 5 , x + 1 , y + 3 - }; - Color fill = new Color(display, CTabFolder.CLOSE_FILL); - gc.setBackground(fill); - gc.fillPolygon(shape); - fill.dispose(); - gc.setForeground(closeBorder); - gc.drawPolygon(shape); - break; - } - case CTabFolder.NONE: { - int[] shape = new int[] - { - x , y , x + 10 , y , x + 10 , y + 10 , x , y + 10 - }; - if (parent.gradientColors !is null && !parent.gradientVertical) { - parent.drawBackground(gc, shape, false); - } - else { - Color defaultBackground = parent.getBackground(); - Image image = parent.bgImage; - Color[] colors = parent.gradientColors; - int[] percents = parent.gradientPercents; - bool vertical = parent.gradientVertical; - parent.drawBackground(gc, shape, x, y, 10, 10, defaultBackground, image, colors, percents, vertical); - } - break; - } + // draw Image + int xDraw = x + LEFT_MARGIN; + if (parent.single && (parent.showClose || showClose)) xDraw += CTabFolder.BUTTON_SIZE; + Image image = getImage(); + if (image !is null) { + Rectangle imageBounds = image.getBounds(); + // only draw image if it won't overlap with close button + int maxImageWidth = rightEdge - xDraw - RIGHT_MARGIN; + if (!parent.single && closeRect.width > 0) maxImageWidth -= closeRect.width + INTERNAL_SPACING; + if (imageBounds.width < maxImageWidth) { + int imageX = xDraw; + int imageY = y + (height - imageBounds.height) / 2; + imageY += parent.onBottom ? -1 : 1; + gc.drawImage(image, imageX, imageY); + xDraw += imageBounds.width + INTERNAL_SPACING; } } - void drawSelected (GC gc) { - Point size = parent.getSize(); - int rightEdge = Math.min(x + width, parent.getRightItemEdge()); + // draw Text + int textWidth = rightEdge - xDraw - RIGHT_MARGIN; + if (!parent.single && closeRect.width > 0) textWidth -= closeRect.width + INTERNAL_SPACING; + if (textWidth > 0) { + Font gcFont = gc.getFont(); + gc.setFont(font is null ? parent.getFont() : font); - // Draw selection border across all tabs - int xx = parent.borderLeft; - int - yy = parent.onBottom ? size.y - parent.borderBottom - parent.tabHeight - parent.highlight_header : parent.borderTop + parent.tabHeight + 1; - int ww = size.x - parent.borderLeft - parent.borderRight; - int hh = parent.highlight_header - 1; - int[] shape = new int[] - { - xx , yy , xx + ww , yy , xx + ww , yy + hh , xx , yy + hh - }; - if (parent.selectionGradientColors !is null && !parent.selectionGradientVertical) { - parent.drawBackground(gc, shape, true); - } - else { - gc.setBackground(parent.selectionBackground); - gc.fillRectangle(xx, yy, ww, hh); - } - - if (parent.single) { - if (!showing) - return; + if (shortenedText is null || shortenedTextWidth !is textWidth) { + shortenedText = shortenText(gc, getText(), textWidth); + shortenedTextWidth = textWidth; } - else { - // if selected tab scrolled out of view or partially out of view - // just draw bottom line - if (!showing) { - int x1 = Math.max(0, parent.borderLeft - 1); - int y1 = (parent.onBottom) ? y - 1 : y + height; - int x2 = size.x - parent.borderRight; - gc.setForeground(CTabFolder.borderColor); - gc.drawLine(x1, y1, x2, y1); - return; - } + Point extent = gc.textExtent(shortenedText, FLAGS); + int textY = y + (height - extent.y) / 2; + textY += parent.onBottom ? -1 : 1; + + gc.setForeground(parent.selectionForeground); + gc.drawText(shortenedText, xDraw, textY, FLAGS); + gc.setFont(gcFont); - // draw selected tab background and outline - shape = null; - if (this.parent.onBottom) { - int[] left = parent.simple ? CTabFolder.SIMPLE_BOTTOM_LEFT_CORNER : CTabFolder.BOTTOM_LEFT_CORNER; - int[] right = parent.simple ? CTabFolder.SIMPLE_BOTTOM_RIGHT_CORNER : parent.curve; - if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { - left = new int[] - { - x , y + height - }; - } - shape = new int[left.length + right.length + 8]; - int index = 0; - shape[index++] = x; // first point repeated here because below we reuse shape to draw outline - shape[index++] = y - 1; - shape[index++] = x; - shape[index++] = y - 1; - for (int i = 0; i < left.length / 2; i++) { - shape[index++] = x + left[2 * i]; - shape[index++] = y + height + left[2 * i + 1] - 1; - } - for (int i = 0; i < right.length / 2; i++) { - shape[index++] = parent.simple ? rightEdge - 1 + right[2 * i] : rightEdge - parent.curveIndent + right[2 * i]; - shape[index++] = parent.simple ? y + height + right[2 * i + 1] - 1 : y + right[2 * i + 1] - 2; - } - shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; - shape[index++] = y - 1; - shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; - shape[index++] = y - 1; + // draw a Focus rectangle + if (parent.isFocusControl()) { + Display display = getDisplay(); + if (parent.simple || parent.single) { + gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); + gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); + gc.drawFocus(xDraw-1, textY-1, extent.x+2, extent.y+2); + } else { + gc.setForeground(display.getSystemColor(CTabFolder.BUTTON_BORDER)); + gc.drawLine(xDraw, textY+extent.y+1, xDraw+extent.x+1, textY+extent.y+1); } - else { - int[] left = parent.simple ? CTabFolder.SIMPLE_TOP_LEFT_CORNER : CTabFolder.TOP_LEFT_CORNER; - int[] right = parent.simple ? CTabFolder.SIMPLE_TOP_RIGHT_CORNER : parent.curve; - if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { - left = new int[] - { - x , y - }; - } - shape = new int[left.length + right.length + 8]; - int index = 0; - shape[index++] = x; // first point repeated here because below we reuse shape to draw outline - shape[index++] = y + height + 1; - shape[index++] = x; - shape[index++] = y + height + 1; - for (int i = 0; i < left.length / 2; i++) { - shape[index++] = x + left[2 * i]; - shape[index++] = y + left[2 * i + 1]; - } - for (int i = 0; i < right.length / 2; i++) { - shape[index++] = parent.simple ? rightEdge - 1 + right[2 * i] : rightEdge - parent.curveIndent + right[2 * i]; - shape[index++] = y + right[2 * i + 1]; - } - shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; - shape[index++] = y + height + 1; - shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent; - shape[index++] = y + height + 1; - } + } + } + if (parent.showClose || showClose) drawClose(gc); +} + +/* + * Draw a highlight effect along the left, top, and right edges of the tab. + * Only for curved tabs, on top. + * Do not draw if insufficient colors. + */ +void drawHighlight(GC gc, int rightEdge) { + //only draw for curvy tabs and only draw for top tabs + if(parent.simple || this.parent.onBottom) + return; + + if(parent.selectionHighlightGradientBegin is null) + return; + + Color[] gradients = parent.selectionHighlightGradientColorsCache; + if(gradients is null) + return; + int gradientsSize = gradients.length; + if(gradientsSize is 0) + return; //shouldn't happen but just to be tidy + + gc.setForeground(gradients[0]); - Rectangle clipping = gc.getClipping(); - Rectangle bounds = getBounds(); - bounds.height += 1; - if (parent.onBottom) - bounds.y -= 1; - bool tabInPaint = clipping.intersects(bounds); + //draw top horizontal line + gc.drawLine( + CTabFolder.TOP_LEFT_CORNER_HILITE[0] + x + 1, //rely on fact that first pair is top/right of curve + 1 + y, + rightEdge - parent.curveIndent, + 1 + y); + + int[] leftHighlightCurve = CTabFolder.TOP_LEFT_CORNER_HILITE; + + int d = parent.tabHeight - parent.topCurveHighlightEnd.length /2; + + int lastX = 0; + int lastY = 0; + int lastColorIndex = 0; + + //draw upper left curve highlight + for (int i = 0; i < leftHighlightCurve.length /2; i++) { + int rawX = leftHighlightCurve[i * 2]; + int rawY = leftHighlightCurve[i * 2 + 1]; + lastX = rawX + x; + lastY = rawY + y; + lastColorIndex = rawY - 1; + gc.setForeground(gradients[lastColorIndex]); + gc.drawPoint(lastX, lastY); + } + //draw left vertical line highlight + for(int i = lastColorIndex; i < gradientsSize; i++) { + gc.setForeground(gradients[i]); + gc.drawPoint(lastX, 1 + lastY++); + } + + int rightEdgeOffset = rightEdge - parent.curveIndent; - if (tabInPaint) { - // fill in tab background - if (parent.selectionGradientColors !is null && !parent.selectionGradientVertical) { - parent.drawBackground(gc, shape, true); - } - else { - Color defaultBackground = parent.selectionBackground; - Image image = parent.selectionBgImage; - Color[] colors = parent.selectionGradientColors; - int[] percents = parent.selectionGradientPercents; - bool vertical = parent.selectionGradientVertical; - xx = x; - yy = parent.onBottom ? y - 1 : y + 1; - ww = width; - hh = height; - if (!parent.single && !parent.simple) - ww += parent.curveWidth - parent.curveIndent; - parent.drawBackground(gc, shape, xx, yy, ww, hh, defaultBackground, image, colors, percents, vertical); - } - } + //draw right swoop highlight up to diagonal portion + for (int i = 0; i < parent.topCurveHighlightStart.length /2; i++) { + int rawX = parent.topCurveHighlightStart[i * 2]; + int rawY = parent.topCurveHighlightStart[i * 2 + 1]; + lastX = rawX + rightEdgeOffset; + lastY = rawY + y; + lastColorIndex = rawY - 1; + if(lastColorIndex >= gradientsSize) + break; //can happen if tabs are unusually short and cut off the curve + gc.setForeground(gradients[lastColorIndex]); + gc.drawPoint(lastX, lastY); + } + //draw right diagonal line highlight + for(int i = lastColorIndex; i < lastColorIndex + d; i++) { + if(i >= gradientsSize) + break; //can happen if tabs are unusually short and cut off the curve + gc.setForeground(gradients[i]); + gc.drawPoint(1 + lastX++, 1 + lastY++); + } - //Highlight MUST be drawn before the outline so that outline can cover it in the right spots (start of swoop) - //otherwise the curve looks jagged - drawHighlight(gc, rightEdge); + //draw right swoop highlight from diagonal portion to end + for (int i = 0; i < parent.topCurveHighlightEnd.length /2; i++) { + int rawX = parent.topCurveHighlightEnd[i * 2]; //d is already encoded in this value + int rawY = parent.topCurveHighlightEnd[i * 2 + 1]; //d already encoded + lastX = rawX + rightEdgeOffset; + lastY = rawY + y; + lastColorIndex = rawY - 1; + if(lastColorIndex >= gradientsSize) + break; //can happen if tabs are unusually short and cut off the curve + gc.setForeground(gradients[lastColorIndex]); + gc.drawPoint(lastX, lastY); + } +} - // draw outline - shape[0] = Math.max(0, parent.borderLeft - 1); - if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) { - shape[1] = parent.onBottom ? y + height - 1 : y; - shape[5] = shape[3] = shape[1]; - } - shape[shape.length - 2] = size.x - parent.borderRight + 1; - for (int i = 0; i < shape.length / 2; i++) { - if (shape[2 * i + 1] is y + height + 1) - shape[2 * i + 1] -= 1; - } - RGB inside = parent.selectionBackground.getRGB(); - if (parent.selectionBgImage !is null || (parent.selectionGradientColors !is null && parent.selectionGradientColors.length > 1)) { - inside = null; - } - RGB outside = parent.getBackground().getRGB(); - if (parent.bgImage !is null || (parent.gradientColors !is null && parent.gradientColors.length > 1)) { - outside = null; - } - parent.antialias(shape, CTabFolder.borderColor.getRGB(), inside, outside, gc); - gc.setForeground(CTabFolder.borderColor); - gc.drawPolyline(shape); +/* + * Draw the unselected border for the receiver on the right. + * + * @param gc + */ +void drawRightUnselectedBorder(GC gc) { + + int[] shape = null; + int startX = x + width - 1; + + if (this.parent.onBottom) { + int[] right = parent.simple + ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER + : CTabFolder.BOTTOM_RIGHT_CORNER; + + shape = new int[right.length + 2]; + int index = 0; - if (!tabInPaint) - return; + for (int i = 0; i < right.length / 2; i++) { + shape[index++] = startX + right[2 * i]; + shape[index++] = y + height + right[2 * i + 1] - 1; + } + shape[index++] = startX; + shape[index++] = y - 1; + } else { + int[] right = parent.simple + ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER + : CTabFolder.TOP_RIGHT_CORNER; + + shape = new int[right.length + 2]; + int index = 0; + + for (int i = 0; i < right.length / 2; i++) { + shape[index++] = startX + right[2 * i]; + shape[index++] = y + right[2 * i + 1]; } - // draw Image - int xDraw = x + LEFT_MARGIN; - if (parent.single && (parent.showClose || showClose)) - xDraw += CTabFolder.BUTTON_SIZE; - Image image = getImage(); - if (image !is null) { - Rectangle imageBounds = image.getBounds(); - // only draw image if it won't overlap with close button - int maxImageWidth = rightEdge - xDraw - RIGHT_MARGIN; - if (!parent.single && closeRect.width > 0) - maxImageWidth -= closeRect.width + INTERNAL_SPACING; - if (imageBounds.width < maxImageWidth) { - int imageX = xDraw; - int imageY = y + (height - imageBounds.height) / 2; - imageY += parent.onBottom ? -1 : 1; - gc.drawImage(image, imageX, imageY); - xDraw += imageBounds.width + INTERNAL_SPACING; - } - } - - // draw Text - int textWidth = rightEdge - xDraw - RIGHT_MARGIN; - if (!parent.single && closeRect.width > 0) - textWidth -= closeRect.width + INTERNAL_SPACING; - if (textWidth > 0) { - Font gcFont = gc.getFont(); - gc.setFont(font is null ? parent.getFont() : font); - - if (shortenedText is null || shortenedTextWidth !is textWidth) { - shortenedText = shortenText(gc, getText(), textWidth); - shortenedTextWidth = textWidth; - } - Point extent = gc.textExtent(shortenedText, FLAGS); - int textY = y + (height - extent.y) / 2; - textY += parent.onBottom ? -1 : 1; - - gc.setForeground(parent.selectionForeground); - gc.drawText(shortenedText, xDraw, textY, FLAGS); - gc.setFont(gcFont); - - // draw a Focus rectangle - if (parent.isFocusControl()) { - Display display = getDisplay(); - if (parent.simple || parent.single) { - gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); - gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); - gc.drawFocus(xDraw - 1, textY - 1, extent.x + 2, extent.y + 2); - } - else { - gc.setForeground(display.getSystemColor(CTabFolder.BUTTON_BORDER)); - gc.drawLine(xDraw, textY + extent.y + 1, xDraw + extent.x + 1, textY + extent.y + 1); - } - } - } - if (parent.showClose || showClose) - drawClose(gc); - } - - /* - * Draw a highlight effect along the left, top, and right edges of the tab. - * Only for curved tabs, on top. - * Do not draw if insufficient colors. - */ - void drawHighlight (GC gc, int rightEdge) { - //only draw for curvy tabs and only draw for top tabs - if (parent.simple || this.parent.onBottom) - return; - - if (parent.selectionHighlightGradientBegin is null) - return; - - Color[] gradients = parent.selectionHighlightGradientColorsCache; - if (gradients is null) - return; - int gradientsSize = gradients.length; - if (gradientsSize is 0) - return; //shouldn't happen but just to be tidy - - gc.setForeground(gradients[0]); - - //draw top horizontal line - gc.drawLine(CTabFolder.TOP_LEFT_CORNER_HILITE[0] + x + 1, //rely on fact that first pair is top/right of curve - 1 + y, rightEdge - parent.curveIndent, 1 + y); - - int[] leftHighlightCurve = CTabFolder.TOP_LEFT_CORNER_HILITE; - - int d = parent.tabHeight - parent.topCurveHighlightEnd.length / 2; - - int lastX = 0; - int lastY = 0; - int lastColorIndex = 0; - - //draw upper left curve highlight - for (int i = 0; i < leftHighlightCurve.length / 2; i++) { - int rawX = leftHighlightCurve[i * 2]; - int rawY = leftHighlightCurve[i * 2 + 1]; - lastX = rawX + x; - lastY = rawY + y; - lastColorIndex = rawY - 1; - gc.setForeground(gradients[lastColorIndex]); - gc.drawPoint(lastX, lastY); - } - //draw left vertical line highlight - for (int i = lastColorIndex; i < gradientsSize; i++) { - gc.setForeground(gradients[i]); - gc.drawPoint(lastX, 1 + lastY++); - } - - int rightEdgeOffset = rightEdge - parent.curveIndent; - - //draw right swoop highlight up to diagonal portion - for (int i = 0; i < parent.topCurveHighlightStart.length / 2; i++) { - int rawX = parent.topCurveHighlightStart[i * 2]; - int rawY = parent.topCurveHighlightStart[i * 2 + 1]; - lastX = rawX + rightEdgeOffset; - lastY = rawY + y; - lastColorIndex = rawY - 1; - if (lastColorIndex >= gradientsSize) - break; //can happen if tabs are unusually short and cut off the curve - gc.setForeground(gradients[lastColorIndex]); - gc.drawPoint(lastX, lastY); - } - //draw right diagonal line highlight - for (int i = lastColorIndex; i < lastColorIndex + d; i++) { - if (i >= gradientsSize) - break; //can happen if tabs are unusually short and cut off the curve - gc.setForeground(gradients[i]); - gc.drawPoint(1 + lastX++, 1 + lastY++); - } - - //draw right swoop highlight from diagonal portion to end - for (int i = 0; i < parent.topCurveHighlightEnd.length / 2; i++) { - int rawX = parent.topCurveHighlightEnd[i * 2]; //d is already encoded in this value - int rawY = parent.topCurveHighlightEnd[i * 2 + 1]; //d already encoded - lastX = rawX + rightEdgeOffset; - lastY = rawY + y; - lastColorIndex = rawY - 1; - if (lastColorIndex >= gradientsSize) - break; //can happen if tabs are unusually short and cut off the curve - gc.setForeground(gradients[lastColorIndex]); - gc.drawPoint(lastX, lastY); - } - } - - /* - * Draw the unselected border for the receiver on the right. - * - * @param gc - */ - void drawRightUnselectedBorder (GC gc) { - - int[] shape = null; - int startX = x + width - 1; - - if (this.parent.onBottom) { - int[] right = parent.simple ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER : CTabFolder.BOTTOM_RIGHT_CORNER; - - shape = new int[right.length + 2]; - int index = 0; - - for (int i = 0; i < right.length / 2; i++) { - shape[index++] = startX + right[2 * i]; - shape[index++] = y + height + right[2 * i + 1] - 1; - } - shape[index++] = startX; - shape[index++] = y - 1; - } - else { - int[] right = parent.simple ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER : CTabFolder.TOP_RIGHT_CORNER; - - shape = new int[right.length + 2]; - int index = 0; - - for (int i = 0; i < right.length / 2; i++) { - shape[index++] = startX + right[2 * i]; - shape[index++] = y + right[2 * i + 1]; - } - - shape[index++] = startX; - shape[index++] = y + height; - - } - - drawBorder(gc, shape); + shape[index++] = startX; + shape[index++] = y + height; } - /* - * Draw the border of the tab - * - * @param gc - * @param shape - */ - void drawBorder (GC gc, int[] shape) { + drawBorder(gc, shape); + +} - gc.setForeground(CTabFolder.borderColor); - gc.drawPolyline(shape); - } +/* + * Draw the border of the tab + * + * @param gc + * @param shape + */ +void drawBorder(GC gc, int[] shape) { - /* - * Draw the unselected border for the receiver on the left. - * - * @param gc - */ - void drawLeftUnselectedBorder (GC gc) { + gc.setForeground(CTabFolder.borderColor); + gc.drawPolyline(shape); +} + +/* + * Draw the unselected border for the receiver on the left. + * + * @param gc + */ +void drawLeftUnselectedBorder(GC gc) { - int[] shape = null; - if (this.parent.onBottom) { - int[] left = parent.simple ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER : CTabFolder.BOTTOM_LEFT_CORNER; + int[] shape = null; + if (this.parent.onBottom) { + int[] left = parent.simple + ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER + : CTabFolder.BOTTOM_LEFT_CORNER; - shape = new int[left.length + 2]; - int index = 0; - shape[index++] = x; - shape[index++] = y - 1; - for (int i = 0; i < left.length / 2; i++) { - shape[index++] = x + left[2 * i]; - shape[index++] = y + height + left[2 * i + 1] - 1; - } + shape = new int[left.length + 2]; + int index = 0; + shape[index++] = x; + shape[index++] = y - 1; + for (int i = 0; i < left.length / 2; i++) { + shape[index++] = x + left[2 * i]; + shape[index++] = y + height + left[2 * i + 1] - 1; } - else { - int[] left = parent.simple ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER : CTabFolder.TOP_LEFT_CORNER; + } else { + int[] left = parent.simple + ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER + : CTabFolder.TOP_LEFT_CORNER; - shape = new int[left.length + 2]; - int index = 0; - shape[index++] = x; - shape[index++] = y + height; - for (int i = 0; i < left.length / 2; i++) { - shape[index++] = x + left[2 * i]; - shape[index++] = y + left[2 * i + 1]; - } - + shape = new int[left.length + 2]; + int index = 0; + shape[index++] = x; + shape[index++] = y + height; + for (int i = 0; i < left.length / 2; i++) { + shape[index++] = x + left[2 * i]; + shape[index++] = y + left[2 * i + 1]; } - drawBorder(gc, shape); - } - - void drawUnselected (GC gc) { - // Do not draw partial items - if (!showing) - return; - - Rectangle clipping = gc.getClipping(); - Rectangle bounds = getBounds(); - if (!clipping.intersects(bounds)) - return; - - // draw border - int index = parent.indexOf(this); - - if (index > 0 && index < parent.selectedIndex) - drawLeftUnselectedBorder(gc); - // If it is the last one then draw a line - if (index > parent.selectedIndex) - drawRightUnselectedBorder(gc); - - // draw Image - int xDraw = x + LEFT_MARGIN; - Image image = getImage(); - if (image !is null && parent.showUnselectedImage) { - Rectangle imageBounds = image.getBounds(); - // only draw image if it won't overlap with close button - int maxImageWidth = x + width - xDraw - RIGHT_MARGIN; - if (parent.showUnselectedClose && (parent.showClose || showClose)) { - maxImageWidth -= closeRect.width + INTERNAL_SPACING; - } - if (imageBounds.width < maxImageWidth) { - int imageX = xDraw; - int imageHeight = imageBounds.height; - int imageY = y + (height - imageHeight) / 2; - imageY += parent.onBottom ? -1 : 1; - int imageWidth = imageBounds.width * imageHeight / imageBounds.height; - gc.drawImage(image, imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height, imageX, imageY, imageWidth, imageHeight); - xDraw += imageWidth + INTERNAL_SPACING; - } - } - // draw Text - int textWidth = x + width - xDraw - RIGHT_MARGIN; - if (parent.showUnselectedClose && (parent.showClose || showClose)) { - textWidth -= closeRect.width + INTERNAL_SPACING; - } - if (textWidth > 0) { - Font gcFont = gc.getFont(); - gc.setFont(font is null ? parent.getFont() : font); - if (shortenedText is null || shortenedTextWidth !is textWidth) { - shortenedText = shortenText(gc, getText(), textWidth); - shortenedTextWidth = textWidth; - } - Point extent = gc.textExtent(shortenedText, FLAGS); - int textY = y + (height - extent.y) / 2; - textY += parent.onBottom ? -1 : 1; - gc.setForeground(parent.getForeground()); - gc.drawText(shortenedText, xDraw, textY, FLAGS); - gc.setFont(gcFont); - } - // draw close - if (parent.showUnselectedClose && (parent.showClose || showClose)) - drawClose(gc); - } - - /** - * Returns a rectangle describing the receiver's size and location - * relative to its parent. - * - * @return the receiver's bounding column rectangle - * - * @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 Rectangle getBounds () { - //checkWidget(); - int w = width; - if (!parent.simple && !parent.single && parent.indexOf(this) is parent.selectedIndex) - w += parent.curveWidth - parent.curveIndent; - return new Rectangle(x, y, w, height); - } - - /** - * Gets the control that is displayed in the content area of the tab item. - * - * @return the control - * - * @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 Control getControl () { - checkWidget(); - return control; - } - - /** - * Get the image displayed in the tab if the tab is disabled. - * - * @return the disabled image 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
    • - *
    - * - * @deprecated the disabled image is not used - */ - public Image getDisabledImage () { - checkWidget(); - return disabledImage; - } - - /** - * Returns the font that the receiver will use to paint textual information. - * - * @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(); - if (font !is null) - return font; - return parent.getFont(); - } - - /** - * Returns the receiver's parent, which must be a CTabFolder. - * - * @return the receiver's parent - * - * @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 CTabFolder getParent () { - //checkWidget(); - return parent; - } - - /** - * Returns 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
      - *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • - *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • - *
    - * - * @since 3.4 - */ - public bool getShowClose () { - checkWidget(); - return showClose; - } - - /** - * Returns the receiver's tool tip text, or null if it has - * not been set. - * - * @return the receiver's tool tip text - * - * @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 getToolTipText () { - checkWidget(); - if (toolTipText is null && shortenedText !is null) { - String text = getText(); - if (!shortenedText.opEquals(text)) - return text; - } - return toolTipText; } - /** - * Returns 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
      - *
    • 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 bool isShowing () { - checkWidget(); - return showing; - } + drawBorder(gc, shape); +} + +void drawUnselected(GC gc) { + // Do not draw partial items + if (!showing) return; + + Rectangle clipping = gc.getClipping(); + Rectangle bounds = getBounds(); + if (!clipping.intersects(bounds)) return; + + // draw border + int index = parent.indexOf(this); + + if (index > 0 && index < parent.selectedIndex) + drawLeftUnselectedBorder(gc); + // If it is the last one then draw a line + if (index > parent.selectedIndex) + drawRightUnselectedBorder(gc); - void onPaint (GC gc, bool isSelected) { - if (width is 0 || height is 0) - return; - if (isSelected) { - drawSelected(gc); + // draw Image + int xDraw = x + LEFT_MARGIN; + Image image = getImage(); + if (image !is null && parent.showUnselectedImage) { + Rectangle imageBounds = image.getBounds(); + // only draw image if it won't overlap with close button + int maxImageWidth = x + width - xDraw - RIGHT_MARGIN; + if (parent.showUnselectedClose && (parent.showClose || showClose)) { + maxImageWidth -= closeRect.width + INTERNAL_SPACING; } - else { - drawUnselected(gc); + if (imageBounds.width < maxImageWidth) { + int imageX = xDraw; + int imageHeight = imageBounds.height; + int imageY = y + (height - imageHeight) / 2; + imageY += parent.onBottom ? -1 : 1; + int imageWidth = imageBounds.width * imageHeight / imageBounds.height; + gc.drawImage(image, + imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height, + imageX, imageY, imageWidth, imageHeight); + xDraw += imageWidth + INTERNAL_SPACING; } } - - int preferredHeight (GC gc) { - Image image = getImage(); - int h = (image is null) ? 0 : image.getBounds().height; + // draw Text + int textWidth = x + width - xDraw - RIGHT_MARGIN; + if (parent.showUnselectedClose && (parent.showClose || showClose)) { + textWidth -= closeRect.width + INTERNAL_SPACING; + } + if (textWidth > 0) { + Font gcFont = gc.getFont(); + gc.setFont(font is null ? parent.getFont() : font); + if (shortenedText is null || shortenedTextWidth !is textWidth) { + shortenedText = shortenText(gc, getText(), textWidth); + shortenedTextWidth = textWidth; + } + Point extent = gc.textExtent(shortenedText, FLAGS); + int textY = y + (height - extent.y) / 2; + textY += parent.onBottom ? -1 : 1; + gc.setForeground(parent.getForeground()); + gc.drawText(shortenedText, xDraw, textY, FLAGS); + gc.setFont(gcFont); + } + // draw close + if (parent.showUnselectedClose && (parent.showClose || showClose)) drawClose(gc); +} +/** + * Returns a rectangle describing the receiver's size and location + * relative to its parent. + * + * @return the receiver's bounding column rectangle + * + * @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 Rectangle getBounds () { + //checkWidget(); + int w = width; + if (!parent.simple && !parent.single && parent.indexOf(this) is parent.selectedIndex) w += parent.curveWidth - parent.curveIndent; + return new Rectangle(x, y, w, height); +} +/** +* Gets the control that is displayed in the content area of the tab item. +* +* @return the control +* +* @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 Control getControl () { + checkWidget(); + return control; +} +/** + * Get the image displayed in the tab if the tab is disabled. + * + * @return the disabled image 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
    • + *
    + * + * @deprecated the disabled image is not used + */ +public Image getDisabledImage(){ + checkWidget(); + return disabledImage; +} +/** + * Returns the font that the receiver will use to paint textual information. + * + * @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(); + if (font !is null) return font; + return parent.getFont(); +} +/** + * Returns the receiver's parent, which must be a CTabFolder. + * + * @return the receiver's parent + * + * @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 CTabFolder getParent () { + //checkWidget(); + return parent; +} +/** + * Returns 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
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public bool getShowClose() { + checkWidget(); + return showClose; +} +/** + * Returns the receiver's tool tip text, or null if it has + * not been set. + * + * @return the receiver's tool tip text + * + * @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 getToolTipText () { + checkWidget(); + if (toolTipText is null && shortenedText !is null) { String text = getText(); + if (shortenedText!=text) return text; + } + return toolTipText; +} +/** +* Returns 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
      + *
    • 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 bool isShowing () { + checkWidget(); + return showing; +} +void onPaint(GC gc, bool isSelected) { + if (width is 0 || height is 0) return; + if (isSelected) { + drawSelected(gc); + } else { + drawUnselected(gc); + } +} +int preferredHeight(GC gc) { + Image image = getImage(); + int h = (image is null) ? 0 : image.getBounds().height; + String text = getText(); + if (font is null) { + h = Math.max(h, gc.textExtent(text, FLAGS).y); + } else { + Font gcFont = gc.getFont(); + gc.setFont(font); + h = Math.max(h, gc.textExtent(text, FLAGS).y); + gc.setFont(gcFont); + } + return h + TOP_MARGIN + BOTTOM_MARGIN; +} +int preferredWidth(GC gc, bool isSelected, bool minimum) { + // NOTE: preferred width does not include the "dead space" caused + // by the curve. + if (isDisposed()) return 0; + int w = 0; + Image image = getImage(); + if (image !is null && (isSelected || parent.showUnselectedImage)) { + w += image.getBounds().width; + } + String text = null; + if (minimum) { + int minChars = parent.minChars; + text = minChars is 0 ? null : getText(); + if (text !is null && text.length > minChars) { + if (useEllipses()) { + int end = minChars < ELLIPSIS.length + 1 ? minChars : minChars - ELLIPSIS.length; + text = text[ 0 .. end ]; + if (minChars > ELLIPSIS.length + 1) text ~= ELLIPSIS; + } else { + int end = minChars; + text = text[ 0 .. end ]; + } + } + } else { + text = getText(); + } + if (text !is null) { + if (w > 0) w += INTERNAL_SPACING; if (font is null) { - h = Math.max(h, gc.textExtent(text, FLAGS).y); - } - else { + w += gc.textExtent(text, FLAGS).x; + } else { Font gcFont = gc.getFont(); gc.setFont(font); - h = Math.max(h, gc.textExtent(text, FLAGS).y); + w += gc.textExtent(text, FLAGS).x; gc.setFont(gcFont); } - return h + TOP_MARGIN + BOTTOM_MARGIN; } - - int preferredWidth (GC gc, bool isSelected, bool minimum) { - // NOTE: preferred width does not include the "dead space" caused - // by the curve. - if (isDisposed()) - return 0; - int w = 0; - Image image = getImage(); - if (image !is null && (isSelected || parent.showUnselectedImage)) { - w += image.getBounds().width; - } - String text = null; - if (minimum) { - int minChars = parent.minChars; - text = minChars is 0 ? null : getText(); - if (text !is null && text.length() > minChars) { - if (useEllipses()) { - int end = minChars < ELLIPSIS.length() + 1 ? minChars : minChars - ELLIPSIS.length(); - text = text.substring(0, end); - if (minChars > ELLIPSIS.length() + 1) - text += ELLIPSIS; - } - else { - int end = minChars; - text = text.substring(0, end); - } - } - } - else { - text = getText(); + if (parent.showClose || showClose) { + if (isSelected || parent.showUnselectedClose) { + if (w > 0) w += INTERNAL_SPACING; + w += CTabFolder.BUTTON_SIZE; } - if (text !is null) { - if (w > 0) - w += INTERNAL_SPACING; - if (font is null) { - w += gc.textExtent(text, FLAGS).x; - } - else { - Font gcFont = gc.getFont(); - gc.setFont(font); - w += gc.textExtent(text, FLAGS).x; - gc.setFont(gcFont); - } - } - if (parent.showClose || showClose) { - if (isSelected || parent.showUnselectedClose) { - if (w > 0) - w += INTERNAL_SPACING; - w += CTabFolder.BUTTON_SIZE; - } - } - return w + LEFT_MARGIN + RIGHT_MARGIN; } - - /** - * Sets the control that is used to fill the client area of - * the tab folder when the user selects the tab item. - * - * @param control the new control (or null) - * - * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT - if the control has been disposed
    • - *
    • ERROR_INVALID_PARENT - if the control is not in the same widget tree
    • - *
    - * @exception 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 setControl (Control control) { - checkWidget(); - if (control !is null) { - if (control.isDisposed()) - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - if (control.getParent() !is parent) - DWT.error(DWT.ERROR_INVALID_PARENT); - } - if (this.control !is null && !this.control.isDisposed()) { + return w + LEFT_MARGIN + RIGHT_MARGIN; +} +/** + * Sets the control that is used to fill the client area of + * the tab folder when the user selects the tab item. + * + * @param control the new control (or null) + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_ARGUMENT - if the control has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the control is not in the same widget tree
    • + *
    + * @exception 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 setControl (Control control) { + checkWidget(); + if (control !is null) { + if (control.isDisposed()) DWT.error (DWT.ERROR_INVALID_ARGUMENT); + if (control.getParent() !is parent) DWT.error (DWT.ERROR_INVALID_PARENT); + } + if (this.control !is null && !this.control.isDisposed()) { + this.control.setVisible(false); + } + this.control = control; + if (this.control !is null) { + int index = parent.indexOf (this); + if (index is parent.getSelectionIndex ()){ + this.control.setBounds(parent.getClientArea ()); + this.control.setVisible(true); + } else { this.control.setVisible(false); } - this.control = control; - if (this.control !is null) { - int index = parent.indexOf(this); - if (index is parent.getSelectionIndex()) { - this.control.setBounds(parent.getClientArea()); - this.control.setVisible(true); - } - else { - this.control.setVisible(false); - } - } } - - /** - * Sets the image that is displayed if the tab item is disabled. - * Null will clear the image. - * - * @param image the image to be displayed when the item is disabled 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
    • - *
    - * - * @deprecated This image is not used - */ - public void setDisabledImage (Image image) { - checkWidget(); - if (image !is null && image.isDisposed()) { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - this.disabledImage = image; - } - - /** - * 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 (font is null && this.font is null) - return; - if (font !is null && font.opEquals(this.font)) - return; - this.font = font; - if (!parent.updateTabHeight(false)) { - parent.updateItems(); - parent.redrawTabs(); - } +} +/** + * Sets the image that is displayed if the tab item is disabled. + * Null will clear the image. + * + * @param image the image to be displayed when the item is disabled 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
    • + *
    + * + * @deprecated This image is not used + */ +public void setDisabledImage (Image image) { + checkWidget(); + if (image !is null && image.isDisposed ()) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); } - - public void setImage (Image image) { - checkWidget(); - if (image !is null && image.isDisposed()) { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - Image oldImage = getImage(); - if (image is null && oldImage is null) - return; - if (image !is null && image.opEquals(oldImage)) - return; - super.setImage(image); - if (!parent.updateTabHeight(false)) { - // If image is the same size as before, - // redraw only the image - if (oldImage !is null && image !is null) { - Rectangle oldBounds = oldImage.getBounds(); - Rectangle bounds = image.getBounds(); - if (bounds.width is oldBounds.width && bounds.height is oldBounds.height) { - if (showing) { - bool selected = parent.indexOf(this) is parent.selectedIndex; - if (selected || parent.showUnselectedImage) { - int imageX = x + LEFT_MARGIN, maxImageWidth; - if (selected) { - if (parent.single && (parent.showClose || showClose)) - imageX += CTabFolder.BUTTON_SIZE; - int rightEdge = Math.min(x + width, parent.getRightItemEdge()); - maxImageWidth = rightEdge - imageX - RIGHT_MARGIN; - if (!parent.single && closeRect.width > 0) - maxImageWidth -= closeRect.width + INTERNAL_SPACING; - } - else { - maxImageWidth = x + width - imageX - RIGHT_MARGIN; - if (parent.showUnselectedClose && (parent.showClose || showClose)) { - maxImageWidth -= closeRect.width + INTERNAL_SPACING; - } - } - if (bounds.width < maxImageWidth) { - int imageY = y + (height - bounds.height) / 2 + (parent.onBottom ? -1 : 1); - parent.redraw(imageX, imageY, bounds.width, bounds.height, false); - } - } - } - return; - } - } - parent.updateItems(); - parent.redrawTabs(); - } + this.disabledImage = image; +} +/** + * 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); } - - /** - * Sets to true to indicate that the receiver's close button should be shown. - * If the parent cast(CTabFolder) was created with DWT.CLOSE style, changing this value has - * no effect. - * - * @param close the new state of the close button - * - * @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.4 - */ - public void setShowClose (bool close) { - checkWidget(); - if (showClose is close) - return; - showClose = close; + if (font is null && this.font is null) return; + if (font !is null && font==this.font) return; + this.font = font; + if (!parent.updateTabHeight(false)) { parent.updateItems(); parent.redrawTabs(); } - - public void setText (String String) { - checkWidget(); - if (String is null) - DWT.error(DWT.ERROR_NULL_ARGUMENT); - if (String.opEquals(getText())) - return; - super.setText(String); - shortenedText = null; - shortenedTextWidth = 0; - if (!parent.updateTabHeight(false)) { - parent.updateItems(); - parent.redrawTabs(); +} +public override void setImage (Image image) { + checkWidget(); + if (image !is null && image.isDisposed ()) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + Image oldImage = getImage(); + if (image is null && oldImage is null) return; + if (image !is null && image==oldImage) return; + super.setImage(image); + if (!parent.updateTabHeight(false)) { + // If image is the same size as before, + // redraw only the image + if (oldImage !is null && image !is null) { + Rectangle oldBounds = oldImage.getBounds(); + Rectangle bounds = image.getBounds(); + if (bounds.width is oldBounds.width && bounds.height is oldBounds.height) { + if (showing) { + bool selected = parent.indexOf(this) is parent.selectedIndex; + if (selected || parent.showUnselectedImage) { + int imageX = x + LEFT_MARGIN, maxImageWidth; + if (selected) { + if (parent.single && (parent.showClose || showClose)) imageX += CTabFolder.BUTTON_SIZE; + int rightEdge = Math.min (x + width, parent.getRightItemEdge()); + maxImageWidth = rightEdge - imageX - RIGHT_MARGIN; + if (!parent.single && closeRect.width > 0) maxImageWidth -= closeRect.width + INTERNAL_SPACING; + } else { + maxImageWidth = x + width - imageX - RIGHT_MARGIN; + if (parent.showUnselectedClose && (parent.showClose || showClose)) { + maxImageWidth -= closeRect.width + INTERNAL_SPACING; + } + } + if (bounds.width < maxImageWidth) { + int imageY = y + (height - bounds.height) / 2 + (parent.onBottom ? -1 : 1); + parent.redraw(imageX, imageY, bounds.width, bounds.height, false); + } + } + } + return; + } } + parent.updateItems(); + parent.redrawTabs(); } - - /** - * Sets the receiver's tool tip text to the argument, which - * may be null indicating that no tool tip text should be shown. - * - * @param String the new tool tip text (or null) - * - * @exception 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 setToolTipText (String String) { - checkWidget(); - toolTipText = String; +} +/** + * Sets to 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
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public void setShowClose(bool close) { + checkWidget(); + if (showClose is close) return; + showClose = close; + parent.updateItems(); + parent.redrawTabs(); +} +public override void setText (String string) { + checkWidget(); + // DWT extension: allow null for zero length string + //if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + if (string.equals (getText())) return; + super.setText(string); + shortenedText = null; + shortenedTextWidth = 0; + if (!parent.updateTabHeight(false)) { + parent.updateItems(); + parent.redrawTabs(); } +} +/** + * Sets the receiver's tool tip text to the argument, which + * may be null indicating that no tool tip text should be shown. + * + * @param string the new tool tip text (or null) + * + * @exception 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 setToolTipText (String string) { + checkWidget(); + toolTipText = string; +} } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/ControlEditor.d --- a/dwt/custom/ControlEditor.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/ControlEditor.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,13 +7,12 @@ * * Contributors: * IBM Corporation - initial API and implementation - * * Port to the D programming language: - * Jacob Carlborg + * Frank Benoit *******************************************************************************/ module dwt.custom.ControlEditor; -import Math = tango.math.Math; +import dwt.dwthelper.utils; import dwt.DWT; import dwt.graphics.Rectangle; @@ -24,90 +23,92 @@ import dwt.widgets.ScrollBar; /** - * - * A ControlEditor is a manager for a Control that appears above a composite and tracks with the - * moving and resizing of that composite. It can be used to display one control above - * another control. This could be used when editing a control that does not have editing - * capabilities by using a text editor or for launching a dialog by placing a button - * above a control. - * - *

    Here is an example of using a ControlEditor: - * - *

    - * 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);
    - * 
    - */ +* +* A ControlEditor is a manager for a Control that appears above a composite and tracks with the +* moving and resizing of that composite. It can be used to display one control above +* another control. This could be used when editing a control that does not have editing +* capabilities by using a text editor or for launching a dialog by placing a button +* above a control. +* +*

    Here is an example of using a ControlEditor: +* +*

    +* 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);
    +* 
    +* +* @see Sample code and further information +*/ 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. - */ + * 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. - */ + * 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. - */ + * 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. - */ + * 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. - */ + * 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. - */ + * 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; @@ -116,160 +117,146 @@ 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; + private final 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); + controlListener = new class() Listener { + public void handleEvent(Event e) { + layout (); } - - 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); + }; + for (int i=0; inot 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); + + 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; iNote: 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; } - void scroll (Event e) { - if (editor is null || editor.isDisposed()) - return; - layout(); - } - - /** - * Specify the Control that is to be displayed. - * - *

    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); - } + this.editor = editor; + layout(); + if (this.editor is null || this.editor.isDisposed()) return; + editor.setVisible(true); } +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/DefaultContent.d --- a/dwt/custom/DefaultContent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/DefaultContent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,39 +7,52 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.DefaultContent; -import dwt.*; +import dwt.DWT; +import dwt.DWTException; import dwt.internal.Compatibility; -import dwt.widgets.*; -import java.util.Vector; +import dwt.widgets.TypedListener; +import dwt.custom.StyledTextContent; +import dwt.custom.TextChangeListener; +import dwt.custom.StyledTextEvent; +import dwt.custom.StyledTextListener; +import dwt.custom.StyledText; +import dwt.dwthelper.utils; + +static import tango.io.model.IFile; +static import tango.text.Text; + +alias tango.text.Text.Text!(char) StringBuffer; class DefaultContent : StyledTextContent { - private final static String LineDelimiter = System.getProperty("line.separator"); + private final static String LineDelimiter = tango.io.model.IFile.FileConst.NewlineString; - Vector textListeners = new Vector(); // stores text listeners for event sending - char[] textStore = new char[0]; // stores the actual text + StyledTextListener[] textListeners; // stores text listeners for event sending + char[] textStore; // 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 highWatermark = 300; + int lowWatermark = 50; + + int[][] lines; // 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 StyledTextContent will always have * at least one empty line. */ this() { - super(); + lines = new int[][]( 50, 2 ); setText(""); } -/** +/** * Adds a line to the end of the line indexes array. Increases the size of the array if necessary. * lineCount is updated to reflect the new entry. *

    @@ -49,19 +62,19 @@ */ void addLineIndex(int start, int length) { int size = lines.length; - if (lineCount is size) { + if (lineCount_ is size) { // expand the lines by powers of 2 - int[][] newLines = new int[size+Compatibility.pow2(expandExp)][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++; + int[] range = [start, length]; + lines[lineCount_] = range; + lineCount_++; } -/** - * Adds a line index to the end of linesArray. Increases the +/** + * Adds a line index to the end of linesArray. Increases the * size of the array if necessary and returns a new array. *

    * @@ -75,19 +88,19 @@ int size = linesArray.length; int[][] newLines = linesArray; if (count is size) { - newLines = new int[size+Compatibility.pow2(replaceExpandExp)][2]; + newLines = new int[][]( size+Compatibility.pow2(replaceExpandExp), 2 ); replaceExpandExp++; System.arraycopy(linesArray, 0, newLines, 0, size); } - int[] range = new int[] {start, length}; + int[] range = [start, length]; newLines[count] = range; return newLines; } /** - * Adds a TextChangeListener listening for - * TextChangingEvent and TextChangedEvent. A + * Adds a 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 + * A TextChangedEvent is sent after changes to the text * occurred. *

    * @@ -99,8 +112,8 @@ public void addTextChangeListener(TextChangeListener listener) { if (listener is null) error(DWT.ERROR_NULL_ARGUMENT); StyledTextListener typedListener = new StyledTextListener(listener); - textListeners.addElement(typedListener); -} + textListeners ~= typedListener; +} /** * Adjusts the gap to accommodate a text change that is occurring. *

    @@ -124,16 +137,16 @@ moveAndResizeGap(position, sizeHint, line); } /** - * Calculates the indexes of each line in the text store. Assumes no gap exists. + * 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; + lineCount_ = 0; int textLength = textStore.length; int i; for (i = start; i < textLength; i++) { - char ch = textStore[i]; + char ch = textStore[i]; if (ch is DWT.CR) { // see if the next character is a LF if (i + 1 < textLength) { @@ -151,8 +164,8 @@ } addLineIndex(start, i - start); } -/** - * Returns whether or not the given character is a line delimiter. Both CR and LF +/** + * Returns whether or not the given character is a line delimiter. Both CR and LF * are valid line delimiters. *

    * @@ -163,7 +176,7 @@ 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. @@ -179,30 +192,30 @@ // 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); + char before = getTextRange(start - 1, 1)[0]; if (before is '\r') { - char after = getTextRange(start, 1).charAt(0); + char after = getTextRange(start, 1)[0]; if (after is '\n') return false; } } else { // deleting text, see if part of a \r\n line delimiter is being deleted - char startChar = getTextRange(start, 1).charAt(0); + char startChar = getTextRange(start, 1)[0]; if (startChar is '\n') { // see if char before delete position is \r if (start !is 0) { - char before = getTextRange(start - 1, 1).charAt(0); + char before = getTextRange(start - 1, 1)[0]; if (before is '\r') return false; } } - char endChar = getTextRange(start + replaceLength - 1, 1).charAt(0); + char endChar = getTextRange(start + replaceLength - 1, 1)[0]; if (endChar is '\r') { // see if char after delete position is \n if (start + replaceLength !is getCharCount()) { - char after = getTextRange(start + replaceLength, 1).charAt(0); + char after = getTextRange(start + replaceLength, 1)[0]; if (after is '\n') return false; } } - } + } return true; } /** @@ -213,44 +226,44 @@ * @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 + * @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[][] indexedLines = new int[][]( numLines, 2 ); int start = 0; - int lineCount = 0; + int lineCount_ = 0; int i; replaceExpandExp = 1; for (i = start; i < length; i++) { - int location = i + offset; + int location = i + offset; if ((location >= gapStart) && (location < gapEnd)) { // ignore the gap } else { - char ch = textStore[location]; + 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++; + 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++; + 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; + int[][] newLines = new int[][]( lineCount_+1, 2 ); + System.arraycopy(indexedLines, 0, newLines, 0, lineCount_); + int[] range = [start, i - start]; + newLines[lineCount_] = range; + return newLines; } /** * Inserts text. @@ -259,30 +272,30 @@ * @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; - +void insert(int position, String text) { + if (text.length is 0) return; + int startLine = getLineAtOffset(position); - int change = text.length(); + 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 + // 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(); - + int startLineLength = getPhysicalLine(startLine).length; + if (change > 0) { - // shrink gap + // shrink gap gapStart += (change); - for (int i = 0; i < text.length(); i++) { - textStore[position + i]= text.charAt(i); + for (int i = 0; i < text.length; i++) { + textStore[position + i]= text[i]; } } - + // figure out the number of new lines that have been inserted int [][] newLines = indexLines(startLineOffset, startLineLength, 10); // only insert an empty line if it is the last line in the text @@ -292,17 +305,17 @@ 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 + // 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--) { + for (int i = lineCount_ - 1; i > startLine; i--) { lines[i + numNewLines]=lines[i]; } // insert the new lines @@ -315,13 +328,13 @@ newLines[numNewLines][0] += startLineOffset; lines[startLine + numNewLines] = newLines[numNewLines]; } - - lineCount += 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 + * 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. *

    * @@ -343,11 +356,11 @@ // 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++) { + for (int i = gapLine + 1; i < lineCount_; i++) { lines[i][0] = lines[i][0] - oldSize; } } - + if (newSize < 0) { if (oldSize > 0) { // removing the gap @@ -364,7 +377,7 @@ int newGapEnd = newGapStart + newSize; if (oldSize is 0) { System.arraycopy(textStore, 0, content, 0, newGapStart); - System.arraycopy(textStore, newGapStart, content, newGapEnd, content.length - newGapEnd); + System.arraycopy(textStore, newGapStart, content, newGapEnd, content.length - newGapEnd); } else if (newGapStart < gapStart) { int delta = gapStart - newGapStart; System.arraycopy(textStore, 0, content, 0, newGapStart); @@ -379,7 +392,7 @@ textStore = content; gapStart = newGapStart; gapEnd = newGapEnd; - + // add the new gap to the lines information if (gapExists()) { gapLine = newGapLine; @@ -387,12 +400,12 @@ 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++) { + 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. *

    * @@ -404,7 +417,7 @@ if (length is 0) { return 0; } - int lineCount = 0; + int lineCount_ = 0; int count = 0; int i = startOffset; if (i >= gapStart) { @@ -414,7 +427,7 @@ if ((i >= gapStart) && (i < gapEnd)) { // ignore the gap } else { - char ch = textStore[i]; + char ch = textStore[i]; if (ch is DWT.CR) { // see if the next character is a LF if (i + 1 < textStore.length) { @@ -422,19 +435,19 @@ if (ch is DWT.LF) { i++; count++; - } - } - lineCount++; + } + } + lineCount_++; } else if (ch is DWT.LF) { - lineCount++; + lineCount_++; } count++; } i++; } - return lineCount; + return lineCount_; } -/** +/** * Returns the number of lines that are in the specified text. *

    * @@ -442,20 +455,20 @@ * @return number of lines in the text */ int lineCount(String text){ - int lineCount = 0; - int length = text.length(); + int lineCount_ = 0; + int length = text.length; for (int i = 0; i < length; i++) { - char ch = text.charAt(i); + char ch = text[i]; if (ch is DWT.CR) { - if (i + 1 < length && text.charAt(i + 1) is DWT.LF) { + if (i + 1 < length && text[i + 1] is DWT.LF) { i++; } - lineCount++; + lineCount_++; } else if (ch is DWT.LF) { - lineCount++; + lineCount_++; } } - return lineCount; + return lineCount_; } /** * @return the logical length of the text store @@ -475,31 +488,31 @@ * */ public String getLine(int index) { - if ((index >= lineCount) || (index < 0)) error(DWT.ERROR_INVALID_ARGUMENT); + 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; + 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--; + while ((length_ - 1 >= 0) && isDelimiter(textStore[start+length_-1])) { + length_--; } - return new String(textStore, start, length); + return textStore[ start .. start + length_].dup; } else { // gap is in the specified range, strip out the gap StringBuffer buf = new StringBuffer(); int gapLength = gapEnd - gapStart; - buf.append(textStore, start, gapStart - start); - buf.append(textStore, gapEnd, length - gapLength - (gapStart - start)); - length = buf.length(); - while ((length - 1 >=0) && isDelimiter(buf.charAt(length - 1))) { - length--; + buf.append(textStore[ start .. gapStart ] ); + buf.append(textStore[ gapEnd .. gapEnd + length_ - gapLength - (gapStart - start) ]); + length_ = buf.length; + while ((length_ - 1 >=0) && isDelimiter(buf.slice[length_ - 1])) { + length_--; } - return buf.toString().substring(0, length); + return buf.toString()[ 0 .. length_ ].dup; } } /** - * Returns the line delimiter that should be used by the StyledText + * 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. *

    @@ -518,18 +531,18 @@ */ String getFullLine(int index) { int start = lines[index][0]; - int length = lines[index][1]; - int end = start + length - 1; + 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); + return textStore[ start .. start + length_ ].dup; } else { // gap is in the specified range, strip out the gap StringBuffer buffer = new StringBuffer(); int gapLength = gapEnd - gapStart; - buffer.append(textStore, start, gapStart - start); - buffer.append(textStore, gapEnd, length - gapLength - (gapStart - start)); - return buffer.toString(); + buffer.append(textStore[ start .. gapStart ]); + buffer.append(textStore[ gapEnd .. gapEnd + length_ - gapLength - (gapStart - start) ]); + return buffer.toString().dup; } } /** @@ -537,18 +550,18 @@ *

    * * @param index the line index - * @return the physical line + * @return the physical line */ String getPhysicalLine(int index) { int start = lines[index][0]; - int length = lines[index][1]; - return getPhysicalText(start, length); + int length_ = lines[index][1]; + return getPhysicalText(start, length_); } /** * @return the number of lines in the text store */ public int getLineCount(){ - return lineCount; + return lineCount_; } /** * Returns the line at the given offset. @@ -571,18 +584,18 @@ 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 + // 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]) + if (lineCount_ > 0) { + int lastLine = lineCount_ - 1; + if (position is lines[lastLine][0] + lines[lastLine][1]) return lastLine; } - int high = lineCount; + int high = lineCount_; int low = -1; - int index = lineCount; + int index = lineCount_; while (high - low > 1) { index = (high + low) / 2; int lineStart = lines[index][0]; @@ -606,9 +619,9 @@ * @return the line index */ int getLineAtPhysicalOffset(int position){ - int high = lineCount; + int high = lineCount_; int low = -1; - int index = lineCount; + int index = lineCount_; while (high - low > 1) { index = (high + low) / 2; int lineStart = lines[index][0]; @@ -628,7 +641,7 @@ * Returns the logical offset of the given line. *

    * - * @param lineIndex index of 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

      @@ -637,14 +650,14 @@ */ public int getOffsetAtLine(int lineIndex) { if (lineIndex is 0) return 0; - if ((lineIndex >= lineCount) || (lineIndex < 0)) error(DWT.ERROR_INVALID_ARGUMENT); + 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. *

      @@ -653,14 +666,14 @@ */ void expandLinesBy(int numLines) { int size = lines.length; - if (size - lineCount >= numLines) { + if (size - lineCount_ >= numLines) { return; } - int[][] newLines = new int[size+Math.max(10, numLines)][2]; + int[][] newLines = new int[][]( size+Math.max(10, numLines), 2 ); System.arraycopy(lines, 0, newLines, 0, size); lines = newLines; } -/** +/** * Reports an DWT error. *

      * @@ -669,7 +682,7 @@ void error (int code) { DWT.error(code); } -/** +/** * Returns whether or not a gap exists in the text store. *

      * @@ -679,7 +692,7 @@ return gapStart !is gapEnd; } /** - * Returns a String representing the continuous content of + * Returns a string representing the continuous content of * the text store. *

      * @@ -687,11 +700,11 @@ * @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); +String getPhysicalText(int start, int length_) { + return textStore[ start .. start + length_ ].dup; } /** - * Returns a String representing the logical content of + * Returns a string representing the logical content of * the text store (i.e., gap stripped out). *

      * @@ -699,72 +712,73 @@ * @param length the logical length of the text to return * @return the text */ -public String getTextRange(int start, int length) { +public String getTextRange(int start, int length_) { if (textStore is null) return ""; - if (length is 0) + if (length_ is 0) return ""; - int end= start + length; + int end= start + length_; if (!gapExists() || (end < gapStart)) - return new String(textStore, start, length); + return textStore[ start .. start + length_].dup; if (gapStart < start) { int gapLength= gapEnd - gapStart; - return new String(textStore, start + gapLength , length); + return textStore[ start + gapLength .. start + gapLength + length_ ].dup; } StringBuffer buf = new StringBuffer(); - buf.append(textStore, start, gapStart - start); - buf.append(textStore, gapEnd, end - gapStart); - return buf.toString(); + buf.append(textStore[ start .. start + gapStart - start ] ); + buf.append(textStore[ gapEnd .. gapEnd + end - gapStart ] ); + return buf.toString().dup; } /** * Removes the specified TextChangeListener. *

      * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @exception IllegalArgumentException

        *
      • ERROR_NULL_ARGUMENT when listener is null
      • *
      */ public void removeTextChangeListener(TextChangeListener listener){ if (listener is null) error(DWT.ERROR_NULL_ARGUMENT); - for (int i = 0; i < textListeners.size(); i++) { - TypedListener typedListener = cast(TypedListener) textListeners.elementAt(i); + for (int i = 0; i < textListeners.length; i++) { + TypedListener typedListener = cast(TypedListener) textListeners[i]; if (typedListener.getEventListener () is listener) { - textListeners.removeElementAt(i); + textListeners = textListeners[ 0 .. i ] ~ textListeners[ i+1 .. $ ]; break; } } } /** - * Replaces the text with newText starting at position start + * Replaces the text with newText starting at position start * for a length of replaceLength. Notifies the appropriate listeners. *

      * - * When sending the TextChangingEvent, 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 + * When sending the TextChangingEvent, 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: *

        - *
      • (replaceText,newText) ==> (replaceLineCount,newLineCount) - *
      • ("","\n") ==> (0,1) - *
      • ("\n\n","a") ==> (2,0) + *
      • (replaceText,newText) is> (replaceLineCount,newLineCount) + *
      • ("","\n") is> (0,1) + *
      • ("\n\n","a") is> (2,0) *
      *

      * * @param start start offset of text to replace * @param replaceLength start offset of text to replace * @param newText start offset of text to replace - * + * * @exception DWTException
        *
      • ERROR_INVALID_ARGUMENT when the text change results in a multi byte - * line delimiter being split or partially deleted. Splitting a line - * delimiter by inserting text between the CR and LF characters of the + * line delimiter being split or partially deleted. Splitting a line + * delimiter by inserting text between the CR and LF characters of the * \r\n delimiter or deleting part of this line delimiter is not supported
      • *
      */ public void replaceTextRange(int start, int replaceLength, String newText){ // check for invalid replace operations - if (!isValidReplace(start, replaceLength, newText)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + if (!isValidReplace(start, replaceLength, newText)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); // inform listeners StyledTextEvent event = new StyledTextEvent(this); @@ -774,11 +788,11 @@ event.text = newText; event.newLineCount = lineCount(newText); event.replaceCharCount = replaceLength; - event.newCharCount = newText.length(); + event.newCharCount = newText.length; sendTextEvent(event); // first delete the text to be replaced - delete(start, replaceLength, event.replaceLineCount + 1); + delete_(start, replaceLength, event.replaceLineCount + 1); // then insert the new text insert(start, newText); // inform listeners @@ -790,19 +804,19 @@ * Sends the text listeners the TextChanged event. */ void sendTextEvent(StyledTextEvent event) { - for (int i = 0; i < textListeners.size(); i++) { - (cast(StyledTextListener)textListeners.elementAt(i)).handleEvent(event); + for (int i = 0; i < textListeners.length; i++) { + (cast(StyledTextListener)textListeners[i]).handleEvent(event); } -} +} /** - * Sets the content to text and removes the gap since there are no sensible predictions + * Sets the content to text and removes the gap since there are no sensible predictions * about where the next change will occur. *

      * * @param text the text */ public void setText (String text){ - textStore = text.toCharArray(); + textStore = text.dup; gapStart = -1; gapEnd = -1; expandExp = 1; @@ -819,32 +833,32 @@ * @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; - +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); + 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)) { + if (position + length_ < getCharCount()) { + endText = getTextRange(position + length_ - 1, 2); + if ((endText[0] is DWT.CR) && (endText[1] is DWT.LF)) { splittingDelimiter = true; } } - adjustGap(position + length, -length, startLine); - int [][] oldLines = indexLines(position, length + (gapEnd - gapStart), numLines); - + 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; + if (position + length_ is gapStart) { + gapStart -= length_; } else { - gapEnd += length; - } + gapEnd += length_; + } // figure out the length of the new concatenated line, do so by // finding the first line delimiter after position @@ -860,7 +874,7 @@ } } eol = true; - } + } } j++; } @@ -871,10 +885,39 @@ 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++) { + for (int i = endLine + 1; i < lineCount_; i++) { lines[i - numOldLines] = lines[i]; } - lineCount -= numOldLines; - gapLine = getLineAtPhysicalOffset(gapStart); + lineCount_ -= numOldLines; + gapLine = getLineAtPhysicalOffset(gapStart); } + +/++ + + DWT extension + +/ +int utf8AdjustOffset( int offset ){ + if (textStore is null) + return offset; + if (offset is 0) + return offset; + if( offset >= textStore.length ){ + return offset; + } + if (!gapExists() || (offset < gapStart)){ + while( textStore[offset] & 0xC0 is 0x80 ){ + offset--; + } + return offset; + } + int gapLength= gapEnd - gapStart; + if( offset+gapLength >= textStore.length ){ + return offset; + } + while( textStore[offset+gapLength] & 0xC0 is 0x80 ){ + offset--; + } + return offset; } + + +} diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/ExtendedModifyEvent.d --- a/dwt/custom/ExtendedModifyEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/ExtendedModifyEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,26 +7,39 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.ExtendedModifyEvent; -import dwt.events.*; +import dwt.dwthelper.utils; + +import dwt.events.TypedEvent; +import dwt.custom.StyledTextEvent; /** * This event is sent after a text change occurs. + * + * @see Sample code and further information */ public final class ExtendedModifyEvent : TypedEvent { /** start offset of the new text */ - public int start; + public int start; /** length of the new text */ public int length; - /** replaced text or empty String if no text was replaced */ + /** replaced text or empty string if no text was replaced */ public String replacedText; - + static final long serialVersionUID = 3258696507027830832L; - + +/** + * Constructs a new instance of this class based on the + * information in the given event. + * + * @param e the event containing the information + */ public this(StyledTextEvent e) { - super(e); + super(cast(Object)e); start = e.start; length = e.end - e.start; replacedText = e.text; diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/ExtendedModifyListener.d --- a/dwt/custom/ExtendedModifyListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/ExtendedModifyListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,24 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.ExtendedModifyListener; import dwt.internal.DWTEventListener; +import dwt.custom.ExtendedModifyEvent; +/** + * Classes which implement this interface provide a method + * that deals with the event that is generated when text + * is modified. + * + * @see ExtendedModifyEvent + * @see Sample code and further information + */ public interface ExtendedModifyListener : DWTEventListener { + /** * This method is called after a text change occurs. *

      diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/LineBackgroundEvent.d --- a/dwt/custom/LineBackgroundEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/LineBackgroundEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,36 +7,50 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.LineBackgroundEvent; -import dwt.events.*; -import dwt.graphics.*; +import dwt.dwthelper.utils; + + +import dwt.events.TypedEvent; +import dwt.graphics.Color; +import dwt.custom.StyledTextEvent; /** * This event is sent when a line is about to be drawn. + * + * @see Sample code and further information */ public class LineBackgroundEvent : TypedEvent { - + /** * line start offset */ public int lineOffset; - + /** * line text */ public String lineText; - + /** * line background color */ - public Color lineBackground; - + public Color lineBackground; + static final long serialVersionUID = 3978711687853324342L; - + +/** + * Constructs a new instance of this class based on the + * information in the given event. + * + * @param e the event containing the information + */ public this(StyledTextEvent e) { - super(e); + super(cast(Object)e); lineOffset = e.detail; lineText = e.text; lineBackground = e.lineBackground; diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/LineBackgroundListener.d --- a/dwt/custom/LineBackgroundListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/LineBackgroundListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,13 +7,24 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.LineBackgroundListener; import dwt.internal.DWTEventListener; +import dwt.custom.LineBackgroundEvent; +/** + * Classes which implement this interface provide a method + * that can provide the background color for a line that + * is to be drawn. + * + * @see LineBackgroundEvent + * @see Sample code and further information + */ public interface LineBackgroundListener : DWTEventListener { - + /** * This method is called when a line is about to be drawn in order to get its * background color. diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/LineStyleEvent.d --- a/dwt/custom/LineStyleEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/LineStyleEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,36 +7,45 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.LineStyleEvent; + +import dwt.dwthelper.utils; -import dwt.events.*; +import dwt.events.TypedEvent; +import dwt.custom.StyleRange; +import dwt.custom.Bullet; +import dwt.custom.StyledTextEvent; /** * This event is sent when a line is about to be drawn. + * + * @see Sample code and further information */ public class LineStyleEvent : TypedEvent { - + /** * line start offset (input) */ public int lineOffset; - + /** * line text (input) */ public String lineText; - + /** * line ranges (output) - * + * * @since 3.2 */ public int[] ranges; - + /** * line styles (output) - * + * * 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 @@ -45,23 +54,23 @@ */ 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; @@ -77,11 +86,17 @@ * @since 3.2 */ public int bulletIndex; - + static final long serialVersionUID = 3906081274027192884L; - + +/** + * Constructs a new instance of this class based on the + * information in the given event. + * + * @param e the event containing the information + */ public this(StyledTextEvent e) { - super(e); + super(cast(Object)e); styles = e.styles; ranges = e.ranges; lineOffset = e.detail; diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/LineStyleListener.d --- a/dwt/custom/LineStyleListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/LineStyleListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,24 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.LineStyleListener; import dwt.internal.DWTEventListener; +import dwt.custom.LineStyleEvent; +/** + * Classes which implement this interface provide a method + * that can provide the style information for a line that + * is to be drawn. + * + * @see LineStyleEvent + * @see Sample code and further information + */ 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. diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/MovementEvent.d --- a/dwt/custom/MovementEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/MovementEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,54 +7,67 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.MovementEvent; -import dwt.events.*; +import dwt.dwthelper.utils; + +import dwt.events.TypedEvent; +import dwt.custom.StyledTextEvent; /** * This event is sent when a new offset is required based on the current * offset and a movement type. - * + * + * @see Sample code and further information + * * @since 3.3 */ public class MovementEvent : TypedEvent { - + /** * line start offset (input) */ public int lineOffset; - + /** * line text (input) */ public String lineText; - + /** * the current offset (input) */ public int offset; - + /** * the new offset (input, output) */ public int newOffset; - + /** * the movement type (input) - * + * * @see dwt.DWT#MOVEMENT_WORD - * @see dwt.DWT#MOVEMENT_WORD_END + * @see dwt.DWT#MOVEMENT_WORD_END * @see dwt.DWT#MOVEMENT_WORD_START * @see dwt.DWT#MOVEMENT_CHAR * @see dwt.DWT#MOVEMENT_CLUSTER */ public int movement; - + static final long serialVersionUID = 3978765487853324342L; - + +/** + * Constructs a new instance of this class based on the + * information in the given event. + * + * @param e the event containing the information + */ public this(StyledTextEvent e) { - super(e); + super(cast(Object)e); lineOffset = e.detail; lineText = e.text; movement = e.count; diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/MovementListener.d --- a/dwt/custom/MovementListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/MovementListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * 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 @@ -7,28 +7,31 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.MovementListener; import dwt.internal.DWTEventListener; +import dwt.custom.MovementEvent; /** * This listener is invoked when a new offset is required based on the current * offset and a movement type. * * @see dwt.DWT#MOVEMENT_WORD - * @see dwt.DWT#MOVEMENT_WORD_END + * @see dwt.DWT#MOVEMENT_WORD_END * @see dwt.DWT#MOVEMENT_WORD_START * @see dwt.DWT#MOVEMENT_CHAR * @see dwt.DWT#MOVEMENT_CLUSTER - * + * * @since 3.3 */ public interface MovementListener : DWTEventListener { /** * This method is called when a new offset is required based on the current * offset and a movement type. - * + * *

      * The following event fields are used:

        *
      • event.lineOffset line start offset (input)
      • @@ -39,7 +42,7 @@ *
      * * @param event the event - * + * * @see MovementEvent * @see StyledText#addWordMovementListener(MovementListener) */ @@ -47,7 +50,7 @@ /** * This method is called when a new offset is required based on the current * offset and a movement type. - * + * *

      * The following event fields are used:

        *
      • event.lineOffset line start offset (input)
      • @@ -58,7 +61,7 @@ *
      * * @param event the event - * + * * @see MovementEvent * @see StyledText#addWordMovementListener(MovementListener) */ diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/PaintObjectEvent.d --- a/dwt/custom/PaintObjectEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/PaintObjectEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,63 +7,77 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.PaintObjectEvent; + -import dwt.events.*; -import dwt.graphics.*; +import dwt.events.TypedEvent; +import dwt.graphics.GC; +import dwt.custom.StyleRange; +import dwt.custom.Bullet; +import dwt.custom.StyledTextEvent; /** * This event is sent when an object needs to be drawn. - * + * + * @see Sample code and further information + * * @since 3.2 */ public class PaintObjectEvent : TypedEvent { - + /** * the GC */ public GC gc; - + /** * the x location */ public int x; - + /** * the y location */ public int y; - + /** * the line ascent */ public int ascent; - + /** * the line descent */ public int descent; - + /** * the StyleRange */ public StyleRange style; - + /** * the Bullet */ public Bullet bullet; - + /** * the bullet index */ public int bulletIndex; - + static final long serialVersionUID = 3906081274027192855L; - + +/** + * Constructs a new instance of this class based on the + * information in the given event. + * + * @param e the event containing the information + */ public this(StyledTextEvent e) { - super(e); + super(cast(Object)e); gc = e.gc; x = e.x; y = e.y; diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/PaintObjectListener.d --- a/dwt/custom/PaintObjectListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/PaintObjectListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * 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 @@ -7,11 +7,15 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.PaintObjectListener; import dwt.internal.DWTEventListener; +import dwt.custom.PaintObjectEvent; + /** * This listener is invoked when an object needs to be drawn. * @@ -20,7 +24,7 @@ public interface PaintObjectListener : DWTEventListener { /** * This method is called when an object needs to be drawn. - * + * *

      * The following event fields are used:

        *
      • event.x the x location (input)
      • @@ -32,7 +36,7 @@ *
      * * @param event the event - * + * * @see PaintObjectEvent * @see StyledText#addPaintObjectListener(PaintObjectListener) */ diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/PopupList.d --- a/dwt/custom/PopupList.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/PopupList.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,72 +7,92 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.PopupList; + +import dwt.dwthelper.utils; + -import dwt.*; -import dwt.events.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.DWTException; +import dwt.events.ControlEvent; +import dwt.events.ControlListener; +import dwt.events.KeyEvent; +import dwt.events.KeyListener; +import dwt.events.MouseEvent; +import dwt.events.MouseListener; +import dwt.graphics.Font; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Display; +import dwt.widgets.Event; +import dwt.widgets.List; +import dwt.widgets.Listener; +import dwt.widgets.Shell; + /** * A PopupList is a list of selectable items that appears in its own shell positioned above * its parent shell. It is used for selecting items when editing a Table cell (similar to the * list that appears when you open a Combo box). * * The list will be positioned so that it does not run off the screen and the largest number of items -* are visible. It may appear above the current cursor location or below it depending how close you +* are visible. It may appear above the current cursor location or below it depending how close you * are to the edge of the screen. +* +* @see Sample code and further information */ public class PopupList { Shell shell; List list; int minimumWidth; -/** +/** * Creates a PopupList above the specified shell. -* +* * @param parent a Shell control which will be the parent of the new instance (cannot be null) */ public this(Shell parent) { this (parent, 0); } -/** +/** * Creates a PopupList above the specified shell. -* +* * @param parent a widget which will be the parent of the new instance (cannot be null) * @param style the style of widget to construct -* -* @since 3.0 +* +* @since 3.0 */ public this(Shell parent, int style) { shell = new Shell(parent, checkStyle(style)); - - list = new List(shell, DWT.SINGLE | DWT.V_SCROLL); + + list = new List(shell, DWT.SINGLE | DWT.V_SCROLL); // close dialog if user selects outside of the shell - shell.addListener(DWT.Deactivate, new Listener() { - public void handleEvent(Event e){ + shell.addListener(DWT.Deactivate, new class() Listener { + public void handleEvent(Event e){ shell.setVisible (false); } }); - + // resize shell when list resizes - shell.addControlListener(new ControlListener() { + shell.addControlListener(new class() ControlListener { public void controlMoved(ControlEvent e){} public void controlResized(ControlEvent e){ Rectangle shellSize = shell.getClientArea(); list.setSize(shellSize.width, shellSize.height); } }); - + // return list selection on Mouse Up or Carriage Return - list.addMouseListener(new MouseListener() { + list.addMouseListener(new class() MouseListener { public void mouseDoubleClick(MouseEvent e){} public void mouseDown(MouseEvent e){} public void mouseUp(MouseEvent e){ shell.setVisible (false); } }); - list.addKeyListener(new KeyListener() { + list.addKeyListener(new class() KeyListener { public void keyReleased(KeyEvent e){} public void keyPressed(KeyEvent e){ if (e.character is '\r'){ @@ -80,7 +100,7 @@ } } }); - + } private static int checkStyle (int style) { int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; @@ -149,7 +169,7 @@ listSize.y += 2; } y = rect.y - listSize.y; - + } else { // place popup list below table cell if (listSize.y > spaceBelow){ @@ -159,18 +179,18 @@ } y = rect.y + rect.height; } - + // Make dialog as wide as the cell listSize.x = rect.width; // dialog width should not be less than minimumWidth if (listSize.x < minimumWidth) listSize.x = minimumWidth; - + // Align right side of dialog with right side of cell int x = rect.x + rect.width - listSize.x; - + shell.setBounds(x, y, listSize.x, listSize.y); - + shell.open(); list.setFocus(); @@ -178,37 +198,37 @@ while (!shell.isDisposed () && shell.isVisible ()) { if (!display.readAndDispatch()) display.sleep(); } - + String result = null; if (!shell.isDisposed ()) { - String [] Strings = list.getSelection (); + String [] strings = list.getSelection (); shell.dispose(); - if (Strings.length !is 0) result = Strings [0]; + if (strings.length !is 0) result = strings [0]; } return result; } /** * Selects an item with text that starts with specified String. *

      -* 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. +* 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 +* @param string the text of the item * * @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 select(String String) { +public void select(String string) { String[] items = list.getItems(); // find the first entry in the list that starts with the - // specified String - if (String !is null){ + // specified string + if (string !is null){ for (int i = 0; i < items.length; i++) { - if (items[i].startsWith(String)){ + if ( tango.text.Util.locatePattern( items[i], string) is 0 ){ int index = list.indexOf(items[i]); list.select(index); break; @@ -223,7 +243,7 @@ * to the default system font for the widget. * * @param font the new font (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
      • @@ -240,13 +260,12 @@ * The new items are added. * The top index is set to 0. * -* @param Strings the array of items +* @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
          -*
        • ERROR_NULL_ARGUMENT - if the items array is null
        • *
        • ERROR_INVALID_ARGUMENT - if an item in the items array is null
        • *
        * @exception DWTException
          @@ -254,8 +273,8 @@ *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • *
        */ -public void setItems (String[] Strings) { - list.setItems(Strings); +public void setItems (String[] strings) { + list.setItems(strings); } /** * Sets the minimum width of the list. @@ -265,7 +284,7 @@ public void setMinimumWidth (int width) { if (width < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - + minimumWidth = width; } } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/ST.d --- a/dwt/custom/ST.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/ST.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,123 +7,127 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.ST; /** * This class provides access to the public constants provided by StyledText. + * + * @see Sample code and further information */ public class ST { - + /* * Navigation Key Actions. Key bindings for the actions are set * by the StyledText widget. - */ - public static 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 + public static const int LINE_UP = 16777217; // binding = DWT.ARROW_UP + public static const int LINE_DOWN = 16777218; // binding = DWT.ARROW_DOWN + public static const int LINE_START = 16777223; // binding = DWT.HOME + public static const int LINE_END = 16777224; // binding = DWT.END + public static const int COLUMN_PREVIOUS = 16777219; // binding = DWT.ARROW_LEFT + public static const int COLUMN_NEXT = 16777220; // binding = DWT.ARROW_RIGHT + public static const int PAGE_UP = 16777221; // binding = DWT.PAGE_UP + public static const int PAGE_DOWN = 16777222; // binding = DWT.PAGE_DOWN + public static const int WORD_PREVIOUS = 17039363; // binding = DWT.MOD1 + DWT.ARROW_LEFT + public static const int WORD_NEXT = 17039364; // binding = DWT.MOD1 + DWT.ARROW_RIGHT + public static const int TEXT_START = 17039367; // binding = DWT.MOD1 + DWT.HOME + public static const int TEXT_END = 17039368; // binding = DWT.MOD1 + DWT.END + public static const int WINDOW_START = 17039365; // binding = DWT.MOD1 + DWT.PAGE_UP + public static const int WINDOW_END = 17039366; // binding = DWT.MOD1 + DWT.PAGE_DOWN /* - * Modification Key Actions + * Selection 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; + public static const int SELECT_ALL = 262209; // binding = DWT.MOD1 + 'A' + public static const int SELECT_LINE_UP = 16908289; // binding = DWT.MOD2 + DWT.ARROW_UP + public static const int SELECT_LINE_DOWN = 16908290; // binding = DWT.MOD2 + DWT.ARROW_DOWN + public static const int SELECT_LINE_START = 16908295; // binding = DWT.MOD2 + DWT.HOME + public static const int SELECT_LINE_END = 16908296; // binding = DWT.MOD2 + DWT.END + public static const int SELECT_COLUMN_PREVIOUS = 16908291; // binding = DWT.MOD2 + DWT.ARROW_LEFT + public static const int SELECT_COLUMN_NEXT = 16908292; // binding = DWT.MOD2 + DWT.ARROW_RIGHT + public static const int SELECT_PAGE_UP = 16908293; // binding = DWT.MOD2 + DWT.PAGE_UP + public static const int SELECT_PAGE_DOWN = 16908294; // binding = DWT.MOD2 + DWT.PAGE_DOWN + public static const int SELECT_WORD_PREVIOUS = 17170435; // binding = DWT.MOD1 + DWT.MOD2 + DWT.ARROW_LEFT + public static const int SELECT_WORD_NEXT = 17170436; // binding = DWT.MOD1 + DWT.MOD2 + DWT.ARROW_RIGHT + public static const int SELECT_TEXT_START = 17170439; // binding = DWT.MOD1 + DWT.MOD2 + DWT.HOME + public static const int SELECT_TEXT_END = 17170440; // binding = DWT.MOD1 + DWT.MOD2 + DWT.END + public static const int SELECT_WINDOW_START = 17170437; // binding = DWT.MOD1 + DWT.MOD2 + DWT.PAGE_UP + public static const int SELECT_WINDOW_END = 17170438; // binding = DWT.MOD1 + DWT.MOD2 + DWT.PAGE_DOWN - /* - * Miscellaneous Key Actions + /* + * Modification Key Actions */ - public static final int TOGGLE_OVERWRITE = 16777225; // binding = DWT.INSERT; - + public static const int CUT = 131199; // binding = DWT.MOD2 + DWT.DEL + public static const int COPY = 17039369; // binding = DWT.MOD1 + DWT.INSERT; + public static const int PASTE = 16908297; // binding = DWT.MOD2 + DWT.INSERT ; + public static const int DELETE_PREVIOUS = '\b'; // binding = DWT.BS; + public static const int DELETE_NEXT = 0x7F; // binding = DWT.DEL; + public static const int DELETE_WORD_PREVIOUS = 262152; // binding = DWT.BS | DWT.MOD1; + public static const int DELETE_WORD_NEXT = 262271; // binding = DWT.DEL | DWT.MOD1; + + /* + * Miscellaneous Key Actions + */ + public static const int TOGGLE_OVERWRITE = 16777225; // binding = DWT.INSERT; + /** * Bullet style dot. - * + * * @see Bullet - * + * * @since 3.2 */ - public static final int BULLET_DOT = 1 << 0; + public static const int BULLET_DOT = 1 << 0; /** * Bullet style number. - * + * * @see Bullet - * + * * @since 3.2 */ - public static final int BULLET_NUMBER = 1 << 1; + public static const int BULLET_NUMBER = 1 << 1; /** * Bullet style lower case letter. - * + * * @see Bullet - * + * * @since 3.2 */ - public static final int BULLET_LETTER_LOWER = 1 << 2; + public static const 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; + public static const int BULLET_LETTER_UPPER = 1 << 3; /** * Bullet style text. - * + * * @see Bullet - * + * * @since 3.2 */ - public static final int BULLET_TEXT = 1 << 4; + public static const int BULLET_TEXT = 1 << 4; /** * Bullet style custom draw. - * + * * @see StyledText#addPaintObjectListener(PaintObjectListener) * @see StyledText#removePaintObjectListener(PaintObjectListener) - * @see Bullet - * + * @see Bullet + * * @since 3.2 */ - public static final int BULLET_CUSTOM = 1 << 5; + public static const int BULLET_CUSTOM = 1 << 5; } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/SashForm.d --- a/dwt/custom/SashForm.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/SashForm.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,13 +7,26 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.SashForm; + -import dwt.*; -import dwt.widgets.*; -import dwt.graphics.*; +import dwt.DWT; +import dwt.DWTException; +import dwt.graphics.Color; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Event; +import dwt.widgets.Layout; +import dwt.widgets.Listener; +import dwt.widgets.Sash; +import dwt.custom.SashFormLayout; +import dwt.custom.SashFormData; +import dwt.dwthelper.utils; /** * The SashForm is a composite control that lays out its children in a @@ -27,23 +40,30 @@ *
        HORIZONTAL, VERTICAL, SMOOTH
        *
    *

    + * + * @see SashForm snippets + * @see DWT Example: CustomControlExample + * @see Sample code and further information */ public class SashForm : Composite { + /** + * The width of all sashes in the form. + */ public int SASH_WIDTH = 3; int sashStyle; - Sash[] sashes = new Sash[0]; + Sash[] sashes; // Remember background and foreground // colors to determine whether to set // sashes to the default color (null) or // a specific color Color background = null; Color foreground = null; - Control[] controls = new Control[0]; + Control[] controls; Control maxControl = null; Listener sashListener; - static final int DRAG_MINIMUM = 20; + static const int DRAG_MINIMUM = 20; /** * Constructs a new instance of this class given its parent @@ -51,7 +71,7 @@ *

    * 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 + * 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. @@ -78,7 +98,7 @@ sashStyle = ((style & DWT.VERTICAL) !is 0) ? DWT.HORIZONTAL : DWT.VERTICAL; if ((style & DWT.BORDER) !is 0) sashStyle |= DWT.BORDER; if ((style & DWT.SMOOTH) !is 0) sashStyle |= DWT.SMOOTH; - sashListener = new Listener() { + sashListener = new class() Listener { public void handleEvent(Event e) { onDragSash(e); } @@ -91,7 +111,7 @@ /** * Returns DWT.HORIZONTAL if the controls in the SashForm are laid out side by side * or DWT.VERTICAL if the controls in the SashForm are laid out top to bottom. - * + * * @return DWT.HORIZONTAL or DWT.VERTICAL */ public int getOrientation() { @@ -115,16 +135,16 @@ checkWidget(); return SASH_WIDTH; } -public int getStyle() { +public override int getStyle() { int style = super.getStyle(); style |= getOrientation() is DWT.VERTICAL ? DWT.VERTICAL : DWT.HORIZONTAL; if ((sashStyle & DWT.SMOOTH) !is 0) style |= DWT.SMOOTH; return style; } /** - * Answer the control that currently is maximized in the SashForm. + * Answer the control that currently is maximized in the SashForm. * This value may be null. - * + * * @return the control that currently is maximized or null */ public Control getMaximizedControl(){ @@ -133,13 +153,13 @@ } /** * Answer the relative weight of each child in the SashForm. The weight represents the - * percent of the total width (if SashForm has Horizontal orientation) or + * percent of the total width (if SashForm has Horizontal orientation) or * total height (if SashForm has Vertical orientation) each control occupies. * The weights are returned in order of the creation of the widgets (weight[0] * corresponds to the weight of the first child created). - * + * * @return the relative weight of each child - * + * * @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
    • @@ -152,8 +172,8 @@ int[] ratios = new int[cArray.length]; for (int i = 0; i < cArray.length; i++) { Object data = cArray[i].getLayoutData(); - if (data !is null && null !is cast(SashFormData)data ) { - ratios[i] = cast(int)((cast(SashFormData)data).weight * 1000 >> 16); + if ( auto sfd = cast(SashFormData)data ) { + ratios[i] = cast(int)(sfd.weight * 1000 >> 16); } else { ratios[i] = 200; } @@ -164,7 +184,7 @@ Control[] children = getChildren(); Control[] result = new Control[0]; for (int i = 0; i < children.length; i++) { - if (children[i] instanceof Sash) continue; + if ( null !is cast(Sash)children[i]) continue; if (onlyVisible && !children[i].getVisible()) continue; Control[] newResult = new Control[result.length + 1]; @@ -189,13 +209,13 @@ Control c2 = controls[sashIndex + 1]; Rectangle b1 = c1.getBounds(); Rectangle b2 = c2.getBounds(); - + Rectangle sashBounds = sash.getBounds(); Rectangle area = getClientArea(); bool correction = false; if (getOrientation() is DWT.HORIZONTAL) { correction = b1.width < DRAG_MINIMUM || b2.width < DRAG_MINIMUM; - int totalWidth = b2.x + b2.width - b1.x; + int totalWidth = b2.x + b2.width - b1.x; int shift = event.x - sashBounds.x; b1.width += shift; b2.x += shift; @@ -253,7 +273,7 @@ c1.setLayoutData(data1); } Object data2 = c2.getLayoutData(); - if (data2 is null || !( null !is cast(SashFormData)data2 )) { + if (data2 is null || !(null !is cast(SashFormData)data2 )) { data2 = new SashFormData(); c2.setLayoutData(data2); } @@ -267,12 +287,12 @@ } } /** - * If orientation is DWT.HORIZONTAL, lay the controls in the SashForm - * out side by side. If orientation is DWT.VERTICAL, lay the + * If orientation is DWT.HORIZONTAL, lay the controls in the SashForm + * out side by side. If orientation is DWT.VERTICAL, lay the * controls in the SashForm out top to bottom. - * + * * @param orientation DWT.HORIZONTAL or DWT.VERTICAL - * + * * @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
      • @@ -296,14 +316,14 @@ } layout(false); } -public void setBackground (Color color) { +public override void setBackground (Color color) { super.setBackground(color); background = color; for (int i = 0; i < sashes.length; i++) { sashes[i].setBackground(background); } } -public void setForeground (Color color) { +public override void setForeground (Color color) { super.setForeground(color); foreground = color; for (int i = 0; i < sashes.length; i++) { @@ -325,19 +345,19 @@ *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • *
      */ -public void setLayout (Layout layout) { +public override void setLayout (Layout layout) { checkWidget(); return; } /** - * Specify the control that should take up the entire client area of the SashForm. - * If one control has been maximized, and this method is called with a different control, + * Specify the control that should take up the entire client area of the SashForm. + * If one control has been maximized, and this method is called with a different control, * the previous control will be minimized and the new control will be maximized. * If the value of control is null, the SashForm will minimize all controls and return to * the default layout where all controls are laid out separated by sashes. - * + * * @param control the control to be maximized 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
      • @@ -355,7 +375,7 @@ } return; } - + for (int i= 0; i < sashes.length; i++){ sashes[i].setVisible(false); } @@ -384,13 +404,13 @@ } /** * Specify the relative weight of each child in the SashForm. This will determine - * what percent of the total width (if SashForm has Horizontal orientation) or + * what percent of the total width (if SashForm has Horizontal orientation) or * total height (if SashForm has Vertical orientation) each control will occupy. * The weights must be positive values and there must be an entry for each * non-sash child of the SashForm. - * + * * @param weights the relative weight of each child - * + * * @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
        • @@ -403,7 +423,7 @@ if (weights is null || weights.length !is cArray.length) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); } - + int total = 0; for (int i = 0; i < weights.length; i++) { if (weights[i] < 0) { diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/SashFormData.d --- a/dwt/custom/SashFormData.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/SashFormData.d Tue Oct 07 16:29:55 2008 +0200 @@ -7,27 +7,34 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.SashFormData; + +import dwt.dwthelper.utils; + +static import tango.text.Util; +import tango.util.Convert; class SashFormData { long weight; String getName () { - String String = getClass ().getName (); - int index = String.lastIndexOf ('.'); - if (index is -1) return String; - return String.substring (index + 1, String.length ()); + String string = this.classinfo.name; + int index = tango.text.Util.locatePrior( string ,'.' ); + if (index is string.length ) return string; + return string[ index + 1 .. $ ]; } /** - * Returns a String containing a concise, human-readable + * Returns a string containing a concise, human-readable * description of the receiver. * - * @return a String representation of the event + * @return a string representation of the event */ -public String toString () { - return getName()+" {weight="+weight+"}"; //$NON-NLS-2$ +public override String toString () { + return getName()~" {weight="~to!(String)(weight)~"}"; //$NON-NLS-2$ } } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/SashFormLayout.d --- a/dwt/custom/SashFormLayout.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/SashFormLayout.d Tue Oct 07 16:29:55 2008 +0200 @@ -7,25 +7,35 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.SashFormLayout; + -import dwt.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Layout; +import dwt.widgets.Sash; +import dwt.custom.SashForm; +import dwt.custom.SashFormData; +import dwt.dwthelper.utils; /** * This class provides the layout for SashForm - * + * * @see SashForm */ class SashFormLayout : Layout { -protected Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { +protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { SashForm sashForm = cast(SashForm)composite; Control[] cArray = sashForm.getControls(true); int width = 0; int height = 0; - if (cArray.length is 0) { + if (cArray.length is 0) { if (wHint !is DWT.DEFAULT) width = wHint; if (hHint !is DWT.DEFAULT) height = hHint; return new Point(width, height); @@ -56,13 +66,13 @@ long total = 0; for (int i = 0; i < cArray.length; i++) { Object data = cArray[i].getLayoutData(); - if (data !is null && null !is cast(SashFormData)data ) { - ratios[i] = (cast(SashFormData)data).weight; + if ( auto sfd = cast(SashFormData)data) { + ratios[i] = sfd.weight; } else { data = new SashFormData(); cArray[i].setLayoutData(data); (cast(SashFormData)data).weight = ratios[i] = ((200 << 16) + 999) / 1000; - + } total += ratios[i]; } @@ -81,21 +91,21 @@ return new Point(width, height); } -protected bool flushCache(Control control) { +protected override bool flushCache(Control control) { return true; } -protected void layout(Composite composite, bool flushCache) { +protected override void layout(Composite composite, bool flushCache) { SashForm sashForm = cast(SashForm)composite; Rectangle area = sashForm.getClientArea(); if (area.width <= 1 || area.height <= 1) return; - + Control[] newControls = sashForm.getControls(true); if (sashForm.controls.length is 0 && newControls.length is 0) return; sashForm.controls = newControls; - + Control[] controls = sashForm.controls; - + if (sashForm.maxControl !is null && !sashForm.maxControl.isDisposed()) { for (int i= 0; i < controls.length; i++){ if (controls[i] !is sashForm.maxControl) { @@ -106,7 +116,7 @@ } return; } - + // keep just the right number of sashes if (sashForm.sashes.length < controls.length - 1) { Sash[] newSashes = new Sash[controls.length - 1]; @@ -141,17 +151,17 @@ long total = 0; for (int i = 0; i < controls.length; i++) { Object data = controls[i].getLayoutData(); - if (data !is null && null !is cast(SashFormData)data ) { - ratios[i] = (cast(SashFormData)data).weight; + if ( auto sfd = cast(SashFormData)data ) { + ratios[i] = sfd.weight; } else { data = new SashFormData(); controls[i].setLayoutData(data); (cast(SashFormData)data).weight = ratios[i] = ((200 << 16) + 999) / 1000; - + } total += ratios[i]; } - + int sashwidth = sashes.length > 0 ? sashForm.SASH_WIDTH + sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH; if (sashForm.getOrientation() is DWT.HORIZONTAL) { int width = cast(int)(ratios[0] * (area.width - sashes.length * sashwidth) / total); diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/ScrolledComposite.d --- a/dwt/custom/ScrolledComposite.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/ScrolledComposite.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,13 +7,29 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.ScrolledComposite; + +import dwt.dwthelper.utils; + -import dwt.*; -import dwt.events.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.DWTException; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwt.widgets.Event; +import dwt.widgets.Layout; +import dwt.widgets.Listener; +import dwt.widgets.ScrollBar; +import dwt.widgets.Shell; +import dwt.custom.ScrolledCompositeLayout; /** * A ScrolledComposite provides scrollbars and will scroll its content when the user @@ -21,17 +37,17 @@ * * *

          There are two ways to use the ScrolledComposite: - * + * *

          - * 1) Set the size of the control that is being scrolled and 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 + * 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 ();
          @@ -39,7 +55,7 @@
            *      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);
          @@ -51,7 +67,7 @@
            *      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);
          @@ -65,7 +81,7 @@
            *      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};
          @@ -77,7 +93,7 @@
            *              // 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
          @@ -85,7 +101,7 @@
            *              c2.layout();
            *          }
            *      });
          - * 
          + *
            *      shell.open ();
            *      while (!shell.isDisposed ()) {
            *          if (!display.readAndDispatch ()) display.sleep ();
          @@ -97,13 +113,16 @@
            * 
          *
          Styles:
          H_SCROLL, V_SCROLL *
          + * + * @see ScrolledComposite snippets + * @see Sample code and further information */ public class ScrolledComposite : Composite { Control content; Listener contentListener; Listener filter; - + int minHeight = 0; int minWidth = 0; bool expandHorizontal = false; @@ -117,7 +136,7 @@ *

          * 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 + * 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. @@ -137,47 +156,46 @@ * @see DWT#H_SCROLL * @see DWT#V_SCROLL * @see #getStyle() - */ + */ public this(Composite parent, int style) { super(parent, checkStyle(style)); super.setLayout(new ScrolledCompositeLayout()); ScrollBar hBar = getHorizontalBar (); if (hBar !is null) { hBar.setVisible(false); - hBar.addListener (DWT.Selection, new Listener () { + hBar.addListener (DWT.Selection, new class() Listener { public void handleEvent (Event e) { hScroll(); } }); } - + ScrollBar vBar = getVerticalBar (); if (vBar !is null) { vBar.setVisible(false); - vBar.addListener (DWT.Selection, new Listener () { + vBar.addListener (DWT.Selection, new class() Listener { public void handleEvent (Event e) { vScroll(); } }); } - - contentListener = new Listener() { + + contentListener = new class() Listener { public void handleEvent(Event e) { if (e.type !is DWT.Resize) return; layout(false); } }; - - filter = new Listener() { + + filter = new class() Listener { public void handleEvent(Event event) { - if ( null !is cast(Control)event.widget ) { - Control control = cast(Control) event.widget; + if (auto control = cast(Control)event.widget ) { if (contains(control)) showControl(control); } } }; - - addDisposeListener(new DisposeListener() { + + addDisposeListener(new class() DisposeListener { public void widgetDisposed(DisposeEvent e) { getDisplay().removeFilter(DWT.FocusIn, filter); } @@ -201,12 +219,12 @@ } /** - * Returns the Always Show Scrollbars flag. True if the scrollbars are - * always shown even if they are not required. False if the scrollbars are only + * Returns the Always Show Scrollbars flag. True if the scrollbars are + * always shown even if they are not required. False if the scrollbars are only * visible when some part of the composite needs to be scrolled to be seen. - * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the + * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the * horizontal and vertical directions. - * + * * @return the Always Show Scrollbars flag value */ public bool getAlwaysShowScrollBars() { @@ -215,7 +233,7 @@ } /** - * Returns true if the content control + * Returns true if the content control * will be expanded to fill available horizontal space. * * @return the receiver's horizontal expansion state @@ -224,7 +242,7 @@ *

        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • *
        - * + * * @since 3.2 */ public bool getExpandHorizontal() { @@ -233,7 +251,7 @@ } /** - * Returns true if the content control + * Returns true if the content control * will be expanded to fill available vertical space. * * @return the receiver's vertical expansion state @@ -242,7 +260,7 @@ *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • *
      - * + * * @since 3.2 */ public bool getExpandVertical() { @@ -259,7 +277,7 @@ *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    - * + * * @since 3.2 */ public int getMinWidth() { @@ -276,7 +294,7 @@ *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • * - * + * * @since 3.2 */ public int getMinHeight() { @@ -286,7 +304,7 @@ /** * Get the content that is being scrolled. - * + * * @return the control displayed in the content area */ public Control getContent() { @@ -295,14 +313,16 @@ } /** - * Returns true if the receiver automatically scrolls to a focused child control + * Returns true if the receiver automatically scrolls to a focused child control * to make it visible. Otherwise, returns false. - * + * + * @return a bool indicating whether focused child controls are automatically scrolled into the viewport + * * @exception 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.4 */ public bool getShowFocusedControl() { @@ -320,13 +340,13 @@ bool needHScroll(Rectangle contentRect, bool vVisible) { ScrollBar hBar = getHorizontalBar(); if (hBar is null) return false; - + Rectangle hostRect = getBounds(); int border = getBorderWidth(); hostRect.width -= 2*border; ScrollBar vBar = getVerticalBar(); if (vVisible && vBar !is null) hostRect.width -= vBar.getSize().x; - + if (!expandHorizontal && contentRect.width > hostRect.width) return true; if (expandHorizontal && minWidth > hostRect.width) return true; return false; @@ -335,31 +355,31 @@ bool needVScroll(Rectangle contentRect, bool hVisible) { ScrollBar vBar = getVerticalBar(); if (vBar is null) return false; - + Rectangle hostRect = getBounds(); int border = getBorderWidth(); hostRect.height -= 2*border; ScrollBar hBar = getHorizontalBar(); if (hVisible && hBar !is null) hostRect.height -= hBar.getSize().y; - + if (!expandVertical && contentRect.height > hostRect.height) return true; if (expandVertical && minHeight > hostRect.height) return true; return false; } /** - * Return the point in the content that currently appears in the top left + * Return the point in the content that currently appears in the top left * corner of the scrolled composite. - * - * @return the point in the content that currently appears in the top left + * + * @return the point in the content that currently appears in the top left * corner of the scrolled composite. If no content has been set, this returns * (0, 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
    • *
    - * + * * @since 2.0 */ public Point getOrigin() { @@ -369,14 +389,14 @@ return new Point(-location.x, -location.y); } /** - * Scrolls the content so that the specified point in the content is in the top - * left corner. If no content has been set, nothing will occur. - * - * Negative values will be ignored. Values greater than the maximum scroll + * Scrolls the content so that the specified point in the content is in the top + * left corner. If no content has been set, nothing will occur. + * + * Negative values will be ignored. Values greater than the maximum scroll * distance will result in scrolling to the end of the scrollbar. * - * @param origin the point on the content to appear in the top left corner - * + * @param origin the point on the content to appear in the top left corner + * * @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
    • @@ -388,21 +408,21 @@ setOrigin(origin.x, origin.y); } /** - * Scrolls the content so that the specified point in the content is in the top - * left corner. If no content has been set, nothing will occur. - * - * Negative values will be ignored. Values greater than the maximum scroll + * Scrolls the content so that the specified point in the content is in the top + * left corner. If no content has been set, nothing will occur. + * + * Negative values will be ignored. Values greater than the maximum scroll * distance will result in scrolling to the end of the scrollbar. * - * @param x the x coordinate of the content to appear in the top left corner - * - * @param y the y coordinate of the content to appear in the top left corner - * + * @param x the x coordinate of the content to appear in the top left corner + * + * @param y the y coordinate of the content to appear in the top left corner + * * @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 setOrigin(int x, int y) { @@ -425,14 +445,14 @@ content.setLocation(x, y); } /** - * Set the Always Show Scrollbars flag. True if the scrollbars are - * always shown even if they are not required. False if the scrollbars are only + * Set the Always Show Scrollbars flag. True if the scrollbars are + * always shown even if they are not required. False if the scrollbars are only * visible when some part of the composite needs to be scrolled to be seen. - * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the + * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the * horizontal and vertical directions. - * + * * @param show true to show the scrollbars even when not required, false to show scrollbars only when required - * + * * @exception DWTException
        *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • @@ -451,9 +471,9 @@ /** * Set the content that will be scrolled. - * + * * @param content the control to be displayed in the content area - * + * * @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
        • @@ -463,9 +483,9 @@ checkWidget(); if (this.content !is null && !this.content.isDisposed()) { this.content.removeListener(DWT.Resize, contentListener); - this.content.setBounds(new Rectangle(-200, -200, 0, 0)); + this.content.setBounds(new Rectangle(-200, -200, 0, 0)); } - + this.content = content; ScrollBar vBar = getVerticalBar (); ScrollBar hBar = getHorizontalBar (); @@ -489,15 +509,15 @@ } } /** - * Configure the ScrolledComposite to resize the content object to be as wide as the + * Configure the ScrolledComposite to resize the content object to be as wide as the * ScrolledComposite when the width of the ScrolledComposite is greater than the * minimum width specified in setMinWidth. If the ScrolledComposite is less than the * minimum width, the content will not be resized and instead the horizontal scroll bar will be * used to view the entire width. * If expand is false, this behaviour is turned off. By default, this behaviour is turned off. - * + * * @param expand true to expand the content control to fill available horizontal space - * + * * @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
          • @@ -510,15 +530,15 @@ layout(false); } /** - * Configure the ScrolledComposite to resize the content object to be as tall as the + * Configure the ScrolledComposite to resize the content object to be as tall as the * ScrolledComposite when the height of the ScrolledComposite is greater than the * minimum height specified in setMinHeight. If the ScrolledComposite is less than the * minimum height, the content will not be resized and instead the vertical scroll bar will be * used to view the entire height. * If expand is false, this behaviour is turned off. By default, this behaviour is turned off. - * + * * @param expand true to expand the content control to fill available vertical space - * + * * @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
            • @@ -545,17 +565,17 @@ *
            • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
            • *
            */ -public void setLayout (Layout layout) { +public override void setLayout (Layout layout) { checkWidget(); return; } /** * Specify the minimum height at which the ScrolledComposite will begin scrolling the - * content with the vertical scroll bar. This value is only relevant if + * content with the vertical scroll bar. This value is only relevant if * setExpandVertical(true) has been set. - * + * * @param height the minimum height or 0 for default height - * + * * @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
            • @@ -566,11 +586,11 @@ } /** * Specify the minimum width and height at which the ScrolledComposite will begin scrolling the - * content with the horizontal scroll bar. This value is only relevant if + * content with the horizontal scroll bar. This value is only relevant if * setExpandHorizontal(true) and setExpandVertical(true) have been set. - * + * * @param size the minimum size or null for the default size - * + * * @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
              • @@ -585,12 +605,12 @@ } /** * Specify the minimum width and height at which the ScrolledComposite will begin scrolling the - * content with the horizontal scroll bar. This value is only relevant if + * content with the horizontal scroll bar. This value is only relevant if * setExpandHorizontal(true) and setExpandVertical(true) have been set. - * + * * @param width the minimum width or 0 for default width * @param height the minimum height or 0 for default height - * + * * @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
                • @@ -605,11 +625,11 @@ } /** * Specify the minimum width at which the ScrolledComposite will begin scrolling the - * content with the horizontal scroll bar. This value is only relevant if + * content with the horizontal scroll bar. This value is only relevant if * setExpandHorizontal(true) has been set. - * + * * @param width the minimum width or 0 for default width - * + * * @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
                  • @@ -622,18 +642,18 @@ /** * Configure the receiver to automatically scroll to a focused child control * to make it visible. - * - * If show is false, show a focused control is off. + * + * If show is false, show a focused control is off. * By default, show a focused control is off. - * + * * @param show true to show a focused control. - * + * * @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.4 + * + * @since 3.4 */ public void setShowFocusedControl(bool show) { checkWidget(); @@ -668,7 +688,7 @@ if (control is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (control.isDisposed ()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); if (!contains(control)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - + Rectangle itemRect = getDisplay().map(control.getParent(), this, control.getBounds()); Rectangle area = getClientArea(); Point origin = getOrigin(); diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/ScrolledCompositeLayout.d --- a/dwt/custom/ScrolledCompositeLayout.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/ScrolledCompositeLayout.d Tue Oct 07 16:29:55 2008 +0200 @@ -7,25 +7,35 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.ScrolledCompositeLayout; + -import dwt.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Layout; +import dwt.widgets.ScrollBar; +import dwt.custom.ScrolledComposite; + +import Math = tango.math.Math; /** * This class provides the layout for ScrolledComposite - * + * * @see ScrolledComposite */ class ScrolledCompositeLayout : Layout { - + bool inLayout = false; static final int DEFAULT_WIDTH = 64; static final int DEFAULT_HEIGHT = 64; - -protected Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { + +protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { ScrolledComposite sc = cast(ScrolledComposite)composite; Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT); if (sc.content !is null) { @@ -41,11 +51,11 @@ return size; } -protected bool flushCache(Control control) { +protected override bool flushCache(Control control) { return true; } -protected void layout(Composite composite, bool flushCache) { +protected override void layout(Composite composite, bool flushCache) { if (inLayout) return; ScrolledComposite sc = cast(ScrolledComposite)composite; if (sc.content is null) return; @@ -72,7 +82,7 @@ } Rectangle hostRect = sc.getClientArea(); if (sc.expandHorizontal) { - contentRect.width = Math.max(sc.minWidth, hostRect.width); + contentRect.width = Math.max(sc.minWidth, hostRect.width); } if (sc.expandVertical) { contentRect.height = Math.max(sc.minHeight, hostRect.height); @@ -105,7 +115,7 @@ contentRect.y = -vSelection; } } - + sc.content.setBounds (contentRect); inLayout = false; } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/StackLayout.d --- a/dwt/custom/StackLayout.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StackLayout.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,30 +7,41 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StackLayout; + +import dwt.dwthelper.utils; + -import dwt.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Layout; + +import tango.util.Convert; +static import tango.text.Util; /** * This Layout stacks all the controls one on top of the other and resizes all controls * to have the same size and location. * The control specified in topControl is visible and all other controls are not visible. - * Users must set the topControl value to flip between the visible items and then call + * Users must set the topControl value to flip between the visible items and then call * layout() on the composite which has the StackLayout. - * - *

                    Here is an example which places ten buttons in a stack layout and + * + *

                    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();
                    @@ -41,7 +52,7 @@
                      *          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];
                    @@ -52,18 +63,22 @@
                      *              parent.layout();
                      *          }
                      *      });
                    - *  
                    + *
                      *      shell.open();
                      *      while (shell !is null && !shell.isDisposed()) {
                      *          if (!display.readAndDispatch())
                    - *              display.sleep(); 
                    - *      }   
                    + *              display.sleep();
                    + *      }
                      *  }
                      * 
                    + * + * @see StackLayout snippets + * @see DWT Example: LayoutExample + * @see Sample code and further information */ public class StackLayout : Layout { - + /** * marginWidth specifies the number of pixels of horizontal margin * that will be placed along the left and right edges of the layout. @@ -85,7 +100,7 @@ */ public Control topControl; -protected Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { +protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { Control children[] = composite.getChildren(); int maxWidth = 0; int maxHeight = 0; @@ -101,11 +116,11 @@ return new Point(width, height); } -protected bool flushCache(Control control) { +protected override bool flushCache(Control control) { return true; } -protected void layout(Composite composite, bool flushCache) { +protected override void layout(Composite composite, bool flushCache) { Control children[] = composite.getChildren(); Rectangle rect = composite.getClientArea(); rect.x += marginWidth; @@ -115,30 +130,30 @@ 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 ()); + String string = this.classinfo.name; + int index = tango.text.Util.locatePrior( string ,'.'); + if (index is string.length ) return string; + return string[ index + 1 .. $ ]; } /** - * Returns a String containing a concise, human-readable + * Returns a string containing a concise, human-readable * description of the receiver. * - * @return a String representation of the layout + * @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; +public override String toString () { + String string = getName ()~" {"; + if (marginWidth !is 0) string ~= "marginWidth="~to!(String)(marginWidth)~" "; + if (marginHeight !is 0) string ~= "marginHeight="~to!(String)(marginHeight)~" "; + if (topControl !is null) string ~= "topControl="~to!(String)(topControl)~" "; + string = tango.text.Util.trim(string); + string ~= "}"; + return string; } } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/StyleRange.d --- a/dwt/custom/StyleRange.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyleRange.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,20 +7,44 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyleRange; + +import dwt.dwthelper.utils; + + +import dwt.DWT; +import dwt.graphics.Color; +import dwt.graphics.TextStyle; +import dwt.internal.CloneableCompatibility; +import dwt.custom.StyleRange; +import dwt.custom.TextChangedEvent; +import dwt.custom.TextChangingEvent; -import dwt.*; -import dwt.graphics.*; -import dwt.internal.CloneableCompatibility; +static import tango.text.Text; +alias tango.text.Text.Text!(char) StringBuffer; -public class StyleRange : TextStyle : CloneableCompatibility { - +/** + * StyleRange defines a set of styles for a specified + * range of text. + *

                    + * The hashCode() method in this class uses the values of the public + * fields to compute the hash value. When storing instances of the + * class in hashed collections, do not modify these fields after the + * object has been inserted. + *

                    + * + * @see Sample code and further information + */ +public class StyleRange : TextStyle, CloneableCompatibility { + /** * the start offset of the range, zero-based from the document start */ public int start; - + /** * the length of the range */ @@ -29,37 +53,46 @@ /** * 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 this() { } +/++ + + DWT extension for clone implementation + +/ +protected this( StyleRange other ){ + super( other ); + start = other.start; + length = other.length; + fontStyle = other.fontStyle; +} -/** +/** * Create a new style range from an existing text style. * - *@param style the text style to copy + * @param style the text style to copy * - *@since 3.4 + * @since 3.4 */ public this(TextStyle style) { super(style); } -/** +/** * Create a new style range. * * @param start start offset of the style - * @param length length of the style - * @param foreground foreground color of the style, null if none + * @param length length of the style + * @param foreground foreground color of the style, null if none * @param background background color of the style, null if none */ public this(int start, int length, Color foreground, Color background) { @@ -68,12 +101,12 @@ 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 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 */ @@ -90,12 +123,11 @@ * @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() + * @see #hashCode() */ -public bool opEquals(Object object) { +public override int opEquals(Object object) { if (object is this) return true; - if ( null !is cast(StyleRange)object ) { - StyleRange style = cast(StyleRange)object; + if (auto style = cast(StyleRange) object ) { if (start !is style.start) return false; if (length !is style.length) return false; return similarTo(style); @@ -104,23 +136,23 @@ } /** - * 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 + * 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 #opEquals(Object) + * @see #equals(Object) */ -public int toHash() { +public override hash_t toHash() { return super.toHash() ^ fontStyle; } bool isVariableHeight() { return font !is null || metrics !is null || rise !is 0; } /** - * Returns whether or not the receiver is unstyled (i.e., does not have any + * 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. @@ -139,7 +171,7 @@ } /** - * Compares the specified object to this StyleRange and answer if the two + * 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. * @@ -156,22 +188,18 @@ * 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; - } + */ +public /+override+/ Object clone() { + return new StyleRange( this ); } /** - * Returns a String containing a concise, human-readable + * Returns a string containing a concise, human-readable * description of the receiver. * - * @return a String representation of the StyleRange + * @return a string representation of the StyleRange */ -public String toString() { +public override String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("StyleRange {"); buffer.append(start); @@ -192,9 +220,10 @@ buffer.append("normal"); } String str = super.toString(); - int index = str.indexOf('{'); - str = str.substring(index + 1); - if (str.length() > 1) buffer.append(", "); + int index = tango.text.Util.locate( str, '{'); + if( index is str.length ) index = -1; + str = str[ index + 1 .. $ ]; + if (str.length > 1) buffer.append(", "); buffer.append(str); return buffer.toString(); } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/StyledText.d --- a/dwt/custom/StyledText.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyledText.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,39 +7,109 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyledText; -import java.util.*; +import dwt.DWT; +import dwt.DWTError; +import dwt.DWTException; +import dwt.accessibility.ACC; +import dwt.accessibility.Accessible; +import dwt.accessibility.AccessibleAdapter; +import dwt.accessibility.AccessibleControlAdapter; +import dwt.accessibility.AccessibleControlEvent; +import dwt.accessibility.AccessibleEvent; +import dwt.accessibility.AccessibleTextAdapter; +import dwt.accessibility.AccessibleTextEvent; +import dwt.dnd.Clipboard; +import dwt.dnd.DND; +import dwt.dnd.RTFTransfer; +import dwt.dnd.TextTransfer; +import dwt.dnd.Transfer; +import dwt.events.ModifyListener; +import dwt.events.SelectionEvent; +import dwt.events.SelectionListener; +import dwt.events.VerifyListener; +import dwt.graphics.Color; +import dwt.graphics.Cursor; +import dwt.graphics.Font; +import dwt.graphics.FontData; +import dwt.graphics.FontMetrics; +import dwt.graphics.GC; +import dwt.graphics.GlyphMetrics; +import dwt.graphics.Image; +import dwt.graphics.Device; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.graphics.Resource; +import dwt.graphics.TextLayout; +import dwt.internal.BidiUtil; +import dwt.internal.Compatibility; +import dwt.printing.Printer; +import dwt.printing.PrinterData; +import dwt.widgets.Canvas; +import dwt.widgets.Caret; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwt.widgets.Event; +import dwt.widgets.IME; +import dwt.widgets.Label; +import dwt.widgets.Listener; +import dwt.widgets.ScrollBar; +import dwt.widgets.TypedListener; +import dwt.custom.StyledTextContent; +import dwt.custom.TextChangeListener; +import dwt.custom.StyledTextRenderer; +import dwt.custom.StyledTextPrintOptions; +import dwt.custom.ExtendedModifyListener; +import dwt.custom.BidiSegmentListener; +import dwt.custom.LineBackgroundListener; +import dwt.custom.LineStyleListener; +import dwt.custom.PaintObjectListener; +import dwt.custom.VerifyKeyListener; +import dwt.custom.MovementListener; +import dwt.custom.Bullet; +import dwt.custom.StyledTextEvent; +import dwt.custom.StyleRange; +import dwt.custom.TextChangedEvent; +import dwt.custom.TextChangingEvent; +import dwt.custom.DefaultContent; +import dwt.custom.StyledTextDropTargetEffect; +import dwt.custom.StyledTextListener; +import dwt.custom.ST; +import dwt.dwthelper.Runnable; -import dwt.*; -import dwt.accessibility.*; -import dwt.dnd.*; -import dwt.events.*; -import dwt.graphics.*; -import dwt.internal.*; -import dwt.printing.*; -import dwt.widgets.*; +static import tango.text.Text; +static import tango.text.Util; +static import tango.io.model.IFile; +static import tango.text.convert.Utf; +import tango.util.Convert; +import dwt.dwthelper.utils; -/** - * A StyledText is an editable user interface object that displays lines - * of text. The following style attributes can be defined for the text: +alias tango.text.Text.Text!(char) StringBuffer; + +/** + * A StyledText is an editable user interface object that displays lines + * of text. The following style attributes can be defined for the text: *
                      - *
                    • foreground color + *
                    • foreground color *
                    • background color *
                    • font style (bold, italic, bold-italic, regular) *
                    • underline *
                    • strikeout *
                    *

                    - * In addition to text style attributes, the background color of a line may + * 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 + * 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: *

                      @@ -51,11 +121,11 @@ *
                    *

                    * 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 + * You may use the API that is defined for StyledText or you may define your own + * LineBackgroundListener. If you define your own listener, you will be responsible + * for maintaining the line background color information for the widget. + * IMPORTANT: You may not define your own listener and use the StyledText API. + * The following StyledText API is not supported if you have defined a * LineBackgroundListener: *

                      *
                    • getLineBackground(int) @@ -64,7 +134,7 @@ *

                      * 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. + * setContent(StyledTextContent) to initialize the widget. *

                      *

                      *
                      Styles:
                      FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP @@ -73,31 +143,37 @@ *

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

                      + * + * @see StyledText snippets + * @see DWT Examples: CustomControlExample, TextEditor + * @see Sample code and further information */ 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; - + alias Canvas.computeSize computeSize; + + static const char TAB = '\t'; + static const String PlatformLineDelimiter = tango.io.model.IFile.FileConst.NewlineString; + static const int BIDI_CARET_WIDTH = 3; + static const int DEFAULT_WIDTH = 64; + static const int DEFAULT_HEIGHT = 64; + static const int V_SCROLL_RATE = 50; + static const int H_SCROLL_RATE = 10; + + static const int ExtendedModify = 3000; + static const int LineGetBackground = 3001; + static const int LineGetStyle = 3002; + static const int TextChanging = 3003; + static const int TextSet = 3004; + static const int VerifyKey = 3005; + static const int TextChanged = 3006; + static const int LineGetSegments = 3007; + static const int PaintObject = 3008; + static const int WordNext = 3009; + static const int WordPrevious = 3010; + + static const int PREVIOUS_OFFSET_TRAILING = 0; + static const int OFFSET_LEADING = 1; + Color selectionBackground; // selection background color Color selectionForeground; // selection foreground color StyledTextContent content; // native content (default or user specified) @@ -118,30 +194,30 @@ 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 selection; // x and y are start and end caret offsets of selection Point clipboardSelection; // x and y are start and end caret offsets of previous selection int selectionAnchor; // position of selection anchor. 0 based offset from beginning of text Point doubleClickSelection; // selection after last mouse double click bool editable = true; bool wordWrap = false; - bool doubleClickEnabled = true; // see getDoubleClickEnabled - bool overwrite = false; // insert/overwrite edit mode + 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(); + int[int] keyActionMap; 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 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 + 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; @@ -149,32 +225,32 @@ Caret defaultCaret = null; bool updateCaretDirection = true; bool fixedLineHeight; - bool dragDetect = true; + bool dragDetect_ = true; IME ime; - + int alignment; bool justify; int indent; int lineSpacing; - final static bool IS_CARBON, IS_GTK, IS_MOTIF; - static { + const static bool IS_CARBON, IS_GTK, IS_MOTIF; + static this(){ String platform = DWT.getPlatform(); - IS_CARBON = "carbon".opEquals(platform); - IS_GTK = "gtk".opEquals(platform); - IS_MOTIF = "motif".opEquals(platform); + IS_CARBON = ("carbon" == platform); + IS_GTK = ("gtk" == platform); + IS_MOTIF = ("motif" == platform); } /** * The Printing class : printing of a range of text. - * An instance of Printing is returned in the - * StyledText#print(Printer) API. The run() method may be + * An instance of Printing 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 + const static int LEFT = 0; // left aligned header/footer segment + const static int CENTER = 1; // centered header/footer segment + const static int RIGHT = 2; // right aligned header/footer segment Printer printer; StyledTextRenderer printerRenderer; @@ -182,7 +258,7 @@ Rectangle clientArea; FontData fontData; Font printerFont; - Hashtable resources; + Resource[Resource] resources; int tabLength; GC gc; // printer GC int pageWidth; // width of a printer page in pixels @@ -190,30 +266,30 @@ 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 + bool singleLine; // widget single line mode Point selection = null; // selected text - bool mirrored; // indicates the printing gc should be mirrored + 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 + * Copies the widget content and rendering data that needs * to be requested from listeners. *

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

                      - * @param printerContent StyledTextContent to request + * @param printerContent StyledTextContent to request * line data for. */ void cacheLineData(StyledText styledText) { @@ -252,7 +328,7 @@ 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); @@ -268,15 +344,18 @@ } Point screenDPI = styledText.getDisplay().getDPI(); Point printerDPI = printer.getDPI(); - resources = new Hashtable (); + resources = null; for (int i = 0; i < lineCount; i++) { Color color = printerRenderer.getLineBackground(i, null); if (color !is null) { if (printOptions.printLineBackground) { - Color printerColor = cast(Color)resources.get(color); - if (printerColor is null) { + Color printerColor; + if ( auto p = color in resources ) { + printerColor = cast(Color)*p; + } + else { printerColor = new Color (printer, color.getRGB()); - resources.put(color, printerColor); + resources[color]=printerColor; } printerRenderer.setLineBackground(i, 1, printerColor); } else { @@ -293,20 +372,26 @@ StyleRange style = styles[i]; Font font = style.font; if (style.font !is null) { - Font printerFont = cast(Font)resources.get(font); - if (printerFont is null) { + Font printerFont; + if ( auto p = font in resources ) { + printerFont = cast(Font)*p; + } + else { printerFont = new Font (printer, font.getFontData()); - resources.put(font, printerFont); + resources[font]= printerFont; } style.font = printerFont; } Color color = style.foreground; if (color !is null) { - Color printerColor = cast(Color)resources.get(color); if (printOptions.printTextForeground) { - if (printerColor is null) { + Color printerColor; + if ( auto p = color in resources ) { + printerColor = cast(Color)*p; + } + else { printerColor = new Color (printer, color.getRGB()); - resources.put(color, printerColor); + resources[color]=printerColor; } style.foreground = printerColor; } else { @@ -315,11 +400,14 @@ } color = style.background; if (color !is null) { - Color printerColor = cast(Color)resources.get(color); if (printOptions.printTextBackground) { - if (printerColor is null) { + Color printerColor; + if ( auto p = color in resources ) { + printerColor = cast(Color)*p; + } + else { printerColor = new Color (printer, color.getRGB()); - resources.put(color, printerColor); + resources[color]=printerColor; } style.background = printerColor; } else { @@ -370,14 +458,10 @@ gc.dispose(); gc = null; } - if (resources !is null) { - Enumeration enumeration = resources.elements(); - while (enumeration.hasMoreElements()) { - Resource resource = cast(Resource) enumeration.nextElement(); - resource.dispose(); - } - resources = null; - } + foreach( resource; resources.values ){ + resource.dispose(); + } + resources = null; if (printerFont !is null) { printerFont.dispose(); printerFont = null; @@ -390,15 +474,15 @@ void init_() { Rectangle trim = printer.computeTrim(0, 0, 0, 0); Point dpi = printer.getDPI(); - - printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), DWT.NORMAL); + + printerFont = new Font( cast(Device)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.x = dpi.x + trim.x; clientArea.y = dpi.y + trim.y; clientArea.width -= (clientArea.x + trim.width); - clientArea.height -= (clientArea.y + trim.height); + clientArea.height -= (clientArea.y + trim.height); int style = mirrored ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT; gc = new GC(printer, style); @@ -412,16 +496,16 @@ 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) { + if (data.scope_ is PrinterData.PAGE_RANGE) { int pageSize = clientArea.height / lineHeight;//WRONG startLine = (startPage - 1) * pageSize; - } else if (data.scope is PrinterData.SELECTION) { + } else if (data.scope_ is PrinterData.SELECTION) { startLine = content.getLineAtOffset(selection.x); if (selection.y > 0) { endLine = content.getLineAtOffset(selection.x + selection.y - 1); @@ -477,7 +561,7 @@ } TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing); Color lineBackground = printerRenderer.getLineBackground(i, background); - int paragraphBottom = paintY + layout.getBounds().height; + 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); @@ -507,7 +591,7 @@ printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); gc.setClipping(cast(Rectangle)null); printDecoration(page, false, printLayout); - printer.endPage(); + printer.endPage(); page++; if (page <= endPage) { printer.startPage(); @@ -532,7 +616,7 @@ } /** * 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 */ @@ -541,16 +625,16 @@ if (text is null) return; int lastSegmentIndex = 0; for (int i = 0; i < 3; i++) { - int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); + int segmentIndex = text.indexOf( StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); String segment; - if (segmentIndex is -1) { + 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(); + lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length; } } } @@ -558,22 +642,22 @@ * 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 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) { + 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(); + 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) { + segment = buffer.toString().dup; + } + if (segment.length > 0) { layout.setText(segment); int segmentWidth = layout.getBounds().width; int segmentHeight = printerRenderer.getLineHeight(); @@ -598,7 +682,7 @@ 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); @@ -620,7 +704,7 @@ printLayout.setText(""); } } else { - printLayout.setText(String.valueOf(index)); + printLayout.setText(to!(String)(index)); } int paintX = x - printMargin - printLayout.getBounds().width; printLayout.draw(gc, paintX, y); @@ -639,64 +723,66 @@ jobName = "Printing"; } if (printer.startJob(jobName)) { - init(); + init_(); print(); dispose(); printer.endJob(); } - } + } } /** * The RTFWriter class is used to write widget content as - * rich text. The implementation complies with the RTF specification + * 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. + * 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 + * 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 + * 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; + + alias TextWriter.write write; + + static const int DEFAULT_FOREGROUND = 0; + static const int DEFAULT_BACKGROUND = 1; + Color[] colorTable; + Font[] fontTable; bool WriteUnicode; - + /** * Creates a RTF writer that writes content starting at offset "start" - * in the document. start and lengthcan be set to specify partial + * in the document. start and lengthcan be set to specify partial * lines. * - * @param start start offset of content to write, 0 based from + * @param start start offset of content to write, 0 based from * beginning of document * @param length length of content to write */ public this(int start, int length) { super(start, length); - colorTable = new Vector(); - fontTable = new Vector(); - colorTable.addElement(getForeground()); - colorTable.addElement(getBackground()); - fontTable.addElement(getFont()); + colorTable ~= getForeground(); + colorTable ~= getBackground(); + fontTable ~= getFont(); setUnicode(); } /** * Closes the RTF writer. Once closed no more content can be written. - * NOTE: toString() does not return a valid RTF String until + * NOTE: toString() does not return a valid RTF string until * close() has been called. */ - public void close() { + public override void close() { if (!isClosed()) { writeHeader(); write("\n}}\0"); super.close(); } - } + } /** * Returns the index of the specified color in the RTF color table. * @@ -707,10 +793,16 @@ */ int getColorIndex(Color color, int defaultIndex) { if (color is null) return defaultIndex; - int index = colorTable.indexOf(color); + int index = -1; + foreach( i, col; colorTable ){ + if( col == color ){ + index = i; + break; + } + } if (index is -1) { - index = colorTable.size(); - colorTable.addElement(color); + index = colorTable.length; + colorTable ~= color; } return index; } @@ -723,10 +815,16 @@ * or "defaultIndex" if "color" is null. */ int getFontIndex(Font font) { - int index = fontTable.indexOf(font); + int index = -1; + foreach( i, f; colorTable ){ + if( f == font ){ + index = i; + break; + } + } if (index is -1) { - index = fontTable.size(); - fontTable.addElement(font); + index = fontTable.length; + fontTable ~= font; } return index; } @@ -735,68 +833,72 @@ * 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); +// const String Win95 = "windows 95"; +// const String Win98 = "windows 98"; +// const String WinME = "windows me"; +// const String WinNT = "windows nt"; +// String osName = System.getProperty("os.name").toLowerCase(); +// String osVersion = System.getProperty("os.version"); +// int majorVersion = 0; +// +// if (osName.startsWith(WinNT) && osVersion !is null) { +// int majorIndex = osVersion.indexOf('.'); +// if (majorIndex !is -1) { +// osVersion = osVersion.substring(0, majorIndex); +// try { +// majorVersion = Integer.parseInt(osVersion); +// } catch (NumberFormatException exception) { +// // ignore exception. version number remains unknown. +// // will write without Unicode +// } +// } +// } +// WriteUnicode = !osName.startsWith(Win95) && +// !osName.startsWith(Win98) && +// !osName.startsWith(WinME) && +// (!osName.startsWith(WinNT) || majorVersion > 4); + WriteUnicode = true; // we are on linux-gtk } /** - * Appends the specified segment of "String" to the RTF data. + * 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 + * @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); + void write(String string, int start, int end) { + start = 0; + end = string.length; + int incr = 1; + for (int index = start; index < end; index+=incr) { + dchar ch = firstCodePoint( string[index .. $], incr ); if (ch > 0xFF && WriteUnicode) { - // write the sub String from the last escaped character + // 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( string[start .. index ] ); } write("\\u"); - write(Integer.toString(cast(short) ch)); + write( to!(String)( cast(short)ch )); write(' '); // control word delimiter - start = index + 1; + start = index + incr; } else if (ch is '}' || ch is '{' || ch is '\\') { - // write the sub String from the last escaped character + // 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(string[start .. index]); } write('\\'); - write(ch); + write(cast(char)ch); // ok because one of {}\ start = index + 1; } } // write from the last escaped character to the end. // Fixes bug 21698. if (start < end) { - write(String.substring(start, end)); + write(string[ start .. end]); } } /** @@ -806,28 +908,31 @@ StringBuffer header = new StringBuffer(); FontData fontData = getFont().getFontData()[0]; header.append("{\\rtf1\\ansi"); - // specify code page, necessary for copy to work in bidi + // specify code page, necessary for copy to work in bidi // systems that don't support Unicode RTF. - String cpg = System.getProperty("file.encoding").toLowerCase(); + // PORTING_TODO: String cpg = System.getProperty("file.encoding").toLowerCase(); + String cpg = "UTF16"; + /+ if (cpg.startsWith("cp") || cpg.startsWith("ms")) { cpg = cpg.substring(2, cpg.length()); header.append("\\ansicpg"); header.append(cpg); } + +/ header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil "); header.append(fontData.getName()); header.append(";"); - for (int i = 1; i < fontTable.size(); i++) { + for (int i = 1; i < fontTable.length; i++) { header.append("\\f"); header.append(i); header.append(" "); - FontData fd = (cast(Font)fontTable.elementAt(i)).getFontData()[0]; + FontData fd = (cast(Font)fontTable[i]).getFontData()[0]; header.append(fd.getName()); - header.append(";"); + header.append(";"); } header.append("}}\n{\\colortbl"); - for (int i = 0; i < colorTable.size(); i++) { - Color color = cast(Color) colorTable.elementAt(i); + for (int i = 0; i < colorTable.length; i++) { + Color color = cast(Color) colorTable[i]; header.append("\\red"); header.append(color.getRed()); header.append("\\green"); @@ -836,7 +941,7 @@ header.append(color.getBlue()); header.append(";"); } - // some RTF readers ignore the deff0 font tag. Explicitly + // 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 @@ -845,20 +950,20 @@ 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 + * 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 + * @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
                        *
                      • ERROR_IO when the writer is closed.
                      • *
                      */ - public void writeLine(String line, int lineOffset) { + public override void writeLine(String line, int lineOffset) { if (isClosed()) { DWT.error(DWT.ERROR_IO); } @@ -876,12 +981,12 @@ styles = event.styles; } else { lineAlignment = renderer.getLineAlignment(lineIndex, alignment); - lineIndent = renderer.getLineIndent(lineIndex, indent); + lineIndent = renderer.getLineIndent(lineIndex, indent); lineJustify = renderer.getLineJustify(lineIndex, justify); - ranges = renderer.getRanges(lineOffset, line.length()); - styles = renderer.getStyleRanges(lineOffset, line.length(), false); - } - if (styles is null) styles = new StyleRange[0]; + ranges = renderer.getRanges(lineOffset, line.length); + styles = renderer.getStyleRanges(lineOffset, line.length, false); + } + if (styles is null) styles = new StyleRange[0]; Color lineBackground = renderer.getLineBackground(lineIndex, null); event = getLineBackgroundData(lineOffset, line); if (event !is null && event.lineBackground !is null) lineBackground = event.lineBackground; @@ -895,11 +1000,11 @@ *
                    • ERROR_IO when the writer is closed.
                    • *
                    */ - public void writeLineDelimiter(String lineDelimiter) { + public override void writeLineDelimiter(String lineDelimiter) { if (isClosed()) { DWT.error(DWT.ERROR_IO); } - write(lineDelimiter, 0, lineDelimiter.length()); + write(lineDelimiter, 0, lineDelimiter.length); write("\\par "); } /** @@ -913,34 +1018,35 @@ * * @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 + * @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. + * @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 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; + default: } if (justify) write("\\qj"); write(" "); - + if (lineBackground !is null) { write("{\\highlight"); write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); - write(" "); + write(" "); } int endOffset = startOffset + super.getCharCount(); int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); @@ -965,7 +1071,7 @@ // write any unstyled text if (lineIndex < start) { // copy to start of style - // style starting beyond end of write range or end of line + // style starting beyond end of write range or end of line // is guarded against above. write(line, lineIndex, start); lineIndex = start; @@ -988,10 +1094,10 @@ write(fontData.getHeight() * 2); } else { if ((style.fontStyle & DWT.BOLD) !is 0) { - write("\\b"); + write("\\b"); } if ((style.fontStyle & DWT.ITALIC) !is 0) { - write("\\i"); + write("\\i"); } } if (style.underline) { @@ -1000,7 +1106,7 @@ if (style.strikeout) { write("\\strike"); } - write(" "); + 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 @@ -1008,10 +1114,10 @@ write(line, lineIndex, copyEnd); if (font is null) { if ((style.fontStyle & DWT.BOLD) !is 0) { - write("\\b0"); + write("\\b0"); } if ((style.fontStyle & DWT.ITALIC) !is 0) { - write("\\i0"); + write("\\i0"); } } if (style.underline) { @@ -1032,21 +1138,21 @@ } /** * The TextWriter class is used to write widget content to - * a String. Whole and partial lines and line breaks can be written. To write - * partial lines, specify the start and length of the desired segment + * 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() + * NOTE: toString() is guaranteed to return a valid string only after close() * has been called. *

                    */ class TextWriter { private StringBuffer buffer; private int startOffset; // offset of first character that will be written - private int endOffset; // offset of last character that will be written. - // 0 based from the beginning of the widget text. - private bool isClosed = false; - + private int endOffset; // offset of last character that will be written. + // 0 based from the beginning of the widget text. + private bool isClosed_ = false; + /** * Creates a writer that writes content starting at offset "start" * in the document. start and length can be set to specify partial lines. @@ -1061,23 +1167,23 @@ } /** * Closes the writer. Once closed no more content can be written. - * NOTE: toString() is not guaranteed to return a valid String unless + * NOTE: toString() is not guaranteed to return a valid string unless * the writer is closed. */ public void close() { - if (!isClosed) { - isClosed = true; - } - } - /** + 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 + } + /** + * 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 */ @@ -1089,37 +1195,38 @@ * @return a bool specifying whether or not the writer is closed */ public bool isClosed() { - return isClosed; + return isClosed_; } /** - * Returns the String. close() must be called before toString() - * is guaranteed to return a valid String. + * Returns the string. close() must be called before toString() + * is guaranteed to return a valid string. * - * @return the String + * @return the string */ - public String toString() { + public override String toString() { return buffer.toString(); } /** - * Appends the given String to the data. + * Appends the given string to the data. */ - void write(String String) { - buffer.append(String); + void write(String string) { + buffer.append(string); } /** - * Inserts the given String to the data at the specified offset. + * 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. + * @param string text to insert + * @param offset offset in the existing data to insert "string" at. */ - void write(String String, int offset) { + void write(String string, int offset) { if (offset < 0 || offset > buffer.length()) { return; } - buffer.insert(offset, String); + buffer.select( offset ); + buffer.prepend( string ); } /** * Appends the given int to the data. @@ -1138,19 +1245,19 @@ * * @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 + * @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
                      *
                    • ERROR_IO when the writer is closed.
                    • *
                    */ - public void writeLine(String line, int lineOffset) { - if (isClosed) { + public void writeLine(String line, int lineOffset) { + if (isClosed_) { DWT.error(DWT.ERROR_IO); - } + } int writeOffset = startOffset - lineOffset; - int lineLength = line.length(); + int lineLength = line.length; int lineIndex; if (writeOffset >= lineLength) { return; // whole line is outside write range @@ -1173,7 +1280,7 @@ *
                  */ public void writeLineDelimiter(String lineDelimiter) { - if (isClosed) { + if (isClosed_) { DWT.error(DWT.ERROR_IO); } write(lineDelimiter); @@ -1186,7 +1293,7 @@ *

                  * 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 + * 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. @@ -1211,13 +1318,14 @@ * @see #getStyle */ public this(Composite parent, int style) { + selection = new Point(0, 0); super(parent, checkStyle(style)); // set the fg in the OS to ensure that these are the same as StyledText, necessary // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses super.setForeground(getForeground()); super.setDragDetect(false); Display display = getDisplay(); - isMirrored = (super.getStyle() & DWT.MIRRORED) !is 0; + isMirrored_ = (super.getStyle() & DWT.MIRRORED) !is 0; fixedLineHeight = true; if ((style & DWT.READ_ONLY) !is 0) { setEditable(false); @@ -1240,7 +1348,7 @@ } if (isBidiCaret()) { createCaretBitmaps(); - Runnable runnable = new Runnable() { + Runnable runnable = new class() Runnable { public void run() { int direction = BidiUtil.getKeyboardLanguage() is BidiUtil.KEYBOARD_BIDI ? DWT.RIGHT : DWT.LEFT; if (direction is caretDirection) return; @@ -1251,7 +1359,7 @@ }; BidiUtil.addLanguageListener(this, runnable); } - setCaret(defaultCaret); + setCaret(defaultCaret); calculateScrollBars(); createKeyBindings(); setCursor(display.getSystemCursor(DWT.CURSOR_IBEAM)); @@ -1259,8 +1367,8 @@ initializeAccessible(); setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this)); } -/** - * Adds an extended modify listener. An ExtendedModify event is sent by the +/** + * Adds an extended modify listener. An ExtendedModify event is sent by the * widget when the widget text has changed. * * @param extendedModifyListener the listener @@ -1281,15 +1389,15 @@ /** * Adds a bidirectional segment listener. *

                  - * A BidiSegmentEvent is sent - * whenever a line of text is measured or rendered. The user can - * specify text ranges in the line that should be treated as if they + * 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 + * 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. + * way they are stored. *

                  * * @param listener the listener @@ -1309,7 +1417,7 @@ addListener(LineGetSegments, new StyledTextListener(listener)); } /** - * Adds a line background listener. A LineGetBackground event is sent by the + * Adds a line background listener. A LineGetBackground event is sent by the * widget to determine the background color for a line. * * @param listener the listener @@ -1330,7 +1438,7 @@ addListener(LineGetBackground, new StyledTextListener(listener)); } /** - * Adds a line style listener. A LineGetStyle event is sent by the widget to + * Adds a line style listener. A LineGetStyle event is sent by the widget to * determine the styles for a line. * * @param listener the listener @@ -1351,8 +1459,8 @@ } addListener(LineGetStyle, new StyledTextListener(listener)); } -/** - * Adds a modify listener. A Modify event is sent by the widget when the widget text +/** + * Adds a modify listener. A Modify event is sent by the widget when the widget text * has changed. * * @param modifyListener the listener @@ -1369,7 +1477,7 @@ if (modifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(DWT.Modify, new TypedListener(modifyListener)); } -/** +/** * Adds a paint object listener. A paint object event is sent by the widget when an object * needs to be drawn. * @@ -1381,9 +1489,9 @@ * @exception IllegalArgumentException
                    *
                  • ERROR_NULL_ARGUMENT when listener is null
                  • *
                  - * + * * @since 3.2 - * + * * @see PaintObjectListener * @see PaintObjectEvent */ @@ -1392,15 +1500,15 @@ if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(PaintObject, new StyledTextListener(listener)); } -/** - * Adds a selection listener. A Selection event is sent by the widget when the +/** + * Adds a selection listener. A Selection event is sent by the widget when the * user changes the selection. *

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

                  - * + * * @param listener the listener which should be notified when the user changes the receiver's selection * @exception IllegalArgumentException
                    @@ -1420,10 +1528,10 @@ if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(DWT.Selection, new TypedListener(listener)); } -/** - * Adds a verify key listener. A VerifyKey event is sent by the widget when a key - * is pressed. The widget ignores the key press if the listener sets the doit field - * of the event to false. +/** + * Adds a verify key listener. A VerifyKey event is sent by the widget when a key + * is pressed. The widget ignores the key press if the listener sets the doit field + * of the event to false. * * @param listener the listener * @exception DWTException
                      @@ -1439,10 +1547,10 @@ if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(VerifyKey, new StyledTextListener(listener)); } -/** - * Adds a verify listener. A Verify event is sent by the widget when the widget text - * is about to change. The listener can set the event text and the doit field to - * change the text that is set in the widget or to force the widget to ignore the +/** + * Adds a verify listener. A Verify event is sent by the widget when the widget text + * is about to change. The listener can set the event text and the doit field to + * change the text that is set in the widget or to force the widget to ignore the * text change. * * @param verifyListener the listener @@ -1459,9 +1567,9 @@ if (verifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(DWT.Verify, new TypedListener(verifyListener)); } -/** - * Adds a word movement listener. A movement event is sent when the boundary - * of a word is needed. For example, this occurs during word next and word +/** + * Adds a word movement listener. A movement event is sent when the boundary + * of a word is needed. For example, this occurs during word next and word * previous actions. * * @param movementListener the listener @@ -1472,12 +1580,12 @@ * @exception IllegalArgumentException
                        *
                      • ERROR_NULL_ARGUMENT when listener is null
                      • *
                      - * + * * @see MovementEvent * @see MovementListener * @see #removeWordMovementListener - * - * @since 3.3 + * + * @since 3.3 */ public void addWordMovementListener(MovementListener movementListener) { checkWidget(); @@ -1485,26 +1593,24 @@ addListener(WordNext, new StyledTextListener(movementListener)); addListener(WordPrevious, new StyledTextListener(movementListener)); } -/** - * Appends a String to the text at the end of the widget. - * - * @param String the String to be appended +/** + * Appends a string to the text at the end of the widget. + * + * @param string the string to be appended * @see #replaceTextRange(int,int,String) * @exception 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 when listener is null
                      • - *
                      - */ -public void append(String String) { - checkWidget(); - if (String is null) { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } + */ +public void append(String string) { + checkWidget(); + // DWT extension: allow null for zero length string +// if (string is null) { +// DWT.error(DWT.ERROR_NULL_ARGUMENT); +// } int lastChar = Math.max(getCharCount(), 0); - replaceTextRange(lastChar, 0, String); + replaceTextRange(lastChar, 0, string); } /** * Calculates the scroll bars @@ -1515,7 +1621,7 @@ setScrollBars(true); if (verticalBar !is null) { verticalBar.setIncrement(getVerticalIncrement()); - } + } if (horizontalBar !is null) { horizontalBar.setIncrement(getHorizontalIncrement()); } @@ -1535,7 +1641,7 @@ return; } topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement); - // Set top index to partially visible top line if no line is fully + // Set top index to partially visible top line if no line is fully // visible but at least some of the widget client area is visible. // Fixes bug 15088. if (topIndex > 0) { @@ -1543,7 +1649,7 @@ int bottomPixel = getVerticalScrollOffset() + clientAreaHeight; int fullLineTopPixel = topIndex * verticalIncrement; int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; - // set top index to partially visible line if no line fully fits in + // set top index to partially visible line if no line fully fits in // client area or if space is available but not used (the latter should // never happen because we use claimBottomFreeSpace) if (fullLineVisibleHeight < verticalIncrement) { @@ -1608,7 +1714,7 @@ return style; } /** - * Scrolls down the text to use new space made available by a resize or by + * Scrolls down the text to use new space made available by a resize or by * deleted lines. */ void claimBottomFreeSpace() { @@ -1632,11 +1738,11 @@ */ void claimRightFreeSpace() { int newHorizontalOffset = Math.max(0, renderer.getWidth() - (clientAreaWidth - leftMargin - rightMargin)); - if (newHorizontalOffset < horizontalScrollOffset) { + if (newHorizontalOffset < horizontalScrollOffset) { // item is no longer drawn past the right border of the client area - // align the right end of the item with the right border of the + // align the right end of the item with the right border of the // client area (window is scrolled right). - scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); + scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); } } /** @@ -1646,7 +1752,7 @@ */ void clearSelection(bool sendEvent) { int selectionStart = selection.x; - int selectionEnd = selection.y; + int selectionEnd = selection.y; resetSelection(); // redraw old selection, if any if (selectionEnd - selectionStart > 0) { @@ -1663,7 +1769,7 @@ } } } -public Point computeSize (int wHint, int hHint, bool changed) { +public override Point computeSize (int wHint, int hHint, bool changed) { checkWidget(); int lineCount = (getStyle() & DWT.SINGLE) !is 0 ? 1 : content.getLineCount(); int width = 0; @@ -1701,7 +1807,7 @@ *

                      * 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 + * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or * by menu action. *

                      * @@ -1715,24 +1821,24 @@ copy(DND.CLIPBOARD); } /** - * Copies the selected text to the specified clipboard. The text will be put in the + * Copies the selected text to the specified clipboard. The text will be put in the * clipboard in plain text format and RTF format. *

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

                      - * + * * @param clipboardType indicates the type of clipboard * * @exception 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 copy(int clipboardType) { @@ -1743,7 +1849,7 @@ try { setClipboardContent(selection.x, length, clipboardType); } catch (DWTError error) { - // Copy to clipboard failed. This happens when another application + // Copy to clipboard failed. This happens when another application // is accessing the clipboard while we copy. Ignore the error. // Fixes 1GDQAVN // Rethrow all other errors. Fixes bug 17578. @@ -1755,16 +1861,16 @@ } /** * Returns the alignment of the widget. - * + * * @return the alignment - * - * @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 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 #getLineAlignment(int) - * + * * @since 3.2 */ public int getAlignment() { @@ -1802,24 +1908,24 @@ return Math.min(height, availableHeight); } /** - * Returns a String that uses only the line delimiter specified by the + * Returns a string that uses only the line delimiter specified by the * StyledTextContent implementation. *

                      * 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 + * @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 + * @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(); +String getModelDelimitedText(String text) { + int length = text.length; if (length is 0) { return text; - } + } int crIndex = 0; int lfIndex = 0; int i = 0; @@ -1827,10 +1933,10 @@ String delimiter = getLineDelimiter(); while (i < length) { if (crIndex !is -1) { - crIndex = text.indexOf(DWT.CR, i); + crIndex = text.indexOf (DWT.CR, i); } if (lfIndex !is -1) { - lfIndex = text.indexOf(DWT.LF, i); + lfIndex = text.indexOf (DWT.LF, i); } if (lfIndex is -1 && crIndex is -1) { // no more line breaks? break; @@ -1850,7 +1956,7 @@ } convertedText.append(delimiter); } - // copy remaining text if any and if not in single line mode or no + // 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)); @@ -1877,9 +1983,9 @@ 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_UP, ST.LINE_UP); setKeyBinding(DWT.ARROW_DOWN, ST.LINE_DOWN); if (IS_CARBON) { setKeyBinding(previousKey | DWT.MOD1, ST.LINE_START); @@ -1904,23 +2010,23 @@ 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_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.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_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.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); @@ -1930,8 +2036,8 @@ 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); - + setKeyBinding(previousKey | DWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); + // Modification // Cut, Copy, Paste setKeyBinding('X' | DWT.MOD1, ST.CUT); @@ -1952,7 +2058,7 @@ 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); } @@ -1965,30 +2071,30 @@ int caretWidth = BIDI_CARET_WIDTH; Display display = getDisplay(); if (leftCaretBitmap !is null) { - if (defaultCaret !is null && leftCaretBitmap.opEquals(defaultCaret.getImage())) { + if (defaultCaret !is null && leftCaretBitmap==/*eq*/defaultCaret.getImage()) { defaultCaret.setImage(null); } leftCaretBitmap.dispose(); } int lineHeight = renderer.getLineHeight(); leftCaretBitmap = new Image(display, caretWidth, lineHeight); - GC gc = new GC (leftCaretBitmap); + GC 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(); - + gc.dispose(); + if (rightCaretBitmap !is null) { - if (defaultCaret !is null && rightCaretBitmap.opEquals(defaultCaret.getImage())) { + if (defaultCaret !is null && rightCaretBitmap==/*eq*/defaultCaret.getImage()) { defaultCaret.setImage(null); } rightCaretBitmap.dispose(); } rightCaretBitmap = new Image(display, caretWidth, lineHeight); - gc = new GC (rightCaretBitmap); + gc = new GC (rightCaretBitmap); gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); gc.fillRectangle(0, 0, caretWidth, lineHeight); gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); @@ -1998,7 +2104,7 @@ gc.dispose(); } /** - * Moves the selected text to the clipboard. The text will be put in the + * Moves the selected text to the clipboard. The text will be put in the * clipboard in plain text format and RTF format. * * @exception DWTException
                        @@ -2013,7 +2119,7 @@ try { setClipboardContent(selection.x, length, DND.CLIPBOARD); } catch (DWTError error) { - // Copy to clipboard failed. This happens when another application + // Copy to clipboard failed. This happens when another application // is accessing the clipboard while we copy. Ignore the error. // Fixes 1GDQAVN // Rethrow all other errors. Fixes bug 17578. @@ -2027,9 +2133,9 @@ doDelete(); } } -/** +/** * A mouse move event has occurred. See if we should start autoscrolling. If - * the move position is outside of the client area, initiate autoscrolling. + * the move position is outside of the client area, initiate autoscrolling. * Otherwise, we've moved back into the widget so end autoscrolling. */ void doAutoScroll(Event event) { @@ -2045,7 +2151,7 @@ endAutoScroll(); } } -/** +/** * Initiates autoscrolling. * * @param direction DWT.UP, DWT.DOWN, DWT.COLUMN_NEXT, DWT.COLUMN_PREVIOUS @@ -2056,13 +2162,15 @@ if (autoScrollDirection is direction) { return; } - + Runnable timer = null; - final Display display = getDisplay(); + final Display disp = getDisplay(); // Set a timer that will simulate the user pressing and holding // down a cursor key (i.e., arrowUp, arrowDown). if (direction is DWT.UP) { - timer = new Runnable() { + timer = new class(disp) Runnable { + Display display; + this( Display d ){ this.display = d; } public void run() { if (autoScrollDirection is DWT.UP) { doSelectionPageUp(autoScrollDistance); @@ -2073,7 +2181,9 @@ autoScrollDirection = direction; display.timerExec(V_SCROLL_RATE, timer); } else if (direction is DWT.DOWN) { - timer = new Runnable() { + timer = new class(disp) Runnable { + Display display; + this( Display d ){ this.display = d; } public void run() { if (autoScrollDirection is DWT.DOWN) { doSelectionPageDown(autoScrollDistance); @@ -2084,7 +2194,9 @@ autoScrollDirection = direction; display.timerExec(V_SCROLL_RATE, timer); } else if (direction is ST.COLUMN_NEXT) { - timer = new Runnable() { + timer = new class(disp) Runnable { + Display display; + this( Display d ){ this.display = d; } public void run() { if (autoScrollDirection is ST.COLUMN_NEXT) { doVisualNext(); @@ -2097,7 +2209,9 @@ autoScrollDirection = direction; display.timerExec(H_SCROLL_RATE, timer); } else if (direction is ST.COLUMN_PREVIOUS) { - timer = new Runnable() { + timer = new class(disp) Runnable { + Display display; + this( Display d ){ this.display = d; } public void run() { if (autoScrollDirection is ST.COLUMN_PREVIOUS) { doVisualPrevious(); @@ -2126,13 +2240,14 @@ int lineIndex = content.getLineAtOffset(caretOffset); int lineOffset = content.getOffsetAtLine(lineIndex); if (caretOffset is lineOffset) { + // DWT: on line start, delete line break lineOffset = content.getOffsetAtLine(lineIndex - 1); - event.start = lineOffset + content.getLine(lineIndex - 1).length(); + event.start = lineOffset + content.getLine(lineIndex - 1).length; event.end = caretOffset; } else { TextLayout layout = renderer.getTextLayout(lineIndex); - int start = layout.getPreviousOffset(caretOffset - lineOffset, DWT.MOVEMENT_CHAR); - renderer.disposeTextLayout(layout); + int start = layout.getPreviousOffset(caretOffset - lineOffset, DWT.MOVEMENT_CLUSTER); + renderer.disposeTextLayout(layout); event.start = start + lineOffset; event.end = caretOffset; } @@ -2140,16 +2255,16 @@ } } /** - * Replaces the selection with the character or insert the character at the + * Replaces the selection with the character or insert the character at the * current caret position if no selection exists. *

                        - * If a carriage return was typed replace it with the line break character + * 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) { +void doContent(dchar key) { Event event = new Event(); event.start = selection.x; event.end = selection.y; @@ -2162,18 +2277,18 @@ } } 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)? + // 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 + // 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}); + if (event.end < lineOffset + line.length) { + event.end+=dcharToString( key ).length; + } + event.text = dcharToString( key ); } else { - event.text = new String(new char[] {key}); + event.text = dcharToString( key ); } if (event.text !is null) { if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) { @@ -2186,12 +2301,12 @@ * 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 + // place caret at end of first line if receiver is in single // line mode. fixes 4820. if (isSingleLine()) { doLineEnd(); } else { - int length = content.getCharCount(); + int length = content.getCharCount(); if (caretOffset < length) { caretOffset = length; showCaret(); @@ -2209,7 +2324,7 @@ } /** * Moves the caret to the start of the selection if a selection exists. - * Otherwise, if no selection exists move the cursor according to the + * Otherwise, if no selection exists move the cursor according to the * cursor selection rules. * * @see #doSelectionCursorPrevious @@ -2225,7 +2340,7 @@ } /** * Moves the caret to the end of the selection if a selection exists. - * Otherwise, if no selection exists move the cursor according to the + * Otherwise, if no selection exists move the cursor according to the * cursor selection rules. * * @see #doSelectionCursorNext @@ -2252,7 +2367,7 @@ } else if (caretOffset < content.getCharCount()) { int line = content.getLineAtOffset(caretOffset); int lineOffset = content.getOffsetAtLine(line); - int lineLength = content.getLine(line).length(); + int lineLength = content.getLine(line).length; if (caretOffset is lineOffset + lineLength) { event.start = caretOffset; event.end = content.getOffsetAtLine(line + 1); @@ -2268,7 +2383,7 @@ */ void doDeleteWordNext() { if (selection.x !is selection.y) { - // if a selection exists, treat the as if + // if a selection exists, treat the as if // only the delete key was pressed doDelete(); } else { @@ -2284,7 +2399,7 @@ */ void doDeleteWordPrevious() { if (selection.x !is selection.y) { - // if a selection exists, treat as if + // if a selection exists, treat as if // only the backspace key was pressed doBackspace(); } else { @@ -2296,8 +2411,8 @@ } } /** - * 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 + * 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) { @@ -2330,8 +2445,8 @@ int oldColumnX = columnX; int oldHScrollOffset = horizontalScrollOffset; if (select) { - setMouseWordSelectionAnchor(); - // select first and then scroll to reduce flash when key + setMouseWordSelectionAnchor(); + // select first and then scroll to reduce flash when key // repeat scrolls lots of lines doSelection(ST.COLUMN_NEXT); } @@ -2344,7 +2459,7 @@ */ void doLineEnd() { int caretLine = getCaretLine(); - int lineOffset = content.getOffsetAtLine(caretLine); + int lineOffset = content.getOffsetAtLine(caretLine); int lineEndOffset; if (wordWrap) { TextLayout layout = renderer.getTextLayout(caretLine); @@ -2354,7 +2469,7 @@ lineEndOffset = lineOffset + offsets[lineIndex + 1]; renderer.disposeTextLayout(layout); } else { - int lineLength = content.getLine(caretLine).length(); + int lineLength = content.getLine(caretLine).length; lineEndOffset = lineOffset + lineLength; } if (caretOffset < lineEndOffset) { @@ -2384,8 +2499,8 @@ } } /** - * 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 + * 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) { @@ -2435,25 +2550,25 @@ int line = getLineIndex(y); updateCaretDirection = true; - // allow caret to be placed below first line only if receiver is + // 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 + + // 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 || + if (0 <= y && y < clientAreaHeight && + (0 <= x && x < clientAreaWidth || wordWrap || newCaretLine !is content.getLineAtOffset(caretOffset))) { if (newCaretOffset !is caretOffset || caretAlignment !is oldCaretAlignment) { caretOffset = newCaretOffset; @@ -2470,8 +2585,8 @@ * Updates the selection based on the caret position */ void doMouseSelection() { - if (caretOffset <= selection.x || - (caretOffset > selection.x && + if (caretOffset <= selection.x || + (caretOffset > selection.x && caretOffset < selection.y && selectionAnchor is selection.x)) { doSelection(ST.COLUMN_PREVIOUS); } else { @@ -2479,20 +2594,20 @@ } } /** - * 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 + * Returns the offset of the word at the specified offset. + * If the current selection extends from high index to low index + * (i.e., right to left, or caret is at left border of selection on * non-bidi platforms) the start offset of the word preceding the - * selection is returned. If the current selection : from - * low index to high index the end offset of the word following + * selection is returned. If the current selection extends from + * low index to high index the end offset of the word following * the selection is returned. - * + * * @param x mouse x location * @param newCaretOffset caret offset of the mouse cursor location * @param line line index of the mouse cursor location */ int doMouseWordSelect(int x, int newCaretOffset, int line) { - // flip selection anchor based on word selection direction from + // 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) @@ -2517,7 +2632,7 @@ if (line + 1 < content.getLineCount()) { lineEnd = content.getOffsetAtLine(line + 1); } - newCaretOffset = lineEnd; + newCaretOffset = lineEnd; } } } @@ -2527,9 +2642,9 @@ * 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 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. *

                        * @@ -2546,7 +2661,7 @@ 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 + // 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)); @@ -2627,10 +2742,10 @@ height = getAvailableHeightBellow(height); scrollVertical(height, true); if (height is 0) setCaretLocation(); - } + } showCaret(); int hScrollChange = oldHScrollOffset - horizontalScrollOffset; - columnX = oldColumnX + hScrollChange; + columnX = oldColumnX + hScrollChange; } /** * Moves the cursor to the end of the last fully visible line. @@ -2652,14 +2767,14 @@ index--; } if (index is -1 && lineIndex > 0) { - bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length(); + 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(); + bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length; } if (caretOffset < bottomOffset) { caretOffset = bottomOffset; @@ -2695,7 +2810,7 @@ } else { topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index]; } - renderer.disposeTextLayout(layout); + renderer.disposeTextLayout(layout); } else { topOffset = content.getOffsetAtLine(topIndex); } @@ -2708,17 +2823,17 @@ /** * 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 + * 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; + int oldColumnX = columnX; if (isFixedLineHeight()) { - int caretLine = getCaretLine(); + int caretLine = getCaretLine(); if (caretLine > 0) { int lineHeight = renderer.getLineHeight(); int lines = (height is -1 ? clientAreaHeight : height) / lineHeight; @@ -2798,11 +2913,11 @@ lineHeight = renderer.getLineHeight(--lineIndex); } lineHeight = renderer.getLineHeight(lineIndex); - caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex); + caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex); if (select) doSelection(ST.COLUMN_PREVIOUS); height = getAvailableHeightAbove(height); scrollVertical(-height, true); - if (height is 0) setCaretLocation(); + if (height is 0) setCaretLocation(); } showCaret(); int hScrollChange = oldHScrollOffset - horizontalScrollOffset; @@ -2813,15 +2928,15 @@ */ void doSelection(int direction) { int redrawStart = -1; - int redrawEnd = -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; + redrawEnd = selection.x; + redrawStart = selection.x = caretOffset; // check if selection has reversed direction if (selection.y !is selectionAnchor) { redrawEnd = selection.y; @@ -2829,10 +2944,10 @@ } // 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 + // caret moved towards selection anchor (left side of selection). + // shrink selection redrawEnd = selection.y; - redrawStart = selection.y = caretOffset; + redrawStart = selection.y = caretOffset; } } else { if (caretOffset > selection.y) { @@ -2841,15 +2956,15 @@ redrawEnd = selection.y = caretOffset; // check if selection has reversed direction if (selection.x !is selectionAnchor) { - redrawStart = selection.x; + redrawStart = selection.x; selection.x = selectionAnchor; } - // test whether selection actually changed. Fixes 1G71EO1 + // 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 + // caret moved towards selection anchor (right side of selection). + // shrink selection redrawStart = selection.x; - redrawEnd = selection.x = caretOffset; + redrawEnd = selection.x = caretOffset; } } if (redrawStart !is -1 && redrawEnd !is -1) { @@ -2858,14 +2973,14 @@ } } /** - * Moves the caret to the next character or to the beginning of the + * 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()) { + 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)]; @@ -2874,14 +2989,14 @@ caretAlignment = offsetInLine is lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING; showCaret(); } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) { - caretLine++; + caretLine++; caretOffset = content.getOffsetAtLine(caretLine); caretAlignment = PREVIOUS_OFFSET_TRAILING; showCaret(); } } /** - * Moves the caret to the previous character or to the end of the previous + * 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() { @@ -2889,21 +3004,22 @@ 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(); + 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 + * 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 + * 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 @@ -2915,8 +3031,8 @@ 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 + * 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. @@ -2925,17 +3041,17 @@ * direction. */ void doSelectionLineUp() { - int oldColumnX = columnX = getPointAtOffset(caretOffset).x; - doLineUp(true); + 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 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 @@ -2952,8 +3068,8 @@ * 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 + * 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. *

                        @@ -2974,9 +3090,9 @@ 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 + // don't change caret position if in single line mode and the cursor // would be on a different line. fixes 5673 - if (!isSingleLine() || + if (!isSingleLine() || content.getLineAtOffset(caretOffset) is content.getLineAtOffset(newCaretOffset)) { caretOffset = newCaretOffset; showCaret(); @@ -2999,8 +3115,8 @@ } /** * 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 + * 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() { @@ -3009,8 +3125,8 @@ } /** * 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 + * 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() { @@ -3043,13 +3159,13 @@ doSelectionWordPrevious(); } } -/** +/** * Ends the autoscroll process. */ void endAutoScroll() { autoScrollDirection = DWT.NULL; } -public Color getBackground() { +public override Color getBackground() { checkWidget(); if (background is null) { return getDisplay().getSystemColor(DWT.COLOR_LIST_BACKGROUND); @@ -3058,9 +3174,9 @@ } /** * 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). + * + * 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

                          @@ -3068,7 +3184,7 @@ *
                        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                        • *
                        * @since 3.0 - * + * * @see #getBaseline(int) */ public int getBaseline() { @@ -3076,20 +3192,20 @@ return renderer.getBaseline(); } /** - * Returns the baseline at the given offset, in pixels. + * Returns the baseline at the given offset, in pixels. * * @param offset the offset - * + * * @return baseline the baseline - * + * * @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_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
                        • - *
                        - * + *
                      • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
                      • + *
                      + * * @since 3.2 */ public int getBaseline(int offset) { @@ -3103,7 +3219,7 @@ int lineIndex = content.getLineAtOffset(offset); int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); - int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); + int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length)); FontMetrics metrics = layout.getLineMetrics(lineInParagraph); renderer.disposeTextLayout(layout); return metrics.getAscent() + metrics.getLeading(); @@ -3118,14 +3234,14 @@ *
                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                    • *
                    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                    • *
                    - * + * * @deprecated use BidiSegmentListener instead. */ public bool getBidiColoring() { checkWidget(); return bidiColoring; } -/** +/** * Returns the index of the last fully visible line. * * @return index of the last fully visible line. @@ -3161,7 +3277,7 @@ int lineOffset = content.getOffsetAtLine(lineIndex); String line = content.getLine(lineIndex); Rectangle bounds; - if (line.length() !is 0) { + if (line.length !is 0) { int offsetInLine = offset - lineOffset; TextLayout layout = renderer.getTextLayout(lineIndex); bounds = layout.getBounds(offsetInLine, offsetInLine); @@ -3170,7 +3286,7 @@ bounds = new Rectangle (0, 0, 0, renderer.getLineHeight()); } if (offset is caretOffset) { - int lineEnd = lineOffset + line.length(); + int lineEnd = lineOffset + line.length; if (offset is lineEnd && caretAlignment is PREVIOUS_OFFSET_TRAILING) { bounds.width += getCaretWidth(); } @@ -3207,7 +3323,7 @@ return clipboard.getContents(plainTextTransfer, clipboardType); } int getClusterNext(int offset, int lineIndex) { - int lineOffset = content.getOffsetAtLine(lineIndex); + int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); offset -= lineOffset; offset = layout.getNextOffset(offset, DWT.MOVEMENT_CLUSTER); @@ -3216,7 +3332,7 @@ return offset; } int getClusterPrevious(int offset, int lineIndex) { - int lineOffset = content.getOffsetAtLine(lineIndex); + int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); offset -= lineOffset; offset = layout.getPreviousOffset(offset, DWT.MOVEMENT_CLUSTER); @@ -3226,9 +3342,9 @@ } /** * Returns the content implementation that is used for text storage. - * + * * @return content the user defined content implementation that is used for - * text storage or the default content implementation if no user defined + * text storage or the default content implementation if no user defined * content implementation has been set. * @exception DWTException
                      *
                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                    • @@ -3239,12 +3355,12 @@ checkWidget(); return content; } -public bool getDragDetect () { +public override bool getDragDetect () { checkWidget (); - return dragDetect; -} -/** - * Returns whether the widget : double click mouse behavior. + return dragDetect_; +} +/** + * Returns whether the widget implements double click mouse behavior. * * @return true if double clicking a word selects the word, false if double clicks * have the same effect as regular mouse clicks @@ -3270,22 +3386,22 @@ checkWidget(); return editable; } -public Color getForeground() { +public override Color getForeground() { checkWidget(); if (foreground is null) { return getDisplay().getSystemColor(DWT.COLOR_LIST_FOREGROUND); } return foreground; } -/** +/** * Returns the horizontal scroll increment. * * @return horizontal scroll increment. */ -int getHorizontalIncrement() { +int getHorizontalIncrement() { return renderer.averageCharWidth; } -/** +/** * Returns the horizontal scroll offset relative to the start of the line. * * @return horizontal scroll offset relative to the start of the line, @@ -3299,7 +3415,7 @@ checkWidget(); return horizontalScrollOffset / getHorizontalIncrement(); } -/** +/** * Returns the horizontal scroll offset relative to the start of the line. * * @return the horizontal scroll offset relative to the start of the line, @@ -3315,16 +3431,16 @@ } /** * Returns the line indentation of the widget. - * + * * @return the line indentation - * - * @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 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 #getLineIndent(int) - * + * * @since 3.2 */ public int getIndent() { @@ -3333,32 +3449,32 @@ } /** * Returns whether the widget justifies lines. - * + * * @return whether lines are justified - * - * @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 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 #getLineJustify(int) - * + * * @since 3.2 */ public bool getJustify() { checkWidget(); return justify; } -/** +/** * Returns the action assigned to the key. * Returns DWT.NULL if there is no action associated with the key. * - * @param key a key code defined in DWT.java or a character. + * @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 + * 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. - * @return one of the predefined actions defined in ST.java or DWT.NULL + * @return one of the predefined actions defined in ST.java or DWT.NULL * if there is no action associated with the key. * @exception DWTException
                        *
                      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                      • @@ -3367,8 +3483,10 @@ */ public int getKeyBinding(int key) { checkWidget(); - Integer action = cast(Integer) keyActionMap.get(new Integer(key)); - return action is null ? DWT.NULL : action.intValue(); + if( auto p = key in keyActionMap ){ + return *p; + } + return DWT.NULL; } /** * Gets the number of characters. @@ -3386,36 +3504,36 @@ /** * Returns the line at the given line index without delimiters. * Index 0 is the first line of the content. When there are not - * any lines, getLine(0) is a valid call that answers an empty String. + * any lines, getLine(0) is a valid call that answers an empty string. *

                        * * @param lineIndex index of the line to return. * @return the line text without delimiters - * + * * @exception 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_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
                        • + *
                        • ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
                        • *
                        * @since 3.4 */ public String getLine(int lineIndex) { checkWidget(); - if (lineIndex < 0 || + if (lineIndex < 0 || (lineIndex > 0 && lineIndex >= content.getLineCount())) { - DWT.error(DWT.ERROR_INVALID_RANGE); + DWT.error(DWT.ERROR_INVALID_RANGE); } return content.getLine(lineIndex); } /** * Returns the alignment of the line at the given index. - * + * * @param index the index of the line - * + * * @return the line alignment - * + * * @exception DWTException
                          *
                        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                        • *
                        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                        • @@ -3423,9 +3541,9 @@ * @exception IllegalArgumentException
                            *
                          • ERROR_INVALID_ARGUMENT when the index is invalid
                          • *
                          - * + * * @see #getAlignment() - * + * * @since 3.2 */ public int getLineAlignment(int index) { @@ -3440,7 +3558,7 @@ * where 0 < offset < getCharCount() so that getLineAtOffset(getCharCount()) * returns the line of the insert location. * - * @param offset offset relative to the start of the content. + * @param offset offset relative to the start of the content. * 0 <= offset <= getCharCount() * @return line at the specified offset in the text * @exception DWTException
                            @@ -3448,26 +3566,26 @@ *
                          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                          • *
                          * @exception IllegalArgumentException
                            - *
                          • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
                          • + *
                          • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
                          • *
                          */ public int getLineAtOffset(int offset) { - checkWidget(); + checkWidget(); if (offset < 0 || offset > getCharCount()) { - DWT.error(DWT.ERROR_INVALID_RANGE); + DWT.error(DWT.ERROR_INVALID_RANGE); } return content.getLineAtOffset(offset); } /** * Returns the background color of the line at the given index. - * Returns null if a LineBackgroundListener has been set or if no background + * Returns null if a LineBackgroundListener has been set or if no background * color has been specified for the line. Should not be called if a * LineBackgroundListener has been set since the listener maintains the * line background colors. - * + * * @param index the index of the line * @return the background color of the line at the given index. - * + * * @exception DWTException
                            *
                          • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                          • *
                          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                          • @@ -3485,11 +3603,11 @@ } /** * Returns the bullet of the line at the given index. - * + * * @param index the index of the line - * + * * @return the line bullet - * + * * @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
                            • @@ -3497,7 +3615,7 @@ * @exception IllegalArgumentException
                                *
                              • ERROR_INVALID_ARGUMENT when the index is invalid
                              • *
                              - * + * * @since 3.2 */ public Bullet getLineBullet(int index) { @@ -3508,9 +3626,9 @@ return isListening(LineGetStyle) ? null : renderer.getLineBullet(index, null); } /** - * Returns the line background data for the given line or null if + * Returns the line background data for the given line or null if * there is none. - * + * * @param lineOffset offset of the line start relative to the start * of the content. * @param line line to get line background data for @@ -3519,7 +3637,7 @@ StyledTextEvent getLineBackgroundData(int lineOffset, String line) { return sendLineEvent(LineGetBackground, lineOffset, line); } -/** +/** * Gets the number of text lines. * * @return the number of lines in the widget @@ -3533,10 +3651,10 @@ return content.getLineCount(); } /** - * Returns the number of lines that can be completely displayed in the + * Returns the number of lines that can be completely displayed in the * widget client area. * - * @return number of lines that can be completely displayed in the widget + * @return number of lines that can be completely displayed in the widget * client area. */ int getLineCountWhole() { @@ -3564,7 +3682,7 @@ /** * Returns the line height. *

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

                              * @@ -3583,17 +3701,17 @@ * Returns the line height at the given offset. * * @param offset the offset - * + * * @return line height in pixels - * + * * @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_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
                              • - *
                              - * + *
                            • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
                            • + *
                            + * * @since 3.2 */ public int getLineHeight(int offset) { @@ -3607,18 +3725,18 @@ int lineIndex = content.getLineAtOffset(offset); int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); - int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); + int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length)); int height = layout.getLineBounds(lineInParagraph).height; renderer.disposeTextLayout(layout); return height; } /** * Returns the indentation of the line at the given index. - * + * * @param index the index of the line - * + * * @return the line indentation - * + * * @exception DWTException
                              *
                            • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                            • *
                            • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                            • @@ -3626,9 +3744,9 @@ * @exception IllegalArgumentException
                                *
                              • ERROR_INVALID_ARGUMENT when the index is invalid
                              • *
                              - * + * * @see #getIndent() - * + * * @since 3.2 */ public int getLineIndent(int index) { @@ -3640,11 +3758,11 @@ } /** * Returns whether the line at the given index is justified. - * + * * @param index the index of the line - * - * @return whether the line is justified - * + * + * @return whether the line is justified + * * @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
                              • @@ -3652,9 +3770,9 @@ * @exception IllegalArgumentException
                                  *
                                • ERROR_INVALID_ARGUMENT when the index is invalid
                                • *
                                - * + * * @see #getJustify() - * + * * @since 3.2 */ public bool getLineJustify(int index) { @@ -3662,18 +3780,18 @@ if (index < 0 || index > content.getLineCount()) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); } - return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify); + return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify); } /** * Returns the line spacing of the widget. - * + * * @return the line spacing - * - * @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 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.2 */ public int getLineSpacing() { @@ -3681,18 +3799,18 @@ return lineSpacing; } /** - * Returns the line style data for the given line or null if there is + * Returns the line style data for the given line or null if there is * none. *

                                - * If there is a LineStyleListener but it does not set any styles, - * the StyledTextEvent.styles field will be initialized to an empty + * 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 + * + * @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 + * @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) { @@ -3701,11 +3819,13 @@ /** * 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. - * + * It means this function can be used to retrieve the bottom pixel of any line. + * + * @return the top pixel of a given line index + * * @since 3.2 */ public int getLinePixel(int lineIndex) { @@ -3733,6 +3853,10 @@ * Returns the line index for a y, relative to the client area. * The line index returned is always in the range 0..lineCount - 1. * + * @param y the y-coordinate pixel + * + * @return the line index for a given y-coordinate pixel + * * @since 3.2 */ public int getLineIndex(int y) { @@ -3762,59 +3886,59 @@ 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 + * 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. + * @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 + * @return x, y location of the upper left corner of the character * bounding box at the specified offset in the text. * @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_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
                                • + *
                                • ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
                                • *
                                */ public Point getLocationAtOffset(int offset) { checkWidget(); if (offset < 0 || offset > getCharCount()) { - DWT.error(DWT.ERROR_INVALID_RANGE); + DWT.error(DWT.ERROR_INVALID_RANGE); } return getPointAtOffset(offset); } /** * Returns the character offset of the first character of the given line. * - * @param lineIndex index of the line, 0 based relative to the first + * @param lineIndex index of the line, 0 based relative to the first * line in the content. 0 <= lineIndex < getLineCount(), except * lineIndex may always be 0 * @return offset offset of the first character of the line, relative to * the beginning of the document. The first character of the document is - * at offset 0. - * When there are not any lines, getOffsetAtLine(0) is a valid call that + * at offset 0. + * When there are not any lines, getOffsetAtLine(0) is a valid call that * answers 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
                                • *
                                * @exception IllegalArgumentException
                                  - *
                                • ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
                                • + *
                                • ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
                                • *
                                * @since 2.0 */ public int getOffsetAtLine(int lineIndex) { checkWidget(); - if (lineIndex < 0 || + if (lineIndex < 0 || (lineIndex > 0 && lineIndex >= content.getLineCount())) { - DWT.error(DWT.ERROR_INVALID_RANGE); + DWT.error(DWT.ERROR_INVALID_RANGE); } return content.getOffsetAtLine(lineIndex); } /** - * Returns the offset of the character at the given location relative + * Returns the offset of the character at the given location relative * to the first character in the document. *

                                * The return value reflects the character offset that the caret will @@ -3823,9 +3947,9 @@ * the returned offset will be behind the character. *

                                * - * @param point the origin of character bounding box relative to + * @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 + * @return offset of the character at the given location relative * to the first character in the document. * @exception DWTException
                                  *
                                • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                • @@ -3864,7 +3988,7 @@ int getOffsetAtPoint(int x, int y, int lineIndex) { TextLayout layout = renderer.getTextLayout(lineIndex); x += horizontalScrollOffset - leftMargin; - int[] trailing = new int[1]; + int[1] trailing; int offsetInLine = layout.getOffset(x, y, trailing); caretAlignment = OFFSET_LEADING; if (trailing[0] !is 0) { @@ -3874,11 +3998,11 @@ offsetInLine += trailing[0]; caretAlignment = PREVIOUS_OFFSET_TRAILING; } else { - String line = content.getLine(lineIndex); + String line = content.getLine(lineIndex); int level; int offset = offsetInLine; - while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; - if (offset is 0 && Character.isDigit(line.charAt(offset))) { + while (offset > 0 && tango.text.Unicode.isDigit(line[offset])) offset--; + if (offset is 0 && tango.text.Unicode.isDigit(line[offset])) { level = isMirrored() ? 1 : 0; } else { level = layout.getLevel(offset) & 0x1; @@ -3906,7 +4030,7 @@ } int lineIndex = getLineIndex(y); int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); x += horizontalScrollOffset - leftMargin ; y -= getLinePixel(lineIndex); int offset = layout.getOffset(x, y, trailing); @@ -3921,19 +4045,19 @@ * Returns the orientation of the receiver. * * @return the orientation style - * - * @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 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.2 */ public int getOrientation () { checkWidget(); return isMirrored() ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT; } -/** +/** * Returns the index of the last partially visible line. * * @return index of the last partially visible line. @@ -3946,7 +4070,7 @@ } return getLineIndex(clientAreaHeight - bottomMargin); } -/** +/** * Returns the index of the first partially visible line. * * @return index of the first partially visible line. @@ -3959,11 +4083,11 @@ return topIndexY <= 0 ? topIndex : topIndex - 1; } /** - * Returns the content in the specified range using the platform line + * Returns the content in the specified range using the platform line * delimiter to separate lines. * * @param writer the TextWriter to write line text into - * @return the content in the specified range using the platform line + * @return the content in the specified range using the platform line * delimiter to separate lines as written by the specified TextWriter. */ String getPlatformDelimitedText(TextWriter writer) { @@ -3972,14 +4096,14 @@ int endLine = content.getLineAtOffset(end); String endLineText = content.getLine(endLine); int endLineOffset = content.getOffsetAtLine(endLine); - + for (int i = startLine; i <= endLine; i++) { writer.writeLine(content.getLine(i), content.getOffsetAtLine(i)); if (i < endLine) { writer.writeLineDelimiter(PlatformLineDelimiter); } } - if (end > endLineOffset + endLineText.length()) { + if (end > endLineOffset + endLineText.length) { writer.writeLineDelimiter(PlatformLineDelimiter); } writer.close(); @@ -3987,8 +4111,8 @@ } /** * Returns all the ranges of text that have an associated StyleRange. - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. *

                                  * The ranges array contains start and length pairs. Each pair refers to @@ -3996,16 +4120,16 @@ * that starts at ranges[n] with length ranges[n+1] uses the style * at styles[n/2] returned by getStyleRanges(int, int, bool). *

                                  - * + * * @return the ranges or an empty array if a LineStyleListener has been set. - * - * @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 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.2 - * + * * @see #getStyleRanges(bool) */ public int[] getRanges() { @@ -4018,8 +4142,8 @@ } /** * Returns the ranges of text that have an associated StyleRange. - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. *

                                  * The ranges array contains start and length pairs. Each pair refers to @@ -4030,19 +4154,19 @@ * * @param start the start offset of the style ranges to return * @param length the number of style ranges to return - * + * * @return the ranges or an empty array if a LineStyleListener has been set. - * + * * @exception 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_INVALID_RANGE if start or length are outside the widget content
                                  • - *
                                  - * + *
                                • ERROR_INVALID_RANGE if start or length are outside the widget content
                                • + *
                                + * * @since 3.2 - * + * * @see #getStyleRanges(int, int, bool) */ public int[] getRanges(int start, int length) { @@ -4062,15 +4186,15 @@ * Returns the selection. *

                                * Text selections are specified in terms of caret positions. In a text - * widget that contains N characters, there are N+1 caret positions, + * 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 + * @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 cast(RtoL) vs. left-to-right - * cast(LtoR), compare the caretOffset to the start and end of the selection + * 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
                                  @@ -4085,12 +4209,12 @@ /** * Returns the selection. * - * @return start and length of the selection, x is the offset of the - * first selected character, relative to the first character of the - * widget content. y is the length of the selection. - * The selection values returned are visual (i.e., length will always always be - * positive). To determine if a selection is right-to-left cast(RtoL) vs. left-to-right - * cast(LtoR), compare the caretOffset to the start and end of the selection + * @return start and length of the selection, x is the offset of the + * first selected character, relative to the first character of the + * widget content. y is the length of the selection. + * The selection values returned are visual (i.e., length will always always be + * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right + * (LtoR), compare the caretOffset to the start and end of the selection * (e.g., caretOffset is start of selection implies that the selection is RtoL). * @exception DWTException
                                    *
                                  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                  • @@ -4163,7 +4287,7 @@ checkWidget(); return content.getTextRange(selection.x, selection.y - selection.x); } -public int getStyle() { +public override int getStyle() { int style = super.getStyle(); style &= ~(DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT | DWT.MIRRORED); if (isMirrored()) { @@ -4175,18 +4299,18 @@ } /** - * Returns the text segments that should be treated as if they + * Returns the text segments that should be treated as if they * had a different direction than the surrounding text. * - * @param lineOffset offset of the first character in the line. + * @param lineOffset offset of the first character in the line. * 0 based from the beginning of the document. * @param line text of the line to specify bidi segments for * @return text segments that should be treated as if they had a - * different direction than the surrounding text. Only the start - * index of a segment is specified, relative to the start of the - * line. Always starts with 0 and ends with the line length. + * different direction than the surrounding text. Only the start + * index of a segment is specified, relative to the start of the + * line. Always starts with 0 and ends with the line length. * @exception IllegalArgumentException
                                      - *
                                    • ERROR_INVALID_ARGUMENT - if the segment indices returned + *
                                    • ERROR_INVALID_ARGUMENT - if the segment indices returned * by the listener do not start with 0, are not in ascending order, * exceed the line length or have duplicates
                                    • *
                                    @@ -4197,21 +4321,21 @@ return getBidiSegmentsCompatibility(line, lineOffset); } StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line); - int lineLength = line.length(); + int lineLength = line.length; int[] segments; if (event is null || event.segments is null || event.segments.length is 0) { - segments = new int[] {0, lineLength}; + segments = [0, lineLength]; } else { int segmentCount = event.segments.length; - + // test segment index consistency if (event.segments[0] !is 0) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } + } for (int i = 1; i < segmentCount; i++) { if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } + } } // ensure that last segment index is line end offset if (event.segments[segmentCount - 1] !is lineLength) { @@ -4229,9 +4353,9 @@ * Supports deprecated setBidiColoring API. Remove when API is removed. */ int [] getBidiSegmentsCompatibility(String line, int lineOffset) { - int lineLength = line.length(); + int lineLength = line.length; if (!bidiColoring) { - return new int[] {0, lineLength}; + return [0, lineLength]; } StyleRange [] styles = null; StyledTextEvent event = getLineStyleData(lineOffset, line); @@ -4241,7 +4365,7 @@ styles = renderer.getStyleRanges(lineOffset, lineLength, true); } if (styles is null || styles.length is 0) { - return new int[] {0, lineLength}; + return [0, lineLength]; } int k=0, count = 1; while (k < styles.length && styles[k].start is 0 && styles[k].length is lineLength) { @@ -4252,7 +4376,7 @@ StyleRange style = styles[i]; int styleLineStart = Math.max(style.start - lineOffset, 0); int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart); - styleLineEnd = Math.min (styleLineEnd, line.length ()); + styleLineEnd = Math.min (styleLineEnd, line.length ); if (i > 0 && count > 1 && ((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) || (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) && @@ -4284,15 +4408,15 @@ * Returns the style range at the given offset. *

                                    * Returns null if a LineStyleListener has been set or if a style is not set - * for the offset. - * Should not be called if a LineStyleListener has been set since the + * 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. + * @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 + * 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
                                      *
                                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                    • @@ -4316,8 +4440,8 @@ /** * Returns the styles. *

                                      - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * 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 @@ -4333,7 +4457,7 @@ *
                                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                    • *
                                    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                    • *
                                    - * + * * @see #getStyleRanges(bool) */ public StyleRange[] getStyleRanges() { @@ -4343,8 +4467,8 @@ /** * Returns the styles. *

                                    - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * 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 @@ -4353,18 +4477,18 @@ * false, getRanges(int, int) can be used to get the * associated ranges. *

                                    - * + * * @param includeRanges whether the start and length field of the StyleRanges should be set. - * + * * @return the styles or an empty array if a LineStyleListener has been set. - * - * @exception 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 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.2 - * + * * @see #getRanges(int, int) * @see #setStyleRanges(int[], StyleRange[]) */ @@ -4375,8 +4499,8 @@ /** * Returns the styles for the given text range. *

                                    - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * 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 @@ -4388,10 +4512,10 @@ * @param start the start offset of the style ranges to return * @param length the number of style ranges to return * - * @return the styles or an empty array if a LineStyleListener has - * been set. The returned styles will reflect the given range. The first - * returned StyleRange will have a starting offset >= start - * and the last returned StyleRange will have an ending + * @return the styles or an empty array if a LineStyleListener has + * been set. The returned styles will reflect the given range. The first + * returned StyleRange will have a starting offset >= start + * and the last returned StyleRange will have an ending * offset <= start + length - 1 * * @exception DWTException

                                      @@ -4399,11 +4523,11 @@ *
                                    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                    • *
                                    * @exception IllegalArgumentException
                                      - *
                                    • ERROR_INVALID_RANGE when start and/or end are outside the widget content
                                    • - *
                                    - * + *
                                  • ERROR_INVALID_RANGE when start and/or end are outside the widget content
                                  • + *
                                  + * * @see #getStyleRanges(int, int, bool) - * + * * @since 3.0 */ public StyleRange[] getStyleRanges(int start, int length) { @@ -4413,8 +4537,8 @@ /** * Returns the styles for the given text range. *

                                  - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * 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 @@ -4423,15 +4547,15 @@ * false, getRanges(int, int) can be used to get the * associated ranges. *

                                  - * + * * @param start the start offset of the style ranges to return * @param length the number of style ranges to return * @param includeRanges whether the start and length field of the StyleRanges should be set. * - * @return the styles or an empty array if a LineStyleListener has - * been set. The returned styles will reflect the given range. The first - * returned StyleRange will have a starting offset >= start - * and the last returned StyleRange will have an ending + * @return the styles or an empty array if a LineStyleListener has + * been set. The returned styles will reflect the given range. The first + * returned StyleRange will have a starting offset >= start + * and the last returned StyleRange will have an ending * offset <= start + length - 1 * * @exception DWTException
                                    @@ -4439,11 +4563,11 @@ *
                                  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                  • *
                                  * @exception IllegalArgumentException
                                    - *
                                  • ERROR_INVALID_RANGE when start and/or end are outside the widget content
                                  • - *
                                  - * + *
                                • ERROR_INVALID_RANGE when start and/or end are outside the widget content
                                • + *
                                + * * @since 3.2 - * + * * @see #getRanges(int, int) * @see #setStyleRanges(int[], StyleRange[]) */ @@ -4490,7 +4614,7 @@ * Returns the widget content between the two offsets. * * @param start offset of the first character in the returned String - * @param end offset of the last character in the returned String + * @param end offset of the last character in the returned String * @return widget content starting at start and ending at end * @see #getTextRange(int,int) * @exception DWTException
                                  @@ -4498,7 +4622,7 @@ *
                                • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                • *
                                * @exception IllegalArgumentException
                                  - *
                                • ERROR_INVALID_RANGE when start and/or end are outside the widget content
                                • + *
                                • ERROR_INVALID_RANGE when start and/or end are outside the widget content
                                • *
                                */ public String getText(int start, int end) { @@ -4513,20 +4637,20 @@ * Returns the smallest bounding rectangle that includes the characters between two offsets. * * @param start offset of the first character included in the bounding box - * @param end offset of the last character included in the bounding box + * @param end offset of the last character included in the bounding box * @return bounding box of the text between start and end * @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_INVALID_RANGE when start and/or end are outside the widget content
                                • + *
                                • ERROR_INVALID_RANGE when start and/or end are outside the widget content
                                • *
                                * @since 3.1 */ public Rectangle getTextBounds(int start, int end) { - checkWidget(); - int contentLength = getCharCount(); + checkWidget(); + int contentLength = getCharCount(); if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { DWT.error(DWT.ERROR_INVALID_RANGE); } @@ -4537,9 +4661,9 @@ int height = 0; int left = 0x7fffffff, right = 0; for (int i = lineStart; i <= lineEnd; i++) { - int lineOffset = content.getOffsetAtLine(i); + int lineOffset = content.getOffsetAtLine(i); TextLayout layout = renderer.getTextLayout(i); - int length = layout.getText().length(); + int length = layout.getText().length; if (length > 0) { if (i is lineStart) { if (i is lineEnd) { @@ -4569,14 +4693,14 @@ * Returns the widget content starting at start for length characters. * * @param start offset of the first character in the returned String - * @param length number of characters to return + * @param length number of characters to return * @return widget content starting at start and extending length characters. * @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_INVALID_RANGE when start and/or length are outside the widget content
                                • + *
                                • ERROR_INVALID_RANGE when start and/or length are outside the widget content
                                • *
                                */ public String getTextRange(int start, int length) { @@ -4585,12 +4709,12 @@ int end = start + length; if (start > end || start < 0 || end > contentLength) { DWT.error(DWT.ERROR_INVALID_RANGE); - } + } return content.getTextRange(start, length); } /** * Returns the maximum number of characters that the receiver is capable of holding. - * + * * @return the text limit * * @exception DWTException
                                  @@ -4605,8 +4729,8 @@ /** * Gets the top index. *

                                  - * The top index is the index of the fully visible line that is currently - * at the top of the widget or the topmost partially visible line if no line is fully visible. + * The top index 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. *

                                  * @@ -4623,10 +4747,10 @@ /** * Gets the top pixel. *

                                  - * The top pixel is the pixel position of the line that is - * currently at the top of the widget. The text widget can be scrolled by pixels - * by dragging the scroll thumb so that a partial line may be displayed at the top - * the widget. The top pixel changes when the widget is scrolled. The top pixel + * 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. *

                                  * @@ -4640,7 +4764,7 @@ checkWidget(); return getVerticalScrollOffset(); } -/** +/** * Returns the vertical scroll increment. * * @return vertical scroll increment. @@ -4679,12 +4803,12 @@ int lineOffset = content.getOffsetAtLine(caretLine); String line = content.getLine(caretLine); int offset = caretOffset - lineOffset; - int lineLength = line.length(); + int lineLength = line.length; if (lineLength is 0) return isMirrored() ? DWT.RIGHT : DWT.LEFT; if (caretAlignment is PREVIOUS_OFFSET_TRAILING && offset > 0) offset--; if (offset is lineLength && offset > 0) offset--; - while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; - if (offset is 0 && Character.isDigit(line.charAt(offset))) { + while (offset > 0 && tango.text.Unicode.isDigit(line[offset])) offset--; + if (offset is 0 && tango.text.Unicode.isDigit(line[offset])) { return isMirrored() ? DWT.RIGHT : DWT.LEFT; } TextLayout layout = renderer.getTextLayout(caretLine); @@ -4717,7 +4841,7 @@ int lineIndex = content.getLineAtOffset(offset); lineOffset = content.getOffsetAtLine(lineIndex); lineText = content.getLine(lineIndex); - int lineLength = lineText.length(); + int lineLength = lineText.length; if (offset is lineOffset + lineLength) { newOffset = content.getOffsetAtLine(lineIndex + 1); } else { @@ -4742,12 +4866,12 @@ lineText = content.getLine(lineIndex); if (offset is lineOffset) { String nextLineText = content.getLine(lineIndex - 1); - int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); - newOffset = nextLineOffset + nextLineText.length(); + int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); + newOffset = nextLineOffset + nextLineText.length; } else { TextLayout layout = renderer.getTextLayout(lineIndex); newOffset = lineOffset + layout.getPreviousOffset(offset - lineOffset, movement); - renderer.disposeTextLayout(layout); + renderer.disposeTextLayout(layout); } } return sendWordBoundaryEvent(WordPrevious, movement, offset, newOffset, lineText, lineOffset); @@ -4762,7 +4886,7 @@ checkWidget(); return wordWrap; } -/** +/** * Returns the location of the given offset. *

                                  * NOTE: Does not return correct values for true italic fonts (vs. slanted fonts). @@ -4775,7 +4899,7 @@ String line = content.getLine(lineIndex); int lineOffset = content.getOffsetAtLine(lineIndex); int offsetInLine = offset - lineOffset; - int lineLength = line.length(); + int lineLength = line.length; if (lineIndex < content.getLineCount() - 1) { int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1; if (lineLength < offsetInLine && offsetInLine <= endLineOffset) { @@ -4786,7 +4910,9 @@ TextLayout layout = renderer.getTextLayout(lineIndex); if (lineLength !is 0 && offsetInLine <= lineLength) { if (offsetInLine is lineLength) { - point = layout.getLocation(offsetInLine - 1, true); + // DWT: Instead of go back one byte, go back one codepoint + int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); + point = layout.getLocation(offsetInLine_m1, true); } else { switch (caretAlignment) { case OFFSET_LEADING: @@ -4797,7 +4923,9 @@ if (offsetInLine is 0) { point = layout.getLocation(offsetInLine, false); } else { - point = layout.getLocation(offsetInLine - 1, true); + // DWT: Instead of go back one byte, go back one codepoint + int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); + point = layout.getLocation(offsetInLine_m1, true); } break; } @@ -4810,32 +4938,30 @@ point.y += getLinePixel(lineIndex); return point; } -/** - * Inserts a String. The old selection is replaced with the new text. - * - * @param String the String +/** + * Inserts a string. The old selection is replaced with the new text. + * + * @param string the string * @see #replaceTextRange(int,int,String) * @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 when String is null
                                  • - *
                                  - */ -public void insert(String String) { - checkWidget(); - if (String is null) { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } + */ +public void insert(String string) { + checkWidget(); + // DWT extension: allow null for zero length string +// if (string is null) { +// DWT.error(DWT.ERROR_NULL_ARGUMENT); +// } Point sel = getSelectionRange(); - replaceTextRange(sel.x, sel.y, String); + replaceTextRange(sel.x, sel.y, string); } /** * Creates content change listeners and set the default content model. */ void installDefaultContent() { - textChangeListener = new TextChangeListener() { + textChangeListener = new class() TextChangeListener { public void textChanging(TextChangingEvent event) { handleTextChanging(event); } @@ -4849,14 +4975,14 @@ content = new DefaultContent(); content.addTextChangeListener(textChangeListener); } -/** +/** * Adds event listeners */ void installListeners() { ScrollBar verticalBar = getVerticalBar(); ScrollBar horizontalBar = getHorizontalBar(); - - listener = new Listener() { + + listener = new class() Listener { public void handleEvent(Event event) { switch (event.type) { case DWT.Dispose: handleDispose(event); break; @@ -4868,8 +4994,9 @@ case DWT.Paint: handlePaint(event); break; case DWT.Resize: handleResize(event); break; case DWT.Traverse: handleTraverse(event); break; + default: } - } + } }; addListener(DWT.Dispose, listener); addListener(DWT.KeyDown, listener); @@ -4880,24 +5007,25 @@ addListener(DWT.Paint, listener); addListener(DWT.Resize, listener); addListener(DWT.Traverse, listener); - ime.addListener(DWT.ImeComposition, new Listener() { + ime.addListener(DWT.ImeComposition, new class() Listener { public void handleEvent(Event event) { switch (event.detail) { case DWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break; case DWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break; case DWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break; + default: } } }); if (verticalBar !is null) { - verticalBar.addListener(DWT.Selection, new Listener() { + verticalBar.addListener(DWT.Selection, new class() Listener { public void handleEvent(Event event) { handleVerticalScroll(event); } }); } if (horizontalBar !is null) { - horizontalBar.addListener(DWT.Selection, new Listener() { + horizontalBar.addListener(DWT.Selection, new class() Listener { public void handleEvent(Event event) { handleHorizontalScroll(event); } @@ -4930,8 +5058,8 @@ TextLayout layout = renderer.getTextLayout(startLine); int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine); int[] offsets = layout.getLineOffsets(); - int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length())); - + int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length)); + /* Redraw end of line before start line if wrapped and start offset is first char */ if (wordWrap && startIndex > 0 && offsets[startIndex] is start) { Rectangle rect = layout.getLineBounds(startIndex - 1); @@ -4941,9 +5069,9 @@ rect.y += startLineY; super.redraw(rect.x, rect.y, rect.width, rect.height, false); } - + if (startLine is endLine) { - int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); + int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length)); if (startIndex is endIndex) { /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */ Rectangle rect = layout.getBounds(start, end - 1); @@ -4974,7 +5102,7 @@ layout = renderer.getTextLayout(endLine); offsets = layout.getLineOffsets(); } - int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); + int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length)); Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1); if (endRect.height is 0) { Rectangle bounds = layout.getLineBounds(endIndex); @@ -5006,26 +5134,27 @@ String text = event.text; int start = event.start; int end = event.end; - int length = text.length(); + int length = text.length; if (length is ime.getCommitCount()) { content.replaceTextRange(start, end - start, ""); - caretOffset = start; + caretOffset = ime.getCompositionOffset(); caretWidth = 0; caretDirection = DWT.NULL; } else { content.replaceTextRange(start, end - start, text); caretOffset = ime.getCaretOffset(); if (ime.getWideCaret()) { + start = ime.getCompositionOffset(); int lineIndex = getCaretLine(); int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width; renderer.disposeTextLayout(layout); } } showCaret(); } -/** +/** * Frees resources. */ void handleDispose(Event event) { @@ -5067,7 +5196,7 @@ foreground = null; clipboard = null; } -/** +/** * Scrolls the widget horizontally. */ void handleHorizontalScroll(Event event) { @@ -5101,35 +5230,35 @@ } if (action is DWT.NULL) { bool ignore = false; - + if (IS_CARBON) { - // Ignore accelerator key combinations (we do not want to - // insert a character in the text in this instance). Do not + // Ignore accelerator key combinations (we do not want to + // insert a character in the text in this instance). Do not // ignore COMMAND+ALT combinations since that key sequence // produces characters on the mac. ignore = (event.stateMask ^ DWT.COMMAND) is 0 || (event.stateMask ^ (DWT.COMMAND | DWT.SHIFT)) is 0; } else if (IS_MOTIF) { - // Ignore accelerator key combinations (we do not want to - // insert a character in the text in this instance). Do not + // Ignore accelerator key combinations (we do not want to + // insert a character in the text in this instance). Do not // ignore ALT combinations since this key sequence // produces characters on motif. ignore = (event.stateMask ^ DWT.CTRL) is 0 || (event.stateMask ^ (DWT.CTRL | DWT.SHIFT)) is 0; } else { - // Ignore accelerator key combinations (we do not want to - // insert a character in the text in this instance). Don't - // ignore CTRL+ALT combinations since that is the Alt Gr - // key on some keyboards. See bug 20953. - ignore = (event.stateMask ^ DWT.ALT) is 0 || + // Ignore accelerator key combinations (we do not want to + // insert a character in the text in this instance). Don't + // ignore CTRL+ALT combinations since that is the Alt Gr + // key on some keyboards. See bug 20953. + ignore = (event.stateMask ^ DWT.ALT) is 0 || (event.stateMask ^ DWT.CTRL) is 0 || (event.stateMask ^ (DWT.ALT | DWT.SHIFT)) is 0 || (event.stateMask ^ (DWT.CTRL | DWT.SHIFT)) is 0; } // -ignore anything below SPACE except for line delimiter keys and tab. - // -ignore DEL - if (!ignore && event.character > 31 && event.character !is DWT.DEL || - event.character is DWT.CR || event.character is DWT.LF || + // -ignore DEL + if (!ignore && event.character > 31 && event.character !is DWT.DEL || + event.character is DWT.CR || event.character is DWT.LF || event.character is TAB) { doContent(event.character); update(); @@ -5148,7 +5277,7 @@ if (clipboardSelection is null) { clipboardSelection = new Point(selection.x, selection.y); } - + Event verifyEvent = new Event(); verifyEvent.character = event.character; verifyEvent.keyCode = event.keyCode; @@ -5172,7 +5301,7 @@ setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); } } catch (DWTError error) { - // Copy to clipboard failed. This happens when another application + // Copy to clipboard failed. This happens when another application // is accessing the clipboard while we copy. Ignore the error. // Fixes 1GDQAVN // Rethrow all other errors. Fixes bug 17578. @@ -5184,21 +5313,22 @@ } clipboardSelection = null; } -/** - * Updates the caret location and selection if mouse button 1 has been +/** + * Updates the caret location and selection if mouse button 1 has been * pressed. */ void handleMouseDown(Event event) { //force focus (object support) forceFocus(); - + //drag detect - if (dragDetect && checkDragDetect(event)) return; - + if (dragDetect_ && checkDragDetect(event)) return; + //paste clipboard selection if (event.button is 2) { - String text = cast(String)getClipboardContent(DND.SELECTION_CLIPBOARD); - if (text !is null && text.length() > 0) { + auto o = cast(ArrayWrapperString)getClipboardContent(DND.SELECTION_CLIPBOARD); + String text = o.array; + if (text !is null && text.length > 0) { // position cursor doMouseLocationChange(event.x, event.y, false); // insert text @@ -5209,10 +5339,10 @@ sendKeyEvent(e); } } - + //set selection if ((event.button !is 1) || (IS_CARBON && (event.stateMask & DWT.MOD4) !is 0)) { - return; + return; } clickCount = event.count; if (clickCount is 1) { @@ -5245,8 +5375,8 @@ } } } -/** - * Updates the caret location and selection if mouse button 1 is pressed +/** + * Updates the caret location and selection if mouse button 1 is pressed * during the mouse move. */ void handleMouseMove(Event event) { @@ -5255,7 +5385,7 @@ update(); doAutoScroll(event); } -/** +/** * Autoscrolling ends when the mouse button is released. */ void handleMouseUp(Event event) { @@ -5267,7 +5397,7 @@ setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); } } catch (DWTError error) { - // Copy to clipboard failed. This happens when another application + // Copy to clipboard failed. This happens when another application // is accessing the clipboard while we copy. Ignore the error. // Fixes 1GDQAVN // Rethrow all other errors. Fixes bug 17578. @@ -5319,7 +5449,7 @@ } } /** - * Recalculates the scroll bars. Rewraps all lines when in word + * Recalculates the scroll bars. Rewraps all lines when in word * wrap mode. * * @param event resize event @@ -5333,13 +5463,13 @@ /* Redraw the old or new right/bottom margin if needed */ if (oldWidth !is clientAreaWidth) { if (rightMargin > 0) { - int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; + int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; super.redraw(x, 0, rightMargin, oldHeight, false); } } if (oldHeight !is clientAreaHeight) { if (bottomMargin > 0) { - int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; + int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; super.redraw(0, y, oldWidth, bottomMargin, false); } } @@ -5378,10 +5508,14 @@ // } } /** - * Updates the caret position and selection and the scroll bars to reflect + * Updates the caret position and selection and the scroll bars to reflect * the content change. */ void handleTextChanged(TextChangedEvent event) { + int offset = ime.getCompositionOffset(); + if (offset !is -1 && lastTextChangeStart < offset) { + ime.setCompositionOffset(offset + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount); + } int firstLine = content.getLineAtOffset(lastTextChangeStart); resetCache(firstLine, 0); if (!isFixedLineHeight() && topIndex > firstLine) { @@ -5394,7 +5528,6 @@ int newLastLineBottom = getLinePixel(lastLine + 1); if (lastLineBottom !is newLastLineBottom) { super.redraw(); - if (wordWrap) setCaretLocation(); } else { super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false); redrawLinesBullet(renderer.redrawLines); @@ -5403,10 +5536,10 @@ renderer.redrawLines = null; // update selection/caret location after styles have been changed. // otherwise any text measuring could be incorrect - // - // also, this needs to be done after all scrolling. Otherwise, + // + // also, this needs to be done after all scrolling. Otherwise, // selection redraw would be flushed during scroll which is wrong. - // in some cases new text would be drawn in scroll source area even + // in some cases new text would be drawn in scroll source area even // though the intent is to scroll it. updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount); if (lastTextChangeReplaceLineCount > 0 || wordWrap) { @@ -5420,7 +5553,7 @@ * Updates the screen to reflect a pending content change. * * @param event .start the start offset of the change - * @param event .newText text that is going to be inserted or empty String + * @param event .newText text that is going to be inserted or empty String * if no text will be inserted * @param event .replaceCharCount length of text that is going to be replaced * @param event .newCharCount length of text that is going to be inserted @@ -5436,7 +5569,7 @@ lastTextChangeNewLineCount = event.newLineCount; lastTextChangeNewCharCount = event.newCharCount; lastTextChangeReplaceLineCount = event.replaceLineCount; - lastTextChangeReplaceCharCount = event.replaceCharCount; + lastTextChangeReplaceCharCount = event.replaceCharCount; int lineIndex = content.getLineAtOffset(event.start); int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1); int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight(); @@ -5451,7 +5584,7 @@ } renderer.textChanging(event); - + // Update the caret offset if it is greater than the length of the content. // This is necessary since style range API may be called between the // handleTextChanging and handleTextChanged events and this API sets the @@ -5460,20 +5593,20 @@ if (caretOffset > newEndOfText) caretOffset = newEndOfText; } /** - * Called when the widget content is set programmatically, overwriting - * the old content. Resets the caret position, selection and scroll offsets. + * Called when the widget content is set programmatically, overwriting + * the old content. Resets the caret position, selection and scroll offsets. * Recalculates the content width and scroll bars. Redraws the widget. * - * @param event text change event. + * @param event text change event. */ void handleTextSet(TextChangedEvent event) { reset(); } /** * Called when a traversal key is pressed. - * Allow tab next traversal to occur when the widget is in single - * line mode or in multi line and non-editable mode . - * When in editable multi line mode we want to prevent the tab + * Allow tab next traversal to occur when the widget is in single + * line mode or in multi line and non-editable mode . + * When in editable multi line mode we want to prevent the tab * traversal and receive the tab key event instead. * * @param event the event @@ -5496,9 +5629,10 @@ } } break; - } -} -/** + default: + } +} +/** * Scrolls the widget vertically. */ void handleVerticalScroll(Event event) { @@ -5510,7 +5644,7 @@ */ void initializeAccessible() { final Accessible accessible = getAccessible(); - accessible.addAccessibleListener(new AccessibleAdapter() { + accessible.addAccessibleListener(new class() AccessibleAdapter { public void getName (AccessibleEvent e) { String name = null; Label label = getAssociatedLabel (); @@ -5528,26 +5662,26 @@ if (label !is null) { String text = label.getText (); if (text !is null) { - char mnemonic = _findMnemonic (text); + dchar mnemonic = _findMnemonic (text); if (mnemonic !is '\0') { - shortcut = "Alt+"+mnemonic; //$NON-NLS-1$ + shortcut = "Alt+"~tango.text.convert.Utf.toString( [mnemonic] ); //$NON-NLS-1$ } } } e.result = shortcut; } }); - accessible.addAccessibleTextListener(new AccessibleTextAdapter() { + accessible.addAccessibleTextListener(new class() AccessibleTextAdapter { public void getCaretOffset(AccessibleTextEvent e) { - e.offset = StyledText.this.getCaretOffset(); + e.offset = this.outer.getCaretOffset(); } public void getSelectionRange(AccessibleTextEvent e) { - Point selection = StyledText.this.getSelectionRange(); + Point selection = this.outer.getSelectionRange(); e.offset = selection.x; e.length = selection.y; } }); - accessible.addAccessibleControlListener(new AccessibleControlAdapter() { + accessible.addAccessibleControlListener(new class() AccessibleControlAdapter { public void getRole(AccessibleControlEvent e) { e.detail = ACC.ROLE_TEXT; } @@ -5560,58 +5694,60 @@ e.detail = state; } public void getValue(AccessibleControlEvent e) { - e.result = StyledText.this.getText(); - } - }); - addListener(DWT.FocusIn, new Listener() { + e.result = this.outer.getText(); + } + }); + addListener(DWT.FocusIn, new class(accessible) Listener { + Accessible acc; + this( Accessible acc ){ this.acc = acc; } public void handleEvent(Event event) { - accessible.setFocus(ACC.CHILDID_SELF); - } - }); -} -/* - * Return the Label immediately preceding the receiver in the z-order, - * or null if none. + acc.setFocus(ACC.CHILDID_SELF); + } + }); +} +/* + * Return the Label immediately preceding the receiver in the z-order, + * or null if none. */ Label getAssociatedLabel () { Control[] siblings = getParent ().getChildren (); for (int i = 0; i < siblings.length; i++) { - if (siblings [i] is StyledText.this) { - if (i > 0 && siblings [i-1] instanceof Label) { + if (siblings [i] is this) { + if (i > 0 && ( null !is cast(Label)siblings [i-1])) { return cast(Label) siblings [i-1]; } } } return null; } -String stripMnemonic (String String) { +String stripMnemonic (String string) { int index = 0; - int length = String.length (); + int length_ = string.length; do { - while ((index < length) && (String.charAt (index) !is '&')) index++; - if (++index >= length) return String; - if (String.charAt (index) !is '&') { - return String.substring(0, index-1) + String.substring(index, length); + while ((index < length_) && (string[index] !is '&')) index++; + if (++index >= length_) return string; + if (string[index] !is '&') { + return string.substring(0, index-1) ~ string.substring(index, length_); } index++; - } while (index < length); - return String; + } while (index < length_); + return string; } /* * Return the lowercase of the first non-'&' character following - * an '&' character in the given String. If there are no '&' - * characters in the given String, return '\0'. - */ -char _findMnemonic (String String) { - if (String is null) return '\0'; + * an '&' character in the given string. If there are no '&' + * characters in the given string, return '\0'. + */ +dchar _findMnemonic (String string) { + if (string is null) return '\0'; int index = 0; - int length = String.length (); + int length_ = string.length; do { - while (index < length && String.charAt (index) !is '&') index++; - if (++index >= length) return '\0'; - if (String.charAt (index) !is '&') return Character.toLowerCase (String.charAt (index)); + while (index < length_ && string[index] !is '&') index++; + if (++index >= length_) return '\0'; + if (string[index] !is '&') return CharacterFirstToLower(string[index .. $ ] ); index++; - } while (index < length); + } while (index < length_); return '\0'; } /** @@ -5680,7 +5816,7 @@ doPageEnd(); clearSelection(true); break; - // Selection + // Selection case ST.SELECT_LINE_UP: doSelectionLineUp(); break; @@ -5736,7 +5872,7 @@ doPageEnd(); doSelection(ST.COLUMN_NEXT); break; - // Modification + // Modification case ST.CUT: cut(); break; @@ -5762,13 +5898,14 @@ case ST.TOGGLE_OVERWRITE: overwrite = !overwrite; // toggle insert/overwrite mode break; + default: } } /** * Temporary until DWT provides this */ bool isBidi() { - return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored; + return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored_; } bool isBidiCaret() { return BidiUtil.isBidiPlatform(); @@ -5778,45 +5915,45 @@ } /** * Returns whether the given offset is inside a multi byte line delimiter. - * Example: + * Example: * "Line1\r\n" isLineDelimiter(5) is false but isLineDelimiter(6) is true - * + * * @return true if the given offset is inside a multi byte line delimiter. * false if the given offset is before or after a line delimiter. */ bool isLineDelimiter(int offset) { int line = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(line); + int lineOffset = content.getOffsetAtLine(line); int offsetInLine = offset - lineOffset; - // offsetInLine will be greater than line length if the line + // offsetInLine will be greater than line length if the line // delimiter is longer than one character and the offset is set // in between parts of the line delimiter. - return offsetInLine > content.getLine(line).length(); -} -/** - * Returns whether the widget is mirrored (right oriented/right to left - * writing order). - * - * @return isMirrored true=the widget is right oriented, false=the widget + return offsetInLine > content.getLine(line).length; +} +/** + * Returns whether the widget is mirrored (right oriented/right to left + * writing order). + * + * @return isMirrored true=the widget is right oriented, false=the widget * is left oriented */ bool isMirrored() { - return isMirrored; + return isMirrored_; } /** * Returns whether the widget can have only one line. * - * @return true if widget can have only one line, false if widget can have + * @return true if widget can have only one line, false if widget can have * multiple lines */ bool isSingleLine() { return (getStyle() & DWT.SINGLE) !is 0; } /** - * Sends the specified verify event, replace/insert text as defined by + * Sends the specified verify event, replace/insert text as defined by * the event and send a modify event. * - * @param event the text change event. + * @param event the text change event. *
                                    *
                                  • event.start - the replace start offset
                                  • *
                                  • event.end - the replace end offset
                                  • @@ -5834,12 +5971,12 @@ if (isListening(ExtendedModify)) { styledTextEvent = new StyledTextEvent(content); styledTextEvent.start = event.start; - styledTextEvent.end = event.start + event.text.length(); + styledTextEvent.end = event.start + event.text.length; styledTextEvent.text = content.getTextRange(event.start, replacedLength); } if (updateCaret) { //Fix advancing flag for delete/backspace key on direction boundary - if (event.text.length() is 0) { + if (event.text.length is 0) { int lineIndex = content.getLineAtOffset(event.start); int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); @@ -5864,7 +6001,7 @@ // fixes 1GBB8NJ if (updateCaret) { // always update the caret location. fixes 1G8FODP - setSelection(event.start + event.text.length(), 0, true); + setSelection(event.start + event.text.length, 0, true); showCaret(); } sendModifyEvent(event); @@ -5887,10 +6024,10 @@ notifyListeners(PaintObject, event); } } -/** - * Replaces the selection with the text on the DND.CLIPBOARD - * clipboard or, if there is no selection, inserts the text at the current - * caret offset. If the widget has the DWT.SINGLE style and the +/** + * Replaces the selection with the text on the DND.CLIPBOARD + * clipboard or, if there is no selection, inserts the text at the current + * caret offset. If the widget has the DWT.SINGLE style and the * clipboard text contains more than one line, only the first line without * line delimiters is inserted in the widget. * @@ -5900,9 +6037,12 @@ *
                                  */ public void paste(){ - checkWidget(); - String text = cast(String) getClipboardContent(DND.CLIPBOARD); - if (text !is null && text.length() > 0) { + checkWidget(); + String text = null; + if( auto o = cast(ArrayWrapperString) getClipboardContent(DND.CLIPBOARD)){ + text = o.array; + } + if (text !is null && text.length > 0) { Event event = new Event(); event.start = selection.x; event.end = selection.y; @@ -5910,7 +6050,7 @@ sendKeyEvent(event); } } -/** +/** * Prints the widget's text to the default printer. * * @exception DWTException
                                    @@ -5925,18 +6065,21 @@ options.printTextForeground = true; options.printTextBackground = true; options.printTextFontStyle = true; - options.printLineBackground = true; - new Printing(this, printer, options).run(); + options.printLineBackground = true; + (new Printing(this, printer, options)).run(); printer.dispose(); } -/** +/** * Returns a runnable that will print the widget's text * to the specified printer. *

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

                                    - * + * * @param printer the printer to print to + * + * @return a Runnable for printing the receiver's text + * * @exception DWTException
                                      *
                                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                    • *
                                    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                    • @@ -5946,7 +6089,7 @@ *
                                    */ public Runnable print(Printer printer) { - checkWidget(); + checkWidget(); if (printer is null) { DWT.error(DWT.ERROR_NULL_ARGUMENT); } @@ -5957,15 +6100,18 @@ options.printLineBackground = true; return print(printer, options); } -/** +/** * Returns a runnable that will print the widget's text * to the specified printer. *

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

                                    - * + * * @param printer the printer to print to * @param options print options to use during printing + * + * @return a Runnable for printing the receiver's text + * * @exception DWTException
                                      *
                                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                    • *
                                    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                    • @@ -5988,8 +6134,8 @@ * is processed, the control will be completely painted. *

                                      * Recalculates the content width for all lines in the bounds. - * When a LineStyleListener is used a redraw call - * is the only notification to the widget that styles have changed + * 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. *

                                      * @@ -6000,7 +6146,7 @@ * * @see Control#update() */ -public void redraw() { +public override void redraw() { super.redraw(); int itemCount = getPartialBottomIndex() - topIndex + 1; renderer.reset(topIndex, itemCount); @@ -6009,18 +6155,18 @@ } /** * Causes the rectangular area of the receiver specified by - * the arguments to be marked as needing to be redrawn. + * the arguments to be marked as needing to be redrawn. * The next time a paint request is processed, that area of * the receiver will be painted. If the all flag * is true, any children of the receiver which * intersect with the specified area will also paint their - * intersecting areas. If the all flag is + * 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 + * 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. *

                                      * @@ -6037,7 +6183,7 @@ * * @see Control#update() */ -public void redraw(int x, int y, int width, int height, bool all) { +public override void redraw(int x, int y, int width, int height, bool all) { super.redraw(x, y, width, height, all); if (height > 0) { int firstLine = getLineIndex(y); @@ -6046,7 +6192,7 @@ } } void redrawLines(int startLine, int lineCount) { - // do nothing if redraw range is completely invisible + // do nothing if redraw range is completely invisible int partialBottomIndex = getPartialBottomIndex(); if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { return; @@ -6062,7 +6208,7 @@ startLine -= topIndex; int redrawTop = getLinePixel(startLine); int redrawBottom = getLinePixel(startLine + lineCount); - int redrawWidth = clientAreaWidth - leftMargin - rightMargin; + int redrawWidth = clientAreaWidth - leftMargin - rightMargin; super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true); } void redrawLinesBullet (int[] redrawLines) { @@ -6085,7 +6231,7 @@ super.redraw(0, y, width, height, false); } } -/** +/** * Redraws the specified text range. * * @param start offset of the first character to redraw @@ -6093,20 +6239,20 @@ * @param clearBackground true if the background should be cleared as * part of the redraw operation. If true, the entire redraw range will * be cleared before anything is redrawn. If the redraw range includes - * the last character of a line (i.e., the entire line is redrawn) the + * the last character of a line (i.e., the entire line is redrawn) the * line is cleared all the way to the right border of the widget. - * The redraw operation will be faster and smoother if clearBackground - * is set to false. Whether or not the flag can be set to false depends - * on the type of change that has taken place. If font styles or - * background colors for the redraw range have changed, clearBackground - * should be set to true. If only foreground colors have changed for - * the redraw range, clearBackground can be set to false. + * The redraw operation will be faster and smoother if clearBackground + * is set to false. Whether or not the flag can be set to false depends + * on the type of change that has taken place. If font styles or + * background colors for the redraw range have changed, clearBackground + * should be set to true. If only foreground colors have changed for + * the redraw range, clearBackground can be set to false. * @exception 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_INVALID_RANGE when start and/or end are outside the widget content
                                      • + *
                                      • ERROR_INVALID_RANGE when start and/or end are outside the widget content
                                      • *
                                      */ public void redrawRange(int start, int length, bool clearBackground) { @@ -6124,7 +6270,8 @@ /** * Removes the specified bidirectional segment listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @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
                                      • @@ -6132,17 +6279,19 @@ * @exception IllegalArgumentException
                                          *
                                        • ERROR_NULL_ARGUMENT when listener is null
                                        • *
                                        + * * @since 2.0 */ public void removeBidiSegmentListener(BidiSegmentListener listener) { checkWidget(); if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(LineGetSegments, listener); + removeListener(LineGetSegments, listener); } /** * Removes the specified extended modify listener. * - * @param extendedModifyListener the listener + * @param extendedModifyListener the listener which should no longer be notified + * * @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
                                        • @@ -6154,12 +6303,13 @@ public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { checkWidget(); if (extendedModifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(ExtendedModify, extendedModifyListener); + removeListener(ExtendedModify, extendedModifyListener); } /** * Removes the specified line background listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @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
                                          • @@ -6176,7 +6326,8 @@ /** * Removes the specified line style listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @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
                                            • @@ -6193,7 +6344,8 @@ /** * Removes the specified modify listener. * - * @param modifyListener the listener + * @param modifyListener the listener which should no longer be notified + * * @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
                                              • @@ -6210,7 +6362,8 @@ /** * Removes the specified listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @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
                                                • @@ -6250,7 +6403,8 @@ /** * Removes the specified verify listener. * - * @param verifyListener the listener + * @param verifyListener the listener which should no longer be notified + * * @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
                                                  • @@ -6267,7 +6421,8 @@ /** * Removes the specified key verify listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @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
                                                    • @@ -6283,7 +6438,8 @@ /** * Removes the specified word movement listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @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
                                                      • @@ -6291,24 +6447,24 @@ * @exception IllegalArgumentException
                                                          *
                                                        • ERROR_NULL_ARGUMENT when listener is null
                                                        • *
                                                        - * + * * @see MovementEvent * @see MovementListener * @see #addWordMovementListener - * + * * @since 3.3 */ public void removeWordMovementListener(MovementListener listener) { checkWidget(); if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(WordNext, listener); + removeListener(WordNext, listener); removeListener(WordPrevious, listener); } -/** +/** * Replaces the styles in the given range with new styles. This method * effectively deletes the styles in the given range and then adds the - * the new styles. + * the new styles. *

                                                        * Note: Because a StyleRange includes the start and length, the * same instance cannot occur multiple times in the array of styles. @@ -6316,14 +6472,14 @@ * 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 + * 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 + * 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
                                                          @@ -6331,33 +6487,33 @@ *
                                                        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                        • *
                                                        * @exception IllegalArgumentException
                                                          - *
                                                        • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
                                                        • - *
                                                        • ERROR_NULL_ARGUMENT when ranges is null
                                                        • - *
                                                        - * + *
                                                      • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
                                                      • + *
                                                      + * * @since 2.0 - * + * * @see #setStyleRanges(int, int, int[], StyleRange[]) */ public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { checkWidget(); if (isListening(LineGetStyle)) return; - if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + // DWT extension: allow null for zero length string + //if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); setStyleRanges(start, length, null, ranges, false); } /** * Replaces the given text range with new text. - * If the widget has the DWT.SINGLE style and "text" contains more than - * one line, only the first line is rendered but the text is stored - * unchanged. A subsequent call to getText will return the same text - * that was set. Note that only a single line of text should be set when + * If the widget has the DWT.SINGLE style and "text" contains more than + * one line, only the first line is rendered but the text is stored + * unchanged. A subsequent call to getText will return the same text + * that was set. Note that only a single line of text should be set when * the DWT.SINGLE style is used. *

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

                                                        + *
                                                          *
                                                        • selection before replaced text: selection unchanged - *
                                                        • selection after replaced text: adjust the selection so that same text + *
                                                        • selection after replaced text: adjust the selection so that same text * remains selected *
                                                        • selection intersects replaced text: selection is cleared and caret * is placed after inserted text @@ -6372,17 +6528,17 @@ *
                                                        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                        • *
                                                        * @exception IllegalArgumentException
                                                          - *
                                                        • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
                                                        • - *
                                                        • ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. - * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported
                                                        • - *
                                                        • ERROR_NULL_ARGUMENT when String is null
                                                        • + *
                                                        • ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
                                                        • + *
                                                        • ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. + * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported
                                                        • *
                                                        */ public void replaceTextRange(int start, int length, String text) { checkWidget(); - if (text is null) { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } + // DWT extension: allow null for zero length string +// if (text is null) { +// DWT.error(DWT.ERROR_NULL_ARGUMENT); +// } int contentLength = getCharCount(); int end = start + length; if (start > end || start < 0 || end > contentLength) { @@ -6405,14 +6561,14 @@ topIndex = 0; topIndexY = 0; verticalScrollOffset = 0; - horizontalScrollOffset = 0; + horizontalScrollOffset = 0; resetSelection(); renderer.setContent(content); if (verticalBar !is null) { verticalBar.setSelection(0); } if (horizontalBar !is null) { - horizontalBar.setSelection(0); + horizontalBar.setSelection(0); } resetCache(0, 0); setCaretLocation(); @@ -6441,7 +6597,7 @@ selectionAnchor = -1; } -public void scroll(int destX, int destY, int x, int y, int width, int height, bool all) { +public override void scroll(int destX, int destY, int x, int y, int width, int height, bool all) { super.scroll(destX, destY, x, y, width, height, false); if (all) { int deltaX = destX - x, deltaY = destY - y; @@ -6459,11 +6615,11 @@ * * @param pixels number of pixels to scroll, > 0 = scroll left, * < 0 scroll right - * @param adjustScrollBar + * @param adjustScrollBar * true= the scroll thumb will be moved to reflect the new scroll offset. * false = the scroll thumb will not be moved - * @return - * true=the widget was scrolled + * @return + * true=the widget was scrolled * false=the widget was not scrolled, the given offset is not valid. */ bool scrollHorizontal(int pixels, bool adjustScrollBar) { @@ -6502,11 +6658,11 @@ * Scrolls the widget vertically. * * @param pixel the new vertical scroll offset - * @param adjustScrollBar + * @param adjustScrollBar * true= the scroll thumb will be moved to reflect the new scroll offset. * false = the scroll thumb will not be moved - * @return - * true=the widget was scrolled + * @return + * true=the widget was scrolled * false=the widget was not scrolled */ bool scrollVertical(int pixels, bool adjustScrollBar) { @@ -6574,7 +6730,7 @@ super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false); } } -/** +/** * Selects all the text. * * @exception DWTException
                                                          @@ -6589,7 +6745,7 @@ /** * Replaces/inserts text as defined by the event. * - * @param event the text change event. + * @param event the text change event. *
                                                            *
                                                          • event.start - the replace start offset
                                                          • *
                                                          • event.end - the replace end offset
                                                          • @@ -6602,19 +6758,19 @@ } } /** - * Returns a StyledTextEvent that can be used to request data such + * Returns a StyledTextEvent that can be used to request data such * as styles and background color for a line. *

                                                            - * The specified line may be a visual (wrapped) line if in word - * wrap mode. The returned object will always be for a logical + * 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 + * @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 + * @return StyledTextEvent that can be used to request line data * for the given line. */ StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { @@ -6632,14 +6788,14 @@ } void sendModifyEvent(Event event) { Accessible accessible = getAccessible(); - if (event.text.length() is 0) { + 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()); + 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()); + accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length); } } notifyListeners(DWT.Modify, event); @@ -6681,22 +6837,22 @@ return newOffset; } /** - * Sets the alignment of the widget. The argument should be one of DWT.LEFT, + * Sets the alignment of the widget. The argument should be one of DWT.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. *

                                                            - * + * * @param alignment the new alignment - * - * @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 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 #setLineAlignment(int, int, int) - * + * * @since 3.2 */ public void setAlignment(int alignment) { @@ -6711,7 +6867,7 @@ /** * @see Control#setBackground(Color) */ -public void setBackground(Color color) { +public override void setBackground(Color color) { checkWidget(); background = color; super.setBackground(color); @@ -6719,7 +6875,7 @@ } /** * Sets the receiver's caret. Set the caret's height and location. - * + * *

                                                            * @param caret the new caret for the receiver * @@ -6728,7 +6884,7 @@ *
                                                          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                          • *
                                                          */ -public void setCaret(Caret caret) { +public override void setCaret(Caret caret) { checkWidget (); super.setCaret(caret); caretDirection = DWT.NULL; @@ -6746,7 +6902,7 @@ *
                                                        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                        • *
                                                        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                        • *
                                                        - * + * * @deprecated use BidiSegmentListener instead. */ public void setBidiColoring(bool mode) { @@ -6818,7 +6974,7 @@ *
                                                      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                      • *
                                                      * @exception IllegalArgumentException
                                                        - *
                                                      • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + *
                                                      • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) *
                                                      */ @@ -6832,7 +6988,7 @@ caretOffset = length; } else { if (isLineDelimiter(offset)) { - // offset is inside a multi byte line delimiter. This is an + // offset is inside a multi byte line delimiter. This is an // illegal operation and an exception is thrown. Fixes 1GDKK3R DWT.error(DWT.ERROR_INVALID_ARGUMENT); } @@ -6844,14 +7000,14 @@ clearSelection(false); } setCaretLocation(); -} +} /** * Copies the specified text range to the clipboard. The text will be placed * in the clipboard in plain text format and RTF format. * * @param start start index of the text * @param length length of text to place in clipboard - * + * * @exception DWTError, see Clipboard.setContents * @see dwt.dnd.Clipboard#setContents */ @@ -6863,14 +7019,14 @@ Object[] data; Transfer[] types; if (clipboardType is DND.SELECTION_CLIPBOARD) { - data = new Object[]{plainText}; - types = new Transfer[]{plainTextTransfer}; + data = [ cast(Object) new ArrayWrapperString(plainText) ]; + types = [plainTextTransfer]; } else { RTFTransfer rtfTransfer = RTFTransfer.getInstance(); RTFWriter rtfWriter = new RTFWriter(start, length); String rtfText = getPlatformDelimitedText(rtfWriter); - data = new Object[]{rtfText, plainText}; - types = new Transfer[]{rtfTransfer, plainTextTransfer}; + data = [ cast(Object) new ArrayWrapperString(rtfText), new ArrayWrapperString(plainText) ]; + types = [ cast(Transfer)rtfTransfer, plainTextTransfer]; } clipboard.setContents(data, types, clipboardType); } @@ -6887,7 +7043,7 @@ *
                                                    */ public void setContent(StyledTextContent newContent) { - checkWidget(); + checkWidget(); if (newContent is null) { DWT.error(DWT.ERROR_NULL_ARGUMENT); } @@ -6900,12 +7056,12 @@ } /** * Sets the receiver's cursor to the cursor specified by the - * argument. Overridden to handle the null case since the + * argument. Overridden to handle the null case since the * StyledText widget uses an ibeam as its default cursor. * * @see Control#setCursor(Cursor) */ -public void setCursor (Cursor cursor) { +public override void setCursor (Cursor cursor) { if (cursor is null) { Display display = getDisplay(); super.setCursor(display.getSystemCursor(DWT.CURSOR_IBEAM)); @@ -6913,7 +7069,7 @@ super.setCursor(cursor); } } -/** +/** * Sets whether the widget : double click mouse behavior. *

                                                    * @@ -6928,15 +7084,15 @@ checkWidget(); doubleClickEnabled = enable; } -public void setDragDetect (bool dragDetect) { +public override void setDragDetect (bool dragDetect_) { checkWidget (); - this.dragDetect = dragDetect; + this.dragDetect_ = dragDetect_; } /** * Sets whether the widget content can be edited. *

                                                    * - * @param editable if true content can be edited, if false content can not be + * @param editable if true content can be edited, if false content can not be * edited * @exception DWTException
                                                      *
                                                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                    • @@ -6960,10 +7116,10 @@ *
                                                    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                    • *
                                                    */ -public void setFont(Font font) { +public override void setFont(Font font) { checkWidget(); int oldLineHeight = renderer.getLineHeight(); - super.setFont(font); + super.setFont(font); renderer.setFont(getFont(), tabLength); // keep the same top line visible. fixes 5815 if (isFixedLineHeight()) { @@ -6974,32 +7130,29 @@ } } resetCache(0, content.getLineCount()); - claimBottomFreeSpace(); + claimBottomFreeSpace(); calculateScrollBars(); if (isBidiCaret()) createCaretBitmaps(); caretDirection = DWT.NULL; setCaretLocation(); super.redraw(); } -/** - * @see dwt.widgets.Control#setForeground - */ -public void setForeground(Color color) { +public override void setForeground(Color color) { checkWidget(); foreground = color; super.setForeground(getForeground()); super.redraw(); } -/** +/** * Sets the horizontal scroll offset relative to the start of the line. * Do nothing if there is no text set. *

                                                    - * NOTE: The horizontal index is reset to 0 when new text is set in the + * 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 + * @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
                                                      *
                                                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                    • @@ -7010,14 +7163,14 @@ checkWidget(); if (getCharCount() is 0) { return; - } + } if (offset < 0) { offset = 0; } offset *= getHorizontalIncrement(); - // allow any value if client area width is unknown or 0. + // allow any value if client area width is unknown or 0. // offset will be checked in resize handler. - // don't use isVisible since width is known even if widget + // don't use isVisible since width is known even if widget // is temporarily invisible if (clientAreaWidth > 0) { int width = renderer.getWidth(); @@ -7030,15 +7183,15 @@ } scrollHorizontal(offset - horizontalScrollOffset, true); } -/** +/** * Sets the horizontal pixel offset relative to the start of the line. * Do nothing if there is no text set. *

                                                      - * NOTE: The horizontal pixel offset is reset to 0 when new text + * 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 + * @param pixel horizontal pixel offset relative to the start * of the line. * @exception DWTException
                                                        *
                                                      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                      • @@ -7050,13 +7203,13 @@ checkWidget(); if (getCharCount() is 0) { return; - } + } if (pixel < 0) { pixel = 0; } - // allow any value if client area width is unknown or 0. + // allow any value if client area width is unknown or 0. // offset will be checked in resize handler. - // don't use isVisible since width is known even if widget + // don't use isVisible since width is known even if widget // is temporarily invisible if (clientAreaWidth > 0) { int width = renderer.getWidth(); @@ -7072,19 +7225,19 @@ /** * Sets the line indentation of the widget. *

                                                        - * It is the amount of blank space, in pixels, at the beginning of each line. - * When a line wraps in several lines only the first one is indented. + * 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
                                                          - *
                                                        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                        • - *
                                                        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                        • - *
                                                        - * + * + * @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 #setLineIndent(int, int, int) - * + * * @since 3.2 */ public void setIndent(int indent) { @@ -7093,20 +7246,20 @@ this.indent = indent; resetCache(0, content.getLineCount()); setCaretLocation(); - super.redraw(); -} -/** - * Sets whether the widget should justify lines. - * + super.redraw(); +} +/** + * Sets whether the widget should justify lines. + * * @param justify whether lines should be justified - * - * @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 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 #setLineJustify(int, int, bool) - * + * * @since 3.2 */ public void setJustify(bool justify) { @@ -7115,21 +7268,21 @@ this.justify = justify; resetCache(0, content.getLineCount()); setCaretLocation(); - super.redraw(); -} -/** + super.redraw(); +} +/** * Maps a key to an action. *

                                                        - * One action can be associated with N keys. However, each key can only + * 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. + * @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 + * 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. + * @param action one of the predefined actions defined in ST.java. * Use DWT.NULL to remove a key binding. * @exception DWTException
                                                          *
                                                        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                        • @@ -7139,58 +7292,58 @@ public void setKeyBinding(int key, int action) { checkWidget(); int modifierValue = key & DWT.MODIFIER_MASK; - char keyChar = cast(wchar)(key & DWT.KEY_MASK); + char keyChar = cast(char)(key & DWT.KEY_MASK); if (Compatibility.isLetter(keyChar)) { // make the keybinding case insensitive by adding it // in its upper and lower case form - char ch = Character.toUpperCase(keyChar); + char ch = CharacterToUpper(keyChar); int newKey = ch | modifierValue; if (action is DWT.NULL) { - keyActionMap.remove(new Integer(newKey)); + keyActionMap.remove(newKey); } else { - keyActionMap.put(new Integer(newKey), new Integer(action)); - } - ch = Character.toLowerCase(keyChar); + keyActionMap[newKey] = action; + } + ch = CharacterToLower(keyChar); newKey = ch | modifierValue; if (action is DWT.NULL) { - keyActionMap.remove(new Integer(newKey)); + keyActionMap.remove(newKey); } else { - keyActionMap.put(new Integer(newKey), new Integer(action)); + keyActionMap[newKey] = action; } } else { if (action is DWT.NULL) { - keyActionMap.remove(new Integer(key)); + keyActionMap.remove(key); } else { - keyActionMap.put(new Integer(key), new Integer(action)); - } - } -} -/** - * Sets the alignment of the specified lines. The argument should be one of DWT.LEFT, + keyActionMap[key]=action; + } + } +} +/** + * Sets the alignment of the specified lines. The argument should be one of DWT.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. *

                                                          - * Should not be called if a LineStyleListener has been set since the listener + * 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 + * 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. + * 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. - * + * 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

                                                            *
                                                          • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                          • *
                                                          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                          • @@ -7216,30 +7369,30 @@ setCaretLocation(); } } -/** +/** * Sets the background color of the specified lines. *

                                                            * The background color is drawn for the width of the widget. All * line background colors are discarded when setText is called. - * The text background color if defined in a StyleRange overlays the - * line background color. + * 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 + * 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 + * 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. + * 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. + * 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 @@ -7252,7 +7405,7 @@ *
                                                          */ public void setLineBackground(int startLine, int lineCount, Color background) { - checkWidget(); + checkWidget(); if (isListening(LineGetBackground)) return; if (startLine < 0 || startLine + lineCount > content.getLineCount()) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); @@ -7267,26 +7420,26 @@ /** * Sets the bullet of the specified lines. *

                                                          - * Should not be called if a LineStyleListener has been set since the listener + * 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 + * 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. + * 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. + * 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
                                                            *
                                                          • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                          • *
                                                          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                          • @@ -7298,7 +7451,7 @@ */ public void setLineBullet(int startLine, int lineCount, Bullet bullet) { checkWidget(); - if (isListening(LineGetStyle)) return; + if (isListening(LineGetStyle)) return; if (startLine < 0 || startLine + lineCount > content.getLineCount()) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); } @@ -7319,26 +7472,26 @@ /** * Sets the indent of the specified lines. *

                                                            - * Should not be called if a LineStyleListener has been set since the listener + * 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 + * 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. + * 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. + * 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
                                                              *
                                                            • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                            • *
                                                            • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                            • @@ -7367,26 +7520,26 @@ /** * Sets the justify of the specified lines. *

                                                              - * Should not be called if a LineStyleListener has been set since the listener + * 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 + * 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. + * 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. + * 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 DWTException
                                                                *
                                                              • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                              • *
                                                              • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                              • @@ -7414,7 +7567,7 @@ } /** * Sets the line spacing of the widget. The line spacing applies for all lines. - * + * * @param lineSpacing the line spacing * @exception DWTException
                                                                  *
                                                                • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                                • @@ -7425,7 +7578,7 @@ public void setLineSpacing(int lineSpacing) { checkWidget(); if (this.lineSpacing is lineSpacing || lineSpacing < 0) return; - this.lineSpacing = lineSpacing; + this.lineSpacing = lineSpacing; setVariableLineHeight(); resetCache(0, content.getLineCount()); setCaretLocation(); @@ -7456,43 +7609,43 @@ * of the constants DWT.LEFT_TO_RIGHT or DWT.RIGHT_TO_LEFT. * * @param orientation new orientation style - * - * @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 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.2 */ public void setOrientation(int orientation) { - if ((orientation & (DWT.RIGHT_TO_LEFT | DWT.LEFT_TO_RIGHT)) is 0) { + if ((orientation & (DWT.RIGHT_TO_LEFT | DWT.LEFT_TO_RIGHT)) is 0) { return; } if ((orientation & DWT.RIGHT_TO_LEFT) !is 0 && (orientation & DWT.LEFT_TO_RIGHT) !is 0) { - return; + return; } if ((orientation & DWT.RIGHT_TO_LEFT) !is 0 && isMirrored()) { - return; - } + return; + } if ((orientation & DWT.LEFT_TO_RIGHT) !is 0 && !isMirrored()) { return; } if (!BidiUtil.setOrientation(this, orientation)) { return; } - isMirrored = (orientation & DWT.RIGHT_TO_LEFT) !is 0; + isMirrored_ = (orientation & DWT.RIGHT_TO_LEFT) !is 0; caretDirection = DWT.NULL; resetCache(0, content.getLineCount()); setCaretLocation(); - keyActionMap.clear(); + keyActionMap = null; createKeyBindings(); super.redraw(); } /** - * Adjusts the maximum and the page size of the scroll bars to + * Adjusts the maximum and the page size of the scroll bars to * reflect content width/length changes. - * - * @param vertical indicates if the vertical scrollbar also needs to be set + * + * @param vertical indicates if the vertical scrollbar also needs to be set */ void setScrollBars(bool vertical) { int inactive = 1; @@ -7500,7 +7653,7 @@ ScrollBar verticalBar = getVerticalBar(); if (verticalBar !is null) { int maximum = renderer.getHeight(); - // only set the real values if the scroll bar can be used + // only set the real values if the scroll bar can be used // (ie. because the thumb size is less than the scroll maximum) // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 if (clientAreaHeight < maximum) { @@ -7521,7 +7674,7 @@ ScrollBar horizontalBar = getHorizontalBar(); if (horizontalBar !is null && horizontalBar.getVisible()) { int maximum = renderer.getWidth(); - // only set the real values if the scroll bar can be used + // only set the real values if the scroll bar can be used // (ie. because the thumb size is less than the scroll maximum) // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 if (clientAreaWidth < maximum) { @@ -7539,7 +7692,7 @@ } } } -/** +/** * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). * * @param start new caret position @@ -7549,19 +7702,19 @@ *
                                                                • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                                • *
                                                                * @exception IllegalArgumentException
                                                                  - *
                                                                • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + *
                                                                • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) - *
                                                                + *
                                                              */ public void setSelection(int start) { - // checkWidget test done in setSelectionRange + // checkWidget test done in setSelectionRange setSelection(start, start); } -/** +/** * Sets the selection and scrolls it into view. *

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

                                                              * @@ -7574,13 +7727,13 @@ *
                                                            * @exception IllegalArgumentException
                                                              *
                                                            • ERROR_NULL_ARGUMENT when point is null
                                                            • - *
                                                            • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + *
                                                            • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) - *
                                                            + *
                                                          */ public void setSelection(Point point) { checkWidget(); - if (point is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + if (point is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); setSelection(point.x, point.y); } /** @@ -7591,7 +7744,7 @@ * @param color the new color (or null) * * @exception IllegalArgumentException
                                                            - *
                                                          • ERROR_INVALID_ARGUMENT - if the argument has been disposed
                                                          • + *
                                                          • ERROR_INVALID_ARGUMENT - if the argument has been disposed
                                                          • *
                                                          * @exception DWTException
                                                            *
                                                          • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                          • @@ -7610,7 +7763,7 @@ /** * Sets the receiver's selection foreground color to the color specified * by the argument, or to the default system color for the control - * if the argument is null. + * if the argument is null. *

                                                            * Note that this is a HINT. Some platforms do not allow the application * to change the selection foreground color. @@ -7618,7 +7771,7 @@ * @param color the new color (or null) * * @exception IllegalArgumentException

                                                              - *
                                                            • ERROR_INVALID_ARGUMENT - if the argument has been disposed
                                                            • + *
                                                            • ERROR_INVALID_ARGUMENT - if the argument has been disposed
                                                            • *
                                                            * @exception DWTException
                                                              *
                                                            • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                            • @@ -7634,15 +7787,15 @@ selectionForeground = color; super.redraw(); } -/** +/** * Sets the selection and scrolls it into view. *

                                                              * Indexing is zero based. Text selections are specified in terms of - * caret positions. In a text widget that contains N characters, there are + * 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 + * @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) @@ -7651,7 +7804,7 @@ *
                                                            • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                            • *
                                                            * @exception IllegalArgumentException
                                                              - *
                                                            • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + *
                                                            • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) *
                                                            */ @@ -7659,31 +7812,33 @@ setSelectionRange(start, end - start); showSelection(); } -/** +/** * Sets the selection. *

                                                            - * The new selection may not be visible. Call showSelection to scroll + * 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. + * @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 + * @param sendEvent a Selection event is sent when set to true and when * the selection is reset. */ void setSelection(int start, int length, bool sendEvent) { int end = start + length; + start = content.utf8AdjustOffset(start); + end = content.utf8AdjustOffset(end); if (start > end) { int temp = end; end = start; start = temp; } - // is the selection range different or is the selection direction + // 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) || + 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) { @@ -7697,7 +7852,7 @@ internalRedrawRange(selection.x, selection.y - selection.x); } } -/** +/** * Sets the selection. *

                                                            * The new selection may not be visible. Call showSelection to scroll the selection @@ -7706,13 +7861,13 @@ * * @param start offset of the first selected character * @param length number of characters to select - * + * * @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_INVALID_ARGUMENT when either the start or the end of the selection range is inside a + *
                                                            • ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter) *
                                                            */ @@ -7727,23 +7882,23 @@ if (end > contentLength) length = contentLength - start; } if (isLineDelimiter(start) || isLineDelimiter(start + length)) { - // the start offset or end offset of the selection range is inside a - // multi byte line delimiter. This is an illegal operation and an exception + // the start offset or end offset of the selection range is inside a + // multi byte line delimiter. This is an illegal operation and an exception // is thrown. Fixes 1GDKK3R DWT.error(DWT.ERROR_INVALID_ARGUMENT); } setSelection(start, length, false); setCaretLocation(); } -/** +/** * Adds the specified style. *

                                                            * The new style overwrites existing styles for the specified range. - * Existing style ranges are adjusted if they partially overlap with - * the new style. To clear an individual style, call setStyleRange - * with a StyleRange that has null attributes. + * 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 + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. *

                                                            * @@ -7755,7 +7910,7 @@ *
                                                          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                          • *
                                                          * @exception IllegalArgumentException
                                                            - *
                                                          • ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())
                                                          • + *
                                                          • ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())
                                                          • *
                                                          */ public void setStyleRange(StyleRange range) { @@ -7765,14 +7920,14 @@ if (range.isUnstyled()) { setStyleRanges(range.start, range.length, null, null, false); } else { - setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false); + setStyleRanges(range.start, 0, null, [range], false); } } else { setStyleRanges(0, 0, null, null, true); } } -/** - * Clears the styles in the range specified by start and +/** + * Clears the styles in the range specified by start and * length and adds the new styles. *

                                                          * The ranges array contains start and length pairs. Each pair refers to @@ -7784,7 +7939,7 @@ * 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 + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. *

                                                          * @@ -7792,19 +7947,19 @@ * @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
                                                            *
                                                          • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                          • *
                                                          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                          • *
                                                          * @exception IllegalArgumentException
                                                            *
                                                          • ERROR_NULL_ARGUMENT when an element in the styles array is null
                                                          • - *
                                                          • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)
                                                          • - *
                                                          • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
                                                          • - *
                                                          • ERROR_INVALID_RANGE when a range overlaps
                                                          • - *
                                                          - * - * @since 3.2 + *
                                                        • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)
                                                        • + *
                                                        • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
                                                        • + *
                                                        • ERROR_INVALID_RANGE when a range overlaps
                                                        • + *
                                                        + * + * @since 3.2 */ public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) { checkWidget(); @@ -7815,7 +7970,7 @@ setStyleRanges(start, length, ranges, styles, false); } } -/** +/** * Sets styles to be used for rendering the widget content. *

                                                        * All styles in the widget will be replaced with the given set of ranges and styles. @@ -7828,25 +7983,25 @@ * 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 + * 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
                                                          *
                                                        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                        • *
                                                        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                        • *
                                                        * @exception IllegalArgumentException
                                                          *
                                                        • ERROR_NULL_ARGUMENT when an element in the styles array is null
                                                        • - *
                                                        • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)
                                                        • - *
                                                        • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
                                                        • - *
                                                        • ERROR_INVALID_RANGE when a range overlaps
                                                        • - *
                                                        - * - * @since 3.2 + *
                                                      • ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)
                                                      • + *
                                                      • ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
                                                      • + *
                                                      • ERROR_INVALID_RANGE when a range overlaps
                                                      • + *
                                                      + * + * @since 3.2 */ public void setStyleRanges(int[] ranges, StyleRange[] styles) { checkWidget(); @@ -7871,7 +8026,7 @@ if (ranges.length !is styles.length << 1) DWT.error(DWT.ERROR_INVALID_ARGUMENT); } int lastOffset = 0; - bool variableHeight = false; + bool variableHeight = false; for (int i = 0; i < styles.length; i ++) { if (styles[i] is null) DWT.error(DWT.ERROR_INVALID_ARGUMENT); int rangeStart, rangeLength; @@ -7882,7 +8037,7 @@ rangeStart = styles[i].start; rangeLength = styles[i].length; } - if (rangeLength < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + if (rangeLength < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); if (lastOffset > rangeStart) DWT.error(DWT.ERROR_INVALID_ARGUMENT); variableHeight |= styles[i].isVariableHeight(); @@ -7941,13 +8096,13 @@ } height = newLastLineBottom - y; } - super.redraw(0, y, clientAreaWidth, height, false); + super.redraw(0, y, clientAreaWidth, height, false); } } setCaretLocation(); } -/** - * Sets styles to be used for rendering the widget content. All styles +/** + * Sets styles to be used for rendering the widget content. All styles * in the widget will be replaced with the given set of styles. *

                                                      * Note: Because a StyleRange includes the start and length, the @@ -7956,32 +8111,32 @@ * 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 + * 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 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
                                                        *
                                                      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                      • *
                                                      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                      • *
                                                      * @exception IllegalArgumentException
                                                        - *
                                                      • ERROR_NULL_ARGUMENT when the list of ranges is null
                                                      • - *
                                                      • ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())
                                                      • - *
                                                      - * + *
                                                    • ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())
                                                    • + *
                                                    + * * @see #setStyleRanges(int[], StyleRange[]) */ public void setStyleRanges(StyleRange[] ranges) { checkWidget(); if (isListening(LineGetStyle)) return; - if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + // DWT extension: allow null for zero length string + //if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); setStyleRanges(0, 0, null, ranges, true); } -/** - * Sets the tab width. +/** + * Sets the tab width. * * @param tabs tab width measured in characters. * @exception DWTException
                                                      @@ -7990,56 +8145,54 @@ *
                                                    */ public void setTabs(int tabs) { - checkWidget(); + checkWidget(); tabLength = tabs; renderer.setFont(null, tabs); resetCache(0, content.getLineCount()); setCaretLocation(); super.redraw(); } -/** - * Sets the widget content. - * If the widget has the DWT.SINGLE style and "text" contains more than - * one line, only the first line is rendered but the text is stored - * unchanged. A subsequent call to getText will return the same text +/** + * Sets the widget content. + * If the widget has the DWT.SINGLE style and "text" contains more than + * one line, only the first line is rendered but the text is stored + * unchanged. A subsequent call to getText will return the same text * that was set. *

                                                    - * Note: Only a single line of text should be set when the DWT.SINGLE + * 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 + * @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
                                                      *
                                                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                    • *
                                                    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                    • *
                                                    - * @exception IllegalArgumentException
                                                      - *
                                                    • ERROR_NULL_ARGUMENT when String is null
                                                    • - *
                                                    */ public void setText(String text) { checkWidget(); - if (text is null) { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } + // DWT extension: allow null for zero length string +// if (text is null) { +// DWT.error(DWT.ERROR_NULL_ARGUMENT); +// } Event event = new Event(); event.start = 0; event.end = getCharCount(); event.text = text; - event.doit = true; + event.doit = true; notifyListeners(DWT.Verify, event); if (event.doit) { StyledTextEvent styledTextEvent = null; if (isListening(ExtendedModify)) { styledTextEvent = new StyledTextEvent(content); styledTextEvent.start = event.start; - styledTextEvent.end = event.start + event.text.length(); + styledTextEvent.end = event.start + event.text.length; styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); } content.setText(event.text); - sendModifyEvent(event); + sendModifyEvent(event); if (styledTextEvent !is null) { notifyListeners(ExtendedModify, styledTextEvent); } @@ -8071,15 +8224,15 @@ /** * Sets the top index. Do nothing if there is no text set. *

                                                    - * The top index is the index of the line that is currently at the top + * 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 + * @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
                                                      *
                                                    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
                                                    • @@ -8108,7 +8261,7 @@ } else { pixel = getAvailableHeightAbove(pixel); } - } + } scrollVertical(pixel, true); } /** @@ -8120,7 +8273,7 @@ * 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 + * @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
                                                        @@ -8133,7 +8286,7 @@ checkWidget(); if (getCharCount() is 0) { return; - } + } if (pixel < 0) pixel = 0; int lineCount = content.getLineCount(); int height = clientAreaHeight - topMargin - bottomMargin; @@ -8141,7 +8294,7 @@ if (isFixedLineHeight()) { int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); if (pixel > maxTopPixel) pixel = maxTopPixel; - pixel -= verticalOffset; + pixel -= verticalOffset; } else { pixel -= verticalOffset; if (pixel > 0) { @@ -8175,6 +8328,7 @@ setCaretLocation(); super.redraw(); } +// DWT: If necessary, scroll to show the location bool showLocation(Rectangle rect, bool scrollPage) { int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin; int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; @@ -8236,10 +8390,10 @@ startOffset = selection.x; endOffset = selection.y; } - + Rectangle startBounds = getBoundsAtOffset(startOffset); Rectangle endBounds = getBoundsAtOffset(endOffset); - + // can the selection be fully displayed within the widget's visible width? int w = clientAreaWidth - leftMargin - rightMargin; bool selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w; @@ -8254,7 +8408,7 @@ endBounds.width = 0; showLocation(endBounds, false); } else { - // just show the end of the selection since the selection start + // just show the end of the selection since the selection start // will not be visible showLocation(endBounds, true); } @@ -8262,10 +8416,10 @@ /** * Updates the selection and caret position depending on the text change. *

                                                        - * If the selection intersects with the replaced text, the selection is + * 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 + * same text remains selected. If the selection is before the replaced text * it is left unchanged. *

                                                        * @@ -8276,6 +8430,7 @@ void updateSelection(int startOffset, int replacedLength, int newLength) { if (selection.y <= startOffset) { // selection ends before text change + if (wordWrap) setCaretLocation(); return; } if (selection.x < startOffset) { @@ -8284,7 +8439,7 @@ } 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 + // 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; diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/StyledTextContent.d --- a/dwt/custom/StyledTextContent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyledTextContent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,15 +7,19 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyledTextContent; +import dwt.dwthelper.utils; +import dwt.custom.TextChangeListener; /** - * 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. + * 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. */ @@ -46,8 +50,8 @@ * 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 + * @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 */ @@ -57,12 +61,12 @@ * 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. + * @param offset offset of the line to return. The first character of the + * document is at offset 0. An offset of getLength() is valid and should + * answer the number of lines. + * @return the line index. The first line is at index 0. If the character + * at offset is a delimiter character, answer the line index of the line + * that is delimited. * For example, if text = "\r\n\r\n", and delimiter = "\r\n", then: *

                                                          *
                                                        • getLineAtOffset(0) is 0 @@ -81,18 +85,18 @@ * * @return the number of lines. For example: *
                                                            - *
                                                          • text value ==> getLineCount - *
                                                          • null ==> 1 - *
                                                          • "" ==> 1 - *
                                                          • "a\n" ==> 2 - *
                                                          • "\n\n" ==> 3 + *
                                                          • text value is> getLineCount + *
                                                          • null is> 1 + *
                                                          • "" is> 1 + *
                                                          • "a\n" is> 2 + *
                                                          • "\n\n" is> 3 *
                                                          */ public int getLineCount(); /** - * Return the line delimiter that should be used by the StyledText - * widget when inserting new lines. New lines entered using key strokes + * Return the line delimiter that should be used by the StyledText + * widget when inserting new lines. New lines entered using key strokes * and paste operations use this line delimiter. * Implementors may use System.getProperty("line.separator") to return * the platform line delimiter. @@ -106,14 +110,14 @@ /** * Return the character offset of the first character of the given line. *

                                                          - * NOTE: When there is no text (i.e., no lines), getOffsetAtLine(0) + * 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. + * @return offset offset of the first character of the line. The first + * character of the document is at offset 0. The return value should + * include line delimiters. * For example, if text = "\r\ntest\r\n" and delimiter = "\r\n", then: *
                                                            *
                                                          • getOffsetAtLine(0) is 0 @@ -124,10 +128,10 @@ public int getOffsetAtLine(int lineIndex); /** - * Returns a String representing the content at the given range. + * Returns a string representing the content at the given range. *

                                                            * - * @param start the start offset of the text to return. Offset 0 is the + * @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 @@ -138,7 +142,8 @@ * Remove the specified text changed listener. *

                                                            * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @exception IllegalArgumentException

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

                                                            - * Implementors have to notify the TextChangeListeners that were added - * using addTextChangeListener before and after the content - * is changed. A TextChangingEvent has to be sent to the - * textChanging method before the content is changed and a + * 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 + * 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 + * This data will be cached by the widget and will be used when the * TextChangedEvent is received. *

                                                            * The TextChangingEvent should be set as follows: *

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

                                                            * - * @param start start offset of text to replace, none of the offsets include - * delimiters of preceding lines, offset 0 is the first character of the - * document + * @param start start offset of text to replace, none of the offsets include + * delimiters of preceding lines, offset 0 is the first character of the + * document * @param replaceLength length of text to replace * @param text text to replace * @see TextChangeListener @@ -194,8 +199,8 @@ /** * Set text to "text". - * Implementors have to send a TextChangedEvent to the - * textSet method of the TextChangeListeners that were added using + * Implementors have to send a TextChangedEvent to the + * textSet method of the TextChangeListeners that were added using * addTextChangeListener. *

                                                            * @@ -203,4 +208,10 @@ * @see TextChangeListener */ public void setText(String text); + +/++ + + DWT Extension + +/ +int utf8AdjustOffset( int offset ); + } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/StyledTextDropTargetEffect.d --- a/dwt/custom/StyledTextDropTargetEffect.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyledTextDropTargetEffect.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,31 +7,46 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyledTextDropTargetEffect; + -import dwt.*; -import dwt.dnd.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.dnd.DND; +import dwt.dnd.DropTargetAdapter; +import dwt.dnd.DropTargetEffect; +import dwt.dnd.DropTargetEvent; +import dwt.graphics.FontMetrics; +import dwt.graphics.GC; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Event; +import dwt.widgets.Listener; +import dwt.custom.StyledText; +import dwt.custom.StyledTextContent; + +static import tango.core.Exception; +import dwt.dwthelper.utils; /** - * This adapter class provides a default drag under effect (eg. select and scroll) + * 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 + * method and override any other applicable methods in StyledTextDropTargetEffect to * display their own drag under effect.

                                                            * * Subclasses that override any methods of this class should call the corresponding * 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 + *

                                                            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. + * of those DND effect constants. *

                                                            *

                                                            *

                                                            @@ -39,31 +54,32 @@ *
                                                            FEEDBACK_SELECT, FEEDBACK_SCROLL
                                                            *
                                                            *

                                                            - * + * * @see DropTargetAdapter * @see DropTargetEvent - * + * @see Sample code and further information + * * @since 3.3 */ public class StyledTextDropTargetEffect : DropTargetEffect { static final int CARET_WIDTH = 2; static final int SCROLL_HYSTERESIS = 100; // milli seconds static final int SCROLL_TOLERANCE = 20; // pixels - + int currentOffset = -1; long scrollBeginTime; int scrollX = -1, scrollY = -1; Listener paintListener; - + /** - * Creates a new StyledTextDropTargetEffect to handle the drag under effect on the specified + * Creates a new StyledTextDropTargetEffect to handle the drag under effect on the specified * StyledText. - * + * * @param styledText the StyledText over which the user positions the cursor to drop the data */ public this(StyledText styledText) { super(styledText); - paintListener = new Listener () { + paintListener = new class() Listener { public void handleEvent (Event event) { if (currentOffset !is -1) { StyledText text = cast(StyledText) getControl(); @@ -75,22 +91,22 @@ } }; } - + /** * 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) { + public override void dragEnter(DropTargetEvent event) { currentOffset = -1; scrollBeginTime = 0; scrollX = -1; @@ -98,22 +114,22 @@ 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) { + public override void dragLeave(DropTargetEvent event) { StyledText text = cast(StyledText) getControl(); if (currentOffset !is -1) { refreshCaret(text, currentOffset, -1); @@ -127,23 +143,23 @@ /** * 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) { + public override void dragOver(DropTargetEvent event) { int effect = event.feedback; StyledText text = cast(StyledText) getControl(); - + Point pt = text.getDisplay().map(null, text, event.x, event.y); if ((effect & DND.FEEDBACK_SCROLL) is 0) { scrollBeginTime = 0; @@ -190,7 +206,7 @@ } } } - + if ((effect & DND.FEEDBACK_SELECT) !is 0) { int[] trailing = new int [1]; int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false); @@ -220,18 +236,18 @@ /** * 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) { + public override void dropAccept(DropTargetEvent event) { if (currentOffset !is -1) { StyledText text = cast(StyledText) getControl(); text.setSelection(currentOffset); diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/StyledTextEvent.d --- a/dwt/custom/StyledTextEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyledTextEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * 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 @@ -7,15 +7,21 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyledTextEvent; + -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.graphics.Color; +import dwt.widgets.Event; +import dwt.custom.StyleRange; +import dwt.custom.Bullet; +import dwt.custom.StyledTextContent; /** * - */ + */ class StyledTextEvent : Event { // used by LineStyleEvent int[] ranges; @@ -28,10 +34,10 @@ // used by LineBackgroundEvent Color lineBackground; // used by BidiSegmentEvent - int[] segments; + int[] segments; // used by TextChangedEvent - int replaceCharCount; - int newCharCount; + int replaceCharCount; + int newCharCount; int replaceLineCount; int newLineCount; // used by PaintObjectEvent @@ -42,8 +48,7 @@ StyleRange style; this (StyledTextContent content) { - super(); - data = content; + data = cast(Object)content; } } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/StyledTextListener.d --- a/dwt/custom/StyledTextListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyledTextListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,36 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyledTextListener; + -import dwt.events.*; -import dwt.widgets.*; +import dwt.events.VerifyEvent; import dwt.internal.DWTEventListener; +import dwt.widgets.Event; +import dwt.widgets.TypedListener; +import dwt.custom.StyledText; +import dwt.custom.ExtendedModifyEvent; +import dwt.custom.ExtendedModifyListener; +import dwt.custom.StyledTextEvent; +import dwt.custom.LineBackgroundEvent; +import dwt.custom.BidiSegmentEvent; +import dwt.custom.LineStyleEvent; +import dwt.custom.PaintObjectEvent; +import dwt.custom.MovementEvent; +import dwt.custom.TextChangedEvent; +import dwt.custom.TextChangingEvent; +import dwt.custom.LineBackgroundListener; +import dwt.custom.BidiSegmentListener; +import dwt.custom.LineStyleListener; +import dwt.custom.PaintObjectListener; +import dwt.custom.VerifyKeyListener; +import dwt.custom.StyledTextContent; +import dwt.custom.TextChangeListener; +import dwt.custom.MovementListener; + class StyledTextListener : TypedListener { /** @@ -22,24 +46,26 @@ } /** * Process StyledText events by invoking the event's handler. + * + * @param e the event to handle */ -public void handleEvent(Event e) { - +public override void handleEvent(Event e) { + switch (e.type) { case StyledText.ExtendedModify: ExtendedModifyEvent extendedModifyEvent = new ExtendedModifyEvent(cast(StyledTextEvent) e); (cast(ExtendedModifyListener) eventListener).modifyText(extendedModifyEvent); - break; + break; case StyledText.LineGetBackground: LineBackgroundEvent lineBgEvent = new LineBackgroundEvent(cast(StyledTextEvent) e); (cast(LineBackgroundListener) eventListener).lineGetBackground(lineBgEvent); (cast(StyledTextEvent) e).lineBackground = lineBgEvent.lineBackground; - break; + break; case StyledText.LineGetSegments: BidiSegmentEvent segmentEvent = new BidiSegmentEvent(cast(StyledTextEvent) e); (cast(BidiSegmentListener) eventListener).lineGetSegments(segmentEvent); (cast(StyledTextEvent) e).segments = segmentEvent.segments; - break; + break; case StyledText.LineGetStyle: LineStyleEvent lineStyleEvent = new LineStyleEvent(cast(StyledTextEvent) e); (cast(LineStyleListener) eventListener).lineGetStyle(lineStyleEvent); @@ -54,7 +80,7 @@ case StyledText.PaintObject: PaintObjectEvent paintObjectEvent = new PaintObjectEvent(cast(StyledTextEvent) e); (cast(PaintObjectListener) eventListener).paintObject(paintObjectEvent); - break; + break; case StyledText.VerifyKey: VerifyEvent verifyEvent = new VerifyEvent(e); (cast(VerifyKeyListener) eventListener).verifyKey(verifyEvent); @@ -86,6 +112,7 @@ (cast(StyledTextEvent) e).end = wordBoundaryEvent.newOffset; break; } + default: } } } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/StyledTextPrintOptions.d --- a/dwt/custom/StyledTextPrintOptions.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyledTextPrintOptions.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,8 +7,12 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyledTextPrintOptions; + +import dwt.dwthelper.utils; /** * Use StyledTextPrintOptions to specify printing options for the @@ -20,13 +24,16 @@ *

                                                            *
                                                              * StyledTextPrintOptions options = new StyledTextPrintOptions();
                                                            - * options.footer = "\t\t<page>"; 
                                                            + * options.footer = "\t\t<page>";
                                                              * options.jobName = "Example";
                                                              * options.printLineBackground = true;
                                                            - * 
                                                            - * Runnable runnable = styledText.print(new Printer(), options); 
                                                            + *
                                                            + * Runnable runnable = styledText.print(new Printer(), options);
                                                              * runnable.run();
                                                              * 
                                                            + * + * @see Sample code and further information + * * @since 2.1 */ public class StyledTextPrintOptions { @@ -46,7 +53,7 @@ *

                                                            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 + * (StyledTextPrintOptions.PAGE_TAG). The three regions are * left aligned, centered and right aligned. They are separated by a tab * character (StyledTextPrintOptions.SEPARATOR). */ @@ -57,7 +64,7 @@ *

                                                            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 + * (StyledTextPrintOptions.PAGE_TAG). The three regions are * left aligned, centered and right aligned. They are separated by a tab * character (StyledTextPrintOptions.SEPARATOR). */ @@ -66,7 +73,7 @@ * Name of the print job. */ public String jobName = null; - + /** * Print the text foreground color. Default value is false. */ @@ -83,19 +90,19 @@ * 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 fbe68c33eeee -r 6337764516f1 dwt/custom/StyledTextRenderer.d --- a/dwt/custom/StyledTextRenderer.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyledTextRenderer.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,13 +7,44 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyledTextRenderer; + import dwt.DWT; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.graphics.Color; +import dwt.graphics.Device; +import dwt.graphics.Font; +import dwt.graphics.FontData; +import dwt.graphics.FontMetrics; +import dwt.graphics.GC; +import dwt.graphics.GlyphMetrics; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.graphics.TextLayout; +import dwt.graphics.TextStyle; +import dwt.widgets.Display; +import dwt.widgets.IME; +import dwt.widgets.ScrollBar; +import dwt.custom.StyledText; +import dwt.custom.Bullet; +import dwt.custom.StyleRange; +import dwt.custom.StyledText; +import dwt.custom.StyledTextContent; +import dwt.custom.TextChangingEvent; +import dwt.custom.ST; +import dwt.custom.StyledTextEvent; + +import dwt.dwthelper.Runnable; +import dwt.dwthelper.utils; + +static import tango.text.Text; +static import tango.text.Util; +static import tango.text.convert.Utf; +import tango.util.Convert; /** * A StyledTextRenderer renders the content of a StyledText widget. @@ -29,7 +60,7 @@ int tabWidth; int ascent, descent; int averageCharWidth; - + /* Line data */ int topIndex = -1; TextLayout[] layouts; @@ -40,33 +71,33 @@ int maxWidth; int maxWidthLineIndex; bool idleRunning; - + /* Bullet */ Bullet[] bullets; int[] bulletsIndices; int[] redrawLines; - + /* Style data */ int[] ranges; - int styleCount; + 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; @@ -88,7 +119,7 @@ } } } - + this(Device device, StyledText styledText) { this.device = device; this.styledText = styledText; @@ -121,7 +152,7 @@ } } if (MERGE_STYLES) { - int j = modifyStart; + 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]; @@ -222,7 +253,7 @@ } void calculateIdle () { if (idleRunning) return; - Runnable runnable = new Runnable() { + Runnable runnable = new class() Runnable { public void run() { if (styledText is null) return; int i; @@ -234,7 +265,7 @@ } } if (i < lineCount) { - Display display = styledText.getDisplay(); + Display display = styledText.getDisplay(); display.asyncExec(this); } else { idleRunning = false; @@ -242,10 +273,10 @@ ScrollBar bar = styledText.getVerticalBar(); if (bar !is null) { bar.setSelection(styledText.getVerticalScrollOffset()); - } + } } } - }; + }; Display display = styledText.getDisplay(); display.asyncExec(runnable); idleRunning = true; @@ -286,7 +317,7 @@ 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]); + newLines[i] = new LineInfo(lines[i]); } renderer.lineCount = lineCount; } @@ -328,24 +359,25 @@ } Font font = style.font; if (font !is null) gc.setFont(font); - String String = ""; + 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(cast(wchar) (index % 26 + 97)); break; - case ST.BULLET_LETTER_UPPER: String = String.valueOf(cast(wchar) (index % 26 + 65)); break; + case ST.BULLET_DOT: string = "\u2022"; break; + case ST.BULLET_NUMBER: string = to!(String)(index); break; + case ST.BULLET_LETTER_LOWER: string = [cast(char) (index % 26 + 97)]; break; + case ST.BULLET_LETTER_UPPER: string = [cast(char) (index % 26 + 65)]; break; + default: } - if ((bullet.type & ST.BULLET_TEXT) !is 0) String += bullet.text; + if ((bullet.type & ST.BULLET_TEXT) !is 0) string ~= bullet.text; Display display = styledText.getDisplay(); TextLayout layout = new TextLayout(display); - layout.setText(String); + layout.setText(string); layout.setAscent(lineAscent); layout.setDescent(lineDescent); style = cast(StyleRange)style.clone(); style.metrics = null; if (style.font is null) style.font = getFont(style.fontStyle); - layout.setStyle(style, 0, String.length()); + 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(); @@ -354,14 +386,15 @@ TextLayout layout = getTextLayout(lineIndex); String line = content.getLine(lineIndex); int lineOffset = content.getOffsetAtLine(lineIndex); - int lineLength = line.length(); + int lineLength = line.length; Point selection = styledText.getSelection(); int selectionStart = selection.x - lineOffset; int selectionEnd = selection.y - lineOffset; - Rectangle client = styledText.getClientArea(); + 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); @@ -389,7 +422,7 @@ } layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg, flags); } - + // draw objects Bullet bullet = null; int bulletIndex = -1; @@ -473,7 +506,7 @@ int height = lineHeight[i]; if (height is -1) { if (width > 0) { - int length = content.getLine(i).length(); + int length = content.getLine(i).length; height = ((length * averageCharWidth / width) + 1) * defaultLineHeight; } else { height = defaultLineHeight; @@ -587,7 +620,7 @@ StyleRange style = styles[i]; newRanges[j] = style.start; newRanges[j + 1] = style.length; - } + } } if (start > newRanges[0]) { newRanges[1] = newRanges[0] + newRanges[1] - start; @@ -658,7 +691,7 @@ 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; + 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) { @@ -798,13 +831,13 @@ layout.setSegments(segments); layout.setWidth(width); layout.setSpacing(lineSpacing); - layout.setTabs(new int[]{tabWidth}); + layout.setTabs([tabWidth]); layout.setIndent(indent); layout.setAlignment(alignment); layout.setJustify(justify); - + int lastOffset = 0; - int length = line.length(); + int length = line.length; if (styles !is null) { if (ranges !is null) { int rangeCount = styleCount << 1; @@ -849,7 +882,7 @@ int compositionOffset = ime.getCompositionOffset(); if (compositionOffset !is -1) { int commitCount = ime.getCommitCount(); - int compositionLength = ime.getText().length(); + int compositionLength = ime.getText().length; if (compositionLength !is commitCount) { int compositionLine = content.getLineAtOffset(compositionOffset); if (compositionLine is lineIndex) { @@ -895,7 +928,7 @@ } } } - + if (styledText !is null && styledText.isFixedLineHeight()) { int index = -1; int lineCount = layout.getLineCount(); @@ -1116,7 +1149,7 @@ return; } if (newRanges is null && COMPACT_STYLES) { - newRanges = new int[newStyles.length << 1]; + 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++) { @@ -1140,7 +1173,7 @@ } newStyles = tmpStyles; } - + if (styleCount is 0) { if (newRanges !is null) { ranges = new int[newRanges.length]; @@ -1195,7 +1228,7 @@ 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]; + mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart]; mergeCount += 2; } mergeStyles[mergeCount >> 1] = newStyles[i >> 1]; @@ -1229,7 +1262,7 @@ modifyEnd = modifyStart; StyleRange[] mergeStyles = new StyleRange[3]; for (int i = 0; i < newStyles.length; i++) { - StyleRange newStyle = newStyles[i], style; + StyleRange newStyle = newStyles[i], style; int newStart = newStyle.start; int newEnd = newStart + newStyle.length; if (newStart is newEnd) continue; @@ -1263,9 +1296,9 @@ int start = event.start; int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount; int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount; - - updateRanges(start, replaceCharCount, newCharCount); - + + updateRanges(start, replaceCharCount, newCharCount); + int startLine = content.getLineAtOffset(start); if (replaceCharCount is content.getCharCount()) lines = null; if (replaceLineCount is lineCount) { @@ -1278,7 +1311,7 @@ if (lineCount + delta > lineWidth.length) { int[] newWidths = new int[lineCount + delta + GROW]; System.arraycopy(lineWidth, 0, newWidths, 0, lineCount); - lineWidth = newWidths; + lineWidth = newWidths; int[] newHeights = new int[lineCount + delta + GROW]; System.arraycopy(lineHeight, 0, newHeights, 0, lineCount); lineHeight = newHeights; @@ -1440,7 +1473,7 @@ 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]; + styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1]; rangeCount += 2; styleCount++; modifyEnd += 4; diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/TableCursor.d --- a/dwt/custom/TableCursor.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TableCursor.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,27 +7,47 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TableCursor; + +import dwt.dwthelper.utils; + -import dwt.*; -import dwt.graphics.*; -import dwt.widgets.*; -import dwt.events.*; +import dwt.DWT; +import dwt.DWTException; +import dwt.events.SelectionEvent; +import dwt.events.SelectionListener; +import dwt.graphics.Color; +import dwt.graphics.GC; +import dwt.graphics.Image; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Canvas; +import dwt.widgets.Display; +import dwt.widgets.Event; +import dwt.widgets.Listener; +import dwt.widgets.ScrollBar; +import dwt.widgets.Table; +import dwt.widgets.TableColumn; +import dwt.widgets.TableItem; +import dwt.widgets.TypedListener; +import dwt.widgets.Widget; /** * 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));
                                                            @@ -41,22 +61,22 @@
                                                              *      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" 
                                                            + *      // 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 
                                                            + *          // 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 
                                                            + *          // 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);
                                                            @@ -65,7 +85,7 @@
                                                              *              text.setText(row.getText(column));
                                                              *              text.addKeyListener(new KeyAdapter() {
                                                              *                  public void keyPressed(KeyEvent e) {
                                                            - *                      // close the text editor and copy the data over 
                                                            + *                      // close the text editor and copy the data over
                                                              *                      // when the user hits "ENTER"
                                                              *                      if (e.character is DWT.CR) {
                                                              *                          TableItem row = cursor.getRow();
                                                            @@ -87,9 +107,9 @@
                                                              *      // 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 || 
                                                            + *              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);
                                                              *              }
                                                            @@ -103,7 +123,7 @@
                                                              *              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);
                                                            @@ -112,7 +132,7 @@
                                                              *              cursor.setFocus();
                                                              *          }
                                                              *      });
                                                            - *  
                                                            + *
                                                              *      shell.open();
                                                              *      while (!shell.isDisposed()) {
                                                              *          if (!display.readAndDispatch())
                                                            @@ -121,18 +141,23 @@
                                                              *      display.dispose();
                                                              *  }
                                                              * 
                                                            - * + * *
                                                            *
                                                            Styles:
                                                            *
                                                            BORDER
                                                            *
                                                            Events:
                                                            *
                                                            Selection, DefaultSelection
                                                            *
                                                            - * + * * @since 2.0 - * + * + * @see TableCursor snippets + * @see Sample code and further information */ public class TableCursor : Canvas { + + alias Canvas.dispose dispose; + Table table; TableItem row = null; TableColumn column = null; @@ -151,7 +176,7 @@ *

                                                            * 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 + * 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. @@ -178,8 +203,8 @@ table = parent; setBackground(null); setForeground(null); - - Listener listener = new Listener() { + + Listener listener = new class() Listener { public void handleEvent(Event event) { switch (event.type) { case DWT.Dispose : @@ -203,18 +228,20 @@ case DWT.TRAVERSE_RETURN : event.doit = false; break; + default: } break; } + default: } } }; - int[] events = new int[] {DWT.Dispose, DWT.FocusIn, DWT.FocusOut, DWT.KeyDown, DWT.Paint, DWT.Traverse}; + int[] events = [DWT.Dispose, DWT.FocusIn, DWT.FocusOut, DWT.KeyDown, DWT.Paint, DWT.Traverse]; for (int i = 0; i < events.length; i++) { addListener(events[i], listener); } - tableListener = new Listener() { + tableListener = new class() Listener { public void handleEvent(Event event) { switch (event.type) { case DWT.MouseDown : @@ -223,13 +250,14 @@ case DWT.FocusIn : tableFocusIn(event); break; + default: } } }; table.addListener(DWT.FocusIn, tableListener); table.addListener(DWT.MouseDown, tableListener); - disposeItemListener = new Listener() { + disposeItemListener = new class() Listener { public void handleEvent(Event event) { unhookRowColumnListeners(); row = null; @@ -237,7 +265,7 @@ _resize(); } }; - disposeColumnListener = new Listener() { + disposeColumnListener = new class() Listener { public void handleEvent(Event event) { unhookRowColumnListeners(); row = null; @@ -245,7 +273,7 @@ _resize(); } }; - resizeListener = new Listener() { + resizeListener = new class() Listener { public void handleEvent(Event event) { _resize(); } @@ -285,7 +313,7 @@ * @see SelectionListener * @see SelectionEvent * @see #removeSelectionListener(SelectionListener) - * + * */ public void addSelectionListener(SelectionListener listener) { checkWidget(); @@ -316,6 +344,7 @@ case DWT.CR : notifyListeners(DWT.DefaultSelection, new Event()); return; + default: } int rowIndex = table.indexOf(row); int columnIndex = column is null ? 0 : table.indexOf(column); @@ -328,7 +357,7 @@ break; case DWT.ARROW_LEFT : case DWT.ARROW_RIGHT : - { + { int columnCount = table.getColumnCount(); if (columnCount is 0) break; int[] order = table.getColumnOrder(); @@ -387,6 +416,7 @@ setRowColumn(index, columnIndex, true); break; } + default: } } @@ -408,14 +438,14 @@ x += imageSize.width; } String text = row.getText(columnIndex); - if (text.length() > 0) { + if (text.length > 0) { Rectangle bounds = row.getBounds(columnIndex); - Point extent = gc.StringExtent(text); + Point extent = gc.stringExtent(text); // Temporary code - need a better way to determine table trim String platform = DWT.getPlatform(); - if ("win32".opEquals(platform)) { //$NON-NLS-1$ + if ("win32"==platform) { //$NON-NLS-1$ if (table.getColumnCount() is 0 || columnIndex is 0) { - x += 2; + x += 2; } else { int alignmnent = column.getAlignment(); switch (alignmnent) { @@ -428,11 +458,12 @@ case DWT.CENTER: x += (bounds.width - x - extent.x) / 2; break; + default: } } } else { if (table.getColumnCount() is 0) { - x += 5; + x += 5; } else { int alignmnent = column.getAlignment(); switch (alignmnent) { @@ -445,6 +476,7 @@ case DWT.CENTER: x += (bounds.width - x - extent.x) / 2 + 2; break; + default: } } } @@ -557,7 +589,7 @@ } } -public void setVisible(bool visible) { +public override void setVisible(bool visible) { checkWidget(); if (visible) _resize(); super.setVisible(visible); @@ -579,7 +611,7 @@ * * @see SelectionListener * @see #addSelectionListener(SelectionListener) - * + * * @since 3.0 */ public void removeSelectionListener(SelectionListener listener) { @@ -588,7 +620,7 @@ DWT.error(DWT.ERROR_NULL_ARGUMENT); } removeListener(DWT.Selection, listener); - removeListener(DWT.DefaultSelection, listener); + removeListener(DWT.DefaultSelection, listener); } void _resize() { @@ -669,7 +701,7 @@ *

                                                          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                          • *
                                                          */ -public void setBackground (Color color) { +public override void setBackground (Color color) { background = color; super.setBackground(getBackground()); redraw(); @@ -691,13 +723,13 @@ *
                                                        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
                                                        • *
                                                        */ -public void setForeground (Color color) { +public override void setForeground (Color color) { foreground = color; super.setForeground(getForeground()); redraw(); } /** - * Positions the TableCursor over the cell at the given row and column in the parent table. + * Positions the TableCursor over the cell at the given row and column in the parent table. * * @param row the index of the row for the cell to select * @param column the index of column for the cell to select @@ -720,7 +752,7 @@ setRowColumn(row, column, false); } /** - * Positions the TableCursor over the cell at the given row and column in the parent table. + * Positions the TableCursor over the cell at the given row and column in the parent table. * * @param row the TableItem of the row for the cell to select * @param column the index of column for the cell to select diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/TableEditor.d --- a/dwt/custom/TableEditor.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TableEditor.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,14 +7,26 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TableEditor; + +import dwt.dwthelper.utils; + -import dwt.*; -import dwt.events.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.events.ControlEvent; +import dwt.events.ControlListener; +import dwt.graphics.Rectangle; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwt.widgets.Table; +import dwt.widgets.TableColumn; +import dwt.widgets.TableItem; +import dwt.custom.ControlEditor; +import dwt.dwthelper.Runnable; /** * @@ -34,7 +46,7 @@ * } * 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. @@ -43,23 +55,23 @@ * 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 = cast(TableItem)e.item; +* 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 = cast(Text)editor.getEditor(); +* Text text = (Text)editor.getEditor(); * editor.getItem().setText(EDITABLECOLUMN, text.getText()); * } * }); @@ -69,6 +81,9 @@ * } * }); *
    +* +* @see TableEditor snippets +* @see Sample code and further information */ public class TableEditor : ControlEditor { Table table; @@ -86,8 +101,8 @@ public this (Table table) { super(table); this.table = table; - - columnListener = new ControlListener() { + + columnListener = new class() ControlListener { public void controlMoved(ControlEvent e){ layout (); } @@ -95,16 +110,16 @@ layout (); } }; - timer = new Runnable () { + timer = new class() Runnable { public void run() { layout (); } }; - + // To be consistent with older versions of DWT, grabVertical defaults to true grabVertical = true; } -Rectangle computeBounds () { +override Rectangle computeBounds () { if (item is null || column is -1 || item.isDisposed()) return new Rectangle(0, 0, 0, 0); Rectangle cell = item.getBounds(column); Rectangle rect = item.getImageBounds(column); @@ -121,11 +136,11 @@ 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) { @@ -133,7 +148,7 @@ } 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) { @@ -147,7 +162,7 @@ * Removes all associations between the TableEditor and the cell in the table. The * Table and the editor Control are not disposed. */ -public void dispose () { +public override void dispose () { if (table !is null && !table.isDisposed()) { if (this.column > -1 && this.column < table.getColumnCount()){ TableColumn tableColumn = table.getColumn(this.column); @@ -193,8 +208,8 @@ } /** * 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 +* +* @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(); @@ -211,18 +226,23 @@ this.column = -1; } - if (column < 0 || column >= table.getColumnCount()) return; - + 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) { +/** +* Specifies the TableItem that is to be edited. +* +* @param item the item to be edited +*/ +public void setItem (TableItem item) { this.item = item; resize(); } -public void setEditor (Control editor) { +public override void setEditor (Control editor) { super.setEditor(editor); resize(); } @@ -231,7 +251,7 @@ * *

    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 @@ -241,7 +261,7 @@ setColumn(column); setEditor(editor); } -public void layout () { +public override void layout () { if (table is null || table.isDisposed()) return; if (item is null || item.isDisposed()) return; int columnCount = table.getColumnCount(); diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/TableTree.d --- a/dwt/custom/TableTree.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TableTree.d Tue Oct 07 16:29:55 2008 +0200 @@ -7,16 +7,38 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TableTree; + -import dwt.*; -import dwt.events.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.DWTException; +import dwt.events.SelectionEvent; +import dwt.events.SelectionListener; +import dwt.events.TreeListener; +import dwt.graphics.Color; +import dwt.graphics.Font; +import dwt.graphics.GC; +import dwt.graphics.Image; +import dwt.graphics.ImageData; +import dwt.graphics.PaletteData; +import dwt.graphics.Point; +import dwt.graphics.RGB; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Event; +import dwt.widgets.Listener; +import dwt.widgets.Menu; +import dwt.widgets.Table; +import dwt.widgets.TableItem; +import dwt.widgets.TypedListener; +import dwt.custom.TableTreeItem; +import dwt.dwthelper.utils; -/** +/** * A TableTree is a selectable user interface object * that displays a hierarchy of items, and issues * notification when an item is selected. @@ -36,31 +58,34 @@ *

    * 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 { + + alias Composite.computeSize computeSize; + Table table; - TableTreeItem[] items = EMPTY_ITEMS; + TableTreeItem[] 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 + * 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 + * the org.eclipse.swt.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 + * 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 TableTreeItem[] EMPTY_ITEMS; + static final String[] EMPTY_TEXTS; + static final Image[] EMPTY_IMAGES; static final String ITEMID = "TableTreeItemID"; //$NON-NLS-1$ /** @@ -69,7 +94,7 @@ *

    * 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 + * 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. @@ -94,40 +119,43 @@ */ public this(Composite parent, int style) { super(parent, checkStyle (style)); + items = EMPTY_ITEMS; table = new Table(this, style); - Listener tableListener = new Listener() { + Listener tableListener = new class() Listener { public void handleEvent(Event e) { switch (e.type) { case DWT.MouseDown: onMouseDown(e); break; case DWT.Selection: onSelection(e); break; case DWT.DefaultSelection: onSelection(e); break; case DWT.KeyDown: onKeyDown(e); break; + default: } } }; - int[] tableEvents = new int[]{DWT.MouseDown, - DWT.Selection, - DWT.DefaultSelection, - DWT.KeyDown}; + int[] tableEvents = [DWT.MouseDown, + DWT.Selection, + DWT.DefaultSelection, + DWT.KeyDown]; for (int i = 0; i < tableEvents.length; i++) { table.addListener(tableEvents[i], tableListener); } - - Listener listener = new Listener() { + + Listener listener = new class() Listener { public void handleEvent(Event e) { switch (e.type) { case DWT.Dispose: onDispose(e); break; case DWT.Resize: onResize(e); break; case DWT.FocusIn: onFocusIn(e); break; + default: } } }; - int[] events = new int[]{DWT.Dispose, - DWT.Resize, - DWT.FocusIn}; + int[] events = [DWT.Dispose, + DWT.Resize, + DWT.FocusIn]; for (int i = 0; i < events.length; i++) { addListener(events[i], listener); - } + } } int addItem(TableTreeItem item, int index) { @@ -135,13 +163,13 @@ TableTreeItem[] newItems = new TableTreeItem[items.length + 1]; System.arraycopy(items, 0, newItems, 0, index); newItems[index] = item; - System.arraycopy(items, index, newItems, index + 1, items.length - index); + System.arraycopy(items, index, newItems, index + 1, items.length - index); items = newItems; /* Return the index in the table where this table should be inserted */ - if (index is items.length - 1 ) + if (index is items.length - 1 ) return table.getItemCount(); - else + else return table.indexOf(items[index+1].tableItem); } @@ -207,15 +235,15 @@ addListener (DWT.Collapse, typedListener); } private static int checkStyle (int style) { - int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; + int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; style = style & mask; return style; -} -public Point computeSize (int wHint, int hHint, bool changed) { +} +public override Point computeSize (int wHint, int hHint, bool changed) { checkWidget(); return table.computeSize (wHint, hHint, changed); } -public Rectangle computeTrim (int x, int y, int width, int height) { +public override Rectangle computeTrim (int x, int y, int width, int height) { checkWidget(); return table.computeTrim(x, y, width, height); } @@ -248,22 +276,22 @@ notifyListeners(DWT.Expand, event); } } -public Color getBackground () { +public override Color getBackground () { // This method must be overridden otherwise, in a TableTree in which the first // item has no sub items, a grey (Widget background colour) square will appear in // the first column of the first item. // It is not possible in the constructor to set the background of the TableTree - // to be the same as the background of the Table because this interferes with + // to be the same as the background of the Table because this interferes with // the TableTree adapting to changes in the System color settings. return table.getBackground(); } -public Rectangle getClientArea () { +public override Rectangle getClientArea () { return table.getClientArea(); } -public Color getForeground () { +public override Color getForeground () { return table.getForeground(); } -public Font getFont () { +public override Font getFont () { return table.getFont(); } /** @@ -347,7 +375,7 @@ return table.getSelectionCount(); } -public int getStyle () { +public override int getStyle () { checkWidget(); return table.getStyle(); } @@ -363,23 +391,23 @@ } void createImages () { - + int itemHeight = sizeImage.getBounds().height; - // Calculate border around image. + // Calculate border around image. // At least 9 pixels are needed to draw the image // Leave at least a 6 pixel border. int indent = Math.min(6, (itemHeight - 9) / 2); indent = Math.max(0, indent); - int size = Math.max (10, itemHeight - 2 * indent); + int size = Math.max (10, itemHeight - 2 * indent); size = ((size + 1) / 2) * 2; // size must be an even number int midpoint = indent + size / 2; - + Color foreground = getForeground(); Color plusMinus = getDisplay().getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW); Color background = getBackground(); - + /* Plus image */ - PaletteData palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), plusMinus.getRGB()}); + PaletteData palette = new PaletteData( [ foreground.getRGB(), background.getRGB(), plusMinus.getRGB()]); ImageData imageData = new ImageData(itemHeight, itemHeight, 4, palette); imageData.transparentPixel = 1; plusImage = new Image(getDisplay(), imageData); @@ -392,9 +420,9 @@ gc.drawLine(midpoint, indent + 2, midpoint, indent + size - 2); gc.drawLine(indent + 2, midpoint, indent + size - 2, midpoint); gc.dispose(); - + /* Minus image */ - palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(), plusMinus.getRGB()}); + palette = new PaletteData([foreground.getRGB(), background.getRGB(), plusMinus.getRGB()]); imageData = new ImageData(itemHeight, itemHeight, 4, palette); imageData.transparentPixel = 1; minusImage = new Image(getDisplay(), imageData); @@ -420,7 +448,7 @@ /** * Gets the index of an 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 @@ -486,7 +514,7 @@ *

  • 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) { @@ -517,7 +545,7 @@ TableItem item = table.getItem(point); if (item is null) return null; return getItem(item); - + } TableTreeItem getItem(TableItem tableItem) { if (tableItem is null) return null; @@ -542,7 +570,7 @@ if (item.getItemCount() is 0) return; if (item.getExpanded()) { TableTreeItem newSelection = item.getItems()[0]; - table.setSelection(new TableItem[]{newSelection.tableItem}); + table.setSelection([newSelection.tableItem]); showItem(newSelection); type = DWT.Selection; } else { @@ -558,7 +586,7 @@ if (parent !is null) { int index = parent.indexOf(item); if (index !is 0) return; - table.setSelection(new TableItem[]{parent.tableItem}); + table.setSelection([parent.tableItem]); type = DWT.Selection; } } @@ -578,7 +606,7 @@ item.setExpanded(true); type = DWT.Expand; } - } + } if (type is 0) return; Event event = new Event(); event.item = item; @@ -697,7 +725,7 @@ checkWidget(); table.selectAll(); } -public void setBackground (Color color) { +public override void setBackground (Color color) { super.setBackground(color); table.setBackground(color); if (sizeImage !is null) { @@ -708,19 +736,19 @@ gc.dispose(); } } -public void setEnabled (bool enabled) { +public override void setEnabled (bool enabled) { super.setEnabled(enabled); table.setEnabled(enabled); } -public void setFont (Font font) { +public override void setFont (Font font) { super.setFont(font); table.setFont(font); } -public void setForeground (Color color) { +public override void setForeground (Color color) { super.setForeground(color); table.setForeground(color); } -public void setMenu (Menu menu) { +public override void setMenu (Menu menu) { super.setMenu(menu); table.setMenu(menu); } @@ -736,7 +764,6 @@ * @param items the array of items * * @exception IllegalArgumentException
      - *
    • ERROR_NULL_ARGUMENT - if the array of items is null
    • *
    • ERROR_INVALID_ARGUMENT - if one of the item has been disposed
    • *
    * @exception DWTException
      @@ -748,7 +775,8 @@ */ public void setSelection (TableTreeItem[] items) { checkWidget (); - if (items is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + // DWT extension: allow null for zero length string + //if (items is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); int length = items.length; if (length is 0 || ((table.getStyle() & DWT.SINGLE) !is 0 && length > 1)) { deselectAll(); @@ -762,9 +790,9 @@ } table.setSelection(tableItems); } -public void setToolTipText (String String) { - super.setToolTipText(String); - table.setToolTipText(String); +public override void setToolTipText (String string) { + super.setToolTipText(string); + table.setToolTipText(string); } /** diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/TableTreeEditor.d --- a/dwt/custom/TableTreeEditor.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TableTreeEditor.d Tue Oct 07 16:29:55 2008 +0200 @@ -7,20 +7,35 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TableTreeEditor; + +import dwt.dwthelper.utils; -import dwt.*; -import dwt.graphics.*; -import dwt.widgets.*; -import dwt.events.*; +import dwt.DWT; +import dwt.events.ControlEvent; +import dwt.events.ControlListener; +import dwt.events.TreeEvent; +import dwt.events.TreeListener; +import dwt.graphics.Rectangle; +import dwt.widgets.Control; +import dwt.widgets.Table; +import dwt.widgets.TableColumn; +import dwt.custom.ControlEditor; +import dwt.custom.TableTree; +import dwt.custom.TableTreeItem; + +import dwt.dwthelper.Runnable; + /** * * A TableTreeEditor is a manager for a Control that appears above a cell in a TableTree * and tracks with the moving and resizing of that cell. It can be used to display a -* text widget above a cell in a TableTree 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 +* text widget above a cell in a TableTree 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 TableTreeEditor: @@ -41,7 +56,7 @@ * } * 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. @@ -50,23 +65,23 @@ * 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 = cast(TableTreeItem)e.item; +* 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 = cast(Text)editor.getEditor(); +* Text text = (Text)editor.getEditor(); * editor.getItem().setText(EDITABLECOLUMN, text.getText()); * } * }); @@ -76,11 +91,13 @@ * } * }); * -* +* * @deprecated As of 3.1 use TreeEditor with Tree, TreeItem and TreeColumn */ public class TableTreeEditor : ControlEditor { + alias ControlEditor.setEditor setEditor; + TableTree tableTree; TableTreeItem item; int column = -1; @@ -96,15 +113,18 @@ 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); - } - }; + treeListener = new class() TreeListener { + Runnable runnable; + this() { + runnable = new class() Runnable { + public void run() { + if (editor is null || editor.isDisposed()) return; + if (this.outer.outer.tableTree.isDisposed()) return; + layout(); + editor.setVisible(true); + } + }; + } public void treeCollapsed(TreeEvent e) { if (editor is null || editor.isDisposed ()) return; editor.setVisible(false); @@ -117,8 +137,8 @@ } }; tableTree.addTreeListener(treeListener); - - columnListener = new ControlListener() { + + columnListener = new class() ControlListener { public void controlMoved(ControlEvent e){ layout (); } @@ -126,11 +146,12 @@ layout (); } }; - + // To be consistent with older versions of DWT, grabVertical defaults to true grabVertical = true; } -Rectangle computeBounds () { + +override Rectangle computeBounds () { if (item is null || column is -1 || item.isDisposed() || item.tableItem is null) return new Rectangle(0, 0, 0, 0); Rectangle cell = item.getBounds(column); Rectangle area = tableTree.getClientArea(); @@ -144,11 +165,11 @@ 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) { @@ -156,7 +177,7 @@ } 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) { @@ -170,7 +191,7 @@ * 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 () { +public override void dispose () { if (tableTree !is null && !tableTree.isDisposed()) { Table table = tableTree.getTable(); if (table !is null && !table.isDisposed()) { @@ -220,14 +241,14 @@ this.column = -1; } - if (column < 0 || column >= table.getColumnCount()) return; - + 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) { +public void setItem (TableTreeItem item) { this.item = item; layout(); } @@ -237,17 +258,18 @@ * *

      Note: The Control provided as the editor must be created with its parent being the Table control * specified in the TableEditor constructor. -* +* * @param editor the Control that is displayed above the cell being edited * @param item the TableItem for the row of the cell being tracked by this editor * @param column the zero based index of the column of the cell being tracked by this editor */ +alias ControlEditor.setEditor setEditor; public void setEditor (Control editor, TableTreeItem item, int column) { setItem(item); setColumn(column); setEditor(editor); } -public void layout () { +public override void layout () { if (tableTree is null || tableTree.isDisposed()) return; if (item is null || item.isDisposed()) return; Table table = tableTree.getTable(); @@ -256,4 +278,5 @@ if (columnCount > 0 && (column < 0 || column >= columnCount)) return; super.layout(); } + } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/TableTreeItem.d --- a/dwt/custom/TableTreeItem.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TableTreeItem.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,28 +7,43 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TableTreeItem; + -import dwt.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.DWTException; +import dwt.graphics.Color; +import dwt.graphics.Font; +import dwt.graphics.GC; +import dwt.graphics.Image; +import dwt.graphics.Rectangle; +import dwt.widgets.Event; +import dwt.widgets.Item; +import dwt.widgets.Table; +import dwt.widgets.TableItem; +import dwt.widgets.Widget; +import dwt.custom.TableTree; +import dwt.dwthelper.utils; + /** * 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; + TableTreeItem [] items; + String[] texts; + Image[] images; Color background; Color foreground; Font font; @@ -44,7 +59,7 @@ *

      * 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 + * 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. @@ -76,7 +91,7 @@ *

      * 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 + * 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. @@ -109,7 +124,7 @@ *

      * 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 + * 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. @@ -141,7 +156,7 @@ *

      * 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 + * 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. @@ -167,11 +182,16 @@ } this(TableTree parent, TableTreeItem parentItem, int style, int index) { + + items = TableTree.EMPTY_ITEMS; + texts = TableTree.EMPTY_TEXTS; + images = TableTree.EMPTY_IMAGES; + super(parent, style); this.parent = parent; this.parentItem = parentItem; if (parentItem is null) { - + /* Root items are visible immediately */ int tableIndex = parent.addItem(this, index); tableItem = new TableItem(parent.getTable(), style, tableIndex); @@ -206,7 +226,7 @@ void addItem(TableTreeItem item, int index) { if (item is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (index < 0 || index > items.length) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - + /* Now that item has a sub-node it must indicate that it can be expanded */ if (items.length is 0 && index is 0) { if (tableItem !is null) { @@ -214,7 +234,7 @@ tableItem.setImage(0, image); } } - + /* Put the item in the items list */ TableTreeItem[] newItems = new TableTreeItem[items.length + 1]; System.arraycopy(items, 0, newItems, 0, index); @@ -228,14 +248,14 @@ * Returns the receiver's background color. * * @return the background 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 getBackground () { checkWidget (); @@ -290,7 +310,7 @@ *
    • 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 () { @@ -336,9 +356,9 @@ *
  • 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 (); @@ -351,13 +371,13 @@ * 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 () { +public override Image getImage () { checkWidget(); return getImage(0); } @@ -398,7 +418,7 @@ *
  • 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) { @@ -425,7 +445,7 @@ *

    * 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. + * not affect the receiver. *

    * * @return the receiver's items @@ -468,7 +488,7 @@ //checkWidget(); return parentItem; } -public String getText () { +public override String getText () { checkWidget(); return getText(0); } @@ -497,7 +517,7 @@ /** * 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 @@ -508,7 +528,7 @@ * */ public int indexOf (TableTreeItem item) { - //checkWidget(); + //checkWidget(); for (int i = 0; i < items.length; i++) { if (items[i] is item) return i; } @@ -529,7 +549,7 @@ items[i].expandAll(notify); } } -int expandedIndexOf (TableTreeItem item) { +int expandedIndexOf (TableTreeItem item) { int index = 0; for (int i = 0; i < items.length; i++) { if (items[i] is item) return index; @@ -549,7 +569,7 @@ return count; } -public void dispose () { +public override void dispose () { if (isDisposed()) return; for (int i = items.length - 1; i >= 0; i--) { items[i].dispose(); @@ -593,17 +613,17 @@ * if the argument is null. * * @param color the new color (or null) - * + * * @exception IllegalArgumentException

      - *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    • 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 (); @@ -617,7 +637,7 @@ } /** - * Sets the checked state of the checkbox for this item. This state change + * 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 @@ -638,16 +658,16 @@ } /** - * Sets the grayed state of the checkbox for this item. This state change + * 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; + * @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) { @@ -693,13 +713,13 @@ * @param font the new font (or null) * * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    • 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){ @@ -720,17 +740,17 @@ * @param color the new color (or null) * * @since 2.0 - * + * * @exception IllegalArgumentException
      - *
    • ERROR_INVALID_ARGUMENT - if the argument has been disposed
    • + *
    • 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 (); @@ -778,13 +798,13 @@ * 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) { +public override void setImage (Image image) { setImage(0, image); } @@ -799,9 +819,6 @@ * @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
    • @@ -809,7 +826,8 @@ */ public void setText(int index, String text) { checkWidget(); - if (text is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + // DWT extension: allow null for zero length string + //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) { @@ -820,8 +838,8 @@ texts[index] = text; if (tableItem !is null) tableItem.setText(index, text); } -public void setText (String String) { - setText(0, String); +public override void setText (String string) { + setText(0, string); } void setVisible (bool show) { @@ -862,7 +880,7 @@ tableItem.setImage(0, parent.getPlusImage()); } } - + } else { for (int i = 0, length = items.length; i < length; i++) { diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/TextChangeListener.d --- a/dwt/custom/TextChangeListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TextChangeListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * 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 @@ -7,33 +7,37 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TextChangeListener; import dwt.internal.DWTEventListener; +import dwt.custom.TextChangingEvent; +import dwt.custom.TextChangedEvent; /** - * The StyledText widget : this listener to receive + * The StyledText widget implements 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 + * 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 + * 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. - * + * 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 @@ -41,18 +45,18 @@ 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 + * 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 + * 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 fbe68c33eeee -r 6337764516f1 dwt/custom/TextChangedEvent.d --- a/dwt/custom/TextChangedEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TextChangedEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,27 +7,29 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TextChangedEvent; -import dwt.events.*; - +import dwt.events.TypedEvent; +import dwt.custom.StyledTextContent; /** - * This event is sent by the StyledTextContent implementor when a change to + * This event is sent by the StyledTextContent implementor when a change to * the text occurs. + * + * @see Sample code and further information */ 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 + * @param source the object that will be sending the TextChangedEvent, + * cannot be null */ public this(StyledTextContent source) { - super(source); + super(cast(Object)source); } } diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/TextChangingEvent.d --- a/dwt/custom/TextChangingEvent.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TextChangingEvent.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,15 +7,23 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TextChangingEvent; + +import dwt.dwthelper.utils; -import dwt.events.*; +import dwt.events.TypedEvent; +import dwt.custom.StyledTextContent; +import dwt.custom.StyledTextEvent; /** * This event is sent by the StyledTextContent implementor when a change * to the text is about to occur. + * + * @see Sample code and further information */ public class TextChangingEvent : TypedEvent { /** @@ -23,7 +31,7 @@ */ public int start; /** - * Text that is going to be inserted or empty String + * Text that is going to be inserted or empty string * if no text will be inserted */ public String newText; @@ -45,19 +53,19 @@ 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 + * @param source the object that will be sending the new TextChangingEvent, + * cannot be null */ public this(StyledTextContent source) { - super(source); + super( cast(Object)source); } this(StyledTextContent source, StyledTextEvent e) { - super(source); + super( cast(Object)source); start = e.start; replaceCharCount = e.replaceCharCount; newCharCount = e.newCharCount; diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/TreeEditor.d --- a/dwt/custom/TreeEditor.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/TreeEditor.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,14 +7,27 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.TreeEditor; + +import dwt.dwthelper.utils; -import dwt.*; -import dwt.events.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.events.ControlEvent; +import dwt.events.ControlListener; +import dwt.events.TreeEvent; +import dwt.events.TreeListener; +import dwt.graphics.Rectangle; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwt.widgets.Tree; +import dwt.widgets.TreeColumn; +import dwt.widgets.TreeItem; +import dwt.custom.ControlEditor; +import dwt.dwthelper.Runnable; /** * @@ -34,30 +47,30 @@ * 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 = cast(TreeItem)e.item; +* 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 = cast(Text)editor.getEditor(); +* Text text = (Text)editor.getEditor(); * editor.getItem().setText(text.getText()); * } * }); @@ -67,16 +80,20 @@ * } * }); * +* +* @see TreeEditor snippets +* @see Sample code and further information */ -public class TreeEditor : ControlEditor { + +public class TreeEditor : ControlEditor { Tree tree; TreeItem item; int column = 0; ControlListener columnListener; TreeListener treeListener; Runnable timer; - static final int TIMEOUT = 1500; - + static const int TIMEOUT = 1500; + /** * Creates a TreeEditor for the specified Tree. * @@ -87,7 +104,7 @@ super(tree); this.tree = tree; - columnListener = new ControlListener() { + columnListener = new class() ControlListener { public void controlMoved(ControlEvent e){ layout(); } @@ -95,38 +112,41 @@ layout(); } }; - timer = new Runnable () { + timer = new class() 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); - } - }; + treeListener = new class() TreeListener { + Runnable runnable; + this(){ + runnable = new class() Runnable { + public void run() { + if (this.outer.outer.editor is null || this.outer.outer.editor.isDisposed()) return; + if (this.outer.outer.tree.isDisposed()) return; + layout(); + this.outer.outer.editor.setVisible(true); + } + }; + } public void treeCollapsed(TreeEvent e) { - if (editor is null || editor.isDisposed ()) return; - editor.setVisible(false); + if (this.outer.editor is null || this.outer.editor.isDisposed ()) return; + this.outer.editor.setVisible(false); e.display.asyncExec(runnable); } public void treeExpanded(TreeEvent e) { - if (editor is null || editor.isDisposed ()) return; - editor.setVisible(false); + if (this.outer.editor is null || this.outer.editor.isDisposed ()) return; + this.outer.editor.setVisible(false); e.display.asyncExec(runnable); } }; tree.addTreeListener(treeListener); - + // To be consistent with older versions of DWT, grabVertical defaults to true grabVertical = true; } -Rectangle computeBounds () { +override Rectangle computeBounds () { if (item is null || column is -1 || item.isDisposed()) return new Rectangle(0, 0, 0, 0); Rectangle cell = item.getBounds(column); Rectangle rect = item.getImageBounds(column); @@ -142,17 +162,17 @@ if (grabHorizontal) { if (tree.getColumnCount() is 0) { - // Bounds of tree item only include the text area - stretch out to include + // 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) { @@ -160,9 +180,9 @@ } else { // default is CENTER editorRect.x += (cell.width - editorRect.width)/2; } - // don't let the editor overlap with the +/- of the tree + // 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) { @@ -177,7 +197,7 @@ * Removes all associations between the TreeEditor and the row in the tree. The * tree and the editor Control are not disposed. */ -public void dispose () { +public override void dispose () { if (tree !is null && !tree.isDisposed()) { if (this.column > -1 && this.column < tree.getColumnCount()){ TreeColumn treeColumn = tree.getColumn(this.column); @@ -231,7 +251,7 @@ /** * 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 @@ -251,14 +271,19 @@ this.column = -1; } - if (column < 0 || column >= tree.getColumnCount()) return; - + if (column < 0 || column >= tree.getColumnCount()) return; + this.column = column; TreeColumn treeColumn = tree.getColumn(this.column); treeColumn.addControlListener(columnListener); resize(); } +/** +* Specifies the TreeItem that is to be edited. +* +* @param item the item to be edited +*/ public void setItem (TreeItem item) { this.item = item; resize(); @@ -269,7 +294,7 @@ * *

      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 @@ -281,7 +306,7 @@ setColumn(column); setEditor(editor); } -public void setEditor (Control editor) { +public override void setEditor (Control editor) { super.setEditor(editor); resize(); } @@ -291,7 +316,7 @@ * *

      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 */ @@ -300,12 +325,13 @@ setEditor(editor); } -public void layout () { +public override void layout () { if (tree is null || tree.isDisposed()) return; - if (item is null || item.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 fbe68c33eeee -r 6337764516f1 dwt/custom/VerifyKeyListener.d --- a/dwt/custom/VerifyKeyListener.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/VerifyKeyListener.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ -/******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,23 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.VerifyKeyListener; -import dwt.events.*; + +import dwt.events.VerifyEvent; import dwt.internal.DWTEventListener; +/** + * Classes which implement this interface provide a method + * that deals with the event that is generated when a + * key is pressed. + * + * @see VerifyEvent + * @see Sample code and further information + */ public interface VerifyKeyListener : DWTEventListener { /** * The following event fields are used:

        diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/ViewForm.d --- a/dwt/custom/ViewForm.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/ViewForm.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,17 +7,32 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.ViewForm; + +import dwt.dwthelper.utils; + -import dwt.graphics.*; -import dwt.widgets.*; -import dwt.*; +import dwt.DWT; +import dwt.DWTException; +import dwt.graphics.Color; +import dwt.graphics.GC; +import dwt.graphics.Point; +import dwt.graphics.RGB; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Event; +import dwt.widgets.Layout; +import dwt.widgets.Listener; +import dwt.custom.ViewFormLayout; /** * Instances of this class implement a Composite that positions and sizes - * children and allows programmatic control of layout and border parameters. + * 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. *

        @@ -28,11 +43,13 @@ *

        Styles:
        *
        BORDER, FLAT
        *
        Events:
        - *
        cast(None)
        + *
        (None)
        * *

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

        + * + * @see Sample code and further information */ public class ViewForm : Composite { @@ -66,45 +83,45 @@ * 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); + public static RGB borderInsideRGB; /** * Color of middle line of drop shadow border. - * + * * NOTE This field is badly named and can not be fixed for backwards compatibility. * It should be capitalized. - * + * * @deprecated */ - public static RGB borderMiddleRGB = new RGB (143, 141, 138); + public static RGB borderMiddleRGB; /** * Color of outermost line of drop shadow border. - * + * * NOTE This field is badly named and can not be fixed for backwards compatibility. * It should be capitalized. - * + * * @deprecated */ - public static RGB borderOutsideRGB = new RGB (171, 168, 165); - + public static RGB borderOutsideRGB; + // 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; @@ -112,19 +129,26 @@ 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; + + + static this(){ + borderInsideRGB = new RGB (132, 130, 132); + borderMiddleRGB = new RGB (143, 141, 138); + borderOutsideRGB = new RGB (171, 168, 165); + } /** * 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 + * 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. @@ -144,25 +168,26 @@ * @see DWT#BORDER * @see DWT#FLAT * @see #getStyle() - */ + */ public this(Composite parent, int style) { super(parent, checkStyle(style)); super.setLayout(new ViewFormLayout()); - + setBorderVisible((style & DWT.BORDER) !is 0); - - Listener listener = new Listener() { + + Listener listener = new class() 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; + default: } } }; - - int[] events = new int[] {DWT.Dispose, DWT.Paint, DWT.Resize}; - + + int[] events = [DWT.Dispose, DWT.Paint, DWT.Resize]; + for (int i = 0; i < events.length; i++) { addListener(events[i], listener); } @@ -176,12 +201,12 @@ //protected void checkSubclass () { // String name = getClass().getName (); // String validName = ViewForm.class.getName(); -// if (!validName.opEquals(name)) { +// if (!validName.equals(name)) { // DWT.error (DWT.ERROR_INVALID_SUBCLASS); // } //} -public Rectangle computeTrim (int x, int y, int width, int height) { +public override Rectangle computeTrim (int x, int y, int width, int height) { checkWidget (); int trimX = x - borderLeft - highlight; int trimY = y - borderTop - highlight; @@ -189,7 +214,7 @@ int trimHeight = height + borderTop + borderBottom + 2*highlight; return new Rectangle(trimX, trimY, trimWidth, trimHeight); } -public Rectangle getClientArea() { +public override Rectangle getClientArea() { checkWidget(); Rectangle clientArea = super.getClientArea(); clientArea.x += borderLeft; @@ -200,7 +225,7 @@ } /** * Returns the content area. -* +* * @return the control in the content area of the pane or null */ public Control getContent() { @@ -210,7 +235,7 @@ /** * 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() { @@ -220,7 +245,7 @@ /** * 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() { @@ -230,7 +255,7 @@ /** * 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() { @@ -257,9 +282,9 @@ 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}; + int[] shape = [x1,y1, x2,y1, x2,y2, x1,y2, x1,y1+highlight, + x1+highlight,y1+highlight, x1+highlight,y2-highlight, + x2-highlight,y2-highlight, x2-highlight,y1+highlight, x1,y1+highlight]; Color highlightColor = getDisplay().getSystemColor(DWT.COLOR_LIST_SELECTION); gc.setBackground(highlightColor); gc.fillPolygon(shape); @@ -280,16 +305,16 @@ if (oldSize.x < size.x) { width = size.x - oldSize.x + borderRight + highlight; } else if (oldSize.x > size.x) { - width = borderRight + highlight; + 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; + height = size.y - oldSize.y + borderBottom + highlight; } if (oldSize.y > size.y) { - height = borderBottom + highlight; + height = borderBottom + highlight; } redraw(0, size.y - height, size.x, height, false); } @@ -297,11 +322,11 @@ } /** * Sets the content. -* Setting the content to null will remove it from +* 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
        • @@ -334,7 +359,7 @@ *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • *
        */ -public void setLayout (Layout layout) { +public override void setLayout (Layout layout) { checkWidget(); return; } @@ -348,11 +373,11 @@ /** * 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 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
        • @@ -374,11 +399,11 @@ /** * 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 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
          • @@ -400,11 +425,11 @@ /** * 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 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
            • @@ -425,9 +450,9 @@ } /** * 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
              • @@ -436,11 +461,11 @@ 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; + if ((getStyle() & DWT.FLAT)is 0) highlight = 2; } else { borderBottom = borderTop = borderLeft = borderRight = 0; highlight = 0; @@ -449,12 +474,12 @@ redraw(); } /** -* If true, the topCenter will always appear on a separate line by itself, otherwise the +* 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
                • diff -r fbe68c33eeee -r 6337764516f1 dwt/custom/ViewFormLayout.d --- a/dwt/custom/ViewFormLayout.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/ViewFormLayout.d Tue Oct 07 16:29:55 2008 +0200 @@ -7,27 +7,37 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit *******************************************************************************/ -module dwt.custom; +module dwt.custom.ViewFormLayout; + +import dwt.dwthelper.utils; -import dwt.*; -import dwt.graphics.*; -import dwt.widgets.*; +import dwt.DWT; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Layout; +import dwt.widgets.Scrollable; +import dwt.custom.ViewForm; +import dwt.custom.CLayoutData; /** * This class provides the layout for ViewForm - * + * * @see ViewForm */ class ViewFormLayout : Layout { -protected Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { +protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { ViewForm form = cast(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); @@ -51,7 +61,7 @@ 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; @@ -61,22 +71,22 @@ 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); + 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; } @@ -90,28 +100,28 @@ } int computeTrim(Control c) { - if ( null !is cast(Scrollable)c ) { - Rectangle rect = (cast(Scrollable) c).computeTrim (0, 0, 0, 0); + if ( auto sa = cast(Scrollable)c) { + Rectangle rect = sa.computeTrim (0, 0, 0, 0); return rect.width; } return c.getBorderWidth () * 2; } -protected bool flushCache(Control control) { +protected override bool flushCache(Control control) { Object data = control.getLayoutData(); - if (data !is null && null !is cast(CLayoutData)data ) (cast(CLayoutData)data).flushCache(); + if ( auto ld = cast(CLayoutData)data ) ld.flushCache(); return true; } -protected void layout(Composite composite, bool flushCache) { +protected override void layout(Composite composite, bool flushCache) { ViewForm form = cast(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); @@ -124,17 +134,17 @@ 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); @@ -159,7 +169,7 @@ 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()) { @@ -176,7 +186,7 @@ } if (left !is null && !left.isDisposed()) { top = true; - Rectangle trim = left instanceof Composite ? (cast(Composite)left).computeTrim(0, 0, 0, 0) : new Rectangle(0, 0, 0, 0); + Rectangle trim = ( null !is cast(Composite)left ) ? (cast(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); @@ -187,7 +197,7 @@ int oldSeperator = form.separator; form.separator = -1; if (content !is null && !content.isDisposed()) { - if (left !is null || right!= null || center !is null){ + if (left !is null || right !is null || center !is null){ form.separator = y; y++; }