# HG changeset patch # User Frank Benoit # Date 1210612381 -7200 # Node ID ce446666f5a203f2fdfc41cd72a0be39559fdacb # Parent 06a1f68293108b2e6f0bb294fa86ca2bbcf38735 Update to SWT 3.4M7 diff -r 06a1f6829310 -r ce446666f5a2 dwt/DWT.d --- a/dwt/DWT.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/DWT.d Mon May 12 19:13:01 2008 +0200 @@ -649,9 +649,76 @@ */ public static const int PaintItem = 42; + /** + * The IME composition event type (value is 43). + *

+ * The IME composition event is sent to allow + * custom text editors to implement in-line + * editing of international text. + *

+ * + * The detail field indicates the action to be taken: + *

+ * + * @see dwt.widgets.Widget#addListener + * @see dwt.widgets.Display#addFilter + * @see dwt.widgets.Event + * + * @since 3.4 + */ + public static const int ImeComposition = 43; + /* Event Details */ /** + * The IME composition event detail that indicates + * a change in the IME composition. The text field + * of the event is the new composition text. + * The start and end indicate the offsets where the + * composition text should be inserted. + * The styles and ranges are stored in the IME + * object (value is 1). + * + * @see DWT#ImeComposition + * + * @since 3.4 + */ + public static const int COMPOSITION_CHANGED = 1; + + /** + * The IME composition event detail that indicates + * that the IME needs the offset for a given location. + * The x and y fields of the event are used by the + * application to determine the offset. + * + * The index field of the event should be set to the + * text offset at that location. The count field should + * be set to indicate whether the location is closer to + * the leading edge (0) or the trailing edge (1) (value is 2). + * + * @see DWT#ImeComposition + * @see dwt.graphics.TextLayout#getOffset(int, int, int[]) + * + * @since 3.4 + */ + public static const int COMPOSITION_OFFSET = 2; + + /** + * The IME composition event detail that indicates + * that IME needs the selected text and its start + * and end offsets (value is 3). + * + * @see DWT#ImeComposition + * + * @since 3.4 + */ + public static const int COMPOSITION_SELECTION = 3; + + /** * Indicates that a user-interface component is being dragged, * for example dragging the thumb of a scroll bar (value is 1). */ @@ -1144,6 +1211,23 @@ public static const int V_SCROLL = 1 << 9; /** + * Style constant for no scrollbar behavior (value is 1<<4). + *

+ * When neither H_SCROLL or V_SCROLL are specified, controls + * are free to create the default scroll bars for the control. + * Using NO_SCROLL overrides the default and forces the control + * to have no scroll bars. + * + * Used By:

+ * + * @since 3.4 + */ + public static const int NO_SCROLL = 1 << 4; + + /** * Style constant for bordered behavior (value is 1<<11). *
Note that this is a HINT. *

Used By:

*/ public this(Device device, int width, int height) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, width, height); - if (device.tracking) device.new_Object(this); + super(device); + init_(width, height); + init_(); } /** @@ -230,8 +230,7 @@ * */ public this(Device device, Image srcImage, int flag) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (srcImage is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (srcImage.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); switch (flag) { @@ -242,7 +241,7 @@ default: DWT.error(DWT.ERROR_INVALID_ARGUMENT); } - this.device = device; + device = this.device; this.type = srcImage.type; /* Get source image size */ @@ -286,80 +285,79 @@ if (flag is DWT.IMAGE_COPY) { OS.gdk_draw_drawable(pixmap, gdkGC, srcImage.pixmap, 0, 0, 0, 0, width, height); OS.g_object_unref(gdkGC); - if (device.tracking) device.new_Object(this); - return; - } + } else { - /* Retrieve the source pixmap data */ - auto pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, width, height); - if (pixbuf is null) DWT.error(DWT.ERROR_NO_HANDLES); - auto colormap = OS.gdk_colormap_get_system(); - OS.gdk_pixbuf_get_from_drawable(pixbuf, srcImage.pixmap, colormap, 0, 0, 0, 0, width, height); - int stride = OS.gdk_pixbuf_get_rowstride(pixbuf); - auto pixels = OS.gdk_pixbuf_get_pixels(pixbuf); + /* Retrieve the source pixmap data */ + auto pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, width, height); + if (pixbuf is null) DWT.error(DWT.ERROR_NO_HANDLES); + auto colormap = OS.gdk_colormap_get_system(); + OS.gdk_pixbuf_get_from_drawable(pixbuf, srcImage.pixmap, colormap, 0, 0, 0, 0, width, height); + int stride = OS.gdk_pixbuf_get_rowstride(pixbuf); + auto pixels = OS.gdk_pixbuf_get_pixels(pixbuf); - /* Apply transformation */ - switch (flag) { - case DWT.IMAGE_DISABLE: { - Color zeroColor = device.getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW); - RGB zeroRGB = zeroColor.getRGB(); - byte zeroRed = cast(byte)zeroRGB.red; - byte zeroGreen = cast(byte)zeroRGB.green; - byte zeroBlue = cast(byte)zeroRGB.blue; - Color oneColor = device.getSystemColor(DWT.COLOR_WIDGET_BACKGROUND); - RGB oneRGB = oneColor.getRGB(); - byte oneRed = cast(byte)oneRGB.red; - byte oneGreen = cast(byte)oneRGB.green; - byte oneBlue = cast(byte)oneRGB.blue; - byte[] line = new byte[stride]; - for (int y=0; y> 3); + line[offset] = line[offset+1] = line[offset+2] = intensity; } + memmove(pixels + (y * stride), line.ptr, stride); } - memmove(pixels + (y * stride), line.ptr, stride); + break; } - break; + default: } - case DWT.IMAGE_GRAY: { - byte[] line = new byte[stride]; - for (int y=0; y> 3); - line[offset] = line[offset+1] = line[offset+2] = intensity; - } - memmove(pixels + (y * stride), line.ptr, stride); - } - break; - } - default: + + /* Copy data back to destination pixmap */ + OS.gdk_pixbuf_render_to_drawable(pixbuf, pixmap, gdkGC, 0, 0, 0, 0, width, height, OS.GDK_RGB_DITHER_NORMAL, 0, 0); + + /* Free resources */ + OS.g_object_unref(pixbuf); + OS.g_object_unref(gdkGC); } - - /* Copy data back to destination pixmap */ - OS.gdk_pixbuf_render_to_drawable(pixbuf, pixmap, gdkGC, 0, 0, 0, 0, width, height, OS.GDK_RGB_DITHER_NORMAL, 0, 0); - - /* Free resources */ - OS.g_object_unref(pixbuf); - OS.g_object_unref(gdkGC); - if (device.tracking) device.new_Object(this); + init_(); } /** @@ -393,11 +391,10 @@ * */ public this(Device device, Rectangle bounds) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (bounds is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, bounds.width, bounds.height); - if (device.tracking) device.new_Object(this); + init_(bounds.width, bounds.height); + init_(); } /** @@ -419,10 +416,9 @@ * */ public this(Device device, ImageData data) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, data); - if (device.tracking) device.new_Object(this); + super(device); + init_(data); + init_(); } /** @@ -451,8 +447,7 @@ * */ public this(Device device, ImageData source, ImageData mask) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (mask is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (source.width !is mask.width || source.height !is mask.height) { @@ -462,8 +457,8 @@ ImageData image = new ImageData(source.width, source.height, source.depth, source.palette, source.scanlinePad, source.data); image.maskPad = mask.scanlinePad; image.maskData = mask.data; - init_(device, image); - if (device.tracking) device.new_Object(this); + init_(image); + init_(); } /** @@ -515,10 +510,9 @@ * */ public this(Device device, InputStream stream) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, new ImageData(stream)); - if (device.tracking) device.new_Object(this); + super(device); + init_(new ImageData(stream)); + init_(); } /** @@ -549,10 +543,8 @@ * */ public this(Device device, String filename) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (filename is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; try { int length = filename.length; auto pixbuf = OS.gdk_pixbuf_new_from_file(toStringz(filename), null); @@ -591,8 +583,8 @@ return; } } catch (DWTException e) {} - init_(device, new ImageData(filename)); - if (device.tracking) device.new_Object(this); + init_(new ImageData(filename)); + init_(); } void createAlphaMask (int width, int height) { @@ -767,14 +759,7 @@ mask = null; } -/** - * Disposes of the operating system resources associated with - * the image. Applications must dispose of all images which - * they allocate. - */ -public override void dispose () { - if (pixmap is null) return; - if (device.isDisposed()) return; +void destroy() { if (memGC !is null) memGC.dispose(); if (pixmap !is null) OS.g_object_unref(pixmap); if (mask !is null) OS.g_object_unref(mask); @@ -785,8 +770,6 @@ pixmap = null; mask = null; memGC = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -944,12 +927,10 @@ * @private */ public static Image gtk_new(Device device, int type, GdkDrawable* pixmap, GdkDrawable* mask) { - if (device is null) device = Device.getDevice(); - Image image = new Image(); + Image image = new Image(device); image.type = type; image.pixmap = cast(GdkDrawable*)pixmap; image.mask = cast(GdkDrawable*)mask; - image.device = device; return image; } @@ -967,11 +948,10 @@ return cast(hash_t)/*64*/pixmap; } -void init_(Device device, int width, int height) { +void init_(int width, int height) { if (width <= 0 || height <= 0) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } - this.device = device; this.type = DWT.BITMAP; /* Create the pixmap */ @@ -991,9 +971,8 @@ OS.gdk_colormap_free_colors(colormap, white, 1); } -void init_(Device device, ImageData image) { +void init_(ImageData image) { if (image is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; int width = image.width; int height = image.height; PaletteData palette = image.palette; @@ -1101,12 +1080,16 @@ int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; if ((data.style & mask) is 0) { data.style |= DWT.LEFT_TO_RIGHT; + } else { + if ((data.style & DWT.RIGHT_TO_LEFT) !is 0) { + data.style |= DWT.MIRRORED; + } } data.device = device; data.drawable = pixmap; data.background = device.COLOR_WHITE.handle; data.foreground = device.COLOR_BLACK.handle; - data.font = device.systemFont.handle; + data.font = device.systemFont; data.image = this; } return gdkGC; diff -r 06a1f6829310 -r ce446666f5a2 dwt/graphics/ImageData.d --- a/dwt/graphics/ImageData.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/ImageData.d Mon May 12 19:13:01 2008 +0200 @@ -289,7 +289,7 @@ * * @exception IllegalArgumentException
    *
  • ERROR_INVALID_ARGUMENT - if the width or height is negative, or if the depth is not - * one of 1, 2, 4, 8, 16, 24 or 32
  • + * one of 1, 2, 4, 8, 16, 24 or 32, or the data array is too small to contain the image data *
  • ERROR_NULL_ARGUMENT - if the palette or data is null
  • *
  • ERROR_CANNOT_BE_ZERO - if the scanlinePad is zero
  • *
@@ -444,6 +444,17 @@ int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) / scanlinePad * scanlinePad; + + /* + * When the image is being loaded from a PNG, we need to use the theoretical minimum + * number of bytes per line to check whether there is enough data, because the actual + * number of bytes per line is calculated based on the given depth, which may be larger + * than the actual depth of the PNG. + */ + int minBytesPerLine = type is DWT.IMAGE_PNG ? ((((width + 7) / 8) + 3) / 4) * 4 : bytesPerLine; + if (data !is null && data.length < minBytesPerLine * height) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } setAllFields( width, height, diff -r 06a1f6829310 -r ce446666f5a2 dwt/graphics/Path.d --- a/dwt/graphics/Path.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Path.d Mon May 12 19:13:01 2008 +0200 @@ -44,7 +44,7 @@ * @since 3.1 */ public class Path : Resource { - + alias Resource.init_ init_; /** * the OS resource for the Path * (Warning: This field is platform dependent) @@ -82,16 +82,48 @@ * @see #dispose() */ public this (Device device) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; - device.checkCairo(); + super(device); + this.device.checkCairo(); + auto surface = Cairo.cairo_image_surface_create(Cairo.CAIRO_FORMAT_ARGB32, 1, 1); + if (surface is null) DWT.error(DWT.ERROR_NO_HANDLES); + handle = Cairo.cairo_create(surface); + Cairo.cairo_surface_destroy(surface); + if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); + init_(); +} + +public this (Device device, Path path, float flatness) { + super(device); + if (path is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + if (path.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); auto surface = Cairo.cairo_image_surface_create(Cairo.CAIRO_FORMAT_ARGB32, 1, 1); if (surface is null) DWT.error(DWT.ERROR_NO_HANDLES); handle = Cairo.cairo_create(surface); Cairo.cairo_surface_destroy(surface); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + cairo_path_t* copy; + flatness = Math.max(0, flatness); + if (flatness is 0) { + copy = Cairo.cairo_copy_path(path.handle); + } else { + double tolerance = Cairo.cairo_get_tolerance(path.handle); + Cairo.cairo_set_tolerance(path.handle, flatness); + copy = Cairo.cairo_copy_path_flat(path.handle); + Cairo.cairo_set_tolerance(path.handle, tolerance); + } + if (copy is null) { + Cairo.cairo_destroy(handle); + DWT.error(DWT.ERROR_NO_HANDLES); + } + Cairo.cairo_append_path(handle, copy); + Cairo.cairo_path_destroy(copy); + init_(); +} + +public this (Device device, PathData data) { + this(device); + if (data is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + init_(data); } /** @@ -552,17 +584,36 @@ closed = false; } -/** - * Disposes of the operating system resources associated with - * the Path. Applications must dispose of all Paths that - * they allocate. - */ -public override void dispose() { - if (handle is null) return; +void destroy() { Cairo.cairo_destroy(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; +} + +void init_(PathData data) { + byte[] types = data.types; + float[] points = data.points; + for (int i = 0, j = 0; i < types.length; i++) { + switch (types[i]) { + case DWT.PATH_MOVE_TO: + moveTo(points[j++], points[j++]); + break; + case DWT.PATH_LINE_TO: + lineTo(points[j++], points[j++]); + break; + case DWT.PATH_CUBIC_TO: + cubicTo(points[j++], points[j++], points[j++], points[j++], points[j++], points[j++]); + break; + case DWT.PATH_QUAD_TO: + quadTo(points[j++], points[j++], points[j++], points[j++]); + break; + case DWT.PATH_CLOSE: + close(); + break; + default: + dispose(); + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + } } /** diff -r 06a1f6829310 -r ce446666f5a2 dwt/graphics/Pattern.d --- a/dwt/graphics/Pattern.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Pattern.d Mon May 12 19:13:01 2008 +0200 @@ -54,6 +54,8 @@ */ public cairo_pattern_t* handle; + cairo_surface_t * surface; + /** * Constructs a new Pattern given an image. Drawing with the resulting * pattern will cause the image to be tiled over the resulting area. @@ -80,17 +82,16 @@ * @see #dispose() */ public this(Device device, Image image) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (image is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (image.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - this.device = device; - device.checkCairo(); + this.device.checkCairo(); image.createSurface(); handle = Cairo.cairo_pattern_create_for_surface(image.surface); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); Cairo.cairo_pattern_set_extend(handle, Cairo.CAIRO_EXTEND_REPEAT); - if (device.tracking) device.new_Object(this); + surface = image.surface; + init_(); } /** @@ -165,34 +166,24 @@ * @since 3.2 */ public this(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (color1 is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (color1.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); if (color2 is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (color2.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - this.device = device; - device.checkCairo(); + this.device.checkCairo(); handle = Cairo.cairo_pattern_create_linear(x1, y1, x2, y2); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); GC.setCairoPatternColor(handle, 0, color1, alpha1); GC.setCairoPatternColor(handle, 1, color2, alpha2); Cairo.cairo_pattern_set_extend(handle, Cairo.CAIRO_EXTEND_REPEAT); - if (device.tracking) device.new_Object(this); + init_(); } -/** - * Disposes of the operating system resources associated with - * the Pattern. Applications must dispose of all Patterns that - * they allocate. - */ -public override void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { Cairo.cairo_pattern_destroy(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; + surface = null; } /** diff -r 06a1f6829310 -r ce446666f5a2 dwt/graphics/Region.d --- a/dwt/graphics/Region.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Region.d Mon May 12 19:13:01 2008 +0200 @@ -78,16 +78,14 @@ * @since 3.0 */ public this(Device device) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); handle = OS.gdk_region_new(); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } this(Device device, GdkRegion* handle) { - this.device = device; + super(device); this.handle = handle; } @@ -110,7 +108,12 @@ public void add (int[] pointArray) { if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); if (pointArray is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); -//PORTING_FIXME: shall the pointArray be changed to be GdkPoint[] ? + /* + * Bug in GTK. If gdk_region_polygon() is called with one point, + * it segment faults. The fix is to make sure that it is called + * with enough points for a polygon. + */ + if (pointArray.length < 6) return; auto polyRgn = OS.gdk_region_polygon(cast(GdkPoint*)pointArray.ptr, pointArray.length / 2, OS.GDK_EVEN_ODD_RULE); OS.gdk_region_union(handle, polyRgn); OS.gdk_region_destroy(polyRgn); @@ -225,18 +228,9 @@ return contains(pt.x, pt.y); } -/** - * Disposes of the operating system resources associated with - * the region. Applications must dispose of all regions which - * they allocate. - */ -public override void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { OS.gdk_region_destroy(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -468,6 +462,12 @@ public void subtract (int[] pointArray) { if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); if (pointArray is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + /* + * Bug in GTK. If gdk_region_polygon() is called with one point, + * it segment faults. The fix is to make sure that it is called + * with enough points for a polygon. + */ + if (pointArray.length < 6) return; auto polyRgn = OS.gdk_region_polygon( cast(GdkPoint*)pointArray.ptr, pointArray.length / 2, OS.GDK_EVEN_ODD_RULE); OS.gdk_region_subtract(handle, polyRgn); OS.gdk_region_destroy(polyRgn); diff -r 06a1f6829310 -r ce446666f5a2 dwt/graphics/Resource.d --- a/dwt/graphics/Resource.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Resource.d Mon May 12 19:13:01 2008 +0200 @@ -46,12 +46,30 @@ */ Device device; +this() { +} + +this(Device device) { + if (device is null) device = Device.getDevice(); + if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + this.device = device; +} + +void destroy() { +} + /** * Disposes of the operating system resources associated with * this resource. Applications must dispose of all resources * which they allocate. */ -public abstract void dispose(); +public void dispose() { + if (device is null) return; + if (device.isDisposed()) return; + destroy(); + if (device.tracking) device.dispose_Object(this); + device = null; +} /** * Returns the Device where this resource was @@ -67,6 +85,10 @@ return device; } +void init_() { + if (device.tracking) device.new_Object(this); +} + /** * Returns true if the resource has been disposed, * and false otherwise. diff -r 06a1f6829310 -r ce446666f5a2 dwt/graphics/TextLayout.d --- a/dwt/graphics/TextLayout.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/TextLayout.d Mon May 12 19:13:01 2008 +0200 @@ -12,6 +12,7 @@ *******************************************************************************/ module dwt.graphics.TextLayout; +import dwt.internal.Compatibility; import dwt.internal.cairo.Cairo; import dwt.internal.gtk.OS; import dwt.internal.Converter; @@ -94,9 +95,7 @@ * @see #dispose() */ public this (Device device) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); context = OS.gdk_pango_context_get(); if (context is null) DWT.error(DWT.ERROR_NO_HANDLES); OS.pango_context_set_language(context, OS.gtk_get_default_language()); @@ -104,8 +103,9 @@ OS.gdk_pango_context_set_colormap(context, OS.gdk_colormap_get_system()); layout = OS.pango_layout_new(context); if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES); + OS.pango_layout_set_font_description(layout, device.systemFont.handle); OS.pango_layout_set_wrap(layout, OS.PANGO_WRAP_WORD_CHAR); - OS.pango_layout_set_tabs(layout, device.emptyTab); + OS.pango_layout_set_tabs(layout, this.device.emptyTab); if (OS.GTK_VERSION >= OS.buildVERSION(2, 4, 0)) { OS.pango_layout_set_auto_dir(layout, false); } @@ -114,7 +114,7 @@ styles = new StyleItem[2]; styles[0] = new StyleItem(); styles[1] = new StyleItem(); - if (device.tracking) device.new_Object(this); + init_(); } void checkLayout() { @@ -132,18 +132,17 @@ char[] chars = null; int segementsLength = segmentsText.length; if ((ascent !is -1 || descent !is -1) && segementsLength > 0) { - auto iter = OS.pango_layout_get_iter(layout); - if (iter is null) DWT.error(DWT.ERROR_NO_HANDLES); PangoRectangle rect; if (ascent !is -1) rect.y = -(ascent * OS.PANGO_SCALE); rect.height = (Math.max(0, ascent) + Math.max(0, descent)) * OS.PANGO_SCALE; int lineCount = OS.pango_layout_get_line_count(layout); chars = new char[segementsLength + lineCount * 6/*2*/]; - int oldPos = 0, count = 0; - do { - int bytePos = OS.pango_layout_iter_get_index(iter); + int oldPos = 0, lineIndex = 0; + while (lineIndex < lineCount) { + auto line = OS.pango_layout_get_line(layout, lineIndex); + int bytePos = line.start_index; /* Note: The length in bytes of ZWS and ZWNBS are both equals to 3 */ - int offset = count * 6; + int offset = lineIndex * 6; PangoAttribute* attr = OS.pango_attr_shape_new (&rect, &rect); attr.start_index = bytePos + offset; attr.end_index = bytePos + offset + 3; @@ -153,15 +152,15 @@ attr.end_index = bytePos + offset + 6; OS.pango_attr_list_insert(attrList, attr); int pos = bytePos;//OS.g_utf8_pointer_to_offset(ptr, ptr + bytePos); - chars[pos + count * 6 +0 .. pos + count * 6 + 3] = STR_ZWS; - chars[pos + count * 6 +3 .. pos + count * 6 + 6] = STR_ZWNBS; - chars[ oldPos + count*6 .. oldPos + count*6 + pos - oldPos ] = + chars[pos + lineIndex * 6 +0 .. pos + lineIndex * 6 + 3] = STR_ZWS; + chars[pos + lineIndex * 6 +3 .. pos + lineIndex * 6 + 6] = STR_ZWNBS; + chars[ oldPos + lineIndex*6 .. oldPos + lineIndex*6 + pos - oldPos ] = segmentsText[ oldPos .. pos ]; oldPos = pos; - count++; - } while (OS.pango_layout_iter_next_line(iter)); - OS.pango_layout_iter_free (iter); - chars[ oldPos + count*6 .. oldPos + count*6 + segementsLength - oldPos ] = + lineIndex++; + } + segmentsText.getChars(oldPos, segementsLength, chars, oldPos + lineIndex * 2); + chars[ oldPos + lineIndex*6 .. oldPos + lineIndex*6 + segementsLength - oldPos ] = segmentsText[ oldPos .. segementsLength ]; String buffer = chars;// Converter.wcsToMbcs(null, chars, false); @@ -216,12 +215,29 @@ OS.pango_attr_list_insert(attrList, attr); } if (style.underline) { - auto attr = OS.pango_attr_underline_new(OS.PANGO_UNDERLINE_SINGLE); - attr.start_index = byteStart; - attr.end_index = byteEnd; - OS.pango_attr_list_insert(attrList, attr); + int underlineStyle = OS.PANGO_UNDERLINE_NONE; + switch (style.underlineStyle) { + case DWT.UNDERLINE_SINGLE: + underlineStyle = OS.PANGO_UNDERLINE_SINGLE; + break; + case DWT.UNDERLINE_DOUBLE: + underlineStyle = OS.PANGO_UNDERLINE_DOUBLE; + break; + case DWT.UNDERLINE_SQUIGGLE: + case DWT.UNDERLINE_ERROR: + if (OS.GTK_VERSION >= OS.buildVERSION(2, 4, 0)) { + underlineStyle = OS.PANGO_UNDERLINE_ERROR; + } + break; + } + if (underlineStyle !is OS.PANGO_UNDERLINE_NONE && style.underlineColor is null) { + auto attr = OS.pango_attr_underline_new(underlineStyle); + attr.start_index = byteStart; + attr.end_index = byteEnd; + OS.pango_attr_list_insert(attrList, attr); + } } - if (style.strikeout) { + if (style.strikeout && style.strikeoutColor is null) { auto attr = OS.pango_attr_strikethrough_new(true); attr.start_index = byteStart; attr.end_index = byteEnd; @@ -265,12 +281,30 @@ OS.pango_layout_set_attributes(layout, attrList); } -/** - * Disposes of the operating system resources associated with - * the text layout. Applications must dispose of all allocated text layouts. - */ -public override void dispose() { - if (layout is null) return; +int[] computePolyline(int left, int top, int right, int bottom) { + int height = bottom - top; // can be any number + int width = 2 * height; // must be even + int peaks = Compatibility.ceil(right - left, width); + if (peaks is 0 && right - left > 2) { + peaks = 1; + } + int length_ = ((2 * peaks) + 1) * 2; + if (length_ < 0) return new int[0]; + + int[] coordinates = new int[length_]; + for (int i = 0; i < peaks; i++) { + int index = 4 * i; + coordinates[index] = left + (width * i); + coordinates[index+1] = bottom; + coordinates[index+2] = coordinates[index] + width / 2; + coordinates[index+3] = top; + } + coordinates[length_-2] = left + (width * peaks); + coordinates[length_-1] = bottom; + return coordinates; +} + +void destroy() { font = null; text = null; styles = null; @@ -279,8 +313,6 @@ layout = null; if (context !is null) OS.g_object_unref(context); context = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -360,7 +392,7 @@ if (selectionForeground !is null && selectionForeground.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); if (selectionBackground !is null && selectionBackground.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); gc.checkGC(GC.FOREGROUND); - int length = text.length; + int length_ = text.length; bool hasSelection = selectionStart <= selectionEnd && selectionStart !is -1 && selectionEnd !is -1; GCData data = gc.data; auto cairo = data.cairo; @@ -429,29 +461,48 @@ OS.gdk_gc_set_foreground(gc.handle, data.foreground); } } - if (length is 0) return; + if (length_ is 0) return; if (!hasSelection) { if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_save(cairo); + Cairo.cairo_scale(cairo, -1, 1); + Cairo.cairo_translate(cairo, -2 * x - width(), 0); + } Cairo.cairo_move_to(cairo, x, y); OS.pango_cairo_show_layout(cairo, layout); + drawBorder(gc, x, y, null); + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_restore(cairo); + } } else { OS.gdk_draw_layout(data.drawable, gc.handle, x, y, layout); + drawBorder(gc, x, y, null); } } else { - selectionStart = Math.min(Math.max(0, selectionStart), length - 1); - selectionEnd = Math.min(Math.max(0, selectionEnd), length - 1); - length = OS.g_utf8_strlen(OS.pango_layout_get_text(layout), -1); + selectionStart = Math.min(Math.max(0, selectionStart), length_ - 1); + selectionEnd = Math.min(Math.max(0, selectionEnd), length_ - 1); + length_ = OS.g_utf8_strlen(OS.pango_layout_get_text(layout), -1); selectionStart = translateOffset(selectionStart); selectionEnd = translateOffset(selectionEnd); if (selectionForeground is null) selectionForeground = device.getSystemColor(DWT.COLOR_LIST_SELECTION_TEXT); if (selectionBackground is null) selectionBackground = device.getSystemColor(DWT.COLOR_LIST_SELECTION); - bool fullSelection = selectionStart is 0 && selectionEnd is length - 1; + bool fullSelection = selectionStart is 0 && selectionEnd is length_ - 1; if (fullSelection) { if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { auto ptr = OS.pango_layout_get_text(layout); - drawWithCairo(cairo, x, y, 0, strlen(ptr), fullSelection, selectionBackground.handle, selectionForeground.handle); + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_save(cairo); + Cairo.cairo_scale(cairo, -1, 1); + Cairo.cairo_translate(cairo, -2 * x - width(), 0); + } + drawWithCairo(gc, x, y, 0, OS.strlen(ptr), fullSelection, selectionForeground.handle, selectionBackground.handle); + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_restore(cairo); + } } else { OS.gdk_draw_layout_with_colors(data.drawable, gc.handle, x, y, layout, selectionForeground.handle, selectionBackground.handle); + drawBorder(gc, x, y, selectionForeground.handle); } } else { auto ptr = OS.pango_layout_get_text(layout); @@ -461,11 +512,20 @@ byteSelStart = Math.min(byteSelStart, slen); byteSelEnd = Math.min(byteSelEnd, slen); if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { - drawWithCairo(cairo, x, y, byteSelStart, byteSelEnd, fullSelection, selectionBackground.handle, selectionForeground.handle); + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_save(cairo); + Cairo.cairo_scale(cairo, -1, 1); + Cairo.cairo_translate(cairo, -2 * x - width(), 0); + } + drawWithCairo(gc, x, y, byteSelStart, byteSelEnd, fullSelection, selectionForeground.handle, selectionBackground.handle); + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_restore(cairo); + } } else { Region clipping = new Region(); gc.getClipping(clipping); OS.gdk_draw_layout(data.drawable, gc.handle, x, y, layout); + drawBorder(gc, x, y, null); int[] ranges = [byteSelStart, byteSelEnd]; auto rgn = OS.gdk_pango_layout_get_clip_region(layout, x, y, ranges.ptr, ranges.length / 2); if (rgn !is null) { @@ -473,6 +533,7 @@ OS.gdk_region_destroy(rgn); } OS.gdk_draw_layout_with_colors(data.drawable, gc.handle, x, y, layout, selectionForeground.handle, selectionBackground.handle); + drawBorder(gc, x, y, selectionForeground.handle); gc.setClipping(clipping); clipping.dispose(); } @@ -480,27 +541,294 @@ } } -void drawWithCairo(cairo_t* cairo, int x, int y, int byteSelStart, int byteSelEnd, bool fullSelection, GdkColor* selectionBackground, GdkColor* selectionForeground) { +void drawWithCairo(GC gc, int x, int y, int start, int end, bool fullSelection, GdkColor* fg, GdkColor* bg) { + GCData data = gc.data; + cairo_t* cairo = data.cairo; Cairo.cairo_save(cairo); if (!fullSelection) { Cairo.cairo_move_to(cairo, x, y); OS.pango_cairo_show_layout(cairo, layout); + drawBorder(gc, x, y, null); } - int[] ranges = [byteSelStart, byteSelEnd]; + int[] ranges = [start, end]; auto rgn = OS.gdk_pango_layout_get_clip_region(layout, x, y, ranges.ptr, ranges.length / 2); if (rgn !is null) { OS.gdk_cairo_region(cairo, rgn); Cairo.cairo_clip(cairo); - OS.gdk_cairo_set_source_color(cairo, selectionBackground); + Cairo.cairo_set_source_rgba(cairo, (bg.red & 0xFFFF) / cast(float)0xFFFF, (bg.green & 0xFFFF) / cast(float)0xFFFF, (bg.blue & 0xFFFF) / cast(float)0xFFFF, data.alpha / cast(float)0xFF); Cairo.cairo_paint(cairo); OS.gdk_region_destroy(rgn); } - OS.gdk_cairo_set_source_color(cairo, selectionForeground); + Cairo.cairo_set_source_rgba(cairo, (fg.red & 0xFFFF) / cast(float)0xFFFF, (fg.green & 0xFFFF) / cast(float)0xFFFF, (fg.blue & 0xFFFF) / cast(float)0xFFFF, data.alpha / cast(float)0xFF); Cairo.cairo_move_to(cairo, x, y); OS.pango_cairo_show_layout(cairo, layout); + drawBorder(gc, x, y, fg); Cairo.cairo_restore(cairo); } +void drawBorder(GC gc, int x, int y, GdkColor* selectionColor) { + GCData data = gc.data; + auto cairo = data.cairo; + auto gdkGC = gc.handle; + auto ptr = OS.pango_layout_get_text(layout); + GdkGCValues* gcValues = null; + if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_save(cairo); + } + for (int i = 0; i < styles.length - 1; i++) { + TextStyle style = styles[i].style; + if (style is null) continue; + + bool drawBorder = style.borderStyle !is DWT.NONE; + if (drawBorder && !style.isAdherentBorder(styles[i+1].style)) { + int start = styles[i].start; + for (int j = i; j > 0 && style.isAdherentBorder(styles[j-1].style); j--) { + start = styles[j - 1].start; + } + start = translateOffset(start); + int end = translateOffset(styles[i+1].start - 1); + int byteStart = cast(int)/*64*/(OS.g_utf8_offset_to_pointer(ptr, start) - ptr); + int byteEnd = cast(int)/*64*/(OS.g_utf8_offset_to_pointer(ptr, end + 1) - ptr); + int[] ranges = [byteStart, byteEnd]; + auto rgn = OS.gdk_pango_layout_get_clip_region(layout, x, y, ranges.ptr, ranges.length / 2); + if (rgn !is null) { + int nRects; + GdkRectangle* rects; + OS.gdk_region_get_rectangles(rgn, &rects, &nRects); + GdkRectangle rect; + GdkColor* color = null; + if (color is null && style.borderColor !is null) color = style.borderColor.handle; + if (color is null && selectionColor !is null) color = selectionColor; + if (color is null && style.foreground !is null) color = style.foreground.handle; + if (color is null) color = data.foreground; + int width = 1; + float[] dashes = null; + switch (style.borderStyle) { + case DWT.BORDER_SOLID: break; + case DWT.BORDER_DASH: dashes = width !is 0 ? GC.LINE_DASH : GC.LINE_DASH_ZERO; break; + case DWT.BORDER_DOT: dashes = width !is 0 ? GC.LINE_DOT : GC.LINE_DOT_ZERO; break; + } + if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_set_source_rgba(cairo, (color.red & 0xFFFF) / cast(float)0xFFFF, (color.green & 0xFFFF) / cast(float)0xFFFF, (color.blue & 0xFFFF) / cast(float)0xFFFF, data.alpha / cast(float)0xFF); + Cairo.cairo_set_line_width(cairo, width); + if (dashes !is null) { + double[] cairoDashes = new double[dashes.length]; + for (int j = 0; j < cairoDashes.length; j++) { + cairoDashes[j] = width is 0 || data.lineStyle is DWT.LINE_CUSTOM ? dashes[j] : dashes[j] * width; + } + Cairo.cairo_set_dash(cairo, cairoDashes.ptr, cairoDashes.length, 0); + } else { + Cairo.cairo_set_dash(cairo, null, 0, 0); + } + for (int j=0; j 0 && style.isAdherentUnderline(styles[j-1].style); j--) { + start = styles[j - 1].start; + } + start = translateOffset(start); + int end = translateOffset(styles[i+1].start - 1); + int byteStart = cast(int)/*64*/(OS.g_utf8_offset_to_pointer(ptr, start) - ptr); + int byteEnd = cast(int)/*64*/(OS.g_utf8_offset_to_pointer(ptr, end + 1) - ptr); + int[] ranges = [byteStart, byteEnd]; + auto rgn = OS.gdk_pango_layout_get_clip_region(layout, x, y, ranges.ptr, ranges.length / 2); + if (rgn !is null) { + int nRects; + GdkRectangle* rects; + OS.gdk_region_get_rectangles(rgn, &rects, &nRects); + GdkRectangle rect; + GdkColor* color = null; + if (color is null && style.underlineColor !is null) color = style.underlineColor.handle; + if (color is null && selectionColor !is null) color = selectionColor; + if (color is null && style.foreground !is null) color = style.foreground.handle; + if (color is null) color = data.foreground; + if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_set_source_rgba(cairo, (color.red & 0xFFFF) / cast(float)0xFFFF, (color.green & 0xFFFF) / cast(float)0xFFFF, (color.blue & 0xFFFF) / cast(float)0xFFFF, data.alpha / cast(float)0xFF); + } else { + if (gcValues is null) { + gcValues = new GdkGCValues(); + OS.gdk_gc_get_values(gdkGC, gcValues); + } + OS.gdk_gc_set_foreground(gdkGC, color); + } + int underlinePosition = -1; + int underlineThickness = 1; + if (OS.GTK_VERSION >= OS.buildVERSION(2, 6, 0)) { + Font font = style.font; + if (font is null) font = this.font; + if (font is null) font = device.systemFont; + auto lang = OS.pango_context_get_language(context); + auto metrics = OS.pango_context_get_metrics(context, font.handle, lang); + underlinePosition = OS.PANGO_PIXELS(OS.pango_font_metrics_get_underline_position(metrics)); + underlineThickness = OS.PANGO_PIXELS(OS.pango_font_metrics_get_underline_thickness(metrics)); + OS.pango_font_metrics_unref(metrics); + } + for (int j=0; j= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_set_line_width(cairo, squigglyThickness); + Cairo.cairo_set_line_cap(cairo, Cairo.CAIRO_LINE_CAP_BUTT); + Cairo.cairo_set_line_join(cairo, Cairo.CAIRO_LINE_JOIN_MITER); + if (points.length > 0) { + double xOffset = 0.5, yOffset = 0.5; + Cairo.cairo_move_to(cairo, points[0] + xOffset, points[1] + yOffset); + for (int k = 2; k < points.length; k += 2) { + Cairo.cairo_line_to(cairo, points[k] + xOffset, points[k + 1] + yOffset); + } + Cairo.cairo_stroke(cairo); + } + } else { + OS.gdk_gc_set_line_attributes(gdkGC, squigglyThickness, OS.GDK_LINE_SOLID, OS.GDK_CAP_BUTT, OS.GDK_JOIN_MITER); + OS.gdk_draw_lines(data.drawable, gdkGC, cast(GdkPoint*)points.ptr, points.length / 2); + } + break; + } + case DWT.UNDERLINE_DOUBLE: + if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_rectangle(cairo, rect.x, underlineY + underlineThickness * 2, rect.width, underlineThickness); + Cairo.cairo_fill(cairo); + } else { + OS.gdk_draw_rectangle(data.drawable, gdkGC, 1, rect.x, underlineY + underlineThickness * 2, rect.width, underlineThickness); + } + //FALLTHROUGH + case DWT.UNDERLINE_SINGLE: + if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_rectangle(cairo, rect.x, underlineY, rect.width, underlineThickness); + Cairo.cairo_fill(cairo); + } else { + OS.gdk_draw_rectangle(data.drawable, gdkGC, 1, rect.x, underlineY, rect.width, underlineThickness); + } + break; + } + } + if (rects !is null) OS.g_free(rects); + OS.gdk_region_destroy(rgn); + } + } + + bool drawStrikeout = false; + if (style.strikeout && style.strikeoutColor !is null) drawStrikeout = true; + if (drawStrikeout && !style.isAdherentStrikeout(styles[i+1].style)) { + int start = styles[i].start; + for (int j = i; j > 0 && style.isAdherentStrikeout(styles[j-1].style); j--) { + start = styles[j - 1].start; + } + start = translateOffset(start); + int end = translateOffset(styles[i+1].start - 1); + int byteStart = cast(int)/*64*/(OS.g_utf8_offset_to_pointer(ptr, start) - ptr); + int byteEnd = cast(int)/*64*/(OS.g_utf8_offset_to_pointer(ptr, end + 1) - ptr); + int[] ranges = [byteStart, byteEnd]; + auto rgn = OS.gdk_pango_layout_get_clip_region(layout, x, y, ranges.ptr, ranges.length / 2); + if (rgn !is null) { + int nRects; + GdkRectangle* rects; + OS.gdk_region_get_rectangles(rgn, &rects, &nRects); + GdkRectangle rect; + GdkColor* color = null; + if (color is null && style.strikeoutColor !is null) color = style.strikeoutColor.handle; + if (color is null && selectionColor !is null) color = selectionColor; + if (color is null && style.foreground !is null) color = style.foreground.handle; + if (color is null) color = data.foreground; + if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_set_source_rgba(cairo, (color.red & 0xFFFF) / cast(float)0xFFFF, (color.green & 0xFFFF) / cast(float)0xFFFF, (color.blue & 0xFFFF) / cast(float)0xFFFF, data.alpha / cast(float)0xFF); + } else { + if (gcValues is null) { + gcValues = new GdkGCValues(); + OS.gdk_gc_get_values(gdkGC, gcValues); + } + OS.gdk_gc_set_foreground(gdkGC, color); + } + int strikeoutPosition = -1; + int strikeoutThickness = 1; + if (OS.GTK_VERSION >= OS.buildVERSION(2, 6, 0)) { + Font font = style.font; + if (font is null) font = this.font; + if (font is null) font = device.systemFont; + auto lang = OS.pango_context_get_language(context); + auto metrics = OS.pango_context_get_metrics(context, font.handle, lang); + strikeoutPosition = OS.PANGO_PIXELS(OS.pango_font_metrics_get_strikethrough_position(metrics)); + strikeoutThickness = OS.PANGO_PIXELS(OS.pango_font_metrics_get_strikethrough_thickness(metrics)); + OS.pango_font_metrics_unref(metrics); + } + for (int j=0; j= OS.buildVERSION(2, 6, 0)) { + int offset = getOffset(rect.x - x, rect.y - y, null); + int lineIndex = getLineIndex(offset); + FontMetrics metrics = getLineMetrics(lineIndex); + strikeoutY = rect.y + metrics.ascent - strikeoutPosition - style.rise; + } + if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_rectangle(cairo, rect.x, strikeoutY, rect.width, strikeoutThickness); + Cairo.cairo_fill(cairo); + } else { + OS.gdk_draw_rectangle(data.drawable, gdkGC, 1, rect.x, strikeoutY, rect.width, strikeoutThickness); + } + } + if (rects !is null) OS.g_free(rects); + OS.gdk_region_destroy(rgn); + } + } + } + if (gcValues !is null) { + int mask = OS.GDK_GC_FOREGROUND | OS.GDK_GC_LINE_WIDTH | OS.GDK_GC_LINE_STYLE | OS.GDK_GC_CAP_STYLE | OS.GDK_GC_JOIN_STYLE; + OS.gdk_gc_set_values(gdkGC, gcValues, mask); + data.state &= ~GC.LINE_STYLE; + } + if (cairo !is null && OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { + Cairo.cairo_restore(cairo); + } +} + void freeRuns() { if (attrList is null) return; OS.pango_layout_set_attributes(layout, null ); @@ -523,12 +851,13 @@ public int getAlignment() { checkLayout(); auto alignment = OS.pango_layout_get_alignment(layout); + bool rtl = OS.pango_context_get_base_dir(context) is OS.PANGO_DIRECTION_RTL; switch ( cast(int)alignment) { - case OS.PANGO_ALIGN_CENTER: return DWT.CENTER; - case OS.PANGO_ALIGN_RIGHT: return DWT.RIGHT; + case OS.PANGO_ALIGN_LEFT: return rtl ? DWT.RIGHT : DWT.LEFT; + case OS.PANGO_ALIGN_RIGHT: return rtl ? DWT.LEFT : DWT.RIGHT; default: } - return DWT.LEFT; + return DWT.CENTER; } /** @@ -565,7 +894,8 @@ int w, h; OS.pango_layout_get_size(layout, &w, &h); int wrapWidth = OS.pango_layout_get_width(layout); - int width = OS.PANGO_PIXELS(wrapWidth !is -1 ? wrapWidth : w); + w = wrapWidth !is -1 ? wrapWidth : w + OS.pango_layout_get_indent(layout); + int width = OS.PANGO_PIXELS(w); int height = OS.PANGO_PIXELS(h); if (ascent !is -1 && descent !is -1) { height = Math.max (height, ascent + descent); @@ -590,11 +920,11 @@ public Rectangle getBounds(int start, int end) { checkLayout(); computeRuns(); - int length = text.length; - if (length is 0) return new Rectangle(0, 0, 0, 0); + int length_ = text.length; + if (length_ is 0) return new Rectangle(0, 0, 0, 0); if (start > end) return new Rectangle(0, 0, 0, 0); - start = Math.min(Math.max(0, start), length - 1); - end = Math.min(Math.max(0, end), length - 1); + start = Math.min(Math.max(0, start), length_ - 1); + end = Math.min(Math.max(0, end), length_ - 1); start = translateOffset(start); end = translateOffset(end); auto ptr = OS.pango_layout_get_text(layout); @@ -646,6 +976,9 @@ OS.gdk_region_get_clipbox(clipRegion, &rect); OS.gdk_region_destroy(clipRegion); + if (OS.pango_context_get_base_dir(context) is OS.PANGO_DIRECTION_RTL) { + rect.x = width() - rect.x - rect.width; + } return new Rectangle(rect.x, rect.y, rect.width, rect.height); } @@ -732,8 +1065,8 @@ public int getLevel(int offset) { checkLayout(); computeRuns(); - int length = text.length; - if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE); + int length_ = text.length; + if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE); offset = translateOffset(offset); auto iter = OS.pango_layout_get_iter(layout); if (iter is null) DWT.error(DWT.ERROR_NO_HANDLES); @@ -785,12 +1118,15 @@ OS.pango_layout_iter_free(iter); int x = OS.PANGO_PIXELS(rect.x); int y = OS.PANGO_PIXELS(rect.y); - int width = OS.PANGO_PIXELS(rect.width); + int width_ = OS.PANGO_PIXELS(rect.width); int height = OS.PANGO_PIXELS(rect.height); if (ascent !is -1 && descent !is -1) { height = Math.max (height, ascent + descent); } - return new Rectangle(x, y, width, height); + if (OS.pango_context_get_base_dir(context) is OS.PANGO_DIRECTION_RTL) { + x = width() - x - width_; + } + return new Rectangle(x, y, width_, height); } /** @@ -826,8 +1162,8 @@ public int getLineIndex(int offset) { checkLayout (); computeRuns(); - int length = text.length; - if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + int length_ = text.length; + if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); offset = translateOffset(offset); int line = 0; auto ptr = OS.pango_layout_get_text(layout); @@ -900,15 +1236,11 @@ int lineCount = OS.pango_layout_get_line_count(layout); int[] offsets = new int [lineCount + 1]; auto ptr = OS.pango_layout_get_text(layout); - auto iter = OS.pango_layout_get_iter(layout); - if (iter is null) DWT.error(DWT.ERROR_NO_HANDLES); - int i = 0; - do { - int bytePos = OS.pango_layout_iter_get_index(iter); - int pos = bytePos;//OS.g_utf8_pointer_to_offset(ptr, ptr + bytePos); - offsets[i++] = untranslateOffset(pos); - } while (OS.pango_layout_iter_next_line(iter)); - OS.pango_layout_iter_free(iter); + for (int i = 0; i < lineCount; i++) { + auto line = OS.pango_layout_get_line(layout, i); + int pos = cast(int)/*64*/OS.g_utf8_pointer_to_offset(ptr, ptr + line.start_index); + offsets[i] = untranslateOffset(pos); + } offsets[lineCount] = text.length; return offsets; } @@ -932,8 +1264,8 @@ public Point getLocation(int offset, bool trailing) { checkLayout(); computeRuns(); - int length = text.length; - if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE); + int length_ = text.length; + if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE); offset = translateOffset(offset); auto ptr = OS.pango_layout_get_text(layout); auto cont = fromStringz(ptr); @@ -946,7 +1278,11 @@ OS.pango_layout_index_to_pos(layout, byteOffset, pos); int x = trailing ? pos.x + pos.width : pos.x; int y = pos.y; - return new Point(OS.PANGO_PIXELS(x), OS.PANGO_PIXELS(y)); + x = OS.PANGO_PIXELS(x); + if (OS.pango_context_get_base_dir(context) is OS.PANGO_DIRECTION_RTL) { + x = width() - x; + } + return new Point(x, OS.PANGO_PIXELS(y)); } /** @@ -975,10 +1311,10 @@ int _getOffset (int offset, int movement, bool forward) { checkLayout(); computeRuns(); - int length = text.length; - if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE); + int length_ = text.length; + if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE); if (forward) { - if (offset is length) return length; + if (offset is length_) return length_; } else { if (offset is 0) return 0; } @@ -997,12 +1333,12 @@ int nAttrs; OS.pango_layout_get_log_attrs(layout, &attrs, &nAttrs); if (attrs is null) return offset + step; - length = OS.g_utf8_strlen(cont, -1); + length_ = OS.g_utf8_strlen(cont, -1); offset = translateOffset(offset); offset = dcont.utf8AdjustOffset( offset ); PangoLogAttr* logAttr = new PangoLogAttr(); offset = validateOffset( dcont, offset, step); - while (0 < offset && offset < length) { + while (0 < offset && offset < length_) { *logAttr = attrs[ offset ]; if (((movement & DWT.MOVEMENT_CLUSTER) !is 0) && ( logAttr.bitfield0 & (1<<4/*is_cursor_position*/))) break; if ((movement & DWT.MOVEMENT_WORD) !is 0) { @@ -1080,6 +1416,9 @@ checkLayout(); computeRuns(); if (trailing !is null && trailing.length < 1) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + if (OS.pango_context_get_base_dir(context) is OS.PANGO_DIRECTION_RTL) { + x = width() - x; + } /* * Feature in GTK. pango_layout_xy_to_index() returns the @@ -1257,8 +1596,8 @@ */ public TextStyle getStyle (int offset) { checkLayout(); - int length = text.length; - if (!(0 <= offset && offset < length)) DWT.error(DWT.ERROR_INVALID_RANGE); + int length_ = text.length; + if (!(0 <= offset && offset < length_)) DWT.error(DWT.ERROR_INVALID_RANGE); for (int i=1; i offset) { @@ -1382,13 +1721,17 @@ if (alignment is 0) return; if ((alignment & DWT.LEFT) !is 0) alignment = DWT.LEFT; if ((alignment & DWT.RIGHT) !is 0) alignment = DWT.RIGHT; - int al = OS.PANGO_ALIGN_LEFT; + bool rtl = OS.pango_context_get_base_dir(context) is OS.PANGO_DIRECTION_RTL; + int align_ = OS.PANGO_ALIGN_CENTER; switch (alignment) { - case DWT.CENTER: al = OS.PANGO_ALIGN_CENTER; break; - case DWT.RIGHT: al = OS.PANGO_ALIGN_RIGHT; break; - default: + case DWT.LEFT: + align_ = rtl ? OS.PANGO_ALIGN_RIGHT : OS.PANGO_ALIGN_LEFT; + break; + case DWT.RIGHT: + align_ = rtl ? OS.PANGO_ALIGN_LEFT : OS.PANGO_ALIGN_RIGHT; + break; } - OS.pango_layout_set_alignment(layout, al); + OS.pango_layout_set_alignment(layout, align_); } /** @@ -1462,13 +1805,13 @@ public void setFont (Font font) { checkLayout (); if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - if (this.font is font) return; - if (font !is null && font.opEquals(this.font)) return; + Font oldFont = this.font; + if (oldFont is font) return; this.font = font; - OS.pango_layout_set_font_description(layout, font !is null ? font.handle : null); + if (oldFont !is null && oldFont.opEquals(font)) return; + OS.pango_layout_set_font_description(layout, font !is null ? font.handle : device.systemFont.handle); } - /** * Sets the indent of the receiver. This indent it applied of the first line of * each paragraph. @@ -1524,6 +1867,11 @@ if (OS.pango_context_get_base_dir(context) is baseDir) return; OS.pango_context_set_base_dir(context, baseDir); OS.pango_layout_context_changed(layout); + int align_ = OS.pango_layout_get_alignment(layout); + if (align_ !is OS.PANGO_ALIGN_CENTER) { + align_ = align_ is OS.PANGO_ALIGN_LEFT ? OS.PANGO_ALIGN_RIGHT : OS.PANGO_ALIGN_LEFT; + OS.pango_layout_set_alignment(layout, align_); + } } /** @@ -1594,11 +1942,11 @@ */ public void setStyle (TextStyle style, int start, int end) { checkLayout(); - int length = text.length; - if (length is 0) return; + int length_ = text.length; + if (length_ is 0) return; if (start > end) return; - start = Math.min(Math.max(0, start), length - 1); - end = Math.min(Math.max(0, end), length - 1); + start = Math.min(Math.max(0, start), length_ - 1); + end = Math.min(Math.max(0, end), length_ - 1); start = text.utf8AdjustOffset( start ); end = text.utf8AdjustOffset( end ); @@ -1614,7 +1962,7 @@ if ((start > 0 ) && isAlef(text[ start .. $ ].firstCodePoint()) && isLam(text.getRelativeCodePoint( start, -1, relIndex ))) { start += relIndex; } - if ((end < length - 1) && isLam(text[ end .. $ ].firstCodePoint()) && isAlef(text.getRelativeCodePoint(end, 1,relIndex))) { + if ((end < length_ - 1) && isLam(text[ end .. $ ].firstCodePoint()) && isAlef(text.getRelativeCodePoint(end, 1,relIndex))) { end += relIndex; } @@ -1766,7 +2114,13 @@ checkLayout (); if (width < -1 || width is 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); freeRuns(); - OS.pango_layout_set_width(layout, width is -1 ? -1 : width * OS.PANGO_SCALE); + if (width is -1) { + OS.pango_layout_set_width(layout, -1); + bool rtl = OS.pango_context_get_base_dir(context) is OS.PANGO_DIRECTION_RTL; + OS.pango_layout_set_alignment(layout, rtl ? OS.PANGO_ALIGN_RIGHT : OS.PANGO_ALIGN_LEFT); + } else { + OS.pango_layout_set_width(layout, width * OS.PANGO_SCALE); + } } static final bool isLam(int ch) { @@ -1806,8 +2160,8 @@ * Translate a client offset to an internal offset */ int translateOffset(int offset) { - int length = text.length; - if (length is 0) return offset; + int length_ = text.length; + if (length_ is 0) return offset; if (invalidOffsets is null) return offset; for (int i = 0; i < invalidOffsets.length; i++) { if (offset < invalidOffsets[i]) break; @@ -1820,8 +2174,8 @@ * Translate an internal offset to a client offset */ int untranslateOffset(int offset) { - int length = text.length; - if (length is 0) return offset; + int length_ = text.length; + if (length_ is 0) return offset; if (invalidOffsets is null) return offset; for (int i = 0; i < invalidOffsets.length; i++) { if (offset is invalidOffsets[i]) { @@ -1853,4 +2207,12 @@ return offset; } +int width () { + int wrapWidth = OS.pango_layout_get_width(layout); + if (wrapWidth !is -1) return OS.PANGO_PIXELS(wrapWidth); + int w, h; + OS.pango_layout_get_size(layout, &w, &h); + return OS.PANGO_PIXELS(w + OS.pango_layout_get_indent(layout)); } + +} diff -r 06a1f6829310 -r ce446666f5a2 dwt/graphics/TextStyle.d --- a/dwt/graphics/TextStyle.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/TextStyle.d Mon May 12 19:13:01 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -59,13 +59,40 @@ public Color background; /** - * the underline flag of the style + * the underline flag of the style. The default underline + * style is DWT.UNDERLINE_SINGLE. + * * * @since 3.1 */ public bool underline; /** + * the underline color of the style + * + * @since 3.4 + */ + public Color underlineColor; + + /** + * the underline style. This style is ignored when + * underline is false. + *

+ * This value should be one of DWT.UNDERLINE_SINGLE, + * DWT.UNDERLINE_DOUBLE, DWT.UNDERLINE_ERROR, + * or DWT.UNDERLINE_SQUIGGLE. + *

+ * + * @see DWT#UNDERLINE_SINGLE + * @see DWT#UNDERLINE_DOUBLE + * @see DWT#UNDERLINE_ERROR + * @see DWT#UNDERLINE_SQUIGGLE + * + * @since 3.4 + */ + public int underlineStyle; + + /** * the strikeout flag of the style * * @since 3.1 @@ -73,6 +100,37 @@ public bool strikeout; /** + * the strikeout color of the style + * + * @since 3.4 + */ + public Color strikeoutColor; + + /** + * the border style. The default border style is DWT.NONE. + *

+ * This value should be one of DWT.BORDER_SOLID, + * DWT.BORDER_DASH,DWT.BORDER_DOT or + * DWT.NONE. + *

+ * + * @see DWT#BORDER_SOLID + * @see DWT#BORDER_DASH + * @see DWT#BORDER_DOT + * @see DWT#NONE + * + * @since 3.4 + */ + public int borderStyle; + + /** + * the border color of the style + * + * @since 3.4 + */ + public Color borderColor; + + /** * the GlyphMetrics of the style * * @since 3.2 @@ -86,17 +144,12 @@ */ public int rise; -/++ - + DWT extension for clone implementation - +/ -protected this( TextStyle other ){ - font = other.font; - foreground = other.foreground; - background = other.background; - underline = other.underline; - strikeout = other.strikeout; - metrics = other.metrics; - rise = other.rise; +/** + * Create an empty text style. + * + * @since 3.4 + */ +public this () { } /** @@ -116,6 +169,30 @@ this.background = background; } + +/** + * Create a new text style from an existing text style. + * + *@param style the style to copy + * + * @since 3.4 + */ +public this (TextStyle style) { + if (style is null) DWT.error (DWT.ERROR_INVALID_ARGUMENT); + font = style.font; + foreground = style.foreground; + background = style.background; + underline = style.underline; + underlineColor = style.underlineColor; + underlineStyle = style.underlineStyle; + strikeout = style.strikeout; + strikeoutColor = style.strikeoutColor; + borderStyle = style.borderStyle; + borderColor = style.borderColor; + metrics = style.metrics; + rise = style.rise; +} + /** * Compares the argument to the receiver, and returns true * if they represent the same object using a class @@ -142,8 +219,20 @@ } else if (style.font !is null) return false; if (metrics !is null || style.metrics !is null) return false; if (underline !is style.underline) return false; + if (underlineStyle !is style.underlineStyle) return false; + if (borderStyle !is style.borderStyle) return false; if (strikeout !is style.strikeout) return false; if (rise !is style.rise) return false; + if (underlineColor !is null) { + if (!underlineColor.opEquals(style.underlineColor)) return false; + } else if (style.underlineColor !is null) return false; + if (strikeoutColor !is null) { + if (!strikeoutColor.opEquals(style.strikeoutColor)) return false; + } else if (style.strikeoutColor !is null) return false; + if (underlineStyle !is style.underlineStyle) return false; + if (borderColor !is null) { + if (!borderColor.opEquals(style.borderColor)) return false; + } else if (style.borderColor !is null) return false; return true; } @@ -166,9 +255,44 @@ if (underline) hash ^= hash; if (strikeout) hash ^= hash; hash ^= rise; + if (underlineColor !is null) hash ^= underlineColor.toHash(); + if (strikeoutColor !is null) hash ^= strikeoutColor.toHash(); + if (borderColor !is null) hash ^= borderColor.toHash(); + hash ^= underlineStyle; return hash; } +bool isAdherentBorder(TextStyle style) { + if (this is style) return true; + if (style is null) return false; + if (borderStyle !is style.borderStyle) return false; + if (borderColor !is null) { + if (!borderColor.opEquals(style.borderColor)) return false; + } else if (style.borderColor !is null) return false; + return true; +} + +bool isAdherentUnderline(TextStyle style) { + if (this is style) return true; + if (style is null) return false; + if (underline !is style.underline) return false; + if (underlineStyle !is style.underlineStyle) return false; + if (underlineColor !is null) { + if (!underlineColor.opEquals(style.underlineColor)) return false; + } else if (style.underlineColor !is null) return false; + return true; +} + +bool isAdherentStrikeout(TextStyle style) { + if (this is style) return true; + if (style is null) return false; + if (strikeout !is style.strikeout) return false; + if (strikeoutColor !is null) { + if (!strikeoutColor.opEquals(style.strikeoutColor)) return false; + } else if (style.strikeoutColor !is null) return false; + return true; +} + /** * Returns a string containing a concise, human-readable * description of the receiver. diff -r 06a1f6829310 -r ce446666f5a2 dwt/graphics/Transform.d --- a/dwt/graphics/Transform.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Transform.d Mon May 12 19:13:01 2008 +0200 @@ -135,14 +135,12 @@ * @see #dispose() */ public this (Device device, float m11, float m12, float m21, float m22, float dx, float dy) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; - device.checkCairo(); + super(device); + this.device.checkCairo(); handle = new double[6]; if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); Cairo.cairo_matrix_init( cast(cairo_matrix_t*)handle.ptr, m11, m12, m21, m22, dx, dy); - if (device.tracking) device.new_Object(this); + init_(); } static float[] checkTransform(float[] elements) { @@ -151,17 +149,8 @@ return elements; } -/** - * Disposes of the operating system resources associated with - * the Transform. Applications must dispose of all Transforms that - * they allocate. - */ -public override void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -190,6 +179,11 @@ elements[5] = cast(float)handle[5]; } +public void identity() { + if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + Cairo.cairo_matrix_init(cast(cairo_matrix_t*)handle.ptr, 1, 0, 0, 1, 0, 0); +} + /** * Modifies the receiver such that the matrix it represents becomes the * the mathematical inverse of the matrix it previously represented. @@ -309,6 +303,12 @@ Cairo.cairo_matrix_init(cast(cairo_matrix_t*)handle.ptr, m11, m12, m21, m22, dx, dy); } +public void shear(float shearX, float shearY) { + if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + double[] matrix = [ 1.0, shearX, shearY, 1, 0, 0]; + Cairo.cairo_matrix_multiply(cast(cairo_matrix_t*)handle.ptr, cast(cairo_matrix_t*)matrix.ptr, cast(cairo_matrix_t*)handle.ptr); +} + /** * Given an array containing points described by alternating x and y values, * modify that array such that each point has been replaced with the result of diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/BidiUtil.d --- a/dwt/internal/BidiUtil.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/BidiUtil.d Mon May 12 19:13:01 2008 +0200 @@ -15,8 +15,9 @@ import dwt.dwthelper.utils; import dwt.graphics.GC; +import dwt.widgets.Control; +import dwt.dwthelper.Runnable; import dwt.internal.gtk.OS; -import dwt.dwthelper.Runnable; /* * This class is supplied so that the StyledText code that supports bidi text (supported @@ -49,6 +50,8 @@ */ public static void addLanguageListener(GtkWidget* hwnd, Runnable runnable) { } +public static void addLanguageListener (Control control, Runnable runnable) { +} /* * Not implemented. * @@ -98,6 +101,8 @@ */ public static void removeLanguageListener(GtkWidget* hwnd) { } +public static void removeLanguageListener (Control control) { +} /* * Not implemented. */ @@ -109,4 +114,7 @@ public static bool setOrientation(GtkWidget* hwnd, int orientation) { return false; } +public static bool setOrientation (Control control, int orientation) { + return false; } +} diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/Compatibility.d --- a/dwt/internal/Compatibility.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/Compatibility.d Mon May 12 19:13:01 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 @@ -13,12 +13,12 @@ module dwt.internal.Compatibility; import dwt.dwthelper.utils; - /+ -import java.io.*; +import java.io.File; import java.text.MessageFormat; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; +/ @@ -26,6 +26,7 @@ public import dwt.dwthelper.FileInputStream; public import dwt.dwthelper.FileOutputStream; public import dwt.dwthelper.InflaterInputStream; +import dwt.dwthelper.BufferedInputStream; import Math = tango.math.Math; import Unicode = tango.text.Unicode; @@ -110,6 +111,17 @@ } /** + * Answers whether the indicated file exists or not. + * + * @param parent the file's parent directory + * @param child the file's name + * @return true if the file exists + */ +public static bool fileExists(String parent, String child) { + return (new File (parent, child)).exists(); +} + +/** * Answers the most positive (i.e. closest to positive infinity) * integer value which is less than the number obtained by dividing * the first argument p by the second argument q. @@ -159,6 +171,21 @@ } /** + * Create an DeflaterOutputStream if such things are supported. + * + * @param stream the output stream + * @return a deflater stream or null + * @exception IOException + * + * @since 3.4 + */ +public static OutputStream newDeflaterOutputStream(OutputStream stream) { + implMissing(__FILE__,__LINE__); + return null; + //DWT_TODO return new DeflaterOutputStream(stream); +} + +/** * Open a file if such things are supported. * * @param filename the name of the file to open diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/DWTMessages.properties --- a/dwt/internal/DWTMessages.properties Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/DWTMessages.properties Mon May 12 19:13:01 2008 +0200 @@ -71,3 +71,5 @@ SWT_Download_Location=Saving {0} from {1} SWT_Download_Started=Downloading... SWT_Download_Status=Download: {0,number,integer} KB of {1,number,integer} KB +SWT_Authentication_Required=Authentication Required +SWT_Enter_Username_and_Password=Enter user name and password for {0} at {1} diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/LONG.d --- a/dwt/internal/LONG.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/LONG.d Mon May 12 19:13:01 2008 +0200 @@ -12,24 +12,6 @@ *******************************************************************************/ module dwt.internal.LONG; -public class LONG { - public int /*long*/ value; - - public this (int /*long*/ value) { - this.value = value; - } +import dwt.dwthelper.utils; - public override int opEquals (Object object) { - if (object is this){ - return true; - } - if ( auto obj = cast(LONG)object ) { - return obj.value == this.value; - } - return false; - } - - public override hash_t toHash () { - return /*64*/value; - } -} +alias Integer LONG; diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/Library.d --- a/dwt/internal/Library.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/Library.d Mon May 12 19:13:01 2008 +0200 @@ -35,7 +35,7 @@ /** * DWT Minor version number (must be in the range 0..999) */ - static const int MINOR_VERSION = 349; + static const int MINOR_VERSION = 442; /** * DWT revision number (must be >= 0) @@ -179,6 +179,20 @@ * @param mapName true if the name should be mapped, false otherwise */ public static void loadLibrary (String name, boolean mapName) { + String prop = System.getProperty ("sun.arch.data.model"); //$NON-NLS-1$ + if (prop is null) prop = System.getProperty ("com.ibm.vm.bitmode"); //$NON-NLS-1$ + if (prop !is null) { + if ("32".equals (prop)) { //$NON-NLS-1$ + if (0x1FFFFFFFFL is (int /*long*/)0x1FFFFFFFFL) { + throw new UnsatisfiedLinkError ("Cannot load 64-bit DWT libraries on 32-bit JVM"); //$NON-NLS-1$ + } + } + if ("64".equals (prop)) { //$NON-NLS-1$ + if (0x1FFFFFFFFL !is (int /*long*/)0x1FFFFFFFFL) { + throw new UnsatisfiedLinkError ("Cannot load 32-bit DWT libraries on 64-bit JVM"); //$NON-NLS-1$ + } + } + } /* Compute the library name and mapped name */ String libName1, libName2, mappedName1, mappedName2; diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/gtk/OS.d --- a/dwt/internal/gtk/OS.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/gtk/OS.d Mon May 12 19:13:01 2008 +0200 @@ -36,6 +36,7 @@ dwt.internal.c.Xrender, dwt.internal.c.glib_object; +static import tango.stdc.string; //version=GTK_DYN_LINK; public alias dwt.internal.c.glib_object.GPollFD GPollFD; @@ -52,6 +53,9 @@ public alias dwt.internal.c.glib_object.GInterfaceInfo GInterfaceInfo; public alias dwt.internal.c.glib_object.GTypeQuery GTypeQuery; public alias dwt.internal.c.glib_object.GError GError; +public alias dwt.internal.c.glib_object.GSignalEmissionHook GSignalEmissionHook; +public alias dwt.internal.c.glib_object.GSignalInvocationHint GSignalInvocationHint; +public alias dwt.internal.c.glib_object.GValue GValue; public alias dwt.internal.c.gdk.GdkColor GdkColor; public alias dwt.internal.c.gdk.GdkRegion GdkRegion; @@ -82,19 +86,21 @@ public alias dwt.internal.c.gdk.GdkEventWindowState GdkEventWindowState; public alias dwt.internal.c.gdk.GdkDragContext GdkDragContext; -public alias dwt.internal.c.pango.PangoFontDescription PangoFontDescription; -public alias dwt.internal.c.pango.PangoTabArray PangoTabArray; +public alias dwt.internal.c.pango.PangoAttrColor PangoAttrColor; +public alias dwt.internal.c.pango.PangoAttribute PangoAttribute; +public alias dwt.internal.c.pango.PangoAttrList PangoAttrList; +public alias dwt.internal.c.pango.PangoAttrInt PangoAttrInt; public alias dwt.internal.c.pango.PangoContext PangoContext; -public alias dwt.internal.c.pango.PangoLayout PangoLayout; -public alias dwt.internal.c.pango.PangoAttrList PangoAttrList; -public alias dwt.internal.c.pango.PangoFontFamily PangoFontFamily; +public alias dwt.internal.c.pango.PangoFontDescription PangoFontDescription; public alias dwt.internal.c.pango.PangoFontFace PangoFontFace; -public alias dwt.internal.c.pango.PangoRectangle PangoRectangle; -public alias dwt.internal.c.pango.PangoAttribute PangoAttribute; +public alias dwt.internal.c.pango.PangoFontFamily PangoFontFamily; +public alias dwt.internal.c.pango.PangoItem PangoItem; public alias dwt.internal.c.pango.PangoLogAttr PangoLogAttr; -public alias dwt.internal.c.pango.PangoItem PangoItem; +public alias dwt.internal.c.pango.PangoLayout PangoLayout; +public alias dwt.internal.c.pango.PangoLayoutLine PangoLayoutLine; public alias dwt.internal.c.pango.PangoLayoutRun PangoLayoutRun; -public alias dwt.internal.c.pango.PangoLayoutLine PangoLayoutLine; +public alias dwt.internal.c.pango.PangoRectangle PangoRectangle; +public alias dwt.internal.c.pango.PangoTabArray PangoTabArray; public alias dwt.internal.c.cairo.cairo_t cairo_t; public alias dwt.internal.c.cairo.cairo_pattern_t cairo_pattern_t; @@ -280,6 +286,7 @@ public alias dwt.internal.c.gtk.GtkFileChooserButtonClass GtkFileChooserButtonClass; public alias dwt.internal.c.gtk.GtkFileChooserButton GtkFileChooserButton; public alias dwt.internal.c.gtk.GtkFileFilterInfo GtkFileFilterInfo; +public alias dwt.internal.c.gtk.GtkFileFilter GtkFileFilter; public alias dwt.internal.c.gtk.GtkFixedChild GtkFixedChild; public alias dwt.internal.c.gtk.GtkFixedClass GtkFixedClass; public alias dwt.internal.c.gtk.GtkFixed GtkFixed; @@ -497,6 +504,7 @@ public alias dwt.internal.c.gtk.GtkEditable GtkEditable; public alias dwt.internal.c.gtk.GtkCallback GtkCallback; public alias dwt.internal.c.gtk.GtkAllocation GtkAllocation; +public alias dwt.internal.c.gtk.GtkPageSetup GtkPageSetup; public alias dwt.internal.c.gtk_unix_print_2_0.GtkPrinter GtkPrinter; @@ -552,6 +560,11 @@ g_signal_emit_by_name( instance, detailed_signal, value1, value2, value3 ); } +private void gdk_pixbuf_save_to_buffer0(GdkPixbuf *pixbuf, char **buffer, uint *buffer_size, + char *type, GError **error ){ + gdk_pixbuf_save_to_buffer( pixbuf, buffer, buffer_size, type, error ); +} + private void gtk_list_store_set1(void* store , void* iter, int column, void* value ){ gtk_list_store_set( cast(GtkListStore *)store, cast(GtkTreeIter *)iter, column, value, -1 ); } @@ -737,9 +750,14 @@ public static const int GDK_FLEUR = 0x34; public static const int GDK_FOCUS_CHANGE = 0xc; public static const int GDK_FOCUS_CHANGE_MASK = 0x4000; + public static const int GDK_GC_FOREGROUND = 0x1; public static const int GDK_GC_CLIP_MASK = 0x80; public static const int GDK_GC_CLIP_X_ORIGIN = 0x800; public static const int GDK_GC_CLIP_Y_ORIGIN = 0x1000; + public static const int GDK_GC_LINE_WIDTH = 0x4000; + public static const int GDK_GC_LINE_STYLE = 0x8000; + public static const int GDK_GC_CAP_STYLE = 0x10000; + public static const int GDK_GC_JOIN_STYLE = 0x20000; public static const int GDK_GRAB_SUCCESS = 0x0; public static const int GDK_HAND2 = 0x3c; public static const int GDK_Help = 0xFF6A; @@ -849,6 +867,7 @@ public static const int GDK_WINDOW_CHILD = 2; public static const int GDK_WINDOW_STATE_ICONIFIED = 1 << 1; public static const int GDK_WINDOW_STATE_MAXIMIZED = 1 << 2; + public static const int GDK_WINDOW_STATE_FULLSCREEN = 1 << 4; public static const int GTK_ACCEL_VISIBLE = 0x1; public static const int GTK_ARROW_DOWN = 0x1; public static const int GTK_ARROW_LEFT = 0x2; @@ -913,6 +932,7 @@ public static const int GTK_PROGRESS_LEFT_TO_RIGHT = 0x0; public static const int GTK_PROGRESS_BOTTOM_TO_TOP = 0x2; public static const int GTK_REALIZED = 1 << 6; + public static const int GTK_RECEIVES_DEFAULT = 1 << 20; public static const int GTK_RELIEF_NONE = 0x2; public static const int GTK_RELIEF_NORMAL = 0; public static const int GTK_RC_BG = 1 << 1; @@ -981,6 +1001,7 @@ public static const int GDK_WINDOW_TYPE_HINT_DIALOG = 1; public static const int GTK_WRAP_NONE = 0; public static const int GTK_WRAP_WORD = 2; + public static const int GTK_WRAP_WORD_CHAR = 3; public static const int G_LOG_FLAG_FATAL = 0x2; public static const int G_LOG_FLAG_RECURSION = 0x1; public static const int G_LOG_LEVEL_MASK = 0xfffffffc; @@ -988,6 +1009,10 @@ public static const int PANGO_ALIGN_LEFT = 0; public static const int PANGO_ALIGN_CENTER = 1; public static const int PANGO_ALIGN_RIGHT = 2; + public static const int PANGO_ATTR_FOREGROUND = 9; + public static const int PANGO_ATTR_BACKGROUND = 10; + public static const int PANGO_ATTR_UNDERLINE = 11; + public static final int PANGO_ATTR_UNDERLINE_COLOR = 18; public static const int PANGO_DIRECTION_LTR = 0; public static const int PANGO_DIRECTION_RTL = 1; public static const int PANGO_SCALE = 1024; @@ -996,8 +1021,11 @@ public static const int PANGO_STYLE_NORMAL = 0x0; public static const int PANGO_STYLE_OBLIQUE = 0x1; public static const int PANGO_TAB_LEFT = 0; + public static const int PANGO_UNDERLINE_NONE = 0; + public static const int PANGO_UNDERLINE_SINGLE = 1; + public static const int PANGO_UNDERLINE_DOUBLE = 2; public static const int PANGO_UNDERLINE_LOW = 3; - public static const int PANGO_UNDERLINE_SINGLE = 1; + public static const int PANGO_UNDERLINE_ERROR = 4; public static const int PANGO_WEIGHT_BOLD = 0x2bc; public static const int PANGO_WEIGHT_NORMAL = 0x190; public static const int PANGO_WRAP_WORD = 0; @@ -1050,6 +1078,7 @@ public static const char[] move_focus = "move-focus"; public static const char[] output = "output"; public static const char[] popup_menu = "popup-menu"; + public static final char[] populate_popup = "populate-popup"; public static const char[] preedit_changed = "preedit-changed"; public static const char[] realize = "realize"; public static const char[] row_activated = "row-activated"; @@ -1186,6 +1215,7 @@ mixin ForwardGtkOsCFunc!(.XFree); mixin ForwardGtkOsCFunc!(.XGetSelectionOwner); mixin ForwardGtkOsCFunc!(.XInternAtom); + mixin ForwardGtkOsCFunc!(.XQueryPointer); mixin ForwardGtkOsCFunc!(.XQueryTree); mixin ForwardGtkOsCFunc!(.XKeysymToKeycode); mixin ForwardGtkOsCFunc!(.XListProperties); @@ -1225,6 +1255,8 @@ mixin ForwardGtkOsCFunc!(.XRenderFindStandardFormat); mixin ForwardGtkOsCFunc!(.XRenderFindVisualFormat); + mixin ForwardGtkOsCFunc!(.g_signal_add_emission_hook); + mixin ForwardGtkOsCFunc!(.g_signal_remove_emission_hook); mixin ForwardGtkOsCFunc!(.g_cclosure_new); mixin ForwardGtkOsCFunc!(.g_closure_ref); mixin ForwardGtkOsCFunc!(.g_closure_unref); @@ -1305,6 +1337,7 @@ mixin ForwardGtkOsCFunc!(.g_utf8_pointer_to_offset); mixin ForwardGtkOsCFunc!(.g_utf8_strlen); mixin ForwardGtkOsCFunc!(.g_utf8_to_utf16); + mixin ForwardGtkOsCFunc!(.g_value_peek_pointer); mixin ForwardGtkOsCFunc!(.gdk_atom_intern); mixin ForwardGtkOsCFunc!(.gdk_atom_name); mixin ForwardGtkOsCFunc!(.gdk_beep); @@ -1347,6 +1380,7 @@ mixin ForwardGtkOsCFunc!(.gdk_event_get_state); mixin ForwardGtkOsCFunc!(.gdk_event_get_time); mixin ForwardGtkOsCFunc!(.gdk_event_handler_set); + mixin ForwardGtkOsCFunc!(.gdk_event_new); mixin ForwardGtkOsCFunc!(.gdk_event_peek); mixin ForwardGtkOsCFunc!(.gdk_event_put); mixin ForwardGtkOsCFunc!(.gdk_error_trap_push); @@ -1386,11 +1420,16 @@ mixin ForwardGtkOsCFunc!(.gdk_pixbuf_get_pixels); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_get_rowstride); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_get_width); + mixin ForwardGtkOsCFunc!(.gdk_pixbuf_loader_new); + mixin ForwardGtkOsCFunc!(.gdk_pixbuf_loader_close); + mixin ForwardGtkOsCFunc!(.gdk_pixbuf_loader_get_pixbuf); + mixin ForwardGtkOsCFunc!(.gdk_pixbuf_loader_write); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_new); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_new_from_file); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_render_to_drawable); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_render_to_drawable_alpha); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_render_pixmap_and_mask); + mixin ForwardGtkOsCFunc!(.gdk_pixbuf_save_to_buffer0); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_scale); mixin ForwardGtkOsCFunc!(.gdk_pixbuf_scale_simple); mixin ForwardGtkOsCFunc!(.gdk_pixmap_new); @@ -1425,7 +1464,8 @@ mixin ForwardGtkOsCFunc!(.gdk_set_program_class); mixin ForwardGtkOsCFunc!(.gdk_utf8_to_compound_text); mixin ForwardGtkOsCFunc!(.gdk_utf8_to_string_target); - mixin ForwardGtkOsCFunc!(.gdk_text_property_to_utf8_list ); + mixin ForwardGtkOsCFunc!(.gdk_text_property_to_utf8_list); + mixin ForwardGtkOsCFunc!(.gtk_tooltip_trigger_tooltip_query); mixin ForwardGtkOsCFunc!(.gdk_unicode_to_keyval); mixin ForwardGtkOsCFunc!(.gdk_visual_get_system); mixin ForwardGtkOsCFunc!(.gdk_window_at_pointer); @@ -1447,6 +1487,7 @@ mixin ForwardGtkOsCFunc!(.gdk_window_hide); mixin ForwardGtkOsCFunc!(.gdk_window_invalidate_rect); mixin ForwardGtkOsCFunc!(.gdk_window_invalidate_region); + mixin ForwardGtkOsCFunc!(.gdk_window_is_visible); mixin ForwardGtkOsCFunc!(.gdk_window_move); mixin ForwardGtkOsCFunc!(.gdk_window_new); mixin ForwardGtkOsCFunc!(.gdk_window_lower); @@ -1515,6 +1556,7 @@ mixin ForwardGtkOsCFunc!(.gtk_combo_disable_activate); mixin ForwardGtkOsCFunc!(.gtk_combo_new); mixin ForwardGtkOsCFunc!(.gtk_combo_set_case_sensitive); + mixin ForwardGtkOsCFunc!(.gtk_combo_box_set_focus_on_click); mixin ForwardGtkOsCFunc!(.gtk_combo_set_popdown_strings); mixin ForwardGtkOsCFunc!(.gtk_combo_box_entry_new_text); mixin ForwardGtkOsCFunc!(.gtk_combo_box_new_text); @@ -1585,13 +1627,17 @@ mixin ForwardGtkOsCFunc!(.gtk_file_chooser_get_current_folder); mixin ForwardGtkOsCFunc!(.gtk_file_chooser_get_filename); mixin ForwardGtkOsCFunc!(.gtk_file_chooser_get_filenames); + mixin ForwardGtkOsCFunc!(.gtk_file_chooser_get_filter); mixin ForwardGtkOsCFunc!(.gtk_file_chooser_set_current_folder); mixin ForwardGtkOsCFunc!(.gtk_file_chooser_set_current_name); + mixin ForwardGtkOsCFunc!(.gtk_file_chooser_set_do_overwrite_confirmation); mixin ForwardGtkOsCFunc!(.gtk_file_chooser_set_extra_widget); mixin ForwardGtkOsCFunc!(.gtk_file_chooser_set_filename); + mixin ForwardGtkOsCFunc!(.gtk_file_chooser_set_filter); mixin ForwardGtkOsCFunc!(.gtk_file_chooser_set_select_multiple); mixin ForwardGtkOsCFunc!(.gtk_file_filter_add_pattern); mixin ForwardGtkOsCFunc!(.gtk_file_filter_new); + mixin ForwardGtkOsCFunc!(.gtk_file_filter_get_name); mixin ForwardGtkOsCFunc!(.gtk_file_filter_set_name); mixin ForwardGtkOsCFunc!(.gtk_file_selection_get_filename); mixin ForwardGtkOsCFunc!(.gtk_file_selection_get_selections); @@ -1652,6 +1698,7 @@ mixin ForwardGtkOsCFunc!(.gtk_label_set_attributes); mixin ForwardGtkOsCFunc!(.gtk_label_set_justify); mixin ForwardGtkOsCFunc!(.gtk_label_set_line_wrap); + mixin ForwardGtkOsCFunc!(.gtk_label_set_line_wrap_mode); mixin ForwardGtkOsCFunc!(.gtk_label_set_text); mixin ForwardGtkOsCFunc!(.gtk_label_set_text_with_mnemonic); mixin ForwardGtkOsCFunc!(.gtk_list_append_items); @@ -1673,6 +1720,7 @@ mixin ForwardGtkOsCFunc!(.gtk_main_do_event); mixin ForwardGtkOsCFunc!(.gtk_menu_bar_new); mixin ForwardGtkOsCFunc!(.gtk_menu_item_remove_submenu); + mixin ForwardGtkOsCFunc!(.gtk_menu_item_get_submenu); mixin ForwardGtkOsCFunc!(.gtk_menu_item_set_submenu); mixin ForwardGtkOsCFunc!(.gtk_menu_new); mixin ForwardGtkOsCFunc!(.gtk_menu_popdown); @@ -1893,7 +1941,9 @@ mixin ForwardGtkOsCFunc!(.gtk_timeout_remove); mixin ForwardGtkOsCFunc!(.gtk_toggle_button_get_active); mixin ForwardGtkOsCFunc!(.gtk_toggle_button_new); + mixin ForwardGtkOsCFunc!(.gtk_toggle_button_get_inconsistent); mixin ForwardGtkOsCFunc!(.gtk_toggle_button_set_active); + mixin ForwardGtkOsCFunc!(.gtk_toggle_button_set_inconsistent); mixin ForwardGtkOsCFunc!(.gtk_toggle_button_set_mode); mixin ForwardGtkOsCFunc!(.gtk_toolbar_insert_widget); mixin ForwardGtkOsCFunc!(.gtk_toolbar_new); @@ -2029,6 +2079,7 @@ mixin ForwardGtkOsCFunc!(.gtk_widget_get_toplevel ); mixin ForwardGtkOsCFunc!(.gtk_widget_grab_focus); mixin ForwardGtkOsCFunc!(.gtk_widget_hide); + mixin ForwardGtkOsCFunc!(.gtk_widget_is_composited); mixin ForwardGtkOsCFunc!(.gtk_widget_is_focus); mixin ForwardGtkOsCFunc!(.gtk_widget_map); mixin ForwardGtkOsCFunc!(.gtk_widget_mnemonic_activate); @@ -2042,6 +2093,7 @@ mixin ForwardGtkOsCFunc!(.gtk_widget_realize); mixin ForwardGtkOsCFunc!(.gtk_widget_remove_accelerator); mixin ForwardGtkOsCFunc!(.gtk_widget_reparent); + mixin ForwardGtkOsCFunc!(.gtk_widget_send_expose); mixin ForwardGtkOsCFunc!(.gtk_widget_set_app_paintable); mixin ForwardGtkOsCFunc!(.gtk_widget_set_default_direction); mixin ForwardGtkOsCFunc!(.gtk_widget_set_direction); @@ -2064,13 +2116,21 @@ mixin ForwardGtkOsCFunc!(.gtk_window_add_accel_group); mixin ForwardGtkOsCFunc!(.gtk_window_deiconify); mixin ForwardGtkOsCFunc!(.gtk_window_get_focus); + mixin ForwardGtkOsCFunc!(.gtk_window_get_group); mixin ForwardGtkOsCFunc!(.gtk_window_get_icon_list); mixin ForwardGtkOsCFunc!(.gtk_window_get_modal); mixin ForwardGtkOsCFunc!(.gtk_window_get_mnemonic_modifier); + mixin ForwardGtkOsCFunc!(.gtk_window_get_opacity); mixin ForwardGtkOsCFunc!(.gtk_window_get_position); mixin ForwardGtkOsCFunc!(.gtk_window_get_size); + mixin ForwardGtkOsCFunc!(.gtk_window_group_add_window); + mixin ForwardGtkOsCFunc!(.gtk_window_group_remove_window); + mixin ForwardGtkOsCFunc!(.gtk_window_group_new); mixin ForwardGtkOsCFunc!(.gtk_window_iconify); + mixin ForwardGtkOsCFunc!(.gtk_window_list_toplevels); mixin ForwardGtkOsCFunc!(.gtk_window_maximize); + mixin ForwardGtkOsCFunc!(.gtk_window_fullscreen); + mixin ForwardGtkOsCFunc!(.gtk_window_unfullscreen); mixin ForwardGtkOsCFunc!(.gtk_window_move); mixin ForwardGtkOsCFunc!(.gtk_window_new); mixin ForwardGtkOsCFunc!(.gtk_window_present); @@ -2078,9 +2138,12 @@ mixin ForwardGtkOsCFunc!(.gtk_window_resize); mixin ForwardGtkOsCFunc!(.gtk_window_set_default); mixin ForwardGtkOsCFunc!(.gtk_window_set_destroy_with_parent); + mixin ForwardGtkOsCFunc!(.gtk_window_set_keep_below); mixin ForwardGtkOsCFunc!(.gtk_window_set_geometry_hints); mixin ForwardGtkOsCFunc!(.gtk_window_set_icon_list); mixin ForwardGtkOsCFunc!(.gtk_window_set_modal); + mixin ForwardGtkOsCFunc!(.gtk_window_set_opacity); + mixin ForwardGtkOsCFunc!(.gtk_widget_set_tooltip_text); mixin ForwardGtkOsCFunc!(.gtk_widget_set_parent_window); mixin ForwardGtkOsCFunc!(.gtk_window_set_resizable); mixin ForwardGtkOsCFunc!(.gtk_window_set_title); @@ -2095,9 +2158,17 @@ mixin ForwardGtkOsCFunc!(.pango_attr_shape_new); mixin ForwardGtkOsCFunc!(.pango_attr_list_insert); mixin ForwardGtkOsCFunc!(.pango_attr_list_change); + mixin ForwardGtkOsCFunc!(.pango_attr_list_get_iterator); + mixin ForwardGtkOsCFunc!(.pango_attr_iterator_next); + mixin ForwardGtkOsCFunc!(.pango_attr_iterator_range); + mixin ForwardGtkOsCFunc!(.pango_attr_iterator_get); + mixin ForwardGtkOsCFunc!(.pango_attr_iterator_get_attrs); + mixin ForwardGtkOsCFunc!(.pango_attr_iterator_destroy); mixin ForwardGtkOsCFunc!(.pango_attr_list_new); mixin ForwardGtkOsCFunc!(.pango_attr_list_unref); + mixin ForwardGtkOsCFunc!(.pango_attr_strikethrough_color_new); mixin ForwardGtkOsCFunc!(.pango_attr_strikethrough_new); + mixin ForwardGtkOsCFunc!(.pango_attr_underline_color_new); mixin ForwardGtkOsCFunc!(.pango_attr_underline_new); mixin ForwardGtkOsCFunc!(.pango_attr_weight_new); // mixin ForwardGtkOsCFunc!(.pango_cairo_font_map_get_default); @@ -2136,6 +2207,10 @@ mixin ForwardGtkOsCFunc!(.pango_font_metrics_get_approximate_char_width); mixin ForwardGtkOsCFunc!(.pango_font_metrics_get_ascent); mixin ForwardGtkOsCFunc!(.pango_font_metrics_get_descent); + mixin ForwardGtkOsCFunc!(.pango_font_metrics_get_underline_thickness); + mixin ForwardGtkOsCFunc!(.pango_font_metrics_get_underline_position); + mixin ForwardGtkOsCFunc!(.pango_font_metrics_get_strikethrough_thickness); + mixin ForwardGtkOsCFunc!(.pango_font_metrics_get_strikethrough_position); mixin ForwardGtkOsCFunc!(.pango_font_metrics_unref); mixin ForwardGtkOsCFunc!(.pango_language_from_string); mixin ForwardGtkOsCFunc!(.pango_layout_context_changed); @@ -2453,6 +2528,13 @@ return cast(bool)g_type_check_instance_is_a( cast(GTypeInstance*)arg0, gtk_image_menu_item_get_type ()); } + static bool GTK_IS_MENU_ITEM( void* arg0 ) + { + lock.lock(); + scope(exit) lock.unlock(); + return cast(bool)g_type_check_instance_is_a( cast(GTypeInstance*)arg0, gtk_menu_item_get_type ()); + } + static bool GTK_IS_PLUG( void* arg0 ) { lock.lock(); @@ -2873,6 +2955,9 @@ *arg1 = arg0.white_gc; } + static int strlen( char* ptr ){ + return tango.stdc.string.strlen( ptr ); + } //localeconv_decimal_point() localeconv()->decimal_point } diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/FileFormat.d --- a/dwt/internal/image/FileFormat.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/FileFormat.d Mon May 12 19:13:01 2008 +0200 @@ -82,7 +82,7 @@ public static ImageData[] load(InputStream istr, ImageLoader loader) { FileFormat fileFormat = null; LEDataInputStream stream = new LEDataInputStream(istr); - bool isSupported = false; + bool isSupported = false; foreach( TFormat; TFormats ){ try{ fileFormat = new TFormat(); diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/GIFFileFormat.d --- a/dwt/internal/image/GIFFileFormat.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/GIFFileFormat.d Mon May 12 19:13:01 2008 +0200 @@ -24,8 +24,6 @@ import tango.core.Exception; import dwt.dwthelper.utils; -///FORTING_TYPE -class Image{} final class GIFFileFormat : FileFormat { String signature; @@ -64,7 +62,7 @@ byte[3] signature; stream.read(signature); stream.unread(signature); - return cast(String)signature == "GIF"; //$NON-NLS-1$ + return signature[0] is 'G' && signature[1] is 'I' && signature[2] is 'F'; } catch (Exception e) { return false; } @@ -75,13 +73,12 @@ * Return an array of ImageData representing the image(s). */ override ImageData[] loadFromByteStream() { - byte[3] signatureBytes; + byte[3] signature; byte[3] versionBytes; byte[7] block; try { - inputStream.read(signatureBytes); - signature = cast(String)signatureBytes.dup; - if (signature != "GIF") //$NON-NLS-1$ + inputStream.read(signature); + if (!(signature[0] is 'G' && signature[1] is 'I' && signature[2] is 'F')) DWT.error(DWT.ERROR_INVALID_IMAGE); inputStream.read(versionBytes); @@ -315,13 +312,11 @@ // Read size of block = 0x0B. inputStream.read(); // Read application identifier. - byte[] applicationBytes = new byte[8]; - inputStream.read(applicationBytes); - String application = cast(String)(applicationBytes.dup); + byte[] application = new byte[8]; + inputStream.read(application); // Read authentication code. - byte[] authenticationBytes = new byte[3]; - inputStream.read(authenticationBytes); - String authentication = cast(String)(authenticationBytes.dup); + byte[] authentication = new byte[3]; + inputStream.read(authentication); // Read application data. byte[] data = new byte[0]; byte[] block = new byte[255]; @@ -335,7 +330,20 @@ size = inputStream.read(); } // Look for the NETSCAPE 'repeat count' field for an animated GIF. - if (application=="NETSCAPE" && authentication=="2.0" && data[0] is 01) { //$NON-NLS-1$ //$NON-NLS-2$ + bool netscape = + application[0] is 'N' && + application[1] is 'E' && + application[2] is 'T' && + application[3] is 'S' && + application[4] is 'C' && + application[5] is 'A' && + application[6] is 'P' && + application[7] is 'E'; + bool authentic = + authentication[0] is '2' && + authentication[1] is '.' && + authentication[2] is '0'; + if (netscape && authentic && data[0] is 01) { //$NON-NLS-1$ //$NON-NLS-2$ repeatCount = (data[1] & 0xFF) | ((data[2] & 0xFF) << 8); loader.repeatCount = repeatCount; } diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/JPEGDecoder.d --- a/dwt/internal/image/JPEGDecoder.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/JPEGDecoder.d Mon May 12 19:13:01 2008 +0200 @@ -979,7 +979,7 @@ r = s >> 4; s &= 15; if (s !is 0) { - if (s !is 1) { /* size of new coef should always be 1 */ + if (s !is 1) { /* size of new coef should always be 1 */ // WARNMS(cinfo, JWRN_HUFF_BAD_CODE); } // CHECK_BIT_BUFFER(br_state, 1, goto undoit); @@ -1242,7 +1242,7 @@ k += 15; /* skip 15 zeroes in band */ } else { /* EOBr, run length is 2^r + appended bits */ EOBRUN = 1 << r; - if (r !is 0) { /* EOBr, r > 0 */ + if (r !is 0) { /* EOBr, r > 0 */ // CHECK_BIT_BUFFER(br_state, r, return FALSE); { if (bits_left < (r)) { @@ -1280,7 +1280,7 @@ return true; } - bool decode_mcu_DC_first (jpeg_decompress_struct cinfo, short[][] MCU_data) { + bool decode_mcu_DC_first (jpeg_decompress_struct cinfo, short[][] MCU_data) { phuff_entropy_decoder entropy = this; int Al = cinfo.Al; int s = 0, r; @@ -1644,7 +1644,7 @@ /* Variables for Floyd-Steinberg dithering */ // FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ - bool on_odd_row; + bool on_odd_row; void start_pass (jpeg_decompress_struct cinfo, bool is_pre_scan) { error(); @@ -4448,7 +4448,7 @@ length -= count; - if ((index & 0x10) !is 0) { /* AC table definition */ + if ((index & 0x10) !is 0) { /* AC table definition */ index -= 0x10; htblptr = cinfo.ac_huff_tbl_ptrs[index] = new JHUFF_TBL(); } else { /* DC table definition */ @@ -5237,7 +5237,7 @@ // GETJOCTET(data[12]), GETJOCTET(data[13])); } totallen -= APP0_DATA_LEN; - if (totallen !is ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) { + if (totallen !is ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) { // TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, cast(int) totallen); } } else if (datalen >= 6 && diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/JPEGFileFormat.d --- a/dwt/internal/image/JPEGFileFormat.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/JPEGFileFormat.d Mon May 12 19:13:01 2008 +0200 @@ -152,7 +152,7 @@ RCbTable, GCbTable, BCbTable, RCrTable, GCrTable, BCrTable, NBitsTable; //public static void static_this() { static this() { - initialize(); + RGB16 = [ new RGB(0,0,0), new RGB(0x80,0,0), @@ -171,6 +171,65 @@ new RGB(0,0xFF,0xFF), new RGB(0xFF,0xFF,0xFF) ]; + int [] rYTable = new int[256]; + int [] gYTable = new int[256]; + int [] bYTable = new int[256]; + int [] rCbTable = new int[256]; + int [] gCbTable = new int[256]; + int [] bCbTable = new int[256]; + int [] rCrTable = new int[256]; + int [] gCrTable = new int[256]; + int [] bCrTable = new int[256]; + for (int i = 0; i < 256; i++) { + rYTable[i] = i * 19595; + gYTable[i] = i * 38470; + bYTable[i] = i * 7471 + 32768; + rCbTable[i] = i * -11059; + gCbTable[i] = i * -21709; + bCbTable[i] = i * 32768 + 8388608; + gCrTable[i] = i * -27439; + bCrTable[i] = i * -5329; + } + RYTable = rYTable; + GYTable = gYTable; + BYTable = bYTable; + RCbTable = rCbTable; + GCbTable = gCbTable; + BCbTable = bCbTable; + RCrTable = bCbTable; + GCrTable = gCrTable; + BCrTable = bCrTable; + + /* Initialize YCbCr-RGB Tables */ + int [] crRTable = new int[256]; + int [] cbBTable = new int[256]; + int [] crGTable = new int[256]; + int [] cbGTable = new int[256]; + for (int i = 0; i < 256; i++) { + int x2 = 2 * i - 255; + crRTable[i] = (45941 * x2 + 32768) >> 16; + cbBTable[i] = (58065 * x2 + 32768) >> 16; + crGTable[i] = -23401 * x2; + cbGTable[i] = -11277 * x2 + 32768; + } + CrRTable = crRTable; + CbBTable = cbBTable; + CrGTable = crGTable; + CbGTable = cbGTable; + + /* Initialize BitCount Table */ + int nBits = 1; + int power2 = 2; + int [] nBitsTable = new int[2048]; + nBitsTable[0] = 0; + for (int i = 1; i < nBitsTable.length; i++) { + if (!(i < power2)) { + nBits++; + power2 *= 2; + } + nBitsTable[i] = nBits; + } + NBitsTable = nBitsTable; } void compress(ImageData image, byte[] dataYComp, byte[] dataCbComp, byte[] dataCrComp) { int srcWidth = image.width; @@ -229,15 +288,15 @@ int delta = componentWidth - compressedWidth; for (int yPos = 0; yPos < compressedHeight; yPos++) { int dstOfs = ((yPos + 1) * componentWidth - delta); - int dataValue = imageComponent[dstOfs - 1] & 0xFF; + int dataValue = imageComponent[(dstOfs > 0) ? dstOfs - 1 : 0] & 0xFF; for (int i = 0; i < delta; i++) { imageComponent[dstOfs + i] = cast(byte)dataValue; } } } if (compressedHeight < componentHeight) { - int srcOfs = (compressedHeight - 1) * componentWidth; - for (int yPos = compressedHeight; yPos <= componentHeight; yPos++) { + int srcOfs = (compressedHeight > 0) ? (compressedHeight - 1) * componentWidth : 1; + for (int yPos = (compressedHeight > 0) ? compressedHeight : 1; yPos <= componentHeight; yPos++) { int dstOfs = (yPos - 1) * componentWidth; System.arraycopy(imageComponent, srcOfs, imageComponent, dstOfs, componentWidth); } @@ -1160,58 +1219,6 @@ } restartInterval = dri.getRestartInterval(); } -static void initialize() { - initializeRGBYCbCrTables(); - initializeYCbCrRGBTables(); - initializeBitCountTable(); -} -static void initializeBitCountTable() { - int nBits = 1; - int power2 = 2; - NBitsTable = new int[2048]; - NBitsTable[0] = 0; - for (int i = 1; i < NBitsTable.length; i++) { - if (!(i < power2)) { - nBits++; - power2 *= 2; - } - NBitsTable[i] = nBits; - } -} -static void initializeRGBYCbCrTables() { - RYTable = new int[256]; - GYTable = new int[256]; - BYTable = new int[256]; - RCbTable = new int[256]; - GCbTable = new int[256]; - BCbTable = new int[256]; - RCrTable = BCbTable; - GCrTable = new int[256]; - BCrTable = new int[256]; - for (int i = 0; i < 256; i++) { - RYTable[i] = i * 19595; - GYTable[i] = i * 38470; - BYTable[i] = i * 7471 + 32768; - RCbTable[i] = i * -11059; - GCbTable[i] = i * -21709; - BCbTable[i] = i * 32768 + 8388608; - GCrTable[i] = i * -27439; - BCrTable[i] = i * -5329; - } -} -static void initializeYCbCrRGBTables() { - CrRTable = new int[256]; - CbBTable = new int[256]; - CrGTable = new int[256]; - CbGTable = new int[256]; - for (int i = 0; i < 256; i++) { - int x2 = 2 * i - 255; - CrRTable[i] = (45941 * x2 + 32768) >> 16; - CbBTable[i] = (58065 * x2 + 32768) >> 16; - CrGTable[i] = -23401 * x2; - CbGTable[i] = -11277 * x2 + 32768; - } -} void inverseDCT(int[] dataUnit) { for (int row = 0; row < 8; row++) { int rIndex = row * DCTSIZE; diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/LEDataInputStream.d --- a/dwt/internal/image/LEDataInputStream.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/LEDataInputStream.d Mon May 12 19:13:01 2008 +0200 @@ -156,9 +156,9 @@ public int readInt() { byte[4] buf = void; read(buf); - return ((((((buf[3] & 0xFF) << 24) | - (buf[2] & 0xFF)) << 16) | - (buf[1] & 0xFF)) << 8) | + return ((buf[3] & 0xFF) << 24) | + ((buf[2] & 0xFF) << 16) | + ((buf[1] & 0xFF) << 8) | (buf[0] & 0xFF); } diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/PNGFileFormat.d --- a/dwt/internal/image/PNGFileFormat.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/PNGFileFormat.d Mon May 12 19:13:01 2008 +0200 @@ -176,7 +176,7 @@ if ((signature[4] & 0xFF) !is 13) return false; // if ((signature[5] & 0xFF) !is 10) return false; // if ((signature[6] & 0xFF) !is 26) return false; // - if ((signature[7] & 0xFF) !is 10) return false; // + if ((signature[7] & 0xFF) !is 10) return false; // return true; } catch (Exception e) { return false; @@ -314,7 +314,7 @@ bool use3_2 = true;//System.getProperty("dwt.internal.image.PNGFileFormat_3.2") !is null; InputStream inflaterStream = use3_2 ? null : Compatibility.newInflaterInputStream(stream); if (inflaterStream !is null) { - stream = new BufferedInputStream(inflaterStream); + stream = inflaterStream; } else { stream = new PngDecodingDataStream(stream); } diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/PngDeflater.d --- a/dwt/internal/image/PngDeflater.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/PngDeflater.d Mon May 12 19:13:01 2008 +0200 @@ -55,7 +55,7 @@ } -class Match { +static class Match { int length, distance; diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/PngEncoder.d --- a/dwt/internal/image/PngEncoder.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/PngEncoder.d Mon May 12 19:13:01 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 @@ -15,10 +15,12 @@ import dwt.internal.image.LEDataOutputStream; import dwt.internal.image.PngDeflater; import dwt.dwthelper.ByteArrayOutputStream; +import dwt.dwthelper.OutputStream; import dwt.DWT; import dwt.graphics.ImageData; import dwt.graphics.ImageLoader; import dwt.graphics.RGB; +import dwt.internal.Compatibility; import dwt.internal.image.PngChunk; import tango.core.Exception; @@ -236,21 +238,23 @@ void writeImageData() { ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + OutputStream os = Compatibility.newDeflaterOutputStream(baos); + if (os is null) os = baos; if (colorType is 3) { - int[] lineData = new int[width]; + byte[] lineData = new byte[width]; for (int y = 0; y < height; y++) { - byte filter[] = [0]; - baos.write(filter, 0, 1); + int filter = 0; + os.write(filter); data.getPixels(0, y, width, lineData, 0); for (int x = 0; x < lineData.length; x++) { - baos.write(cast(byte) lineData[x]); + os.write(lineData[x]); } @@ -261,7 +265,10 @@ else { int[] lineData = new int[width]; - byte[] alphaData = new byte[width]; + byte[] alphaData = null; + if (colorType is 6) { + alphaData = new byte[width]; + } int redMask = data.palette.redMask; int redShift = data.palette.redShift; @@ -272,8 +279,8 @@ for (int y = 0; y < height; y++) { - byte filter[] = [0]; - baos.write(filter, 0, 1); + int filter = 0; + os.write(filter); data.getPixels(0, y, width, lineData, 0); @@ -292,14 +299,12 @@ int b = pixel & blueMask; b = (blueShift < 0) ? b >>> -blueShift : b << blueShift; - byte pixels[] = [cast(byte) r, cast(byte) g, cast(byte) b]; - baos.write(pixels, 0, 3); + os.write(r); + os.write(g); + os.write(b); if (colorType is 6) { - - byte alpha[] = [alphaData[x]]; - baos.write(alpha, 0, 1); - + os.write(alphaData[x]); } } @@ -308,8 +313,14 @@ } - PngDeflater deflater = new PngDeflater(); - byte[] compressed = deflater.deflate(baos.toByteArray()); + os.flush(); + os.close(); + + byte[] compressed = baos.toByteArray(); + if (os is baos) { + PngDeflater deflater = new PngDeflater(); + compressed = deflater.deflate(compressed); + } writeChunk(TAG_IDAT, compressed); diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/PngHuffmanTable.d --- a/dwt/internal/image/PngHuffmanTable.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/PngHuffmanTable.d Mon May 12 19:13:01 2008 +0200 @@ -116,7 +116,7 @@ return codeValues[index]; } -class CodeLengthInfo { +static class CodeLengthInfo { int length; int max; int min; diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/PngPlteChunk.d --- a/dwt/internal/image/PngPlteChunk.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/PngPlteChunk.d Mon May 12 19:13:01 2008 +0200 @@ -112,7 +112,7 @@ // Palette chunks' data fields must be event multiples // of 3. Each 3-byte group represents an RGB value. - if (getLength() % 3 !is 0) DWT.error(DWT.ERROR_INVALID_IMAGE); + if (getLength() % 3 !is 0) DWT.error(DWT.ERROR_INVALID_IMAGE); // Palettes cannot have more entries than 2^bitDepth // where bitDepth is the bit depth of the image given diff -r 06a1f6829310 -r ce446666f5a2 dwt/internal/image/WinICOFileFormat.d --- a/dwt/internal/image/WinICOFileFormat.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/internal/image/WinICOFileFormat.d Mon May 12 19:13:01 2008 +0200 @@ -20,7 +20,7 @@ import tango.core.Exception; -final class WinICOFileFormat : FileFormat { +public final class WinICOFileFormat : FileFormat { byte[] bitInvertData(byte[] data, int startIndex, int endIndex) { // Destructively bit invert data in the given byte array. diff -r 06a1f6829310 -r ce446666f5a2 dwt/layout/RowLayout.d --- a/dwt/layout/RowLayout.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/layout/RowLayout.d Mon May 12 19:13:01 2008 +0200 @@ -138,6 +138,17 @@ public bool fill = false; /** + * center specifies whether the controls in a row should be + * centered vertically in each cell for horizontal layouts, + * or centered horizontally in each cell for vertical layouts. + * + * The default value is false. + * + * @since 3.4 + */ + public bool center = false; + + /** * justify specifies whether the controls in a row should be * fully justified, with any extra space placed between the controls. * @@ -268,7 +279,7 @@ int [] wraps = null; bool wrapped = false; Rectangle [] bounds = null; - if (move && (justify || fill)) { + if (move && (justify || fill || center)) { bounds = new Rectangle [count]; wraps = new int [count]; } @@ -282,17 +293,17 @@ } if (wrap && (i !is 0) && (x + childWidth > width)) { wrapped = true; - if (move && (justify || fill)) wraps [i - 1] = maxHeight; + if (move && (justify || fill || center)) wraps [i - 1] = maxHeight; x = marginLeft + marginWidth; y += spacing + maxHeight; if (pack) maxHeight = 0; } - if (pack || fill) { + if (pack || fill || center) { maxHeight = Math.max (maxHeight, childHeight); } if (move) { int childX = x + clientX, childY = y + clientY; - if (justify || fill) { + if (justify || fill || center) { bounds [i] = new Rectangle (childX, childY, childWidth, childHeight); } else { child.setBounds (childX, childY, childWidth, childHeight); @@ -303,13 +314,13 @@ } maxX = Math.max (clientX + marginLeft + marginWidth, maxX - spacing); if (!wrapped) maxX += marginRight + marginWidth; - if (move && (justify || fill)) { + if (move && (justify || fill || center)) { int space = 0, margin = 0; if (!wrapped) { space = Math.max (0, (width - maxX) / (count + 1)); margin = Math.max (0, ((width - maxX) % (count + 1)) / 2); } else { - if (fill || justify) { + if (fill || justify || center) { int last = 0; if (count > 0) wraps [count - 1] = maxHeight; for (int i=0; i height)) { wrapped = true; - if (move && (justify || fill)) wraps [i - 1] = maxWidth; + if (move && (justify || fill || center)) wraps [i - 1] = maxWidth; x += spacing + maxWidth; y = marginTop + marginHeight; if (pack) maxWidth = 0; } - if (pack || fill) { + if (pack || fill || center) { maxWidth = Math.max (maxWidth, childWidth); } if (move) { int childX = x + clientX, childY = y + clientY; - if (justify || fill) { + if (justify || fill || center) { bounds [i] = new Rectangle (childX, childY, childWidth, childHeight); } else { child.setBounds (childX, childY, childWidth, childHeight); @@ -410,13 +433,13 @@ } maxY = Math.max (clientY + marginTop + marginHeight, maxY - spacing); if (!wrapped) maxY += marginBottom + marginHeight; - if (move && (justify || fill)) { + if (move && (justify || fill || center)) { int space = 0, margin = 0; if (!wrapped) { space = Math.max (0, (height - maxY) / (count + 1)); margin = Math.max (0, ((height - maxY) % (count + 1)) / 2); } else { - if (fill || justify) { + if (fill || justify || center) { int last = 0; if (count > 0) wraps [count - 1] = maxWidth; for (int i=0; i */ public class PrintDialog : Dialog { + PrinterData printerData; int scope_ = PrinterData.ALL_PAGES; int startPage = 1, endPage = 1; bool printToFile = false; @@ -47,9 +49,11 @@ int index; char [] settingsData; - static const String ADD_IDLE_PROC_KEY = "org.eclipse.swt.internal.gtk2.addIdleProc"; - static const String REMOVE_IDLE_PROC_KEY = "org.eclipse.swt.internal.gtk2.removeIdleProc"; - + static const String GET_MODAL_DIALOG = "dwt.internal.gtk.getModalDialog"; + static const String SET_MODAL_DIALOG = "dwt.internal.gtk.setModalDialog"; + static const String ADD_IDLE_PROC_KEY = "dwt.internal.gtk.addIdleProc"; + static const String REMOVE_IDLE_PROC_KEY = "dwt.internal.gtk.removeIdleProc"; + static const String GET_EMISSION_PROC_KEY = "dwt.internal.gtk.getEmissionProc"; /** * Constructs a new instance of this class given only its parent. * @@ -100,11 +104,55 @@ * @see Widget#getStyle */ public this (Shell parent, int style) { - super (parent, style); + super (parent, parent is null? style : checkStyleBit (parent, style)); checkSubclass (); } -protected override void checkSubclass() { +/** + * Sets the printer data that will be used when the dialog + * is opened. + * + * @param data the data that will be used when the dialog is opened + * + * @since 3.4 + */ +public void setPrinterData(PrinterData data) { + this.printerData = data; +} + +/** + * Returns the printer data that will be used when the dialog + * is opened. + * + * @return the data that will be used when the dialog is opened + * + * @since 3.4 + */ +public PrinterData getPrinterData() { + return printerData; +} + +static int checkBits (int style, int int0, int int1, int int2, int int3, int int4, int int5) { + int mask = int0 | int1 | int2 | int3 | int4 | int5; + if ((style & mask) is 0) style |= int0; + if ((style & int0) !is 0) style = (style & ~mask) | int0; + if ((style & int1) !is 0) style = (style & ~mask) | int1; + if ((style & int2) !is 0) style = (style & ~mask) | int2; + if ((style & int3) !is 0) style = (style & ~mask) | int3; + if ((style & int4) !is 0) style = (style & ~mask) | int4; + if ((style & int5) !is 0) style = (style & ~mask) | int5; + return style; +} + +static int checkStyleBit (Shell parent, int style) { + style &= ~DWT.MIRRORED; + if ((style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT)) is 0) { + if (parent !is null) { + if ((parent.getStyle () & DWT.LEFT_TO_RIGHT) !is 0) style |= DWT.LEFT_TO_RIGHT; + if ((parent.getStyle () & DWT.RIGHT_TO_LEFT) !is 0) style |= DWT.RIGHT_TO_LEFT; + } + } + return checkBits (style, DWT.LEFT_TO_RIGHT, DWT.RIGHT_TO_LEFT, 0, 0, 0, 0); } /** @@ -252,7 +300,28 @@ /* Set state into print dialog settings. */ auto settings = OS.gtk_print_settings_new(); auto page_setup = OS.gtk_page_setup_new(); + + if (printerData !is null) { + if (printerData.otherData !is null) { + Printer.restore(printerData.otherData, settings, page_setup); + } + /* Set values of settings from PrinterData. */ + Printer.setScope(settings, printerData.scope_, printerData.startPage, printerData.endPage); + //TODO: Should we look at printToFile, or driver/name for "Print to File", or both? (see gtk bug 345590) + if (printerData.printToFile) { + char* buffer = tango.stdc.stringz.toStringz(printerData.fileName); + OS.gtk_print_settings_set(settings, OS.GTK_PRINT_SETTINGS_OUTPUT_URI.ptr, buffer); + } + if (printerData.driver.equals("GtkPrintBackendFile") && printerData.name.equals("Print to File")) { //$NON-NLS-1$ //$NON-NLS-2$ + char* buffer = tango.stdc.stringz.toStringz(printerData.fileName); + OS.gtk_print_settings_set(settings, OS.GTK_PRINT_SETTINGS_OUTPUT_URI.ptr, buffer); + } + OS.gtk_print_settings_set_n_copies(settings, printerData.copyCount); + OS.gtk_print_settings_set_collate(settings, printerData.collate); + } + Printer.setScope(settings, scope_, startPage, endPage); + if (printToFile) { char* buffer = tango.stdc.stringz.toStringz( "Print to File" ); //$NON-NLS-1$ OS.gtk_print_settings_set_printer(settings, buffer); @@ -265,10 +334,30 @@ PrinterData data = null; //TODO: Handle 'Print Preview' (GTK_RESPONSE_APPLY). Display display = getParent() !is null ? getParent().getDisplay (): Display.getCurrent (); + + int signalId = 0; + int /*long*/ hookId = 0; + if ((getStyle () & DWT.RIGHT_TO_LEFT) !is 0) { + signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); + hookId = OS.g_signal_add_emission_hook (signalId, 0, cast(GSignalEmissionHook)cast(void*)(cast(LONG) display.getData (GET_EMISSION_PROC_KEY)).value, handle, null); + } display.setData (ADD_IDLE_PROC_KEY, null); - if (OS.gtk_dialog_run (handle) is OS.GTK_RESPONSE_OK) { + Object oldModal = null; + if (OS.gtk_window_get_modal (handle)) { + oldModal = display.getData (GET_MODAL_DIALOG); + display.setData (SET_MODAL_DIALOG, this); + } + int response = OS.gtk_dialog_run (handle); + if (OS.gtk_window_get_modal (handle)) { + display.setData (SET_MODAL_DIALOG, oldModal); + } + if ((getStyle () & DWT.RIGHT_TO_LEFT) !is 0) { + OS.g_signal_remove_emission_hook (signalId, hookId); + } + if (response is OS.GTK_RESPONSE_OK) { auto printer = OS.gtk_print_unix_dialog_get_selected_printer(handle); if (printer !is null) { + /* Get state from print dialog. */ settings = OS.gtk_print_unix_dialog_get_settings(handle); // must unref page_setup = OS.gtk_print_unix_dialog_get_page_setup(handle); // do not unref diff -r 06a1f6829310 -r ce446666f5a2 dwt/printing/Printer.d --- a/dwt/printing/Printer.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/printing/Printer.d Mon May 12 19:13:01 2008 +0200 @@ -29,7 +29,7 @@ import dwt.dwthelper.utils; static import tango.stdc.stringz; -static import tango.io.Stdout; +import tango.io.Stdout; import tango.util.Convert; @@ -70,8 +70,8 @@ bool isGCCreated = false; Font systemFont; - String settingsData; - int start, end; + static String settingsData; + static int start, end; static const String GTK_LPR_BACKEND = "GtkPrintBackendLpr"; //$NON-NLS-1$ @@ -88,6 +88,14 @@ if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0) || disablePrinting) { return printerList; } + if (!OS.g_thread_supported ()) { + OS.g_thread_init (null); + } + OS.gtk_set_locale(); + int argc = 0; + if (!OS.gtk_init_check ( &argc, null)) { + DWT.error (DWT.ERROR_NO_HANDLES, null, " [gtk_init_check() failed]"); + } OS.gtk_enumerate_printers(&GtkPrinterFunc_List, null, null, true); return printerList; } @@ -124,6 +132,14 @@ if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0) || disablePrinting) { return null; } + if (!OS.g_thread_supported ()) { + OS.g_thread_init (null); + } + OS.gtk_set_locale(); + int argc = 0; + if (!OS.gtk_init_check (&argc, null)) { + DWT.error (DWT.ERROR_NO_HANDLES, null, " [gtk_init_check() failed]"); + } OS.gtk_enumerate_printers(&GtkPrinterFunc_Default, null, null, true); return printerList[0]; } @@ -132,6 +148,8 @@ if (OS.gtk_printer_is_default(printer)) { printerList[0] = printerDataFromGtkPrinter(printer); return 1; + } else if (OS.GTK_VERSION < OS.buildVERSION(2, 10, 12) && printerDataFromGtkPrinter(printer).driver.equals (GTK_LPR_BACKEND)) { + return 1; } return 0; } @@ -151,6 +169,8 @@ this.printer = printer; OS.g_object_ref(printer); return 1; + } else if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 12) && pd.driver.equals(GTK_LPR_BACKEND)) { + return 1; } return 0; } @@ -166,6 +186,56 @@ return new PrinterData (backendType, name); } +/* +* Restore printer settings and page_setup data from data. +*/ +static void restore(char[] data, GtkPrintSettings* settings, GtkPageSetup* page_setup) { + settingsData = data; + start = end = 0; + while (end < settingsData.length && settingsData[end] !is 0) { + start = end; + while (end < settingsData.length && settingsData[end] !is 0) end++; + end++; + char [] keyBuffer = new char [end - start]; + System.arraycopy (settingsData, start, keyBuffer, 0, keyBuffer.length); + start = end; + while (end < settingsData.length && settingsData[end] !is 0) end++; + end++; + char [] valueBuffer = new char [end - start]; + System.arraycopy (settingsData, start, valueBuffer, 0, valueBuffer.length); + OS.gtk_print_settings_set(settings, keyBuffer.ptr, valueBuffer.ptr); + if (DEBUG) Stdout.formatln("{}: {}", keyBuffer, valueBuffer ); + } + end++; // skip extra null terminator + + /* Retrieve stored page_setup data. + * Note that page_setup properties must be stored (in PrintDialog) and restored (here) in the same order. + */ + OS.gtk_page_setup_set_orientation(page_setup, restoreInt("orientation")); //$NON-NLS-1$ + OS.gtk_page_setup_set_top_margin(page_setup, restoreDouble("top_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ + OS.gtk_page_setup_set_bottom_margin(page_setup, restoreDouble("bottom_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ + OS.gtk_page_setup_set_left_margin(page_setup, restoreDouble("left_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ + OS.gtk_page_setup_set_right_margin(page_setup, restoreDouble("right_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ + char [] name = restoreBytes("paper_size_name", true); //$NON-NLS-1$ + char [] display_name = restoreBytes("paper_size_display_name", true); //$NON-NLS-1$ + char [] ppd_name = restoreBytes("paper_size_ppd_name", true); //$NON-NLS-1$ + double width = restoreDouble("paper_size_width"); //$NON-NLS-1$ + double height = restoreDouble("paper_size_height"); //$NON-NLS-1$ + bool custom = restoreBoolean("paper_size_is_custom"); //$NON-NLS-1$ + GtkPaperSize* paper_size = null; + if (custom) { + if (ppd_name.length > 0) { + paper_size = OS.gtk_paper_size_new_from_ppd(ppd_name.ptr, display_name.ptr, width, height); + } else { + paper_size = OS.gtk_paper_size_new_custom(name.ptr, display_name.ptr, width, height, OS.GTK_UNIT_MM); + } + } else { + paper_size = OS.gtk_paper_size_new(name.ptr); + } + OS.gtk_page_setup_set_paper_size(page_setup, paper_size); + OS.gtk_paper_size_free(paper_size); +} + static void setScope(GtkPrintSettings* settings, int scope_, int startPage, int endPage) { switch (scope_) { case PrinterData.ALL_PAGES: @@ -235,22 +305,22 @@ super(checkNull(data)); } -int restoreInt(String key) { +static int restoreInt(String key) { char [] value = restoreBytes(key, false); return to!(int)( value ); } -double restoreDouble(String key) { +static double restoreDouble(String key) { char [] value = restoreBytes(key, false); return to!(double)( value ); } -bool restoreBoolean(String key) { +static bool restoreBoolean(String key) { char [] value = restoreBytes(key, false); return to!(bool)( value ); } -String restoreBytes(String key, bool nullTerminate) { +static String restoreBytes(String key, bool nullTerminate) { //get key start = end; while (end < settingsData.length && settingsData[end] !is 0) end++; @@ -328,7 +398,10 @@ data.drawable = drawable; data.background = getSystemColor (DWT.COLOR_WHITE).handle; data.foreground = getSystemColor (DWT.COLOR_BLACK).handle; - data.font = getSystemFont ().handle; + data.font = getSystemFont (); + //TODO: We are supposed to return this in pixels, but GTK_UNIT_PIXELS is currently not implemented (gtk bug 346245) + data.width = cast(int)OS.gtk_page_setup_get_paper_width (pageSetup, OS.GTK_UNIT_POINTS); + data.height = cast(int)OS.gtk_page_setup_get_paper_height (pageSetup, OS.GTK_UNIT_POINTS); if (cairo is null) DWT.error(DWT.ERROR_NO_HANDLES); data.cairo = cairo; isGCCreated = true; @@ -656,51 +729,7 @@ settings = OS.gtk_print_settings_new(); pageSetup = OS.gtk_page_setup_new(); if (data.otherData !is null) { - /* Retreive stored printer_settings data. */ - settingsData = data.otherData; - start = end = 0; - while (end < settingsData.length && settingsData[end] !is 0) { - start = end; - while (end < settingsData.length && settingsData[end] !is 0) end++; - end++; - char [] keyBuffer = new char [end - start]; - System.arraycopy (settingsData, start, keyBuffer, 0, keyBuffer.length); - start = end; - while (end < settingsData.length && settingsData[end] !is 0) end++; - end++; - char [] valueBuffer = new char [end - start]; - System.arraycopy (settingsData, start, valueBuffer, 0, valueBuffer.length); - OS.gtk_print_settings_set(settings, keyBuffer.ptr, valueBuffer.ptr); - if (DEBUG) tango.io.Stdout.Stdout.formatln("{}: {}", keyBuffer, valueBuffer); - } - end++; // skip extra null terminator - - /* Retreive stored page_setup data. - * Note that page_setup properties must be stored (in PrintDialog) and restored (here) in the same order. - */ - OS.gtk_page_setup_set_orientation(pageSetup, restoreInt("orientation")); //$NON-NLS-1$ - OS.gtk_page_setup_set_top_margin(pageSetup, restoreDouble("top_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ - OS.gtk_page_setup_set_bottom_margin(pageSetup, restoreDouble("bottom_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ - OS.gtk_page_setup_set_left_margin(pageSetup, restoreDouble("left_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ - OS.gtk_page_setup_set_right_margin(pageSetup, restoreDouble("right_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ - char [] name = restoreBytes("paper_size_name", true); //$NON-NLS-1$ - char [] display_name = restoreBytes("paper_size_display_name", true); //$NON-NLS-1$ - char [] ppd_name = restoreBytes("paper_size_ppd_name", true); //$NON-NLS-1$ - double width = restoreDouble("paper_size_width"); //$NON-NLS-1$ - double height = restoreDouble("paper_size_height"); //$NON-NLS-1$ - bool custom = restoreBoolean("paper_size_is_custom"); //$NON-NLS-1$ - GtkPaperSize* paper_size; - if (custom) { - if (ppd_name.length > 0) { - paper_size = OS.gtk_paper_size_new_from_ppd(ppd_name.ptr, display_name.ptr, width, height); - } else { - paper_size = OS.gtk_paper_size_new_custom(name.ptr, display_name.ptr, width, height, OS.GTK_UNIT_MM); - } - } else { - paper_size = OS.gtk_paper_size_new(name.ptr); - } - OS.gtk_page_setup_set_paper_size(pageSetup, paper_size); - OS.gtk_paper_size_free(paper_size); + restore(data.otherData, settings, pageSetup); } /* Set values of settings from PrinterData. */ diff -r 06a1f6829310 -r ce446666f5a2 dwt/printing/PrinterData.d --- a/dwt/printing/PrinterData.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/printing/PrinterData.d Mon May 12 19:13:01 2008 +0200 @@ -132,6 +132,10 @@ * private, platform-specific data * On Windows, this contains a copy of the DEVMODE struct * returned from the PrintDialog. + * On GTK, this contains a copy of the print_settings and page_setup + * returned from the PrintDialog. + * On OS X Carbon, this contains a copy of the PrintSettings and PageFormat + * returned from the PrintDialog. * This field is not currently used on the X/Window System. */ char [] otherData; diff -r 06a1f6829310 -r ce446666f5a2 dwt/program/Program.d --- a/dwt/program/Program.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/program/Program.d Mon May 12 19:13:01 2008 +0200 @@ -194,6 +194,8 @@ static const String[] CDE_MASK_EXT = [ ".m_m.bm"[], ".l_m.bm", ".s_m.bm", ".t_m.bm" ]; static const String DESKTOP_DATA = "Program_DESKTOP"; static const String ICON_THEME_DATA = "Program_GNOME_ICON_THEME"; + static const String PREFIX_HTTP = "http://"; //$NON-NLS-1$ + static const String PREFIX_HTTPS = "https://"; //$NON-NLS-1$ static const int DESKTOP_UNKNOWN = 0; static const int DESKTOP_GNOME = 1; static const int DESKTOP_GNOME_24 = 2; @@ -855,18 +857,26 @@ * API: When support for multiple displays is added, this method will * become public and the original method above can be deprecated. */ -static bool launch(Display display, String fileName) { +static bool launch (Display display, String fileName) { if (fileName is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); - switch(getDesktop(display)) { + switch (getDesktop (display)) { case DESKTOP_GNOME_24: if (gnome_24_launch (fileName)) return true; default: - int index = fileName.lastIndexOf('.'); + int index = fileName.lastIndexOf ('.'); if (index !is -1) { String extension = fileName.substring (index); Program program = Program.findProgram (display, extension); if (program !is null && program.execute (fileName)) return true; } + String lowercaseName = fileName.toLowerCase (); + if (lowercaseName.startsWith (PREFIX_HTTP) || lowercaseName.startsWith (PREFIX_HTTPS)) { + Program program = Program.findProgram (display, ".html"); //$NON-NLS-1$ + if (program is null) { + program = Program.findProgram (display, ".htm"); //$NON-NLS-1$ + } + if (program !is null && program.execute (fileName)) return true; + } break; } try { diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Button.d --- a/dwt/widgets/Button.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Button.d Mon May 12 19:13:01 2008 +0200 @@ -61,7 +61,7 @@ alias Control.setForegroundColor setForegroundColor; GtkWidget* boxHandle, labelHandle, imageHandle, arrowHandle, groupHandle; - bool selected; + bool selected, grayed; ImageList imageList; Image image; String text; @@ -193,7 +193,7 @@ override void createHandle (int index) { state |= HANDLE; - if ((style & DWT.PUSH) is 0) state |= THEME_BACKGROUND; + if ((style & (DWT.PUSH | DWT.TOGGLE)) is 0) state |= THEME_BACKGROUND; int bits = DWT.ARROW | DWT.TOGGLE | DWT.CHECK | DWT.RADIO | DWT.PUSH; fixedHandle = cast(GtkWidget*)OS.g_object_new (display.gtk_fixed_get_type (), null); if (fixedHandle is null) error (DWT.ERROR_NO_HANDLES); @@ -312,6 +312,12 @@ return DWT.LEFT; } +public bool getGrayed () { + checkWidget(); + if ((style & DWT.CHECK) is 0) return false; + return grayed; +} + /** * Returns the receiver's image if it has one, or null * if it does not. @@ -386,6 +392,16 @@ } else { selectRadio (); } + } else { + if ((style & DWT.CHECK) !is 0) { + if (grayed) { + if (OS.gtk_toggle_button_get_active (handle)) { + OS.gtk_toggle_button_set_inconsistent (handle, true); + } else { + OS.gtk_toggle_button_set_inconsistent (handle, false); + } + } + } } postEvent (DWT.Selection); return 0; @@ -643,6 +659,17 @@ if (imageHandle !is null) setForegroundColor (imageHandle, color); } +public void setGrayed (bool grayed) { + checkWidget(); + if ((style & DWT.CHECK) is 0) return; + this.grayed = grayed; + if (grayed && OS.gtk_toggle_button_get_active (handle)) { + OS.gtk_toggle_button_set_inconsistent (handle, true); + } else { + OS.gtk_toggle_button_set_inconsistent (handle, false); + } +} + /** * Sets the receiver's image to the argument, which may be * null indicating that no image should be displayed. @@ -687,6 +714,7 @@ override void setOrientation () { super.setOrientation (); if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + if (boxHandle !is null) OS.gtk_widget_set_direction (boxHandle, OS.GTK_TEXT_DIR_RTL); if (labelHandle !is null) OS.gtk_widget_set_direction (labelHandle, OS.GTK_TEXT_DIR_RTL); if (imageHandle !is null) OS.gtk_widget_set_direction (imageHandle, OS.GTK_TEXT_DIR_RTL); if (arrowHandle !is null) { @@ -720,6 +748,13 @@ if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return; OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCLICKED); OS.gtk_toggle_button_set_active (cast(GtkToggleButton*)handle, selected); + if ((style & DWT.CHECK) !is 0) { + if (selected && grayed) { + OS.gtk_toggle_button_set_inconsistent (handle, true); + } else { + OS.gtk_toggle_button_set_inconsistent (handle, false); + } + } if ((style & DWT.RADIO) !is 0) OS.gtk_toggle_button_set_active (cast(GtkToggleButton*)groupHandle, !selected); OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCLICKED); } @@ -776,6 +811,7 @@ override int traversalCode (int key, GdkEventKey* event) { int code = super.traversalCode (key, event); + if ((style & DWT.ARROW) !is 0) code &= ~(DWT.TRAVERSE_TAB_NEXT | DWT.TRAVERSE_TAB_PREVIOUS); if ((style & DWT.RADIO) !is 0) code |= DWT.TRAVERSE_ARROW_NEXT | DWT.TRAVERSE_ARROW_PREVIOUS; return code; } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Canvas.d --- a/dwt/widgets/Canvas.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Canvas.d Mon May 12 19:13:01 2008 +0200 @@ -19,6 +19,7 @@ import dwt.widgets.Composite; import dwt.widgets.Caret; import dwt.widgets.Control; +import dwt.widgets.IME; import dwt.graphics.GC; import dwt.graphics.Rectangle; import dwt.graphics.Font; @@ -47,6 +48,7 @@ alias Composite.setBounds setBounds; Caret caret; + IME ime; this () {} @@ -78,7 +80,7 @@ * @see Widget#getStyle */ public this (Composite parent, int style) { - super (parent, style); + super (parent, checkStyle (style)); } /** @@ -137,6 +139,27 @@ return new Point (caret.x, caret.y); } +public IME getIME () { + checkWidget (); + return ime; +} + +override int /*long*/ gtk_button_press_event (GtkWidget* widget, GdkEventButton* event) { + if (ime !is null) { + auto result = ime.gtk_button_press_event (widget, event); + if (result !is 0) return result; + } + return super.gtk_button_press_event (widget, event); +} + +override int /*long*/ gtk_commit (GtkIMContext* imcontext, char* text) { + if (ime !is null) { + auto result = ime.gtk_commit (imcontext, text); + if (result !is 0) return result; + } + return super.gtk_commit (imcontext, text); +} + override int /*long*/ gtk_expose_event (GtkWidget* widget, GdkEventExpose* event) { if ((state & OBSCURED) !is 0) return 0; bool isFocus = caret !is null && caret.isFocusCaret (); @@ -158,6 +181,14 @@ return result; } +override int /*long*/ gtk_preedit_changed (GtkIMContext* imcontext) { + if (ime !is null) { + auto result = ime.gtk_preedit_changed (imcontext); + if (result !is 0) return result; + } + return super.gtk_preedit_changed (imcontext); +} + override void redrawWidget (int x, int y, int width, int height, bool redrawAll, bool all, bool trim) { bool isFocus = caret !is null && caret.isFocusCaret (); if (isFocus) caret.killFocus (); @@ -170,6 +201,10 @@ caret.release (false); caret = null; } + if (ime !is null) { + ime.release (false); + ime = null; + } super.releaseChildren (destroy); } @@ -198,6 +233,11 @@ public void scroll (int destX, int destY, int x, int y, int width, int height, bool all) { checkWidget(); if (width <= 0 || height <= 0) return; + if ((style & DWT.MIRRORED) !is 0) { + int clientWidth = getClientWidth (); + x = clientWidth - width - x; + destX = clientWidth - width - destX; + } int deltaX = destX - x, deltaY = destY - y; if (deltaX is 0 && deltaY is 0) return; if (!isVisible ()) return; @@ -329,6 +369,12 @@ super.setFont (font); } +public void setIME (IME ime) { + checkWidget (); + if (ime !is null && ime.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT); + this.ime = ime; +} + void updateCaret () { auto imHandle = imHandle (); if (imHandle is null) return; diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Caret.d --- a/dwt/widgets/Caret.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Caret.d Mon May 12 19:13:01 2008 +0200 @@ -43,6 +43,8 @@ Image image; Font font; + static final int DEFAULT_WIDTH = 1; + /** * Constructs a new instance of this class given its parent * and a style value describing its behavior and appearance. @@ -109,11 +111,15 @@ if (image !is null && !image.isDisposed() && image.mask is null) { int width; int height; OS.gdk_drawable_get_size(image.pixmap, &width, &height); + int nX = x; + if ((parent.style & DWT.MIRRORED) !is 0) nX = parent.getClientWidth () - width - nX; OS.gdk_draw_drawable(window, gc, image.pixmap, 0, 0, x, y, width, height); } else { int nWidth = width, nHeight = height; - if (nWidth <= 0) nWidth = 1; - OS.gdk_draw_rectangle (window, gc, 1, x, y, nWidth, nHeight); + if (nWidth <= 0) nWidth = DEFAULT_WIDTH; + int nX = x; + if ((parent.style & DWT.MIRRORED) !is 0) nX = parent.getClientWidth () - nWidth - nX; + OS.gdk_draw_rectangle (window, gc, 1, nX, y, nWidth, nHeight); } OS.g_object_unref (gc); OS.gdk_colormap_free_colors (colormap, color, 1); @@ -136,6 +142,10 @@ if (image !is null) { Rectangle rect = image.getBounds (); return new Rectangle (x, y, rect.width, rect.height); + } else { + if (width is 0) { + return new Rectangle (x, y, DEFAULT_WIDTH, height); + } } return new Rectangle (x, y, width, height); } @@ -217,6 +227,10 @@ if (image !is null) { Rectangle rect = image.getBounds (); return new Point (rect.width, rect.height); + } else { + if (width is 0) { + return new Point (DEFAULT_WIDTH, height); + } } return new Point (width, height); } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/ColorDialog.d --- a/dwt/widgets/ColorDialog.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/ColorDialog.d Mon May 12 19:13:01 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 @@ -59,7 +59,7 @@ * @see Widget#getStyle */ public this (Shell parent) { - this (parent, DWT.NONE); + this (parent, DWT.APPLICATION_MODAL); } /** * Constructs a new instance of this class given its parent @@ -90,7 +90,7 @@ * @see Widget#getStyle */ public this (Shell parent, int style) { - super (parent, style); + super (parent, checkStyle (parent, style)); checkSubclass (); } @@ -120,6 +120,7 @@ public RGB open () { char* buffer = toStringz(title); auto handle = cast(GtkWidget*)OS.gtk_color_selection_dialog_new (buffer); + Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); if (parent !is null) { auto shellHandle = parent.topHandle (); OS.gtk_window_set_transient_for (handle, shellHandle); @@ -138,9 +139,28 @@ OS.gtk_color_selection_set_current_color (dialog.colorsel, &color); } OS.gtk_color_selection_set_has_palette (dialog.colorsel, true); - Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); display.addIdleProc (); + Dialog oldModal = null; + if (OS.gtk_window_get_modal (handle)) { + oldModal = display.getModalDialog (); + display.setModalDialog (this); + } + int signalId = 0; + int /*long*/ hookId = 0; + CallbackData emissionData; + emissionData.display = display; + emissionData.data = handle; + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); + hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); + } int response = OS.gtk_dialog_run (handle); + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.g_signal_remove_emission_hook (signalId, hookId); + } + if (OS.gtk_window_get_modal (handle)) { + display.setModalDialog (oldModal); + } bool success = response is OS.GTK_RESPONSE_OK; if (success) { OS.gtk_color_selection_get_current_color (dialog.colorsel, &color); diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Combo.d --- a/dwt/widgets/Combo.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Combo.d Mon May 12 19:13:01 2008 +0200 @@ -75,7 +75,7 @@ alias Composite.setToolTipText setToolTipText; alias Composite.translateTraversal translateTraversal; - GtkWidget* buttonHandle, entryHandle, listHandle, textRenderer; + GtkWidget* buttonHandle, entryHandle, listHandle, textRenderer, cellHandle, popupHandle; int lastEventTime, visibleCount = 5; GdkEventKey* gdkEventKey; int fixStart = -1, fixEnd = -1; @@ -191,6 +191,9 @@ char* buffer = toStringz(string); if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { OS.gtk_combo_box_insert_text (handle, index, buffer); + if ((style & DWT.RIGHT_TO_LEFT) !is 0 && popupHandle !is null) { + display.doSetDirectionProc( popupHandle, OS.GTK_TEXT_DIR_RTL); + } } else { /* * Feature in GTK. When the list is empty and the first item @@ -438,15 +441,19 @@ if (fixedHandle is null) error (DWT.ERROR_NO_HANDLES); OS.gtk_fixed_set_has_window (fixedHandle, true); if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { + auto oldList = OS.gtk_window_list_toplevels (); if ((style & DWT.READ_ONLY) !is 0) { handle = OS.gtk_combo_box_new_text (); if (handle is null) error (DWT.ERROR_NO_HANDLES); + cellHandle = OS.gtk_bin_get_child (handle); + if (cellHandle is null) error (DWT.ERROR_NO_HANDLES); } else { handle = OS.gtk_combo_box_entry_new_text (); if (handle is null) error (DWT.ERROR_NO_HANDLES); entryHandle = OS.gtk_bin_get_child (handle); if (entryHandle is null) error (DWT.ERROR_NO_HANDLES); } + popupHandle = findPopupHandle (oldList); OS.gtk_container_add (fixedHandle, handle); textRenderer = cast(GtkWidget*)OS.gtk_cell_renderer_text_new (); if (textRenderer is null) error (DWT.ERROR_NO_HANDLES); @@ -492,6 +499,15 @@ OS.g_list_free (display.allChildren); display.allChildren = null; } + /* + * Feature in GTK. By default, read only combo boxes + * process the RETURN key rather than allowing the + * default button to process the key. The fix is to + * clear the GTK_RECEIVES_DEFAULT flag. + */ + if ((style & DWT.READ_ONLY) !is 0 && buttonHandle !is null) { + OS.GTK_WIDGET_UNSET_FLAGS (buttonHandle, OS.GTK_RECEIVES_DEFAULT); + } } else { handle = OS.gtk_combo_new (); if (handle is null) error (DWT.ERROR_NO_HANDLES); @@ -500,6 +516,20 @@ entryHandle = combo.entry; listHandle = combo.list; + if (OS.GTK_VERSION < OS.buildVERSION (2, 4, 0)) { + GtkWidget* parentHandle = null; + auto temp = listHandle; + while ((temp = OS.gtk_widget_get_parent(temp)) !is null) { + parentHandle = temp; + } + popupHandle = parentHandle; + if (popupHandle !is null) { + GtkWidget* modalGroup = getShell().modalGroup; + if (modalGroup !is null) { + OS.gtk_window_group_add_window (modalGroup, popupHandle); + } + } + } /* * Feature in GTK. There is no API to query the arrow * handle from a combo box although it is possible to @@ -569,6 +599,47 @@ return false; } +GtkWidget* findPopupHandle (GList* oldList) { + GtkWidget* hdl = null; + GList* currentList = OS.gtk_window_list_toplevels(); + GList* oldFromList = oldList; + GList* newFromList = currentList; + bool isFound; + while (newFromList !is null) { + void* newToplevel = OS.g_list_data(newFromList); + isFound = false; + oldFromList = oldList; + while (oldFromList !is null) { + void* oldToplevel = OS.g_list_data(oldFromList); + if (newToplevel is oldToplevel) { + isFound = true; + break; + } + oldFromList = OS.g_list_next(oldFromList); + } + if (!isFound) { + hdl = cast(GtkWidget*)newToplevel; + break; + } + newFromList = OS.g_list_next(newFromList); + } + OS.g_list_free(oldList); + OS.g_list_free(currentList); + return hdl; +} + +override void fixModal (GtkWidget* group, GtkWidget* modalGroup) { + if (popupHandle !is null) { + if (group !is null) { + OS.gtk_window_group_add_window (group, popupHandle); + } else { + if (modalGroup !is null) { + OS.gtk_window_group_remove_window (modalGroup, popupHandle); + } + } + } +} + void fixIM () { /* * The IM filter has to be called one time for each key press event. @@ -620,6 +691,7 @@ OS.g_signal_connect_closure (entryHandle, OS.insert_text.ptr, display.closures [INSERT_TEXT], false); OS.g_signal_connect_closure (entryHandle, OS.delete_text.ptr, display.closures [DELETE_TEXT], false); OS.g_signal_connect_closure (entryHandle, OS.activate.ptr, display.closures [ACTIVATE], false); + OS.g_signal_connect_closure (entryHandle, OS.populate_popup.ptr, display.closures [POPULATE_POPUP], false); } int eventMask = OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK; @@ -836,6 +908,18 @@ return result; } +public bool getListVisible () { + checkWidget (); + if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { + return popupHandle !is null && OS.GTK_WIDGET_VISIBLE (popupHandle); + } + return false; +} + +String getNameText () { + return getText (); +} + /** * Returns the orientation of the receiver. * @@ -1023,6 +1107,18 @@ return 0; } +override int /*long*/ gtk_button_press_event (GtkWidget* widget, GdkEventButton* event) { + /* + * Feature in GTK. Depending on where the user clicks, GTK prevents + * the left mouse button event from being propagated. The fix is to + * send the mouse event from the event_after handler. + */ + if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { + if (event.type is OS.GDK_BUTTON_PRESS) return 0; + } + return super.gtk_button_press_event (widget, event); +} + override int gtk_changed (GtkWidget* widget) { if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { if (widget is handle) { @@ -1143,6 +1239,54 @@ return 0; } +override int /*long*/ gtk_event_after (GtkWidget* widget, GdkEvent* event) { + /* + * Feature in GTK. Depending on where the user clicks, GTK prevents + * the left mouse button event from being propagated. The fix is to + * send the mouse event from the event_after handler. + * + * Feature in GTK. When the user clicks anywhere in an editable + * combo box, a single focus event should be issued, despite the + * fact that focus might switch between the drop down button and + * the text field. The fix is to use gtk_combo_box_set_focus_on_click () + * to eat all focus events while focus is in the combo box. When the + * user clicks on the drop down button focus is assigned to the text + * field. + */ + if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { + switch (event.type) { + case OS.GDK_BUTTON_PRESS: { + GdkEventButton* gdkEventButton = cast(GdkEventButton*)event; + if (gdkEventButton.button is 1) { + if (!sendMouseEvent (DWT.MouseDown, gdkEventButton.button, display.clickCount, 0, false, gdkEventButton.time, gdkEventButton.x_root, gdkEventButton.y_root, false, gdkEventButton.state)) { + return 1; + } + if (OS.GTK_VERSION >= OS.buildVERSION (2, 6, 0)) { + if ((style & DWT.READ_ONLY) is 0 && widget is buttonHandle) { + OS.gtk_widget_grab_focus (entryHandle); + } + } + } + break; + } + case OS.GDK_FOCUS_CHANGE: { + if (OS.GTK_VERSION >= OS.buildVERSION (2, 6, 0)) { + if ((style & DWT.READ_ONLY) is 0) { + GdkEventFocus* gdkEventFocus = cast(GdkEventFocus*)event; + if (gdkEventFocus.in_ !is 0) { + OS.gtk_combo_box_set_focus_on_click (handle, false); + } else { + OS.gtk_combo_box_set_focus_on_click (handle, true); + } + } + } + break; + } + } + } + return super.gtk_event_after(widget, event); +} + override int gtk_focus_out_event (GtkWidget* widget, GdkEventFocus* event) { fixIM (); return super.gtk_focus_out_event (widget, event); @@ -1196,9 +1340,57 @@ if (result !is 0) fixIM (); if (gdkEventKey is cast(GdkEventKey*)-1) result = 1; gdkEventKey = null; + if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0) && (style & DWT.READ_ONLY) is 0) { + GdkEventKey* keyEvent = cast(GdkEventKey*)event; + int oldIndex = OS.gtk_combo_box_get_active (handle); + int newIndex = oldIndex; + int key = keyEvent.keyval; + switch (key) { + case OS.GDK_Down: + case OS.GDK_KP_Down: + if (oldIndex !is (items.length - 1)) { + newIndex = oldIndex + 1; + } + break; + case OS.GDK_Up: + case OS.GDK_KP_Up: + if (oldIndex !is -1 && oldIndex !is 0) { + newIndex = oldIndex - 1; + } + break; + /* + * Feature in GTK. In gtk_combo_box, the PageUp and PageDown keys + * go the first and last items in the list rather than scrolling + * a page at a time. The fix is to emulate this behavior for + * gtk_combo_box_entry. + */ + case OS.GDK_Page_Up: + case OS.GDK_KP_Page_Up: + newIndex = 0; + break; + case OS.GDK_Page_Down: + case OS.GDK_KP_Page_Down: + newIndex = items.length - 1; + break; + } + if (newIndex !is oldIndex) { + OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); + OS.gtk_combo_box_set_active (handle, newIndex); + OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); + return 1; + } + } return result; } +override int /*long*/ gtk_populate_popup (GtkWidget* widget, GtkWidget* menu) { + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.gtk_widget_set_direction (menu, OS.GTK_TEXT_DIR_RTL); + display.doSetDirectionProc(menu, OS.GTK_TEXT_DIR_RTL); + } + return 0; +} + /** * Searches the receiver's list starting at the first item * (index 0) until an item is found that is equal to the @@ -1250,6 +1442,14 @@ return -1; } +override bool isFocusHandle(GtkWidget* widget) { + if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { + if (buttonHandle !is null && widget is buttonHandle) return true; + if (entryHandle !is null && widget is entryHandle) return true; + } + return super.isFocusHandle (widget); +} + override GdkDrawable* paintWindow () { auto childHandle = entryHandle !is null ? entryHandle : handle; OS.gtk_widget_realize (childHandle); @@ -1546,6 +1746,14 @@ OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); OS.gtk_combo_box_set_active (handle, index); OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); + if ((style & DWT.READ_ONLY) !is 0) { + /* + * Feature in GTK. Read Only combo boxes do not get a chance to send out a + * Modify event in the gtk_changed callback. The fix is to send a Modify event + * here. + */ + sendEvent (DWT.Modify); + } } else { ignoreSelect = true; OS.gtk_list_select_item (listHandle, index); @@ -1565,7 +1773,8 @@ } override int setBounds (int x, int y, int width, int height, bool move, bool resize) { - int newHeight = resize ? getTextHeight () : height; + int newHeight = height; + if (resize) newHeight = Math.max (getTextHeight (), height); return super.setBounds (x, y, width, newHeight, move, resize); } @@ -1652,6 +1861,9 @@ if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { OS.gtk_combo_box_remove_text (handle, index); OS.gtk_combo_box_insert_text (handle, index, buffer); + if ((style & DWT.RIGHT_TO_LEFT) !is 0 && popupHandle !is null) { + display.doSetDirectionProc(popupHandle, OS.GTK_TEXT_DIR_RTL); + } } else { ignoreSelect = true; auto children = OS.gtk_container_get_children (listHandle); @@ -1695,6 +1907,9 @@ String string = items [i]; char* buffer = toStringz(string); OS.gtk_combo_box_insert_text (handle, i, buffer); + if ((style & DWT.RIGHT_TO_LEFT) !is 0 && popupHandle !is null) { + display.doSetDirectionProc(popupHandle, OS.GTK_TEXT_DIR_RTL); + } } } else { lockText = ignoreSelect = true; @@ -1720,7 +1935,7 @@ } } -/*public*/ void setListVisible (bool visible) { +public void setListVisible (bool visible) { checkWidget (); if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { if (visible) { @@ -1736,6 +1951,7 @@ if ((style & DWT.RIGHT_TO_LEFT) !is 0) { if (listHandle !is null) OS.gtk_widget_set_direction (listHandle, OS.GTK_TEXT_DIR_RTL); if (entryHandle !is null) OS.gtk_widget_set_direction (entryHandle, OS.GTK_TEXT_DIR_RTL); + if (cellHandle !is null) OS.gtk_widget_set_direction (cellHandle, OS.GTK_TEXT_DIR_RTL); } } @@ -1754,26 +1970,30 @@ * @since 2.1.2 */ public void setOrientation (int orientation) { - checkWidget(); - int flags = DWT.RIGHT_TO_LEFT | DWT.LEFT_TO_RIGHT; - if ((orientation & flags) is 0 || (orientation & flags) is flags) return; - style &= ~flags; - style |= orientation & flags; - int dir = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? OS.GTK_TEXT_DIR_RTL : OS.GTK_TEXT_DIR_LTR; - OS.gtk_widget_set_direction (fixedHandle, dir); - OS.gtk_widget_set_direction (handle, dir); - if (entryHandle !is null) OS.gtk_widget_set_direction (entryHandle, dir); - if (listHandle !is null) { - OS.gtk_widget_set_direction (listHandle, dir); - auto itemsList = OS.gtk_container_get_children (listHandle); - if (itemsList !is null) { - int count = OS.g_list_length (itemsList); - for (int i=count - 1; i>=0; i--) { - auto widget = OS.gtk_bin_get_child (OS.g_list_nth_data (itemsList, i)); - OS.gtk_widget_set_direction (widget, dir); + if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { + checkWidget(); + int flags = DWT.RIGHT_TO_LEFT | DWT.LEFT_TO_RIGHT; + if ((orientation & flags) is 0 || (orientation & flags) is flags) return; + style &= ~flags; + style |= orientation & flags; + int dir = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? OS.GTK_TEXT_DIR_RTL : OS.GTK_TEXT_DIR_LTR; + OS.gtk_widget_set_direction (fixedHandle, dir); + OS.gtk_widget_set_direction (handle, dir); + if (entryHandle !is null) OS.gtk_widget_set_direction (entryHandle, dir); + if (listHandle !is null) { + OS.gtk_widget_set_direction (listHandle, dir); + auto itemsList = OS.gtk_container_get_children (listHandle); + if (itemsList !is null) { + int count = OS.g_list_length (itemsList); + for (int i=count - 1; i>=0; i--) { + auto widget = OS.gtk_bin_get_child (OS.g_list_nth_data (itemsList, i)); + OS.gtk_widget_set_direction (widget, dir); + } + OS.g_list_free (itemsList); } - OS.g_list_free (itemsList); } + if (cellHandle !is null) OS.gtk_widget_set_direction (cellHandle, dir); + if (popupHandle !is null) display.doSetDirectionProc (popupHandle, dir); } } @@ -1834,6 +2054,12 @@ OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); OS.gtk_combo_box_set_active (handle, index); OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); + /* + * Feature in GTK. Read Only combo boxes do not get a chance to send out a + * Modify event in the gtk_changed callback. The fix is to send a Modify event + * here. + */ + sendEvent (DWT.Modify); return; } } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Composite.d --- a/dwt/widgets/Composite.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Composite.d Mon May 12 19:13:01 2008 +0200 @@ -27,6 +27,7 @@ import dwt.internal.gtk.OS; import dwt.graphics.GC; import dwt.DWT; +import dwt.graphics.Region; import dwt.internal.cairo.Cairo; import dwt.internal.gtk.OS; import dwt.graphics.Rectangle; @@ -118,7 +119,12 @@ * @see Widget#getStyle */ public this (Composite parent, int style) { - super (parent, style); + super (parent, checkStyle (style)); +} + +static int checkStyle (int style) { + style &= ~DWT.TRANSPARENT; + return style; } Control [] _getChildren () { @@ -296,7 +302,7 @@ OS.gtk_fixed_set_has_window (cast(GtkFixed*)handle, true); OS.GTK_WIDGET_SET_FLAGS(handle, OS.GTK_CAN_FOCUS); if ((style & DWT.EMBEDDED) is 0) { - if ((state & CANVAS) !is 0 && (style & DWT.NO_FOCUS) is 0) { + if ((state & CANVAS) !is 0) { /* Prevent an input method context from being created for the Browser widget */ if (display.getData (NO_INPUT_METHOD) is null) { imHandle_ = OS.gtk_im_multicontext_new (); @@ -328,7 +334,7 @@ if (socketHandle is null) DWT.error (DWT.ERROR_NO_HANDLES); OS.gtk_container_add (cast(GtkContainer*)handle, cast(GtkWidget*)socketHandle); } - if ((style & DWT.NO_REDRAW_RESIZE) !is 0) { + if ((style & DWT.NO_REDRAW_RESIZE) !is 0 && (style & DWT.RIGHT_TO_LEFT) is 0) { OS.gtk_widget_set_redraw_on_allocate (handle, false); } /* @@ -373,6 +379,10 @@ auto pattern = Cairo.cairo_pattern_create_for_surface (surface); if (pattern is null) error (DWT.ERROR_NO_HANDLES); Cairo.cairo_pattern_set_extend (pattern, Cairo.CAIRO_EXTEND_REPEAT); + if ((data.style & DWT.MIRRORED) !is 0) { + double[] matrix = [-1.0, 0, 0, 1, 0, 0 ]; + Cairo.cairo_pattern_set_matrix(pattern, cast(cairo_matrix_t*)matrix.ptr); + } Cairo.cairo_set_source (cairo, pattern); Cairo.cairo_surface_destroy (surface); Cairo.cairo_pattern_destroy (pattern); @@ -442,6 +452,13 @@ } } +void fixModal(GtkWidget* group, GtkWidget* modalGroup) { + Control[] controls = _getChildren (); + for (int i = 0; i < controls.length; i++) { + controls[i].fixModal (group, modalGroup); + } +} + override void fixStyle () { super.fixStyle (); if (scrolledHandle is null) fixStyle (handle); @@ -583,6 +600,10 @@ return super.getClientArea(); } +int getClientWidth() { + return (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (clientHandle ()); +} + /** * Returns layout which is associated with the receiver, or * null if one has not been set. @@ -684,6 +705,7 @@ event.y = rectangles[i].y; event.width = rectangles[i].width; event.height = rectangles[i].height; + if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth () - event.width - event.x; auto damageRgn = OS.gdk_region_new (); OS.gdk_region_union_with_rect (damageRgn, rectangles + i ); GCData data = new GCData (); @@ -1085,6 +1107,41 @@ parentHandle = cast(GtkWidget*)fixed; } +void moveChildren(int oldWidth) { + Control[] children = _getChildren (); + for (int i = 0; i < children.length; i++) { + Control child = children[i]; + auto topHandle = child.topHandle (); + int x = OS.GTK_WIDGET_X (topHandle); + int y = OS.GTK_WIDGET_Y (topHandle); + int controlWidth = (child.state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle); + x = oldWidth - controlWidth - x; + int clientWidth = getClientWidth (); + x = clientWidth - controlWidth - x; + if (child.enableWindow !is null) { + OS.gdk_window_move (child.enableWindow, x, y); + } + child.moveHandle (x, y); + /* + * Cause a size allocation this widget's topHandle. Note that + * all calls to gtk_widget_size_allocate() must be preceded by + * a call to gtk_widget_size_request(). + */ + GtkRequisition requisition; + gtk_widget_size_request (topHandle, &requisition); + GtkAllocation allocation; + allocation.x = x; + allocation.y = y; + allocation.width = OS.GTK_WIDGET_WIDTH (topHandle); + allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle); + OS.gtk_widget_size_allocate (topHandle, &allocation); + Control control = child.findBackgroundControl (); + if (control !is null && control.backgroundImage !is null) { + if (child.isVisible ()) child.redrawWidget (0, 0, 0, 0, true, true, true); + } + } +} + Point minimumSize (int wHint, int hHint, bool changed) { Control [] children = _getChildren (); int width = 0, height = 0; @@ -1101,6 +1158,34 @@ return fixedHandle !is null ? fixedHandle : handle; } +override void printWidget (GC gc, GdkDrawable* drawable, int depth, int x, int y) { + Region oldClip = new Region (gc.getDevice ()); + Region newClip = new Region (gc.getDevice ()); + gc.getClipping (oldClip); + Rectangle rect = getBounds (); + newClip.add (oldClip); + newClip.intersect (x, y, rect.width, rect.height); + gc.setClipping (newClip); + super.printWidget (gc, drawable, depth, x, y); + Rectangle clientRect = getClientArea (); + Point pt = display.map (this, parent, clientRect.x, clientRect.y); + clientRect.x = x + pt.x - rect.x; + clientRect.y = y + pt.y - rect.y; + newClip.intersect (clientRect); + gc.setClipping (newClip); + Control [] children = _getChildren (); + for (int i=children.length-1; i>=0; --i) { + Control child = children [i]; + if (child.getVisible ()) { + Point location = child.getLocation (); + child.printWidget (gc, drawable, depth, x + location.x, y + location.y); + } + } + gc.setClipping (oldClip); + oldClip.dispose (); + newClip.dispose (); +} + override void redrawChildren () { super.redrawChildren (); Control [] children = _getChildren (); diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Control.d --- a/dwt/widgets/Control.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Control.d Mon May 12 19:13:01 2008 +0200 @@ -39,6 +39,7 @@ import dwt.graphics.Image; import dwt.graphics.Point; import dwt.graphics.Rectangle; +import dwt.graphics.Region; import dwt.internal.Converter; import dwt.internal.DWTEventListener; import dwt.internal.accessibility.gtk.ATK; @@ -96,6 +97,7 @@ Menu menu; Image backgroundImage; Font font; + Region region; String toolTipText; Object layoutData; Accessible accessible; @@ -137,8 +139,8 @@ createWidget (0); } -PangoFontDescription* defaultFont () { - return display.getSystemFont ().handle; +Font defaultFont () { + return display.getSystemFont (); } override void deregister () { @@ -153,6 +155,7 @@ auto window = OS.GTK_WIDGET_WINDOW (paintHandle); if (window is null) return false; int orientation = vertical ? OS.GTK_ORIENTATION_HORIZONTAL : OS.GTK_ORIENTATION_VERTICAL; + if ((style & DWT.MIRRORED) !is 0) x = getClientWidth () - width - x; char dummy; OS.gtk_paint_handle (OS.gtk_widget_get_style (paintHandle), window, OS.GTK_STATE_NORMAL, OS.GTK_SHADOW_OUT, null, paintHandle, &dummy, x, y, width, height, orientation); return true; @@ -241,8 +244,7 @@ /* Connect the mouse signals */ auto eventHandle = eventHandle (); - int eventMask = OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_PRESS_MASK | - OS.GDK_BUTTON_RELEASE_MASK; + int eventMask = OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK; OS.gtk_widget_add_events (eventHandle, eventMask); OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.closures [BUTTON_PRESS_EVENT], false); OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_RELEASE_EVENT], 0, display.closures [BUTTON_RELEASE_EVENT], false); @@ -296,8 +298,8 @@ OS.g_signal_connect_closure_by_id (paintHandle, display.signalIds [STYLE_SET], 0, display.closures [STYLE_SET], false); - auto topHandle = topHandle (); - OS.g_signal_connect_closure_by_id (topHandle, display.signalIds [MAP], 0, display.closures [MAP], true); + auto topHandle_ = topHandle (); + OS.g_signal_connect_closure_by_id (topHandle_, display.signalIds [MAP], 0, display.closures [MAP], true); } override int /*long*/ hoverProc (GtkWidget* widget) { @@ -315,9 +317,9 @@ } GtkWidget* paintHandle () { - auto topHandle = topHandle (); + auto topHandle_ = topHandle (); auto paintHandle = handle; - while (paintHandle !is topHandle) { + while (paintHandle !is topHandle_) { if ((OS.GTK_WIDGET_FLAGS (paintHandle) & OS.GTK_NO_WINDOW) is 0) break; paintHandle = OS.gtk_widget_get_parent (paintHandle); } @@ -330,6 +332,91 @@ return OS.GTK_WIDGET_WINDOW (paintHandle); } +public bool print (GC gc) { + checkWidget (); + if (gc is null) error (DWT.ERROR_NULL_ARGUMENT); + if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + auto topHandle_ = topHandle (); + OS.gtk_widget_realize (topHandle_); + auto window = OS.GTK_WIDGET_WINDOW (topHandle_); + GCData data = gc.getGCData (); + OS.gdk_window_process_updates (window, cast(int)true); + printWidget (gc, data.drawable, OS.gdk_drawable_get_depth (data.drawable), 0, 0); + return true; +} + +void printWidget (GC gc, GdkDrawable* drawable, int depth, int x, int y) { + bool obscured = (state & OBSCURED) !is 0; + state &= ~OBSCURED; + auto topHandle_ = topHandle (); + auto window = OS.GTK_WIDGET_WINDOW (topHandle_); + printWindow (true, this, gc.handle, drawable, depth, window, x, y); + if (obscured) state |= OBSCURED; +} + +void printWindow (bool first, Control control, GdkGC* gc, GdkDrawable* drawable, int depth, GdkDrawable* window, int x, int y) { + if (OS.gdk_drawable_get_depth (window) !is depth) return; + GdkRectangle rect; + int width, height; + OS.gdk_drawable_get_size (window, &width, &height); + rect.width = width; + rect.height = height; + OS.gdk_window_begin_paint_rect (window, &rect); + GdkDrawable* real_drawable; + int x_offset, y_offset; + OS.gdk_window_get_internal_paint_info (window, &real_drawable, &x_offset, &y_offset); + void* userData; + OS.gdk_window_get_user_data (window, &userData); + if (userData !is null) { + GdkEventExpose* event = cast(GdkEventExpose*) OS.gdk_event_new (OS.GDK_EXPOSE); + event.type = OS.GDK_EXPOSE; + event.window = cast(GdkDrawable*)OS.g_object_ref (window); + event.area.width = rect.width; + event.area.height = rect.height; + event.region = OS.gdk_region_rectangle (&rect); + OS.gtk_widget_send_expose (userData, cast(GdkEvent*)event); + OS.gdk_event_free (cast(GdkEvent*)event); + } + int srcX = x_offset, srcY = y_offset; + int destX = x, destY = y, destWidth = width, destHeight = height; + if (!first) { + int cX, cY; + OS.gdk_window_get_position (window, &cX, &cY); + auto parentWindow = OS.gdk_window_get_parent (window); + int pW, pH; + OS.gdk_drawable_get_size (parentWindow, &pW, &pH); + srcX = x_offset - cX; + srcY = y_offset - cY; + destX = x - cX; + destY = y - cY; + destWidth = Math.min (cX + width, pW); + destHeight = Math.min (cY + height, pH); + } + OS.gdk_draw_drawable (drawable, gc, real_drawable, srcX, srcY, destX, destY, destWidth, destHeight); + OS.gdk_window_end_paint (window); + auto children = OS.gdk_window_get_children (window); + if (children !is null) { + auto windows = children; + while (windows !is null) { + auto child = cast(GdkDrawable*) OS.g_list_data (windows); + if (OS.gdk_window_is_visible (child)) { + void* data; + OS.gdk_window_get_user_data (child, &data); + if (data !is null) { + Widget widget = display.findWidget ( cast(GtkWidget*) data); + if (widget is null || widget is control) { + int x_pos, y_pos; + OS.gdk_window_get_position (child, &x_pos, &y_pos); + printWindow (false, control, gc, drawable, depth, child, x + x_pos, y + y_pos); + } + } + } + windows = OS.g_list_next (windows); + } + OS.g_list_free (children); + } +} + /** * Returns the preferred size of the receiver. *

@@ -423,6 +510,10 @@ if (getBorderWidth () is 0) style &= ~DWT.BORDER; } +void checkMirrored () { + if ((style & DWT.RIGHT_TO_LEFT) !is 0) style |= DWT.MIRRORED; +} + GtkStyle* childStyle () { return parent.childStyle (); } @@ -438,6 +529,7 @@ setInitialBounds (); setZOrder (null, false, false); setRelations (); + checkMirrored (); checkBorder (); } @@ -508,15 +600,15 @@ * topHandle. Note that all calls to gtk_widget_size_allocate() * must be preceded by a call to gtk_widget_size_request(). */ - auto topHandle = topHandle (); + auto topHandle_ = topHandle (); GtkRequisition requisition; - gtk_widget_size_request (topHandle, &requisition); + gtk_widget_size_request (topHandle_, &requisition); GtkAllocation allocation; - allocation.x = OS.GTK_WIDGET_X (topHandle); - allocation.y = OS.GTK_WIDGET_Y (topHandle); - allocation.width = OS.GTK_WIDGET_WIDTH (topHandle); - allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle); - OS.gtk_widget_size_allocate (topHandle, &allocation); + allocation.x = OS.GTK_WIDGET_X (topHandle_); + allocation.y = OS.GTK_WIDGET_Y (topHandle_); + allocation.width = OS.GTK_WIDGET_WIDTH (topHandle_); + allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle_); + OS.gtk_widget_size_allocate (topHandle_, &allocation); } /** @@ -559,11 +651,12 @@ */ public Rectangle getBounds () { checkWidget(); - auto topHandle = topHandle (); - int x = OS.GTK_WIDGET_X (topHandle); - int y = OS.GTK_WIDGET_Y (topHandle); - int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle); - int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle); + auto topHandle_ = topHandle (); + int x = OS.GTK_WIDGET_X (topHandle_); + int y = OS.GTK_WIDGET_Y (topHandle_); + int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); + int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_); + if ((parent.style & DWT.MIRRORED) !is 0) x = parent.getClientWidth () - width - x; return new Rectangle (x, y, width, height); } @@ -623,8 +716,18 @@ /* Do nothing */ } +override void modifyStyle (GtkWidget* handle, GtkRcStyle* style) { + super.modifyStyle(handle, style); + /* + * Bug in GTK. When changing the style of a control that + * has had a region set on it, the region is lost. The + * fix is to set the region again. + */ + if (region !is null) OS.gdk_window_shape_combine_region (OS.GTK_WIDGET_WINDOW (topHandle ()), region.handle, 0, 0); +} + void moveHandle (int x, int y) { - auto topHandle = topHandle (); + auto topHandle_ = topHandle (); auto parentHandle = parent.parentingHandle (); /* * Feature in GTK. Calling gtk_fixed_move() to move a child causes @@ -636,24 +739,38 @@ */ int flags = OS.GTK_WIDGET_FLAGS (parentHandle); OS.GTK_WIDGET_UNSET_FLAGS (parentHandle, OS.GTK_VISIBLE); - OS.gtk_fixed_move (cast(GtkFixed*)parentHandle, topHandle, x, y); + OS.gtk_fixed_move (cast(GtkFixed*)parentHandle, topHandle_, x, y); if ((flags & OS.GTK_VISIBLE) !is 0) { OS.GTK_WIDGET_SET_FLAGS (parentHandle, OS.GTK_VISIBLE); } } void resizeHandle (int width, int height) { - auto topHandle = topHandle (); - OS.gtk_widget_set_size_request (topHandle, width, height); - if (topHandle !is handle) OS.gtk_widget_set_size_request (handle, width, height); + auto topHandle_ = topHandle (); + OS.gtk_widget_set_size_request (topHandle_, width, height); + if (topHandle_ !is handle) OS.gtk_widget_set_size_request (handle, width, height); } int setBounds (int x, int y, int width, int height, bool move, bool resize) { - auto topHandle = topHandle (); + auto topHandle_ = topHandle (); + bool sendMove = move; + if ((parent.style & DWT.MIRRORED) !is 0) { + int clientWidth = parent.getClientWidth (); + int oldWidth = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); + int oldX = clientWidth - oldWidth - OS.GTK_WIDGET_X (topHandle_); + if (move) { + sendMove &= x !is oldX; + x = clientWidth - (resize ? width : oldWidth) - x; + } else { + move = true; + x = clientWidth - (resize ? width : oldWidth) - oldX; + y = OS.GTK_WIDGET_Y (topHandle_); + } + } bool sameOrigin = true, sameExtent = true; if (move) { - int oldX = OS.GTK_WIDGET_X (topHandle); - int oldY = OS.GTK_WIDGET_Y (topHandle); + int oldX = OS.GTK_WIDGET_X (topHandle_); + int oldY = OS.GTK_WIDGET_Y (topHandle_); sameOrigin = x is oldX && y is oldY; if (!sameOrigin) { if (enableWindow !is null) { @@ -662,10 +779,12 @@ moveHandle (x, y); } } + int clientWidth = 0; if (resize) { - int oldWidth = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle); - int oldHeight = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle); + int oldWidth = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); + int oldHeight = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_); sameExtent = width is oldWidth && height is oldHeight; + if (!sameExtent && (style & DWT.MIRRORED) !is 0) clientWidth = getClientWidth (); if (!sameExtent && !(width is 0 && height is 0)) { int newWidth = Math.max (1, width); int newHeight = Math.max (1, height); @@ -685,23 +804,23 @@ * a call to gtk_widget_size_request(). */ GtkRequisition requisition; - gtk_widget_size_request (topHandle, &requisition); + gtk_widget_size_request (topHandle_, &requisition); GtkAllocation allocation; if (move) { allocation.x = x; allocation.y = y; } else { - allocation.x = OS.GTK_WIDGET_X (topHandle); - allocation.y = OS.GTK_WIDGET_Y (topHandle); + allocation.x = OS.GTK_WIDGET_X (topHandle_); + allocation.y = OS.GTK_WIDGET_Y (topHandle_); } if (resize) { allocation.width = width; allocation.height = height; } else { - allocation.width = OS.GTK_WIDGET_WIDTH (topHandle); - allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle); + allocation.width = OS.GTK_WIDGET_WIDTH (topHandle_); + allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle_); } - OS.gtk_widget_size_allocate (topHandle, &allocation); + OS.gtk_widget_size_allocate (topHandle_, &allocation); } /* * Bug in GTK. Widgets cannot be sized smaller than 1x1. @@ -715,15 +834,16 @@ if (enableWindow !is null) { OS.gdk_window_hide (enableWindow); } - OS.gtk_widget_hide (topHandle); + OS.gtk_widget_hide (topHandle_); } else { if ((state & HIDDEN) is 0) { if (enableWindow !is null) { OS.gdk_window_show_unraised (enableWindow); } - OS.gtk_widget_show (topHandle); + OS.gtk_widget_show (topHandle_); } } + if ((style & DWT.MIRRORED) !is 0) moveChildren (clientWidth); } int result = 0; if (move && !sameOrigin) { @@ -731,7 +851,7 @@ if (control !is null && control.backgroundImage !is null) { if (isVisible ()) redrawWidget (0, 0, 0, 0, true, true, true); } - sendEvent (DWT.Move); + if (sendMove) sendEvent (DWT.Move); result |= MOVED; } if (resize && !sameExtent) { @@ -756,9 +876,13 @@ */ public Point getLocation () { checkWidget(); - auto topHandle = topHandle (); - int x = OS.GTK_WIDGET_X (topHandle); - int y = OS.GTK_WIDGET_Y (topHandle); + auto topHandle_ = topHandle (); + int x = OS.GTK_WIDGET_X (topHandle_); + int y = OS.GTK_WIDGET_Y (topHandle_); + if ((parent.style & DWT.MIRRORED) !is 0) { + int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); + x = parent.getClientWidth () - width - x; + } return new Point (x, y); } @@ -817,9 +941,9 @@ */ public Point getSize () { checkWidget(); - auto topHandle = topHandle (); - int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle); - int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle); + auto topHandle_ = topHandle (); + int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); + int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_); return new Point (width, height); } @@ -847,6 +971,16 @@ setBounds (0, 0, Math.max (0, size.x), Math.max (0, size.y), false, true); } +public void setRegion (Region region) { + checkWidget (); + if ((style & DWT.NO_TRIM) is 0) return; + if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT); + auto window = OS.GTK_WIDGET_WINDOW (topHandle ()); + auto shape_region = (region is null) ? null : region.handle; + OS.gdk_window_shape_combine_region (window, shape_region, 0, 0); + this.region = region; +} + void setRelations () { auto parentHandle = parent.parentingHandle (); auto list = OS.gtk_container_get_children (cast(GtkContainer*)parentHandle); @@ -899,6 +1033,10 @@ return true; } +bool isFocusHandle (GtkWidget* widget) { + return widget is focusHandle (); +} + /** * Moves the receiver above the specified control in the * drawing order. If the argument is null, then the receiver @@ -957,6 +1095,9 @@ setZOrder (control, false, true); } +void moveChildren (int oldWidth) { +} + /** * Causes the receiver to be resized to its preferred size. * For a composite, this involves computing the preferred size @@ -1034,7 +1175,10 @@ auto window = eventWindow (); int origin_x, origin_y; OS.gdk_window_get_origin (window, &origin_x, &origin_y); - return new Point (x - origin_x , y - origin_y ); + x -= origin_x ; + y -= origin_y ; + if ((style & DWT.MIRRORED) !is 0) x = getClientWidth () - x; + return new Point (x, y); } /** @@ -1080,7 +1224,10 @@ auto window = eventWindow (); int origin_x, origin_y; OS.gdk_window_get_origin (window, &origin_x, &origin_y); - return new Point (origin_x + x, origin_y + y); + if ((style & DWT.MIRRORED) !is 0) x = getClientWidth () - x; + x += origin_x ; + y += origin_y ; + return new Point (x, y); } /** @@ -1939,6 +2086,9 @@ return 0; } +void fixModal(GtkWidget* group, GtkWidget* modalGroup) { +} + /** * Forces the receiver to have the keyboard focus, causing * all keyboard events to be delivered to it. @@ -2051,6 +2201,10 @@ return 0; } +int getClientWidth () { + return 0; +} + /** * Returns the receiver's cursor, or null if it has not been set. *

@@ -2120,8 +2274,7 @@ */ public Font getFont () { checkWidget(); - if (font !is null) return font; - return Font.gtk_new (display, defaultFont ()); + return font !is null ? font : defaultFont (); } PangoFontDescription* getFontDescription () { @@ -2278,6 +2431,11 @@ return result; } +public Region getRegion () { + checkWidget (); + return region; +} + /** * Returns the receiver's shell. For all controls other than * shells, this simply returns the control's nearest ancestor @@ -2341,6 +2499,7 @@ override int /*long*/ gtk_button_press_event (GtkWidget* widget, GdkEventButton* gdkEvent) { if (gdkEvent.type is OS.GDK_3BUTTON_PRESS) return 0; + /* * When a shell is created with DWT.ON_TOP and DWT.NO_FOCUS, * do not activate the shell when the user clicks on the @@ -2427,6 +2586,21 @@ } override int /*long*/ gtk_enter_notify_event (GtkWidget* widget, GdkEventCrossing* gdkEvent) { + if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) { + /* + * Feature in GTK. Children of a shell will inherit and display the shell's + * tooltip if they do not have a tooltip of their own. The fix is to use the + * new tooltip API in GTK 2.12 to null the shell's tooltip when the control + * being entered does not have any tooltip text set. + */ + char* buffer = null; + if (toolTipText !is null && toolTipText.length !is 0) { + char [] chars = fixMnemonic (toolTipText, false); + buffer = tango.stdc.stringz.toStringz(chars); + } + auto toolHandle = getShell().handle; + OS.gtk_widget_set_tooltip_text (toolHandle, buffer); + } if (display.currentControl is this) return 0; if (gdkEvent.mode !is OS.GDK_CROSSING_NORMAL && gdkEvent.mode !is OS.GDK_CROSSING_UNGRAB) return 0; if ((gdkEvent.state & (OS.GDK_BUTTON1_MASK | OS.GDK_BUTTON2_MASK | OS.GDK_BUTTON3_MASK)) !is 0) return 0; @@ -2459,7 +2633,7 @@ break; } case OS.GDK_FOCUS_CHANGE: { - if (widget !is focusHandle ()) break; + if (!isFocusHandle (widget)) break; GdkEventFocus* gdkEventFocus = cast(GdkEventFocus*)gdkEvent; /* @@ -2503,6 +2677,7 @@ event.y = gdkEvent.area.y; event.width = gdkEvent.area.width; event.height = gdkEvent.area.height; + if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth () - event.width - event.x; GCData data = new GCData (); data.damageRgn = gdkEvent.region; GC gc = event.gc = GC.gtk_new (this, data); @@ -2733,6 +2908,10 @@ int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; if ((data.style & mask) is 0) { data.style |= style & (mask | DWT.MIRRORED); + } else { + if ((data.style & DWT.RIGHT_TO_LEFT) !is 0) { + data.style |= DWT.MIRRORED; + } } data.drawable = cast(GdkDrawable*)window; data.device = display; @@ -2740,7 +2919,7 @@ Control control = findBackgroundControl (); if (control is null) control = this; data.background = control.getBackgroundColor (); - data.font = font !is null ? font.handle : defaultFont (); + data.font = font !is null ? font : defaultFont (); } return gdkGC; } @@ -2969,6 +3148,7 @@ public void redraw (int x, int y, int width, int height, bool all) { checkWidget(); if (!OS.GTK_WIDGET_VISIBLE (topHandle ())) return; + if ((style & DWT.MIRRORED) !is 0) x = getClientWidth () - width - x; redrawWidget (x, y, width, height, false, all, false); } @@ -3046,6 +3226,7 @@ toolTipText = null; layoutData = null; accessible = null; + region = null; } bool sendDragEvent (int button, int stateMask, int x, int y, bool isStateMask) { @@ -3053,6 +3234,7 @@ event.button = button; event.x = x; event.y = y; + if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth () - event.x; if (isStateMask) { event.stateMask = stateMask; } else { @@ -3129,6 +3311,7 @@ event.x = cast(int)x - origin_x; event.y = cast(int)y - origin_y; } + if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth () - event.x; setInputState (event, state); if (send) { sendEvent (type, event); @@ -3207,7 +3390,7 @@ int flags = OS.gtk_rc_style_get_color_flags (style, index); flags = (color is null) ? flags & ~OS.GTK_RC_BG : flags | OS.GTK_RC_BG; OS.gtk_rc_style_set_color_flags (style, index, flags); - OS.gtk_widget_modify_style (handle, style); + modifyStyle (handle, style); } void setBackgroundColor (GdkColor* color) { @@ -3379,8 +3562,8 @@ } } else { OS.gtk_widget_realize (handle); - auto parentHandle = parent.parentingHandle (); - auto window = OS.GTK_WIDGET_WINDOW (parentHandle); + auto parentHandle = parent.eventHandle (); + auto window = parent.eventWindow(); Rectangle rect = getBounds (); GdkWindowAttr attributes; attributes.x = rect.x; @@ -3392,12 +3575,12 @@ attributes.window_type = OS.GDK_WINDOW_CHILD; enableWindow = OS.gdk_window_new (window, &attributes, OS.GDK_WA_X | OS.GDK_WA_Y); if (enableWindow !is null) { - auto topHandle = topHandle (); + auto topHandle_ = topHandle (); OS.gdk_window_set_user_data (enableWindow, parentHandle); if (!OS.GDK_WINDOWING_X11 ()) { OS.gdk_window_raise (enableWindow); } else { - auto topWindow = OS.GTK_WIDGET_WINDOW (topHandle); + auto topWindow = OS.GTK_WIDGET_WINDOW (topHandle_); auto xDisplay = OS.gdk_x11_drawable_get_xdisplay (cast(GdkDrawable*)topWindow); auto xWindow = OS.gdk_x11_drawable_get_xid (cast(GdkDrawable*)enableWindow); int xScreen = OS.XDefaultScreen (xDisplay); @@ -3407,7 +3590,7 @@ changes.stack_mode = OS.Above; OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, &changes); } - if (OS.GTK_WIDGET_VISIBLE (topHandle)) OS.gdk_window_show_unraised (enableWindow); + if (OS.GTK_WIDGET_VISIBLE (topHandle_)) OS.gdk_window_show_unraised (enableWindow); } } if (fixFocus_) fixFocus (control); @@ -3454,7 +3637,7 @@ this.font = font; PangoFontDescription* fontDesc; if (font is null) { - fontDesc = defaultFont (); + fontDesc = defaultFont ().handle; } else { if (font.isDisposed ()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); fontDesc = font.handle; @@ -3526,9 +3709,13 @@ * first sized. The fix is to set the value to (0, 0) as * expected by DWT. */ - auto topHandle = topHandle (); - OS.GTK_WIDGET_SET_X (topHandle, 0); - OS.GTK_WIDGET_SET_Y (topHandle, 0); + auto topHandle_ = topHandle (); + if ((parent.style & DWT.MIRRORED) !is 0) { + OS.GTK_WIDGET_SET_X (topHandle_, parent.getClientWidth ()); + } else { + OS.GTK_WIDGET_SET_X (topHandle_, 0); + } + OS.GTK_WIDGET_SET_Y (topHandle_, 0); } else { resizeHandle (1, 1); forceResize (); @@ -3603,6 +3790,16 @@ if (parent.isDisposed()) DWT.error (DWT.ERROR_INVALID_ARGUMENT); if (this.parent is parent) return true; if (!isReparentable ()) return false; + auto topHandle_ = topHandle (); + int x = OS.GTK_WIDGET_X (topHandle_); + int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_); + if ((this.parent.style & DWT.MIRRORED) !is 0) { + x = this.parent.getClientWidth () - width - x; + } + if ((parent.style & DWT.MIRRORED) !is 0) { + x = parent.getClientWidth () - width - x; + } + int y = OS.GTK_WIDGET_Y (topHandle_); releaseParent (); Shell newShell = parent.getShell (), oldShell = getShell (); Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell (); @@ -3612,12 +3809,9 @@ newDecorations.fixAccelGroup (); oldDecorations.fixAccelGroup (); } - auto topHandle = topHandle (); auto newParent = parent.parentingHandle(); - int x = OS.GTK_WIDGET_X (topHandle); - int y = OS.GTK_WIDGET_Y (topHandle); - OS.gtk_widget_reparent (topHandle, newParent); - OS.gtk_fixed_move (cast(GtkFixed*)newParent, topHandle, x, y); + OS.gtk_widget_reparent (topHandle_, newParent); + OS.gtk_fixed_move (cast(GtkFixed*)newParent, topHandle_, x, y); this.parent = parent; setZOrder (null, false, true); return true; @@ -3723,7 +3917,25 @@ } void setToolTipText (Shell shell, String newString) { - shell.setToolTipText (eventHandle (), newString); + if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) { + /* + * Feature in GTK. In order to prevent children widgets + * from inheriting their parent's tooltip, the tooltip is + * a set on a shell only. In order to force the shell tooltip + * to update when a new tip string is set, the existing string + * in the tooltip is set to null, followed by running a query. + * The real tip text can then be set. + * + * Note that this will only run if the control for which the + * tooltip is being set is the current control (i.e. the control + * under the pointer). + */ + if (display.currentControl is this) { + shell.setToolTipText (shell.handle, eventHandle (), newString); + } + } else { + shell.setToolTipText (eventHandle (), newString); + } } /** @@ -3745,7 +3957,7 @@ public void setVisible (bool visible) { checkWidget(); if (((state & HIDDEN) is 0) is visible) return; - auto topHandle = topHandle(); + auto topHandle_ = topHandle(); if (visible) { /* * It is possible (but unlikely), that application @@ -3757,7 +3969,7 @@ state &= ~HIDDEN; if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) is 0) { if (enableWindow !is null) OS.gdk_window_show_unraised (enableWindow); - OS.gtk_widget_show (topHandle); + OS.gtk_widget_show (topHandle_); } } else { /* @@ -3777,12 +3989,12 @@ } state |= HIDDEN; if (fixFocus_) { - OS.GTK_WIDGET_UNSET_FLAGS (topHandle, OS.GTK_VISIBLE); + OS.GTK_WIDGET_UNSET_FLAGS (topHandle_, OS.GTK_VISIBLE); fixFocus (control); if (isDisposed ()) return; - OS.GTK_WIDGET_SET_FLAGS (topHandle, OS.GTK_VISIBLE); + OS.GTK_WIDGET_SET_FLAGS (topHandle_, OS.GTK_VISIBLE); } - OS.gtk_widget_hide (topHandle); + OS.gtk_widget_hide (topHandle_); if (isDisposed ()) return; if (enableWindow !is null) OS.gdk_window_hide (enableWindow); sendEvent (DWT.Hide); @@ -3826,9 +4038,9 @@ } } - auto topHandle = topHandle (); + auto topHandle_ = topHandle (); auto siblingHandle = sibling !is null ? sibling.topHandle () : null; - auto window = OS.GTK_WIDGET_WINDOW (topHandle); + auto window = OS.GTK_WIDGET_WINDOW (topHandle_); if (window !is null) { GdkWindow* siblingWindow; if (sibling !is null) { @@ -3877,9 +4089,9 @@ } if (fixChildren) { if (above) { - parent.moveAbove (topHandle, siblingHandle); + parent.moveAbove (topHandle_, siblingHandle); } else { - parent.moveBelow (topHandle, siblingHandle); + parent.moveBelow (topHandle_, siblingHandle); } } /* Make sure that the parent internal windows are on the bottom of the stack */ @@ -3922,10 +4134,10 @@ void setWidgetBackground () { if (fixedHandle !is null) { auto style = OS.gtk_widget_get_modifier_style (fixedHandle); - OS.gtk_widget_modify_style (fixedHandle, style); + modifyStyle (fixedHandle, style); } auto style = OS.gtk_widget_get_modifier_style (handle); - OS.gtk_widget_modify_style (handle, style); + modifyStyle (handle, style); } bool showMenu (int x, int y) { @@ -3950,11 +4162,11 @@ void showWidget () { // Comment this line to disable zero-sized widgets state |= ZERO_WIDTH | ZERO_HEIGHT; - auto topHandle = topHandle (); + auto topHandle_ = topHandle (); auto parentHandle = parent.parentingHandle (); - parent.setParentWindow (topHandle); - OS.gtk_container_add (cast(GtkContainer*)parentHandle, topHandle); - if (handle !is null && handle !is topHandle) OS.gtk_widget_show (handle); + parent.setParentWindow (topHandle_); + OS.gtk_container_add (cast(GtkContainer*)parentHandle, topHandle_); + if (handle !is null && handle !is topHandle_) OS.gtk_widget_show (handle); if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) is 0) { if (fixedHandle !is null) OS.gtk_widget_show (fixedHandle); } @@ -4057,6 +4269,9 @@ case OS.GDK_Down: case OS.GDK_Right: { bool next = key is OS.GDK_Down || key is OS.GDK_Right; + if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) { + if (key is OS.GDK_Left || key is OS.GDK_Right) next = !next; + } detail = next ? DWT.TRAVERSE_ARROW_NEXT : DWT.TRAVERSE_ARROW_PREVIOUS; break; } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/CoolBar.d --- a/dwt/widgets/CoolBar.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/CoolBar.d Mon May 12 19:13:01 2008 +0200 @@ -135,7 +135,7 @@ addListener(events[i], listener); } } -private static int checkStyle (int style) { +static int checkStyle (int style) { style |= DWT.NO_FOCUS; return (style | DWT.NO_REDRAW_RESIZE) & ~(DWT.V_SCROLL | DWT.H_SCROLL); } @@ -323,7 +323,7 @@ void insertItemIntoRow(CoolItem item, int rowIndex, int x_root) { int barWidth = getWidth(); int rowY = items[rowIndex][0].internalGetBounds().y; - int x = Math.max(0, x_root - toDisplay(new Point(0, 0)).x); + int x = Math.max(0, Math.abs(x_root - toDisplay(new Point(0, 0)).x)); /* Find the insertion index and add the item. */ int index; @@ -623,7 +623,7 @@ fixEvent(event); CoolItem grabbed = getGrabbedItem(event.x, event.y); if (dragging !is null) { - int left_root = toDisplay(new Point(event.x, event.y)).x - itemXOffset; + int left_root = toDisplay(new Point(event.x - itemXOffset, event.y)).x; Rectangle bounds = dragging.internalGetBounds(); if (event.y < bounds.y) { moveUp(dragging, left_root); diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/CoolItem.d --- a/dwt/widgets/CoolItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/CoolItem.d Mon May 12 19:13:01 2008 +0200 @@ -276,7 +276,7 @@ imageData.transparentPixel = 1; Image image = new Image (display, imageData); - GC gc = new GC (image); + GC gc = new GC (image, parent.getStyle() & DWT.RIGHT_TO_LEFT); gc.setBackground (background); gc.fillRectangle (0, 0, width, height); gc.setForeground (black); diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/DateTime.d --- a/dwt/widgets/DateTime.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/DateTime.d Mon May 12 19:13:01 2008 +0200 @@ -190,7 +190,11 @@ default: assert( false, Format( "no matching switch case for field {}.", field )); } } - + void set( int year, int month, int day ){ + this.year = year; + this.month = month; + this.dayofmonth = day; + } void set(int field, int value){ switch( field ){ case YEAR: @@ -433,6 +437,8 @@ formatSymbols = new DateFormatSymbols(); text = new Text(this, DWT.SINGLE); + /* disable the native drag and drop for the date/time text field */ + OS.gtk_drag_dest_unset(text.handle); if ((this.style & DWT.DATE) !is 0) { setFormat((this.style & DWT.SHORT) !is 0 ? DEFAULT_SHORT_DATE_FORMAT : (this.style & DWT.LONG) !is 0 ? DEFAULT_LONG_DATE_FORMAT : DEFAULT_MEDIUM_DATE_FORMAT); } else { // DWT.TIME @@ -639,8 +645,8 @@ int m = calendar.get(Calendar.MINUTE); int s = calendar.get(Calendar.SECOND); int a = calendar.get(Calendar.AM_PM); - if ((style & DWT.SHORT) !is 0) return "" ~ (h < 10 ? " " : "") ~ to!(String)(h) ~ ":" ~ (m < 10 ? " " : "") ~ to!(String)(m) ~ " " ~ ampm[a]; - return "" ~ (h < 10 ? " " : "") ~ to!(String)(h) ~ ":" ~ (m < 10 ? " " : "") ~ to!(String)(m) ~ ":" ~ (s < 10 ? " " : "") ~ to!(String)(s) ~ " " ~ ampm[a]; + if ((style & DWT.SHORT) !is 0) return "" ~ (h < 10 ? " " : "") ~ to!(String)(h) ~ ":" ~ (m < 10 ? "0" : "") ~ to!(String)(m) ~ " " ~ ampm[a]; + return "" ~ (h < 10 ? " " : "") ~ to!(String)(h) ~ ":" ~ (m < 10 ? "0" : "") ~ to!(String)(m) ~ ":" ~ (s < 10 ? "0" : "") ~ to!(String)(s) ~ " " ~ ampm[a]; } /* DWT.DATE */ int y = calendar.get(Calendar.YEAR); @@ -750,6 +756,15 @@ } } +String getNameText() { + if((style & DWT.TIME) !is 0){ + return Format( "{}:{}:{}", getHours(), getMinutes(), getSeconds() ); + } + else{ + return Format( "{}/{}/{}", (getMonth() + 1), getDay(), getYear() ); + } +} + /** * Returns the receiver's seconds. *

@@ -827,6 +842,12 @@ return value >= min && value <= max; } +bool isValid(int year, int month, int day) { + Calendar valid = Calendar.getInstance(); + valid.set(year, month, day); + return valid.get(Calendar.YEAR) is year && valid.get(Calendar.MONTH) is month && valid.get(Calendar.DAY_OF_MONTH) is day; +} + void incrementField(int amount) { int fieldName = fieldNames[currentField]; int value = calendar.get(fieldName); @@ -1111,7 +1132,7 @@ calendar.roll(Calendar.HOUR_OF_DAY, 12); // TODO: needs more work for setFormat and locale } calendar.set(fieldName, value); - notifyListeners(DWT.Selection, new Event()); + postEvent(DWT.Selection); } void setTextField(int fieldName, int value, bool commit, bool adjust) { @@ -1138,7 +1159,15 @@ /* Convert leading 0's into spaces. */ int prependCount = end - start - buffer.length(); for (int i = 0; i < prependCount; i++) { - buffer.prepend(' '); + switch (fieldName) { + case Calendar.MINUTE: + case Calendar.SECOND: + buffer.prepend('0'); + break; + default: + buffer.prepend(' '); + break; + } } newValue = buffer.toString(); ignoreVerify = true; @@ -1149,6 +1178,41 @@ } /** + * Sets the receiver's year, month, and day in a single operation. + *

+ * This is the recommended way to set the date, because setting the year, + * month, and day separately may result in invalid intermediate dates. + *

+ * + * @param year an integer between 1752 and 9999 + * @param month an integer between 0 and 11 + * @param day a positive integer beginning with 1 + * + * @exception 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 setDate (int year, int month, int day) { + checkWidget (); + if (!isValid(year, month, day)) return; + if ((style & DWT.CALENDAR) !is 0) { + this.year = year; + this.month = month; + this.day = day; + OS.gtk_calendar_select_month(handle, month, year); + OS.gtk_calendar_select_day(handle, day); + } else { + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month); + calendar.set(Calendar.DAY_OF_MONTH, day); + updateControl(); + } +} + +/** * Sets the receiver's date, or day of the month, to the specified day. *

* The first day of the month is 1, and the last day depends on the month and year. @@ -1271,6 +1335,37 @@ } /** + * Sets the receiver's hours, minutes, and seconds in a single operation. + * + * @param hours an integer between 0 and 23 + * @param minutes an integer between 0 and 59 + * @param seconds an integer between 0 and 59 + * + * @exception 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 setTime (int hours, int minutes, int seconds) { + checkWidget (); + if (!isValid(Calendar.HOUR_OF_DAY, hours)) return; + if (!isValid(Calendar.MINUTE, minutes)) return; + if (!isValid(Calendar.SECOND, seconds)) return; + if ((style & DWT.CALENDAR) !is 0) { + this.hours = hours; + this.minutes = minutes; + this.seconds = seconds; + } else { + calendar.set(Calendar.HOUR_OF_DAY, hours); + calendar.set(Calendar.MINUTE, minutes); + calendar.set(Calendar.SECOND, seconds); + updateControl(); + } +} + +/** * Sets the receiver's year. *

* The first year is 1752 and the last year is 9999. diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Dialog.d --- a/dwt/widgets/Dialog.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Dialog.d Mon May 12 19:13:01 2008 +0200 @@ -19,6 +19,7 @@ import dwt.DWTException; import dwt.widgets.Shell; import dwt.widgets.Display; +import dwt.widgets.Widget; /** * This class is the abstract superclass of the classes @@ -171,6 +172,20 @@ parent.checkWidget (); } +static int checkStyle (Shell parent, int style) { + if ((style & (DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) is 0) { + style |= DWT.APPLICATION_MODAL; + } + style &= ~DWT.MIRRORED; + if ((style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT)) is 0) { + if (parent !is null) { + if ((parent.style & DWT.LEFT_TO_RIGHT) !is 0) style |= DWT.LEFT_TO_RIGHT; + if ((parent.style & DWT.RIGHT_TO_LEFT) !is 0) style |= DWT.RIGHT_TO_LEFT; + } + } + return Widget.checkBits (style, DWT.LEFT_TO_RIGHT, DWT.RIGHT_TO_LEFT, 0, 0, 0, 0); +} + /** * Does whatever dialog specific cleanup is required, and then * uses the code in DWTError.error to handle the error. diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/DirectoryDialog.d --- a/dwt/widgets/DirectoryDialog.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/DirectoryDialog.d Mon May 12 19:13:01 2008 +0200 @@ -59,7 +59,7 @@ * */ public this (Shell parent) { - this (parent, DWT.PRIMARY_MODAL); + this (parent, DWT.APPLICATION_MODAL); } /** * Constructs a new instance of this class given its parent @@ -86,7 +86,7 @@ * */ public this (Shell parent, int style) { - super (parent, style); + super (parent, checkStyle (parent, style)); checkSubclass (); } /** @@ -154,7 +154,17 @@ else{ p = filterPath; } - OS.gtk_file_chooser_set_current_folder (handle, tango.stdc.stringz.toStringz(p)); + char* buffer = tango.stdc.stringz.toStringz(p); + /* + * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 + * when setting a file name that is not a true canonical path. + * The fix is to use the canonical path. + */ + char* ptr = OS.realpath (buffer, null); + if (ptr !is null) { + OS.gtk_file_chooser_set_current_folder (handle, ptr); + OS.g_free (ptr); + } } if (message.length > 0) { char* buffer = tango.stdc.stringz.toStringz(message); @@ -171,7 +181,27 @@ String answer = null; Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); display.addIdleProc (); + Dialog oldModal = null; + if (OS.gtk_window_get_modal (handle)) { + oldModal = display.getModalDialog (); + display.setModalDialog (this); + } + int signalId = 0; + int /*long*/ hookId = 0; + CallbackData emissionData; + emissionData.display = display; + emissionData.data = handle; + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); + hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); + } int response = OS.gtk_dialog_run (handle); + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.g_signal_remove_emission_hook (signalId, hookId); + } + if (OS.gtk_window_get_modal (handle)) { + display.setModalDialog (oldModal); + } if (response is OS.GTK_RESPONSE_OK) { auto path = OS.gtk_file_chooser_get_filename (handle); if (path !is null) { @@ -180,7 +210,7 @@ OS.g_free (path); if (utf8Ptr !is null) { answer = utf8Ptr[ 0 .. items_written ].dup; - filterPath = answer[ tango.text.Util.locatePatternPrior( answer, SEPARATOR ) + 1 .. $ ]; + filterPath = answer; OS.g_free (utf8Ptr); } } @@ -227,7 +257,27 @@ } Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); display.addIdleProc (); + Dialog oldModal = null; + if (OS.gtk_window_get_modal (handle)) { + oldModal = display.getModalDialog (); + display.setModalDialog (this); + } + int signalId = 0; + int /*long*/ hookId = 0; + CallbackData emissionData; + emissionData.display = display; + emissionData.data = handle; + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); + hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); + } int response = OS.gtk_dialog_run (handle); + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.g_signal_remove_emission_hook (signalId, hookId); + } + if (OS.gtk_window_get_modal (handle)) { + display.setModalDialog (oldModal); + } if (response is OS.GTK_RESPONSE_OK) { char* fileNamePtr = OS.gtk_file_selection_get_filename (handle); uint items_written; diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Display.d --- a/dwt/widgets/Display.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Display.d Mon May 12 19:13:01 2008 +0200 @@ -32,6 +32,7 @@ import dwt.internal.gtk.OS; import dwt.widgets.Caret; import dwt.widgets.Control; +import dwt.widgets.Dialog; import dwt.widgets.Event; import dwt.widgets.EventTable; import dwt.widgets.Listener; @@ -144,7 +145,7 @@ CallbackData filterProcCallbackData; EventTable eventTable, filterTable; - static String APP_NAME = "DWT"; + static String APP_NAME = "DWT"; //$NON-NLS-1$ static const String DISPATCH_EVENT_KEY = "dwt.internal.gtk.dispatchEvent"; static const String ADD_WIDGET_KEY = "dwt.internal.addWidget"; GClosure*[] closures; @@ -161,6 +162,12 @@ static int SWT_OBJECT_INDEX1; static int SWT_OBJECT_INDEX2; + /* Modality */ + Shell [] modalShells; + Dialog modalDialog; + static final String GET_MODAL_DIALOG = "dwt.internal.gtk.getModalDialog"; //$NON-NLS-1$ + static final String SET_MODAL_DIALOG = "dwt.internal.gtk.setModalDialog"; //$NON-NLS-1$ + /* Focus */ int focusEvent; Control focusControl; @@ -212,9 +219,8 @@ /* Idle proc callback */ CallbackData idleProcCallbackData; int idleHandle; - static const String ADD_IDLE_PROC_KEY = "dwt.internal.gtk2.addIdleProc"; - static const String REMOVE_IDLE_PROC_KEY = "dwt.internal.gtk2.removeIdleProc"; - + static const String ADD_IDLE_PROC_KEY = "dwt.internal.gtk.addIdleProc"; + static const String REMOVE_IDLE_PROC_KEY = "dwt.internal.gtk.removeIdleProc"; Object idleLock; bool idleNeeded; @@ -224,6 +230,11 @@ /* Set direction callback */ CallbackData setDirectionProcCallbackData; + static const String GET_DIRECTION_PROC_KEY = "dwt.internal.gtk.getDirectionProc"; //$NON-NLS-1$ + + /* Set emissionProc callback */ + CallbackData emissionProcCallbackData; + static const String GET_EMISSION_PROC_KEY = "dwt.internal.gtk.getEmissionProc"; //$NON-NLS-1$ /* Get all children callback */ CallbackData allChildrenProcCallbackData; @@ -279,6 +290,8 @@ /* Fixed Subclass */ static int /*long*/ fixed_type; static int /*long*/ fixed_info_ptr; + static extern(C) void function(GtkWidget* handle, GtkAllocation* allocation) oldFixedSizeAllocateProc; + /* Renderer Subclass */ static int /*long*/ text_renderer_type, pixbuf_renderer_type, toggle_renderer_type; @@ -391,18 +404,12 @@ // PACKAGE_NAME = name.substring (0, index + 1); // } - /* - * In order to support CLDC, .class cannot be used because - * it does not compile on some Java compilers when they are - * targeted for CLDC. Use Class.forName() instead. - */ - //synchronized static void static_this() { static this() { - Displays = new Display [4]; - initDeviceFinder(); - SWT_OBJECT_INDEX = OS.g_quark_from_string ("SWT_OBJECT_INDEX"); - SWT_OBJECT_INDEX1 = OS.g_quark_from_string ("SWT_OBJECT_INDEX1"); - SWT_OBJECT_INDEX2 = OS.g_quark_from_string ("SWT_OBJECT_INDEX2"); + Displays = new Display [4]; + initDeviceFinder(); + SWT_OBJECT_INDEX = OS.g_quark_from_string ("SWT_OBJECT_INDEX"); + SWT_OBJECT_INDEX1 = OS.g_quark_from_string ("SWT_OBJECT_INDEX1"); + SWT_OBJECT_INDEX2 = OS.g_quark_from_string ("SWT_OBJECT_INDEX2"); } /* GTK Version */ @@ -694,14 +701,16 @@ * @see #syncExec */ public void asyncExec (Runnable runnable) { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - synchronized (idleLock) { - if (idleNeeded && idleHandle is 0) { - //NOTE: calling unlocked function in OS - idleHandle = OS.g_idle_add (&idleProcFunc, cast(void*) this); + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + synchronized (idleLock) { + if (idleNeeded && idleHandle is 0) { + //NOTE: calling unlocked function in OS + idleHandle = OS.g_idle_add (&idleProcFunc, cast(void*) this); + } } + synchronizer.asyncExec (runnable); } - synchronizer.asyncExec (runnable); } /** @@ -760,11 +769,13 @@ if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); } -static synchronized void checkDisplay (Thread thread, bool multiple) { - for (int i=0; i + *

  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + * + * + * @since 3.4 + */ +public Synchronizer getSynchronizer () { + checkDevice (); + return synchronizer; +} + +/** * Returns the thread that has invoked syncExec * or null if no such runnable is currently being invoked by * the user-interface thread. @@ -1987,8 +2044,10 @@ * */ public Thread getSyncThread () { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - return synchronizer.syncThread; + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + return synchronizer.syncThread; + } } /** @@ -2122,23 +2181,23 @@ switch (id) { case DWT.ICON_ERROR: if (errorImage is null) { - errorImage = createImage ("gtk-dialog-error"); + errorImage = createImage ("gtk-dialog-error"); //$NON-NLS-1$ } return errorImage; case DWT.ICON_INFORMATION: case DWT.ICON_WORKING: if (infoImage is null) { - infoImage = createImage ("gtk-dialog-info"); + infoImage = createImage ("gtk-dialog-info"); //$NON-NLS-1$ } return infoImage; case DWT.ICON_QUESTION: if (questionImage is null) { - questionImage = createImage ("gtk-dialog-question"); + questionImage = createImage ("gtk-dialog-question"); //$NON-NLS-1$ } return questionImage; case DWT.ICON_WARNING: if (warningImage is null) { - warningImage = createImage ("gtk-dialog-warning"); + warningImage = createImage ("gtk-dialog-warning"); //$NON-NLS-1$ } return warningImage; default: @@ -2279,8 +2338,10 @@ * */ public Thread getThread () { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - return thread; + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + return thread; + } } Widget getWidget (GtkWidget* handle) { @@ -2419,6 +2480,7 @@ closures [Widget.MOTION_NOTIFY_EVENT] = do_cclosure_new (windowProc3, Widget.MOTION_NOTIFY_EVENT, 0); closures [Widget.MOTION_NOTIFY_EVENT_INVERSE] = do_cclosure_new (windowProc3, Widget.MOTION_NOTIFY_EVENT_INVERSE, 0); closures [Widget.MOVE_FOCUS] = do_cclosure_new (windowProc3, Widget.MOVE_FOCUS, 0); + closures [Widget.POPULATE_POPUP] = do_cclosure_new (windowProc3, Widget.POPULATE_POPUP, 0); closures [Widget.SCROLL_EVENT] = do_cclosure_new (windowProc3, Widget.SCROLL_EVENT, 0); closures [Widget.SHOW_HELP] = do_cclosure_new (windowProc3, Widget.SHOW_HELP, 0); closures [Widget.SIZE_ALLOCATE] = do_cclosure_new (windowProc3, Widget.SIZE_ALLOCATE, 0); @@ -2454,6 +2516,7 @@ void* getWindowProcUserData( int value ){ return windowProcCallbackDatas[ value ]; + } void initializeSystemSettings () { @@ -2487,7 +2550,7 @@ void initializeWindowManager () { /* Get the window manager name */ - windowManager = ""; + windowManager = ""; //$NON-NLS-1$ if (OS.GTK_VERSION >= OS.buildVERSION (2, 2, 0)) { auto screen = OS.gdk_screen_get_default (); if (screen !is null) { @@ -2549,7 +2612,7 @@ data.drawable = root; data.background = getSystemColor (DWT.COLOR_WHITE).handle; data.foreground = getSystemColor (DWT.COLOR_BLACK).handle; - data.font = getSystemFont ().handle; + data.font = getSystemFont (); } return gdkGC; return null; @@ -2647,6 +2710,7 @@ auto window = from.eventWindow (); int origin_x, origin_y; OS.gdk_window_get_origin (window, &origin_x, &origin_y); + if ((from.style & DWT.MIRRORED) !is 0) point.x = from.getClientWidth () - point.x; point.x += origin_x; point.y += origin_y; } @@ -2656,6 +2720,7 @@ OS.gdk_window_get_origin (window, &origin_x, &origin_y); point.x -= origin_x; point.y -= origin_y; + if ((to.style & DWT.MIRRORED) !is 0) point.x = to.getClientWidth () - point.x; } return point; } @@ -2788,10 +2853,13 @@ if (to !is null && to.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT); Rectangle rect = new Rectangle (x, y, width, height); if (from is to) return rect; + bool fromRTL = false, toRTL = false; if (from !is null) { auto window = from.eventWindow (); int origin_x, origin_y; OS.gdk_window_get_origin (window, &origin_x, &origin_y); + fromRTL = (from.style & DWT.MIRRORED) !is 0; + if (fromRTL) rect.x = from.getClientWidth() - rect.x; rect.x += origin_x; rect.y += origin_y; } @@ -2801,7 +2869,10 @@ OS.gdk_window_get_origin (window, &origin_x, &origin_y); rect.x -= origin_x; rect.y -= origin_y; + toRTL = (to.style & DWT.MIRRORED) !is 0; + if (toRTL) rect.x = to.getClientWidth () - rect.x; } + if (fromRTL !is toRTL) rect.x -= rect.width; return rect; } @@ -2870,67 +2941,69 @@ * */ public bool post (Event event) { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - if (event is null) error (DWT.ERROR_NULL_ARGUMENT); - if (!OS.GDK_WINDOWING_X11()) return false; - auto xDisplay = OS.GDK_DISPLAY (); - int type = event.type; - switch (type) { - case DWT.KeyDown: - case DWT.KeyUp: { - int keyCode = 0; - auto keysym = untranslateKey (event.keyCode); - if (keysym !is 0) keyCode = OS.XKeysymToKeycode (xDisplay, keysym); - if (keyCode is 0) { - char key = event.character; - switch (key) { - case DWT.BS: keysym = OS.GDK_BackSpace; break; - case DWT.CR: keysym = OS.GDK_Return; break; - case DWT.DEL: keysym = OS.GDK_Delete; break; - case DWT.ESC: keysym = OS.GDK_Escape; break; - case DWT.TAB: keysym = OS.GDK_Tab; break; - case DWT.LF: keysym = OS.GDK_Linefeed; break; - default: - keysym = wcsToMbcs (key); + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + if (event is null) error (DWT.ERROR_NULL_ARGUMENT); + if (!OS.GDK_WINDOWING_X11()) return false; + auto xDisplay = OS.GDK_DISPLAY (); + int type = event.type; + switch (type) { + case DWT.KeyDown: + case DWT.KeyUp: { + int keyCode = 0; + auto keysym = untranslateKey (event.keyCode); + if (keysym !is 0) keyCode = OS.XKeysymToKeycode (xDisplay, keysym); + if (keyCode is 0) { + char key = event.character; + switch (key) { + case DWT.BS: keysym = OS.GDK_BackSpace; break; + case DWT.CR: keysym = OS.GDK_Return; break; + case DWT.DEL: keysym = OS.GDK_Delete; break; + case DWT.ESC: keysym = OS.GDK_Escape; break; + case DWT.TAB: keysym = OS.GDK_Tab; break; + case DWT.LF: keysym = OS.GDK_Linefeed; break; + default: + keysym = key; + } + keyCode = OS.XKeysymToKeycode (xDisplay, keysym); + if (keyCode is 0) return false; } - keyCode = OS.XKeysymToKeycode (xDisplay, keysym); - if (keyCode is 0) return false; + OS.XTestFakeKeyEvent (xDisplay, keyCode, type is DWT.KeyDown, 0); + return true; } - OS.XTestFakeKeyEvent (xDisplay, keyCode, type is DWT.KeyDown, 0); - return true; + case DWT.MouseDown: + case DWT.MouseMove: + case DWT.MouseUp: { + if (type is DWT.MouseMove) { + OS.XTestFakeMotionEvent (xDisplay, -1, event.x, event.y, 0); + } else { + int button = event.button; + switch (button) { + case 1: + case 2: + case 3: break; + case 4: button = 6; break; + case 5: button = 7; break; + default: return false; + } + OS.XTestFakeButtonEvent (xDisplay, button, type is DWT.MouseDown, 0); + } + return true; + default: + } + /* + * This code is intentionally commented. After posting a + * mouse wheel event the system may respond unpredictably + * to subsequent mouse actions. + */ +// case DWT.MouseWheel: { +// if (event.count is 0) return false; +// int button = event.count < 0 ? 5 : 4; +// OS.XTestFakeButtonEvent (xDisplay, button, type is DWT.MouseWheel, 0); +// } } - case DWT.MouseDown: - case DWT.MouseMove: - case DWT.MouseUp: { - if (type is DWT.MouseMove) { - OS.XTestFakeMotionEvent (xDisplay, -1, event.x, event.y, 0); - } else { - int button = event.button; - switch (button) { - case 1: - case 2: - case 3: break; - case 4: button = 6; break; - case 5: button = 7; break; - default: return false; - } - OS.XTestFakeButtonEvent (xDisplay, button, type is DWT.MouseDown, 0); - } - return true; - default: - } - /* - * This code is intentionally commented. After posting a - * mouse wheel event the system may respond unpredictably - * to subsequent mouse actions. - */ -// case DWT.MouseWheel: { -// if (event.count is 0) return false; -// int button = event.count < 0 ? 5 : 4; -// OS.XTestFakeButtonEvent (xDisplay, button, type is DWT.MouseWheel, 0); -// } + return false; } - return false; } void postEvent (Event event) { @@ -3008,17 +3081,19 @@ return runAsyncMessages (false); } -synchronized void register () { - for (int i=0; i= 0) { if (types [index] !is 0) break; @@ -43,10 +61,10 @@ } index++; if (index is length) { - int [] newTypes = new int [length + 4]; + int [] newTypes = new int [length + GROW_SIZE]; System.arraycopy (types, 0, newTypes, 0, length); types = newTypes; - Listener [] newListeners = new Listener [length + 4]; + Listener [] newListeners = new Listener [length + GROW_SIZE]; SimpleType!(Listener).arraycopy (listeners, 0, newListeners, 0, length); listeners = newListeners; } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/ExpandItem.d --- a/dwt/widgets/ExpandItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/ExpandItem.d Mon May 12 19:13:01 2008 +0200 @@ -290,8 +290,7 @@ public int getHeaderHeight () { checkWidget (); if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { - auto widget = OS.gtk_expander_get_label_widget (handle); - return OS.GTK_WIDGET_HEIGHT (widget); + return OS.GTK_WIDGET_HEIGHT (handle) - (expanded ? height : 0); } return Math.max (parent.getBandHeight (), imageHeight); } @@ -596,6 +595,14 @@ } } +void setOrientation() { + super.setOrientation (); + if ((parent.style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.gtk_widget_set_direction (handle, OS.GTK_TEXT_DIR_RTL); + display.doSetDirectionProc(handle, OS.GTK_TEXT_DIR_RTL); + } +} + public override void setText (String string) { super.setText (string); if (OS.GTK_VERSION >= OS.buildVERSION (2, 4, 0)) { diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/FileDialog.d --- a/dwt/widgets/FileDialog.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/FileDialog.d Mon May 12 19:13:01 2008 +0200 @@ -49,6 +49,8 @@ String fileName = ""; String[] fileNames; String fullPath = ""; + int filterIndex = -1; + bool overwrite = false; GtkWidget* handle; static final char SEPARATOR = tango.io.FileConst.FileConst.PathSeparatorChar; static final char EXTENSION_SEPARATOR = ';'; @@ -67,7 +69,7 @@ * */ public this (Shell parent) { - this (parent, DWT.PRIMARY_MODAL); + this (parent, DWT.APPLICATION_MODAL); } /** * Constructs a new instance of this class given its parent @@ -94,7 +96,7 @@ * */ public this (Shell parent, int style) { - super (parent, style); + super (parent, checkStyle (parent, style)); checkSubclass (); } String computeResultChooserDialog () { @@ -142,6 +144,28 @@ } } } + filterIndex = -1; + auto filter = OS.gtk_file_chooser_get_filter (handle); + if (filter !is null) { + auto filterNamePtr = OS.gtk_file_filter_get_name (filter); + if (filterNamePtr !is null) { + String filterName = tango.stdc.stringz.fromStringz(filterNamePtr).dup; + //OS.g_free (filterNamePtr); //GTK owns this pointer - do not free + for (int i = 0; i < filterExtensions.length; i++) { + if (filterNames.length > 0) { + if (filterNames[i].equals(filterName)) { + filterIndex = i; + break; + } + } else { + if (filterExtensions[i].equals(filterName)) { + filterIndex = i; + break; + } + } + } + } + } if (fullPath !is null) { int separatorIndex = tango.text.Util.locatePrior( fullPath, SEPARATOR); if( separatorIndex is fullPath.length ) separatorIndex = -1; @@ -151,6 +175,7 @@ return fullPath; } String computeResultClassicDialog () { + filterIndex = -1; GtkFileSelection* selection = cast(GtkFileSelection*)handle; auto entry = selection.selection_entry; auto entryText = OS.gtk_entry_get_text (entry); @@ -248,6 +273,25 @@ return filterExtensions; } /** + * Get the 0-based index of the file extension filter + * which was selected by the user, or -1 if no filter + * was selected. + *

    + * This is an index into the FilterExtensions array and + * the FilterNames array. + *

    + * + * @return index the file extension filter index + * + * @see #getFilterExtensions + * @see #getFilterNames + * + * @since 3.4 + */ +public int getFilterIndex () { + return filterIndex; +} +/** * Returns the names that describe the filter extensions * which the dialog will use to filter the files it shows. * @@ -269,6 +313,18 @@ return filterPath; } /** + * Returns the flag that the dialog will use to + * determine whether to prompt the user for file + * overwrite if the selected file already exists. + * + * @return true if the dialog will prompt for file overwrite, false otherwise + * + * @since 3.4 + */ +public bool getOverwrite () { + return overwrite; +} +/** * Makes the dialog visible and brings it to the front * of the display. * @@ -309,7 +365,28 @@ Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); display.addIdleProc (); String answer = null; - if (OS.gtk_dialog_run (handle) is OS.GTK_RESPONSE_OK) { + Dialog oldModal = null; + if (OS.gtk_window_get_modal (handle)) { + oldModal = display.getModalDialog (); + display.setModalDialog (this); + } + uint signalId = 0; + uint /*long*/ hookId = 0; + CallbackData emissionData; + emissionData.display = display; + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); + emissionData.data = handle; + hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); + } + int response = OS.gtk_dialog_run (handle); + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.g_signal_remove_emission_hook (signalId, hookId); + } + if (OS.gtk_window_get_modal (handle)) { + display.setModalDialog (oldModal); + } + if (response is OS.GTK_RESPONSE_OK) { answer = computeResultChooserDialog (); } display.removeIdleProc (); @@ -332,7 +409,28 @@ Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); display.addIdleProc (); String answer = null; - if (OS.gtk_dialog_run (handle) is OS.GTK_RESPONSE_OK) { + Dialog oldModal = null; + if (OS.gtk_window_get_modal (handle)) { + oldModal = display.getModalDialog (); + display.setModalDialog (this); + } + int signalId = 0; + int /*long*/ hookId = 0; + CallbackData emissionData; + emissionData.display = display; + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); + emissionData.data = handle; + hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); + } + int response = OS.gtk_dialog_run (handle); + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.g_signal_remove_emission_hook (signalId, hookId); + } + if (OS.gtk_window_get_modal (handle)) { + display.setModalDialog (oldModal); + } + if (response is OS.GTK_RESPONSE_OK) { answer = computeResultClassicDialog (); } display.removeIdleProc (); @@ -353,30 +451,40 @@ stringBuffer.append (SEPARATOR); } stringBuffer.append (filterPath); - if (filterPath[filterPath.length - 1 ] !is SEPARATOR) { - stringBuffer.append (SEPARATOR); - } - if (fileName.length > 0) { + if (fileName.length > 0 && (style & DWT.SAVE) is 0) { + if (filterPath[filterPath.length - 1 ] !is SEPARATOR) { + stringBuffer.append (SEPARATOR); + } stringBuffer.append (fileName); - } else { - /* go into the specified directory */ - stringBuffer.append ('.'); - } char* buffer = tango.stdc.stringz.toStringz( stringBuffer.toString ()); - /* - * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 - * when setting a file name that is not a true canonical path. - * The fix is to use the canonical path. - */ + /* + * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 + * when setting a file name that is not a true canonical path. + * The fix is to use the canonical path. + */ auto ptr = OS.realpath (buffer, null); if (ptr !is null) { - OS.gtk_file_chooser_set_filename (handle, ptr); - OS.g_free (ptr); + OS.gtk_file_chooser_set_filename (handle, ptr); + OS.g_free (ptr); + } + } else { + char* buffer = tango.stdc.stringz.toStringz( stringBuffer.toString () ); + /* + * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 + * when setting a file name that is not a true canonical path. + * The fix is to use the canonical path. + */ + auto ptr = OS.realpath (buffer, null); + if (ptr !is null) { + OS.gtk_file_chooser_set_current_folder (handle, ptr); + OS.g_free (ptr); + } } } else { if (fileName.length > 0) { if (fileName[0] is SEPARATOR) { char* buffer = tango.stdc.stringz.toStringz(fileName); + /* * Bug in GTK. GtkFileChooser may crash on GTK versions 2.4.10 to 2.6 * when setting a file name that is not a true canonical path. @@ -394,10 +502,16 @@ char* buffer = tango.stdc.stringz.toStringz(fileName); OS.gtk_file_chooser_set_current_name (handle, buffer); } + if ((style & DWT.SAVE) !is 0) { + if (OS.GTK_VERSION >= OS.buildVERSION (2, 8, 0)) { + OS.gtk_file_chooser_set_do_overwrite_confirmation (handle, overwrite); + } + } /* Set the extension filters */ if (filterNames is null) filterNames = null; if (filterExtensions is null) filterExtensions = null; + GtkFileFilter* initialFilter = null; for (int i = 0; i < filterExtensions.length; i++) { if (filterExtensions [i] !is null) { auto filter = OS.gtk_file_filter_new (); @@ -421,8 +535,14 @@ char* filterString = tango.stdc.stringz.toStringz(current); OS.gtk_file_filter_add_pattern (filter, filterString); OS.gtk_file_chooser_add_filter (handle, filter); + if (i is filterIndex) { + initialFilter = filter; + } } } + if (initialFilter !is null) { + OS.gtk_file_chooser_set_filter(handle, initialFilter); + } fullPath = null; fileNames = null; } @@ -486,6 +606,25 @@ filterExtensions = extensions; } /** + * Set the 0-based index of the file extension filter + * which the dialog will use initially to filter the files + * it shows to the argument. + *

    + * This is an index into the FilterExtensions array and + * the FilterNames array. + *

    + * + * @param index the file extension filter index + * + * @see #setFilterExtensions + * @see #setFilterNames + * + * @since 3.4 + */ +public void setFilterIndex (int index) { + filterIndex = index; +} +/** * Sets the the names that describe the filter extensions * which the dialog will use to filter the files it shows * to the argument, which may be null. @@ -522,4 +661,17 @@ public void setFilterPath (String string) { filterPath = string; } + +/** + * Sets the flag that the dialog will use to + * determine whether to prompt the user for file + * overwrite if the selected file already exists. + * + * @param overwrite true if the dialog will prompt for file overwrite, false otherwise + * + * @since 3.4 + */ +public void setOverwrite (bool overwrite) { + this.overwrite = overwrite; } +} diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/FontDialog.d --- a/dwt/widgets/FontDialog.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/FontDialog.d Mon May 12 19:13:01 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 @@ -58,7 +58,7 @@ * */ public this (Shell parent) { - this (parent, DWT.PRIMARY_MODAL); + this (parent, DWT.APPLICATION_MODAL); } /** * Constructs a new instance of this class given its parent @@ -85,7 +85,7 @@ * */ public this (Shell parent, int style) { - super (parent, style); + super (parent, checkStyle (parent, style)); checkSubclass (); } @@ -144,6 +144,7 @@ GtkWidget* handle; char* titleBytes; titleBytes = tango.stdc.stringz.toStringz(title); + Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); handle = OS.gtk_font_selection_dialog_new (titleBytes); if (parent !is null) { auto shellHandle = parent.topHandle (); @@ -155,16 +156,34 @@ } } if (fontData !is null) { - Display display = parent !is null ? parent.display : Display.getCurrent (); Font font = new Font (display, fontData); auto fontName = OS.pango_font_description_to_string (font.handle); font.dispose(); OS.gtk_font_selection_dialog_set_font_name (handle, fontName); OS.g_free (fontName); } - Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); display.addIdleProc (); - int response = OS.gtk_dialog_run(handle); + Dialog oldModal = null; + if (OS.gtk_window_get_modal (handle)) { + oldModal = display.getModalDialog (); + display.setModalDialog (this); + } + int signalId = 0; + int /*long*/ hookId = 0; + CallbackData emissionData; + emissionData.display = display; + emissionData.data = handle; + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); + hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); + } + int response = OS.gtk_dialog_run (handle); + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.g_signal_remove_emission_hook (signalId, hookId); + } + if (OS.gtk_window_get_modal (handle)) { + display.setModalDialog (oldModal); + } bool success = response is OS.GTK_RESPONSE_OK; if (success) { auto fontName = OS.gtk_font_selection_dialog_get_font_name (handle); diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/IME.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/widgets/IME.d Mon May 12 19:13:01 2008 +0200 @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.widgets.IME; + + +import dwt.DWT; +import dwt.graphics.Color; +import dwt.graphics.TextStyle; +import dwt.internal.Converter; +import dwt.internal.gtk.OS; + +import dwt.widgets.Widget; +import dwt.widgets.Canvas; +import dwt.widgets.Event; + +import dwt.dwthelper.utils; + +public class IME : Widget { + Canvas parent; + int caretOffset; + int startOffset; + int commitCount; + String text; + int [] ranges; + TextStyle [] styles; + bool inComposition; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this () { +} + +/** + * + * @see DWT + */ +public this (Canvas parent, int style) { + super (parent, style); + this.parent = parent; + createWidget (); +} + +void createWidget () { + text = ""; + startOffset = -1; + if (parent.getIME () is null) { + parent.setIME (this); + } +} + +public int getCaretOffset () { + checkWidget (); + return startOffset + caretOffset; +} + +public int getCommitCount () { + checkWidget (); + return commitCount; +} + +public int getCompositionOffset () { + checkWidget (); + return startOffset; +} + +public int [] getRanges () { + checkWidget (); + if (ranges is null) return new int [0]; + int [] result = new int [ranges.length]; + for (int i = 0; i < result.length; i++) { + result [i] = ranges [i] + startOffset; + } + return result; +} + +public TextStyle [] getStyles () { + checkWidget (); + if (styles is null) return new TextStyle [0]; + TextStyle [] result = new TextStyle [styles.length]; + System.arraycopy (styles, 0, result, 0, styles.length); + return result; +} + +public String getText () { + checkWidget (); + return text; +} + +public bool getWideCaret () { + checkWidget (); + return false; +} + +override int /*long*/ gtk_button_press_event (GtkWidget* widget, GdkEventButton* event) { + if (!isInlineEnabled ()) return 0; + auto imHandle_ = imHandle (); + if (imHandle_ !is null) OS.gtk_im_context_reset (imHandle_); + return 0; +} + +override int /*long*/ gtk_commit (GtkIMContext* imcontext, char* textPtr) { + if (!isInlineEnabled ()) return 0; + bool doit = true; + ranges = null; + styles = null; + caretOffset = commitCount = 0; + if (textPtr !is null && inComposition) { + int length = OS.strlen (textPtr); + if (length !is 0) { + char [] chars = tango.stdc.stringz.fromStringz(textPtr).dup; + Event event = new Event(); + event.detail = DWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = startOffset + text.length; + event.text = text = chars !is null ? chars : ""; + commitCount = text.length; + sendEvent (DWT.ImeComposition, event); + doit = event.doit; + text = ""; + startOffset = -1; + commitCount = 0; + } + } + inComposition = false; + return doit ? 0 : 1; +} + +override int /*long*/ gtk_preedit_changed (GtkIMContext* imcontext) { + if (!isInlineEnabled ()) return 0; + ranges = null; + styles = null; + commitCount = 0; + auto imHandle_ = imHandle (); + char* preeditString; + void* pangoAttrs; + int cursorPos; + OS.gtk_im_context_get_preedit_string (imHandle_, &preeditString, &pangoAttrs, &cursorPos); + caretOffset = cursorPos ; + char [] chars = null; + if (preeditString !is null) { + int length = OS.strlen (preeditString); + chars = tango.stdc.stringz.fromStringz(preeditString).dup; + if (pangoAttrs !is null) { + int count = 0; + auto iterator = OS.pango_attr_list_get_iterator (pangoAttrs ); + while (OS.pango_attr_iterator_next (iterator)) count++; + OS.pango_attr_iterator_destroy (iterator); + ranges = new int [count * 2]; + styles = new TextStyle [count]; + iterator = OS.pango_attr_list_get_iterator (pangoAttrs ); + PangoAttrColor* attrColor; + PangoAttrInt* attrInt; + int start; + int end; + for (int i = 0; i < count; i++) { + OS.pango_attr_iterator_range (iterator, &start, &end); + ranges [i * 2] = cast(int)/*64*/OS.g_utf8_pointer_to_offset (preeditString, preeditString + start); + ranges [i * 2 + 1] = cast(int)/*64*/OS.g_utf8_pointer_to_offset (preeditString, preeditString + end) - 1; + styles [i] = new TextStyle (null, null, null); + auto attr = OS.pango_attr_iterator_get (iterator, OS.PANGO_ATTR_FOREGROUND); + if (attr !is null) { + attrColor = cast(PangoAttrColor*) attr; + GdkColor* color = new GdkColor (); + color.red = attrColor.color.red; + color.green = attrColor.color.green; + color.blue = attrColor.color.blue; + styles [i].foreground = Color.gtk_new (display, color); + } + attr = OS.pango_attr_iterator_get (iterator, OS.PANGO_ATTR_BACKGROUND); + if (attr !is null) { + attrColor = cast(PangoAttrColor*) attr; + GdkColor* color = new GdkColor (); + color.red = attrColor.color.red; + color.green = attrColor.color.green; + color.blue = attrColor.color.blue; + styles [i].background = Color.gtk_new (display, color); + } + attr = OS.pango_attr_iterator_get (iterator, OS.PANGO_ATTR_UNDERLINE); + if (attr !is null) { + attrInt = cast(PangoAttrInt*) attr; + styles [i].underline = attrInt.value !is OS.PANGO_UNDERLINE_NONE;; + styles [i].underlineStyle = DWT.UNDERLINE_SINGLE; + switch (attrInt.value) { + case OS.PANGO_UNDERLINE_DOUBLE: + styles [i].underlineStyle = DWT.UNDERLINE_DOUBLE; + break; + case OS.PANGO_UNDERLINE_ERROR: + styles [i].underlineStyle = DWT.UNDERLINE_ERROR; + break; + } + if (styles [i].underline) { + attr = OS.pango_attr_iterator_get(iterator, OS.PANGO_ATTR_UNDERLINE_COLOR); + if (attr !is null) { + attrColor = cast(PangoAttrColor*) attr; + GdkColor* color = new GdkColor; + color.red = attrColor.color.red; + color.green = attrColor.color.green; + color.blue = attrColor.color.blue; + styles [i].underlineColor = Color.gtk_new (display, color); + } + } + } + OS.pango_attr_iterator_next (iterator); + } + OS.pango_attr_iterator_destroy (iterator); + OS.pango_attr_list_unref (pangoAttrs); + } + OS.g_free (preeditString); + } + if (chars !is null) { + if (text.length is 0) startOffset = -1; + int end = startOffset + text.length; + if (startOffset is -1) { + Event event = new Event (); + event.detail = DWT.COMPOSITION_SELECTION; + sendEvent (DWT.ImeComposition, event); + startOffset = event.start; + end = event.end; + } + inComposition = true; + Event event = new Event (); + event.detail = DWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = end; + event.text = text = chars !is null ? chars : ""; + sendEvent (DWT.ImeComposition, event); + } + return 1; +} + +GtkIMContext* imHandle () { + return parent.imHandle (); +} + +bool isInlineEnabled () { + return hooks (DWT.ImeComposition); +} + +void releaseParent () { + super.releaseParent (); + if (this is parent.getIME ()) parent.setIME (null); +} + +void releaseWidget () { + super.releaseWidget (); + parent = null; + text = null; + styles = null; + ranges = null; +} + +public void setCompositionOffset (int offset) { + checkWidget (); + if (offset < 0) return; + if (startOffset !is -1) { + startOffset = offset; + } +} + +} diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Label.d --- a/dwt/widgets/Label.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Label.d Mon May 12 19:13:01 2008 +0200 @@ -214,7 +214,12 @@ OS.gtk_container_add (cast(GtkContainer*)fixedHandle, handle); } if ((style & DWT.SEPARATOR) !is 0) return; - if ((style & DWT.WRAP) !is 0) OS.gtk_label_set_line_wrap (cast(GtkLabel*)labelHandle, true); + if ((style & DWT.WRAP) !is 0) { + OS.gtk_label_set_line_wrap (labelHandle, true); + if (OS.GTK_VERSION >= OS.buildVERSION (2, 10, 0)) { + OS.gtk_label_set_line_wrap_mode (labelHandle, OS.PANGO_WRAP_WORD_CHAR); + } + } if ((style & DWT.LEFT) !is 0) { OS.gtk_misc_set_alignment (cast(GtkMisc*)labelHandle, 0.0f, 0.0f); OS.gtk_label_set_justify (cast(GtkLabel*)labelHandle, OS.GTK_JUSTIFY_LEFT); diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Link.d --- a/dwt/widgets/Link.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Link.d Mon May 12 19:13:01 2008 +0200 @@ -188,6 +188,7 @@ OS.gtk_fixed_set_has_window (handle, true); OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS); layout = new TextLayout (display); + layout.setOrientation((style & DWT.RIGHT_TO_LEFT) !is 0? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT); linkColor = new Color (display, LINK_FOREGROUND); disabledColor = new Color (display, LINK_DISABLED_FOREGROUND); offsets = null; @@ -415,6 +416,7 @@ event.y = gdkEvent.area.y; event.width = gdkEvent.area.width; event.height = gdkEvent.area.height; + if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth () - event.width - event.x; event.gc = gc; sendEvent (DWT.Paint, event); event.gc = null; @@ -488,9 +490,9 @@ override void releaseWidget () { super.releaseWidget (); - if (layout !is null) layout.dispose (); + if (layout !is null) layout.dispose (); layout = null; - if (linkColor !is null) linkColor.dispose (); + if (linkColor !is null) linkColor.dispose (); linkColor = null; if (disabledColor !is null) disabledColor.dispose (); disabledColor = null; @@ -638,7 +640,7 @@ } if (start < length_) { int tmp = parseMnemonics (buffer, start, tagStart, result); - int mnemonic = parseMnemonics (buffer, linkStart, index, result); + int mnemonic = parseMnemonics (buffer, Math.max (tagStart, linkStart), length_, result); if (mnemonic is -1) mnemonic = tmp; mnemonics [linkIndex] = mnemonic; } else { @@ -725,10 +727,14 @@ bool enabled = (state & DISABLED) is 0; TextStyle linkStyle = new TextStyle (null, enabled ? linkColor : disabledColor, null); linkStyle.underline = true; + int [] bidiSegments = new int [offsets.length*2]; for (int i = 0; i < offsets.length; i++) { Point point = offsets [i]; layout.setStyle (linkStyle, point.x, point.y); + bidiSegments[i*2] = point.x; + bidiSegments[i*2+1] = point.y+1; } + layout.setSegments (bidiSegments); TextStyle mnemonicStyle = new TextStyle (null, null, null); mnemonicStyle.underline = true; for (int i = 0; i < mnemonics.length; i++) { diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Menu.d --- a/dwt/widgets/Menu.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Menu.d Mon May 12 19:13:01 2008 +0200 @@ -190,7 +190,15 @@ sendEvent (DWT.Show); if (getItemCount () !is 0) { if ((OS.GTK_VERSION >= OS.buildVERSION (2, 8, 0))) { - OS.gtk_menu_shell_set_take_focus (cast(GtkMenuShell*)handle, false); + /* + * Feature in GTK. ON_TOP shells will send out + * DWT.Deactivate whenever a context menu is shown. + * The fix is to prevent the menu from taking focus + * when it is being shown in an ON_TOP shell. + */ + if ((parent._getShell ().style & DWT.ON_TOP) !is 0) { + OS.gtk_menu_shell_set_take_focus (cast(GtkMenuShell*)handle, false); + } } /* * Bug in GTK. The timestamp passed into gtk_menu_popup is used @@ -710,9 +718,9 @@ OS.gtk_widget_size_request (cast(GtkWidget*)menu, &requisition); int screenHeight = OS.gdk_screen_height (); int reqy = this.y; - if (reqy + requisition.height > screenHeight && reqy - requisition.height >= 0) { - reqy -= requisition.height; - } + if (reqy + requisition.height > screenHeight) { + reqy = Math.max (0, reqy - requisition.height); + } int screenWidth = OS.gdk_screen_width (); int reqx = this.x; if ((style & DWT.RIGHT_TO_LEFT) !is 0) { diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/MenuItem.d --- a/dwt/widgets/MenuItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/MenuItem.d Mon May 12 19:13:01 2008 +0200 @@ -373,6 +373,11 @@ return menu; } +String getNameText () { + if ((style & DWT.SEPARATOR) !is 0) return "|"; + return super.getNameText (); +} + /** * Returns the receiver's parent, which must be a Menu. * @@ -842,7 +847,8 @@ String accelString = ""; int index = string.indexOf ('\t'); if (index !is -1) { - accelString = string.substring (index, string.length); + bool isRTL = (parent.style & DWT.RIGHT_TO_LEFT) !is 0; + accelString = (isRTL? "" : " ") ~ string.substring (index+1, string.length) ~ (isRTL? " " : ""); string = string.substring (0, index); } char [] chars = fixMnemonic (string); @@ -861,6 +867,7 @@ void updateAccelerator (GtkAccelGroup* accelGroup, bool add) { if (accelerator is 0 || !getEnabled ()) return; + if ((accelerator & DWT.COMMAND) !is 0) return; int mask = 0; if ((accelerator & DWT.ALT) !is 0) mask |= OS.GDK_MOD1_MASK; if ((accelerator & DWT.SHIFT) !is 0) mask |= OS.GDK_SHIFT_MASK; diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/MessageBox.d --- a/dwt/widgets/MessageBox.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/MessageBox.d Mon May 12 19:13:01 2008 +0200 @@ -47,6 +47,8 @@ */ public class MessageBox : Dialog { + alias Dialog.checkStyle checkStyle; + String message = ""; GtkWidget* handle; private bool allowNullParent = false; @@ -91,7 +93,7 @@ * */ public this (Shell parent, int style) { - super(parent, checkStyle(style)); + super (parent, checkStyle (parent, checkStyle (style))); checkSubclass (); } @@ -100,7 +102,7 @@ +/ public this (int style) { allowNullParent = true; - super (parent, checkStyle (style)); + super (parent, checkStyle (parent, checkStyle (style))); checkSubclass (); } // PORT @@ -176,10 +178,30 @@ OS.gtk_window_set_title(handle,buffer); Display display = parent !is null ? parent.getDisplay (): Display.getCurrent (); display.addIdleProc (); - int result = OS.gtk_dialog_run (handle); + Dialog oldModal = null; + if (OS.gtk_window_get_modal (handle)) { + oldModal = display.getModalDialog (); + display.setModalDialog (this); + } + int signalId = 0; + int /*long*/ hookId = 0; + CallbackData emissionData; + emissionData.display = display; + emissionData.data = handle; + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); + hookId = OS.g_signal_add_emission_hook (signalId, 0, &Display.emissionFunc, &emissionData, null); + } + int response = OS.gtk_dialog_run (handle); + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.g_signal_remove_emission_hook (signalId, hookId); + } + if (OS.gtk_window_get_modal (handle)) { + display.setModalDialog (oldModal); + } display.removeIdleProc (); OS.gtk_widget_destroy (handle); - return result; + return response; } private void createButtons() { diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Monitor.d --- a/dwt/widgets/Monitor.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Monitor.d Mon May 12 19:13:01 2008 +0200 @@ -22,7 +22,7 @@ * @since 3.0 */ public final class Monitor { - int handle; + int /*long*/ handle; int x, y, width, height; int clientX, clientY, clientWidth, clientHeight; @@ -52,7 +52,8 @@ /** * Returns a rectangle describing the receiver's size and location - * relative to its device. + * relative to its device. Note that on multi-monitor systems the + * origin can be negative. * * @return the receiver's bounding rectangle */ diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/ProgressBar.d --- a/dwt/widgets/ProgressBar.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/ProgressBar.d Mon May 12 19:13:01 2008 +0200 @@ -146,6 +146,11 @@ return selection; } +public int getState () { + checkWidget (); + return DWT.NORMAL; +} + override int gtk_realize (GtkWidget* widget) { int result = super.gtk_realize (widget); if (result !is 0) return result; @@ -234,6 +239,11 @@ updateBar (selection, minimum, maximum); } +public void setState (int state) { + checkWidget (); + //NOT IMPLEMENTED +} + override int /*long*/ timerProc (GtkWidget* widget) { if (isVisible ()) OS.gtk_progress_bar_pulse (handle); return 1; diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Sash.d --- a/dwt/widgets/Sash.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Sash.d Mon May 12 19:13:01 2008 +0200 @@ -201,14 +201,16 @@ if ((style & DWT.SMOOTH) is 0) { event.detail = DWT.DRAG; } + if ((parent.style & DWT.MIRRORED) !is 0) event.x = parent.getClientWidth () - width - event.x; sendEvent (DWT.Selection, event); if (isDisposed ()) return 0; if (event.doit) { dragging = true; lastX = event.x; lastY = event.y; + if ((parent.style & DWT.MIRRORED) !is 0) lastX = parent.getClientWidth () - width - lastX; parent.update (true, (style & DWT.SMOOTH) is 0); - drawBand (event.x, event.y, width, height); + drawBand (lastX, event.y, width, height); if ((style & DWT.SMOOTH) !is 0) { setBounds (event.x, event.y, width, height); // widget could be disposed at this point @@ -233,6 +235,7 @@ event.width = width; event.height = height; drawBand (lastX, lastY, width, height); + if ((parent.style & DWT.MIRRORED) !is 0) event.x = parent.getClientWidth () - width - event.x; sendEvent (DWT.Selection, event); if (isDisposed ()) return result; if (event.doit) { @@ -301,6 +304,7 @@ event.y = newY; event.width = width; event.height = height; + if ((parent.style & DWT.MIRRORED) !is 0) event.x = parent.getClientWidth () - width - event.x; sendEvent (DWT.Selection, event); if (ptrGrabResult is OS.GDK_GRAB_SUCCESS) OS.gdk_pointer_ungrab (OS.GDK_CURRENT_TIME); if (isDisposed ()) break; @@ -308,6 +312,7 @@ if (event.doit) { lastX = event.x; lastY = event.y; + if ((parent.style & DWT.MIRRORED) !is 0) lastX = parent.getClientWidth () - width - lastX; if ((style & DWT.SMOOTH) !is 0) { setBounds (event.x, event.y, width, height); if (isDisposed ()) break; @@ -371,16 +376,18 @@ if ((style & DWT.SMOOTH) is 0) { event.detail = DWT.DRAG; } + if ((parent.style & DWT.MIRRORED) !is 0) event.x = parent.getClientWidth() - width - event.x; sendEvent (DWT.Selection, event); if (isDisposed ()) return 0; if (event.doit) { lastX = event.x; lastY = event.y; + if ((parent.style & DWT.MIRRORED) !is 0) lastX = parent.getClientWidth () - width - lastX; } parent.update (true, (style & DWT.SMOOTH) is 0); drawBand (lastX, lastY, width, height); if ((style & DWT.SMOOTH) !is 0) { - setBounds (lastX, lastY, width, height); + setBounds (event.x, lastY, width, height); // widget could be disposed at this point } return result; diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/ScrollBar.d --- a/dwt/widgets/ScrollBar.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/ScrollBar.d Mon May 12 19:13:01 2008 +0200 @@ -156,6 +156,16 @@ if (adjustmentHandle !is null) display.removeWidget (cast(GtkWidget*)adjustmentHandle); } +void destroyHandle () { + super.destroyWidget (); +} + +void destroyWidget () { + parent.destroyScrollBar (this); + releaseHandle (); + //parent.sendEvent (DWT.Resize); +} + /** * Returns true if the receiver is enabled, and * false otherwise. A disabled control is typically @@ -456,6 +466,11 @@ if (adjustmentHandle !is null) display.addWidget (cast(GtkWidget*)adjustmentHandle, this); } +void releaseHandle () { + super.releaseHandle (); + parent = null; +} + override void releaseParent () { super.releaseParent (); if (parent.horizontalBar is this) parent.horizontalBar = null; @@ -464,7 +479,7 @@ override void releaseWidget () { super.releaseWidget (); - parent = null; + //parent = null; } /** @@ -583,6 +598,17 @@ OS.g_signal_handlers_unblock_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED); } +void setOrientation () { + super.setOrientation (); + if ((parent.style & DWT.MIRRORED) !is 0) { + if ((parent.state & CANVAS) !is 0) { + if ((style & DWT.HORIZONTAL) !is 0) { + OS.gtk_range_set_inverted (handle, true); + } + } + } +} + /** * Sets the amount that the receiver's value will be * modified by when the page increment/decrement areas @@ -709,7 +735,10 @@ */ public void setVisible (bool visible) { checkWidget (); - parent.setScrollBarVisible (this, visible); + if (parent.setScrollBarVisible (this, visible)) { + sendEvent (visible ? DWT.Show : DWT.Hide); + parent.sendEvent (DWT.Resize); + } } } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Scrollable.d --- a/dwt/widgets/Scrollable.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Scrollable.d Mon May 12 19:13:01 2008 +0200 @@ -149,6 +149,7 @@ bar.handle = OS.GTK_SCROLLED_WINDOW_VSCROLLBAR (cast(GtkScrolledWindow*)scrolledHandle); bar.adjustmentHandle = OS.gtk_scrolled_window_get_vadjustment (cast(GtkScrolledWindow*)scrolledHandle); } + bar.setOrientation(); bar.hookEvents (); bar.register (); return bar; @@ -165,6 +166,12 @@ if (scrolledHandle !is null) display.removeWidget (cast(GtkWidget*)scrolledHandle); } +void destroyScrollBar (ScrollBar bar) { + setScrollBarVisible (bar, false); + //This code is intentionally commented + //bar.destroyHandle (); +} + public override int getBorderWidth () { checkWidget(); int border = 0; @@ -301,8 +308,6 @@ vsp = policy; } OS.gtk_scrolled_window_set_policy (cast(GtkScrolledWindow*)scrolledHandle, hsp, vsp); - bar.sendEvent (visible ? DWT.Show : DWT.Hide); - sendEvent (DWT.Resize); return true; } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Shell.d --- a/dwt/widgets/Shell.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Shell.d Mon May 12 19:13:01 2008 +0200 @@ -22,6 +22,7 @@ import dwt.internal.gtk.OS; import dwt.events.ShellListener; import dwt.graphics.Cursor; +import dwt.graphics.GC; import dwt.graphics.Image; import dwt.graphics.Point; import dwt.graphics.Rectangle; @@ -149,17 +150,17 @@ alias Decorations.setToolTipText setToolTipText; alias Decorations.setZOrder setZOrder; - GtkWidget* shellHandle, tooltipsHandle, tooltipWindow; - bool mapped, moved, resized, opened; + GtkWidget* shellHandle, tooltipsHandle, tooltipWindow, group, modalGroup; + bool mapped, moved, resized, opened, fullScreen, showWithParent; + int oldX, oldY, oldWidth, oldHeight; int minWidth, minHeight; Control lastActive; - Region region; CallbackData filterProcCallbackData; CallbackData sizeAllocateProcCallbackData; CallbackData sizeRequestProcCallbackData; - static final int MAXIMUM_TRIM = 128; + static const int MAXIMUM_TRIM = 128; /** * Constructs a new instance of this class. This is equivalent @@ -393,6 +394,7 @@ static int checkStyle (int style) { style = Decorations.checkStyle (style); + style &= ~DWT.TRANSPARENT; if ((style & DWT.ON_TOP) !is 0) style &= ~DWT.SHELL_TRIM; int mask = DWT.SYSTEM_MODAL | DWT.APPLICATION_MODAL | DWT.PRIMARY_MODAL; int bits = style & ~mask; @@ -649,11 +651,6 @@ OS.gtk_style_get_black (OS.gtk_widget_get_style (shellHandle), color); OS.gtk_widget_modify_bg (shellHandle, OS.GTK_STATE_NORMAL, color); } - int bits = DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL; - bool modal = (style & bits) !is 0; - //TEMPORARY CODE - if ((style & DWT.ON_TOP) is 0) modal |= (parent !is null && (parent.style & bits) !is 0); - OS.gtk_window_set_modal (cast(GtkWindow*)shellHandle, modal); } else { vboxHandle = OS.gtk_bin_get_child (cast(GtkBin*)shellHandle); if (vboxHandle is null) error (DWT.ERROR_NO_HANDLES); @@ -666,6 +663,8 @@ handle = OS.gtk_bin_get_child (cast(GtkBin*)scrolledHandle); if (handle is null) error (DWT.ERROR_NO_HANDLES); } + group = cast(GtkWidget*) OS.gtk_window_group_new (); + if (group is null) error (DWT.ERROR_NO_HANDLES); /* * Feature in GTK. Realizing the shell triggers a size allocate event, * which may be confused for a resize event from the window manager if @@ -734,8 +733,6 @@ override void hookEvents () { super.hookEvents (); OS.g_signal_connect_closure_by_id (shellHandle, display.signalIds [KEY_PRESS_EVENT], 0, display.closures [KEY_PRESS_EVENT], false); - OS.g_signal_connect_closure_by_id (shellHandle, display.signalIds [MAP_EVENT], 0, display.closures [MAP_EVENT], false); - OS.g_signal_connect_closure_by_id (shellHandle, display.signalIds [UNMAP_EVENT], 0, display.closures [UNMAP_EVENT], false); OS.g_signal_connect_closure_by_id (shellHandle, display.signalIds [WINDOW_STATE_EVENT], 0, display.closures [WINDOW_STATE_EVENT], false); OS.g_signal_connect_closure_by_id (shellHandle, display.signalIds [SIZE_ALLOCATE], 0, display.closures [SIZE_ALLOCATE], false); OS.g_signal_connect_closure_by_id (shellHandle, display.signalIds [CONFIGURE_EVENT], 0, display.closures [CONFIGURE_EVENT], false); @@ -804,6 +801,13 @@ } } +override void fixedSizeAllocateProc(GtkWidget* widget, GtkAllocation* allocationPtr) { + int clientWidth = 0; + if ((style & DWT.MIRRORED) !is 0) clientWidth = getClientWidth (); + super.fixedSizeAllocateProc (widget, allocationPtr); + if ((style & DWT.MIRRORED) !is 0) moveChildren (clientWidth); +} + override void fixStyle (GtkWidget* handle) { } @@ -823,6 +827,21 @@ OS.gtk_widget_size_allocate (cast(GtkWidget*)vboxHandle, &allocation); } +public int getAlpha () { + checkWidget (); + if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) { + if (OS.gtk_widget_is_composited (shellHandle)) { + return cast(int) (OS.gtk_window_get_opacity (shellHandle) * 255); + } + } + return 255; +} + +public bool getFullScreen () { + checkWidget(); + return fullScreen; +} + override public Point getLocation () { checkWidget (); int x, y; @@ -830,6 +849,11 @@ return new Point (x, y); } +public bool getMaximized () { + checkWidget(); + return !fullScreen && super.getMaximized (); +} + /** * Returns a point describing the minimum receiver's size. The * x coordinate of the result is the minimum width of the receiver. @@ -852,6 +876,34 @@ return new Point (width, height); } +Shell getModalShell () { + Shell shell = null; + Shell [] modalShells = display.modalShells; + if (modalShells !is null) { + int bits = DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL; + int index = modalShells.length; + while (--index >= 0) { + Shell modal = modalShells [index]; + if (modal !is null) { + if ((modal.style & bits) !is 0) { + Control control = this; + while (control !is null) { + if (control is modal) break; + control = control.parent; + } + if (control !is modal) return modal; + break; + } + if ((modal.style & DWT.PRIMARY_MODAL) !is 0) { + if (shell is null) shell = getShell (); + if (modal.parent is shell) return modal; + } + } + } + } + return null; +} + override public Point getSize () { checkWidget (); int width = OS.GTK_WIDGET_WIDTH (vboxHandle); @@ -883,6 +935,7 @@ * */ public Region getRegion () { + /* This method is needed for @since 3.0 Javadoc */ checkWidget (); return region; } @@ -1009,12 +1062,6 @@ return super.gtk_key_press_event (widget, event); } -override int /*long*/ gtk_map_event (GtkWidget* widget, int /*long*/ event) { - minimized = false; - sendEvent (DWT.Deiconify); - return 0; -} - override int /*long*/ gtk_size_allocate (GtkWidget* widget, int /*long*/ allocation) { int width = OS.GTK_WIDGET_WIDTH (shellHandle); int height = OS.GTK_WIDGET_HEIGHT (shellHandle); @@ -1054,15 +1101,18 @@ return result; } -override int /*long*/ gtk_unmap_event (GtkWidget* widget, int /*long*/ event) { - minimized = true; - sendEvent (DWT.Iconify); - return 0; -} - override int /*long*/ gtk_window_state_event (GtkWidget* widget, GdkEventWindowState* event) { minimized = (event.new_window_state & OS.GDK_WINDOW_STATE_ICONIFIED) !is 0; maximized = (event.new_window_state & OS.GDK_WINDOW_STATE_MAXIMIZED) !is 0; + fullScreen = (event.new_window_state & OS.GDK_WINDOW_STATE_FULLSCREEN) !is 0; + if ((event.changed_mask & OS.GDK_WINDOW_STATE_ICONIFIED) !is 0) { + if (minimized) { + sendEvent (DWT.Iconify); + } else { + sendEvent (DWT.Deiconify); + } + updateMinimized (minimized); + } return 0; } @@ -1095,6 +1145,13 @@ if (!restoreFocus () && !traverseGroup (true)) setFocus (); } +public bool print (GC gc) { + checkWidget (); + if (gc is null) error (DWT.ERROR_NULL_ARGUMENT); + if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + return false; +} + /** * Removes the listener from the collection of listeners who will * be notified when operations are performed on the receiver. @@ -1186,6 +1243,16 @@ } } +public void setAlpha (int alpha) { + checkWidget (); + if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) { + if (OS.gtk_widget_is_composited (shellHandle)) { + alpha &= 0xFF; + OS.gtk_window_set_opacity (shellHandle, alpha / 255f); + } + } +} + void resizeBounds (int width, int height, bool notify) { if (redrawWindow !is null) { OS.gdk_window_resize (redrawWindow, width, height); @@ -1210,6 +1277,7 @@ } override int setBounds (int x, int y, int width, int height, bool move, bool resize) { + if (fullScreen) setFullScreen (false); /* * Bug in GTK. When either of the location or size of * a shell is changed while the shell is maximized, the @@ -1323,6 +1391,19 @@ } } +public void setFullScreen (bool fullScreen) { + checkWidget(); + if (fullScreen) { + OS.gtk_window_fullscreen (shellHandle); + } else { + OS.gtk_window_unfullscreen (shellHandle); + if (maximized) { + setMaximized (true); + } + } + this.fullScreen = fullScreen; +} + /** * Sets the input method editor mode to the argument which * should be the result of bitwise OR'ing together one or more @@ -1471,11 +1552,7 @@ public void setRegion (Region region) { checkWidget (); if ((style & DWT.NO_TRIM) is 0) return; - if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT); - auto window = OS.GTK_WIDGET_WINDOW (shellHandle); - auto shape_region = (region is null) ? null : region.handle; - OS.gdk_window_shape_combine_region (window, shape_region, 0, 0); - this.region = region; + super.setRegion (region); } /* @@ -1503,6 +1580,19 @@ public override void setVisible (bool visible) { checkWidget(); + int mask = DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL; + if ((style & mask) !is 0) { + if (visible) { + display.setModalShell (this); + OS.gtk_window_set_modal (shellHandle, true); + } else { + display.clearModal (this); + OS.gtk_window_set_modal (shellHandle, false); + } + } else { + updateModal (); + } + showWithParent = visible; if ((OS.GTK_WIDGET_MAPPED (shellHandle) is visible)) return; if (visible) { sendEvent (DWT.Show); @@ -1520,6 +1610,7 @@ * unminimized or shown on the desktop. */ OS.gtk_widget_show (shellHandle); + if (enableWindow !is null) OS.gdk_window_raise (enableWindow); if (!OS.GTK_IS_PLUG (cast(GTypeInstance*)shellHandle)) { mapped = false; if (isDisposed ()) return; @@ -1550,7 +1641,6 @@ } mapped = true; - int mask = DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL; if ((style & mask) !is 0) { OS.gdk_pointer_ungrab (OS.GDK_CURRENT_TIME); } @@ -1644,6 +1734,7 @@ } int trimHeight () { if ((style & DWT.NO_TRIM) !is 0) return 0; + if (fullScreen) return 0; bool hasTitle = false, hasResize = false, hasBorder = false; hasTitle = (style & (DWT.MIN | DWT.MAX | DWT.TITLE | DWT.MENU)) !is 0; hasResize = (style & DWT.RESIZE) !is 0; @@ -1660,6 +1751,7 @@ int trimWidth () { if ((style & DWT.NO_TRIM) !is 0) return 0; + if (fullScreen) return 0; bool hasTitle = false, hasResize = false, hasBorder = false; hasTitle = (style & (DWT.MIN | DWT.MAX | DWT.TITLE | DWT.MENU)) !is 0; hasResize = (style & DWT.RESIZE) !is 0; @@ -1674,6 +1766,72 @@ return 0; } +void updateModal () { + GtkWidget* group = null; + if (display.getModalDialog () is null) { + Shell modal = getModalShell (); + int mask = DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL; + Composite shell = null; + if (modal is null) { + if ((style & mask) !is 0) shell = this; + } else { + shell = modal; + } + while (shell !is null) { + if ((shell.style & mask) is 0) { + group = shell.getShell ().group; + break; + } + shell = shell.parent; + } + } + if (OS.GTK_VERSION >= OS.buildVERSION (2, 10, 0) && group is null) { + /* + * Feature in GTK. Starting with GTK version 2.10, GTK + * doesn't assign windows to a default group. The fix is to + * get the handle of the default group and add windows to the + * group. + */ + group = cast(GtkWidget*)OS.gtk_window_get_group(null); + } + if (group !is null) { + OS.gtk_window_group_add_window (group, shellHandle); + } else { + if (modalGroup !is null) { + OS.gtk_window_group_remove_window (modalGroup, shellHandle); + } + } + if (OS.GTK_VERSION < OS.buildVERSION (2, 4, 0)) { + fixModal (group, modalGroup); + } + modalGroup = group; +} + +void updateMinimized (bool minimized) { + Shell[] shells = getShells (); + for (int i = 0; i < shells.length; i++) { + bool update = false; + Shell shell = shells[i]; + while (shell !is null && shell !is this && !shell.isUndecorated ()) { + shell = cast(Shell) shell.getParent (); + } + if (shell !is null && shell !is this) update = true; + if (update) { + if (minimized) { + if (shells[i].isVisible ()) { + shells[i].showWithParent = true; + OS.gtk_widget_hide(shells[i].shellHandle); + } + } else { + if (shells[i].showWithParent) { + shells[i].showWithParent = false; + OS.gtk_widget_show(shells[i].shellHandle); + } + } + } + } +} + override void deregister () { super.deregister (); display.removeWidget (shellHandle); @@ -1748,76 +1906,129 @@ override void releaseWidget () { super.releaseWidget (); destroyAccelGroup (); + display.clearModal (this); if (display.activeShell is this) display.activeShell = null; if (tooltipsHandle !is null) OS.g_object_unref (tooltipsHandle); tooltipsHandle = null; + if (group !is null) OS.g_object_unref (group); + group = modalGroup = null; auto window = OS.GTK_WIDGET_WINDOW (shellHandle); display.doWindowRemoveFilter( &filterProcCallbackData, window, shellHandle ); - region = null; + lastActive = null; } -void setToolTipText (GtkWidget* widget, String string) { - char* buffer = toStringz( string ); - if (tooltipsHandle is null) { - tooltipsHandle = cast(GtkWidget*)OS.gtk_tooltips_new (); - if (tooltipsHandle is null) error (DWT.ERROR_NO_HANDLES); - OS.g_object_ref (tooltipsHandle); - OS.gtk_object_sink (cast(GtkObject*)tooltipsHandle); - } - - /* - * Feature in GTK. There is no API to position a tooltip. - * The fix is to connect to the size_allocate signal for - * the tooltip window and position it before it is mapped. - * - * Bug in Solaris-GTK. Invoking gtk_tooltips_force_window() - * can cause a crash in older versions of GTK. The fix is - * to avoid this call if the GTK version is older than 2.2.x. - */ - if (OS.GTK_VERSION >= OS.buildVERSION (2, 2, 1)) { - OS.gtk_tooltips_force_window (cast(GtkTooltips*)tooltipsHandle); - } - auto tipWindow = OS.GTK_TOOLTIPS_TIP_WINDOW (cast(GtkTooltips*)tooltipsHandle); - if (tipWindow !is null && tipWindow !is tooltipWindow) { - display.doSizeAllocateConnect( &sizeAllocateProcCallbackData, tipWindow, shellHandle ); - tooltipWindow = tipWindow; - } +void setToolTipText (GtkWidget* tipWidget, String string) { + setToolTipText (tipWidget, tipWidget, string); +} - /* - * Bug in GTK. If the cursor is inside the window when a new - * tooltip is set and the old tooltip is hidden, the new tooltip - * is not displayed until the mouse re-enters the window. The - * fix is force the new tooltip to be active. - */ - bool set = true; - if (tipWindow !is null) { - if ((OS.GTK_WIDGET_FLAGS (widget) & (OS.GTK_REALIZED | OS.GTK_VISIBLE)) !is 0) { - int x, y; +void setToolTipText (GtkWidget* rootWidget, GtkWidget* tipWidget, String string) { + if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) { + char * buffer = null; + if (string !is null && string.length > 0) { + char [] chars = fixMnemonic (string, false); + buffer = tango.stdc.stringz.toStringz( chars ); + } + OS.gtk_widget_set_tooltip_text (rootWidget, null); + /* + * Bug in GTK. In GTK 2.12, due to a miscalculation of window + * coordinates, using gtk_tooltip_trigger_tooltip_query () + * to update an existing a tooltip will result in the tooltip + * being displayed at a wrong position. The fix is to send out + * 2 fake GDK_MOTION_NOTIFY events (to mimic the GTK call) which + * contain the proper x and y coordinates. + */ + GdkEvent* eventPtr = null; + auto tipWindow = OS.GTK_WIDGET_WINDOW (rootWidget); + if (tipWindow !is null) { + int x, y; auto window = OS.gdk_window_at_pointer (&x, &y); - if (window !is null) { - GtkWidget* user_data; - OS.gdk_window_get_user_data (window, cast(void**)&user_data); - if (widget is user_data) { - /* - * Feature in GTK. Calling gtk_tooltips_set_tip() positions and - * shows the tooltip. If the tooltip is already visible, moving - * it to a new location in the size_allocate signal causes flashing. - * The fix is to hide the tip window in the size_request signal - * and before the new tooltip is forced to be active. - */ - set = false; - int handler_id = display.doSizeRequestConnect( &sizeRequestProcCallbackData, tipWindow, shellHandle ); - OS.gtk_tooltips_set_tip (cast(GtkTooltips*)tooltipsHandle, widget, buffer, null); - OS.gtk_widget_hide (tipWindow); - auto data = OS.gtk_tooltips_data_get (widget); - OS.GTK_TOOLTIPS_SET_ACTIVE (cast(GtkTooltips*)tooltipsHandle, cast(GtkTooltipsData*)data); - OS.gtk_tooltips_set_tip (cast(GtkTooltips*)tooltipsHandle, widget, buffer, null); - if (handler_id !is 0) OS.g_signal_handler_disconnect (tipWindow, handler_id); + void* user_data; + OS.gdk_window_get_user_data (window, &user_data); + if (tipWidget is user_data ) { + eventPtr = OS.gdk_event_new (OS.GDK_MOTION_NOTIFY); + eventPtr.type = OS.GDK_MOTION_NOTIFY; + eventPtr.motion.window = cast(GdkDrawable*)OS.g_object_ref (tipWindow); + eventPtr.motion.x = x; + eventPtr.motion.y = y; + OS.gdk_window_get_origin (window, &x, &y); + eventPtr.motion.x_root = eventPtr.motion.x + x; + eventPtr.motion.y_root = eventPtr.motion.y + y; + OS.gtk_main_do_event (eventPtr); + } + } + OS.gtk_widget_set_tooltip_text (rootWidget, buffer); + if (eventPtr !is null) { + OS.gtk_main_do_event (eventPtr); + OS.gdk_event_free (eventPtr); + } + } else { + char* buffer = null; + if (string !is null && string.length > 0) { + char [] chars = fixMnemonic (string, false); + buffer = tango.stdc.stringz.toStringz( chars ); + } + if (tooltipsHandle is null) { + tooltipsHandle = cast(GtkWidget*)OS.gtk_tooltips_new (); + if (tooltipsHandle is null) error (DWT.ERROR_NO_HANDLES); + OS.g_object_ref (tooltipsHandle); + OS.gtk_object_sink (cast(GtkObject*)tooltipsHandle); + } + + /* + * Feature in GTK. There is no API to position a tooltip. + * The fix is to connect to the size_allocate signal for + * the tooltip window and position it before it is mapped. + * + * Bug in Solaris-GTK. Invoking gtk_tooltips_force_window() + * can cause a crash in older versions of GTK. The fix is + * to avoid this call if the GTK version is older than 2.2.x. + */ + if (OS.GTK_VERSION >= OS.buildVERSION (2, 2, 1)) { + OS.gtk_tooltips_force_window (cast(GtkTooltips*)tooltipsHandle); + } + auto tipWindow = OS.GTK_TOOLTIPS_TIP_WINDOW (cast(GtkTooltips*)tooltipsHandle); + if (tipWindow !is null && tipWindow !is tooltipWindow) { + display.doSizeAllocateConnect( &sizeAllocateProcCallbackData, tipWindow, shellHandle ); + tooltipWindow = tipWindow; + } + + /* + * Bug in GTK. If the cursor is inside the window when a new + * tooltip is set and the old tooltip is hidden, the new tooltip + * is not displayed until the mouse re-enters the window. The + * fix is force the new tooltip to be active. + */ + bool set = true; + if (tipWindow !is null) { + if ((OS.GTK_WIDGET_FLAGS (tipWidget) & (OS.GTK_REALIZED | OS.GTK_VISIBLE)) !is 0) { + int x, y; + auto window = OS.gdk_window_at_pointer (&x, &y); + if (window !is null) { + GtkWidget* user_data; + OS.gdk_window_get_user_data (window, cast(void**)&user_data); + if (tipWidget is user_data) { + /* + * Feature in GTK. Calling gtk_tooltips_set_tip() positions and + * shows the tooltip. If the tooltip is already visible, moving + * it to a new location in the size_allocate signal causes flashing. + * The fix is to hide the tip window in the size_request signal + * and before the new tooltip is forced to be active. + */ + set = false; + int handler_id = display.doSizeRequestConnect( &sizeRequestProcCallbackData, tipWindow, shellHandle ); + OS.gtk_tooltips_set_tip (cast(GtkTooltips*)tooltipsHandle, tipWidget, buffer, null); + OS.gtk_widget_hide (tipWindow); + auto data = OS.gtk_tooltips_data_get (tipWidget); + OS.GTK_TOOLTIPS_SET_ACTIVE (cast(GtkTooltips*)tooltipsHandle, cast(GtkTooltipsData*)data); + OS.gtk_tooltips_set_tip (cast(GtkTooltips*)tooltipsHandle, tipWidget, buffer, null); + if (handler_id !is 0) OS.g_signal_handler_disconnect (tipWindow, handler_id); + } } } } + if (set) OS.gtk_tooltips_set_tip (cast(GtkTooltips*)tooltipsHandle, tipWidget, buffer, null); } - if (set) OS.gtk_tooltips_set_tip (cast(GtkTooltips*)tooltipsHandle, widget, buffer, null); + } } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Slider.d --- a/dwt/widgets/Slider.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Slider.d Mon May 12 19:13:01 2008 +0200 @@ -166,7 +166,17 @@ handle = cast(GtkWidget*)OS.gtk_vscrollbar_new (hAdjustment); } if (handle is null) error (DWT.ERROR_NO_HANDLES); - OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS); + /* + * Bug in GTK. In GTK 2.10, the buttons on either end of + * a horizontal slider are created taller then the slider bar + * when the GTK_CAN_FOCUS flag is set. The fix is not to set + * the flag for horizontal bars in all versions of 2.10. Note + * that a bug has been logged with GTK about this issue. + * (http://bugzilla.gnome.org/show_bug.cgi?id=475909) + */ + if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0) || (style & DWT.VERTICAL) !is 0) { + OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS); + } OS.gtk_container_add (fixedHandle, handle); } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Spinner.d --- a/dwt/widgets/Spinner.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Spinner.d Mon May 12 19:13:01 2008 +0200 @@ -64,6 +64,16 @@ GdkEventKey* gdkEventKey; int fixStart = -1, fixEnd = -1; + /** + * The maximum number of characters that can be entered + * into a text widget. + *

    + * Note that this value is platform dependent, based upon + * the native widget implementation. + *

    + */ + public const static int LIMIT = 0x7FFFFFFF; + /** * Constructs a new instance of this class given its parent * and a style value describing its behavior and appearance. @@ -390,7 +400,7 @@ int digits = OS.gtk_spin_button_get_digits (cast(GtkSpinButton*)handle); auto value = adjustment.step_increment; for (int i = 0; i < digits; i++) value *= 10; - return cast(int) (value + 0.5); + return cast(int) (value > 0 ? value + 0.5 : value - 0.5); } /** @@ -409,7 +419,7 @@ int digits = OS.gtk_spin_button_get_digits (cast(GtkSpinButton*)handle); auto value = adjustment.upper; for (int i = 0; i < digits; i++) value *= 10; - return cast(int) (value + 0.5); + return cast(int) (value > 0 ? value + 0.5 : value - 0.5); } /** @@ -428,7 +438,7 @@ int digits = OS.gtk_spin_button_get_digits (cast(GtkSpinButton*)handle); auto value = adjustment.lower; for (int i = 0; i < digits; i++) value *= 10; - return cast(int) (value + 0.5); + return cast(int) (value > 0 ? value + 0.5 : value - 0.5); } /** @@ -448,7 +458,7 @@ int digits = OS.gtk_spin_button_get_digits (cast(GtkSpinButton*)handle); auto value = adjustment.page_increment; for (int i = 0; i < digits; i++) value *= 10; - return cast(int) (value + 0.5); + return cast(int) (value > 0 ? value + 0.5 : value - 0.5); } /** @@ -467,7 +477,19 @@ int digits = OS.gtk_spin_button_get_digits (cast(GtkSpinButton*)handle); auto value = adjustment.value; for (int i = 0; i < digits; i++) value *= 10; - return cast(int) (value + 0.5); + return cast(int) (value > 0 ? value + 0.5 : value - 0.5); +} + +public String getText () { + checkWidget (); + auto str = OS.gtk_entry_get_text (handle); + return tango.stdc.stringz.fromStringz(str).dup; +} + +public int getTextLimit () { + checkWidget (); + int limit = OS.gtk_entry_get_max_length (handle); + return limit is 0 ? 0xFFFF : limit; } /** @@ -646,6 +668,14 @@ return result; } +override int /*long*/ gtk_populate_popup (GtkWidget* widget, GtkWidget* menu) { + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.gtk_widget_set_direction (menu, OS.GTK_TEXT_DIR_RTL); + display.doSetDirectionProc( menu, OS.GTK_TEXT_DIR_RTL); + } + return 0; +} + override int /*long*/ gtk_value_changed (int adjustment) { postEvent (DWT.Selection); return 0; @@ -658,6 +688,7 @@ OS.g_signal_connect_closure (handle, OS.delete_text.ptr, display.closures [DELETE_TEXT], false); OS.g_signal_connect_closure (handle, OS.value_changed.ptr, display.closures [VALUE_CHANGED], false); OS.g_signal_connect_closure (handle, OS.activate.ptr, display.closures [ACTIVATE], false); + OS.g_signal_connect_closure (handle, OS.populate_popup.ptr, display.closures [POPULATE_POPUP], false); auto imContext = imContext (); if (imContext !is null) { OS.g_signal_connect_closure (imContext, OS.commit.ptr, display.closures [COMMIT], false); @@ -835,7 +866,6 @@ */ public void setMaximum (int value) { checkWidget (); - if (value < 0) return; auto adjustment = OS.gtk_spin_button_get_adjustment (cast(GtkSpinButton*)handle); double newValue = value; int digits = OS.gtk_spin_button_get_digits (cast(GtkSpinButton*)handle); @@ -861,7 +891,6 @@ */ public void setMinimum (int value) { checkWidget (); - if (value < 0) return; auto adjustment = OS.gtk_spin_button_get_adjustment (cast(GtkSpinButton*)handle); double newValue = value; int digits = OS.gtk_spin_button_get_digits (cast(GtkSpinButton*)handle); @@ -919,6 +948,12 @@ OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED); } +public void setTextLimit (int limit) { + checkWidget (); + if (limit is 0) error (DWT.ERROR_CANNOT_BE_ZERO); + OS.gtk_entry_set_max_length (handle, limit); +} + /** * Sets the number of decimal places used by the receiver. *

    @@ -989,7 +1024,6 @@ */ public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) { checkWidget (); - if (minimum < 0) return; if (maximum <= minimum) return; if (digits < 0) return; if (increment < 1) return; @@ -1052,6 +1086,10 @@ } index = 0; } + if (string.length > 0) { + auto adjustment = OS.gtk_spin_button_get_adjustment (handle); + if (adjustment.lower < 0 && string.charAt (0) is '-') index++; + } while (index < string.length) { if (!CharacterIsDigit (string.charAt(index))) break; index++; diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Synchronizer.d --- a/dwt/widgets/Synchronizer.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Synchronizer.d Mon May 12 19:13:01 2008 +0200 @@ -20,6 +20,7 @@ import dwt.DWT; import tango.core.Thread; +import dwt.graphics.Device; import tango.core.Exception; /** @@ -45,6 +46,8 @@ RunnableLock [] messages; Object messageLock; Thread syncThread; + static final int GROW_SIZE = 4; + static final int MESSAGE_LIMIT = 64; /** * Constructs a new instance of this class. @@ -59,9 +62,9 @@ void addLast (RunnableLock lock) { bool wake = false; synchronized (messageLock) { - if (messages is null) messages = new RunnableLock [4]; + if (messages is null) messages = new RunnableLock [GROW_SIZE]; if (messageCount is messages.length) { - RunnableLock[] newMessages = new RunnableLock [messageCount + 4]; + RunnableLock[] newMessages = new RunnableLock [messageCount + GROW_SIZE]; System.arraycopy (messages, 0, newMessages, 0, messageCount); messages = newMessages; } @@ -110,7 +113,7 @@ System.arraycopy (messages, 1, messages, 0, --messageCount); messages [messageCount] = null; if (messageCount is 0) { - if (messages.length > 64) messages = null; + if (messages.length > MESSAGE_LIMIT) messages = null; } return lock; } @@ -157,21 +160,27 @@ * @see #asyncExec */ public void syncExec (Runnable runnable) { - if (display.isValidThread ()) { + RunnableLock lock = null; + synchronized (Device.classinfo) { + if (display is null || display.isDisposed ()) DWT.error (DWT.ERROR_DEVICE_DISPOSED); + if (!display.isValidThread ()) { + if (runnable is null) { + display.wake (); + return; + } + lock = new RunnableLock (runnable); + /* + * Only remember the syncThread for syncExec. + */ + lock.thread = Thread.getThis(); + addLast (lock); + } + } + if (lock is null) { if (runnable !is null) runnable.run (); return; } - if (runnable is null) { - display.wake (); - return; - } - RunnableLock lock = new RunnableLock (runnable); - /* - * Only remember the syncThread for syncExec. - */ - lock.thread = Thread.getThis(); synchronized (lock) { - addLast (lock); bool interrupted = false; while (!lock.done ()) { try { diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/TabFolder.d --- a/dwt/widgets/TabFolder.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/TabFolder.d Mon May 12 19:13:01 2008 +0200 @@ -298,7 +298,7 @@ } override GtkWidget* eventHandle () { - return fixedHandle; + return handle; } /** @@ -327,6 +327,21 @@ return items [index]; } +public TabItem getItem(Point point) { + checkWidget(); + if (point is null) error (DWT.ERROR_NULL_ARGUMENT); + auto list = OS.gtk_container_get_children (handle); + if (list is null) return null; + int itemCount = OS.g_list_length (list); + OS.g_list_free (list); + for (int i = 0; i < itemCount; i++) { + TabItem item = items[i]; + Rectangle rect = item.getBounds(); + if (rect.contains(point)) return item; + } + return null; +} + /** * Returns the number of items contained in the receiver. * diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/TabItem.d --- a/dwt/widgets/TabItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/TabItem.d Mon May 12 19:13:01 2008 +0200 @@ -19,6 +19,7 @@ import dwt.DWT; import dwt.DWTException; import dwt.graphics.Image; +import dwt.graphics.Rectangle; import dwt.internal.gtk.OS; import dwt.widgets.Item; import dwt.widgets.Control; @@ -145,6 +146,16 @@ releaseHandle (); } +public Rectangle getBounds () { + checkWidget(); + int x = OS.GTK_WIDGET_X (handle); + int y = OS.GTK_WIDGET_Y (handle); + int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (handle); + int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (handle); + if ((parent.style & DWT.MIRRORED) !is 0) x = parent.getClientWidth () - width - x; + return new Rectangle (x, y, width, height); +} + /** * Returns the control that is used to fill the client area of * the tab folder when the user selects the tab item. If no diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Table.d --- a/dwt/widgets/Table.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Table.d Mon May 12 19:13:01 2008 +0200 @@ -184,11 +184,17 @@ static int checkStyle (int style) { /* - * To be compatible with Windows, force the H_SCROLL - * and V_SCROLL style bits. On Windows, it is not - * possible to create a table without scroll bars. + * Feature in Windows. Even when WS_HSCROLL or + * WS_VSCROLL is not specified, Windows creates + * trees and tables with scroll bars. The fix + * is to set H_SCROLL and V_SCROLL. + * + * NOTE: This code appears on all platforms so that + * applications have consistent scroll bar behavior. */ - style |= DWT.H_SCROLL | DWT.V_SCROLL; + if ((style & DWT.NO_SCROLL) is 0) { + style |= DWT.H_SCROLL | DWT.V_SCROLL; + } /* GTK is always FULL_SELECTION */ style |= DWT.FULL_SELECTION; return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0); @@ -1153,6 +1159,13 @@ return new Rectangle (fixedX - binX, fixedY - binY, width, height); } +int getClientWidth () { + int w, h; + OS.gtk_widget_realize (handle); + OS.gdk_drawable_get_size(OS.gtk_tree_view_get_bin_window(handle), &w, &h); + return w; +} + /** * Returns the column at the given, zero-relative index in the * receiver. Throws an exception if the index is out of range. @@ -2362,22 +2375,9 @@ } items = new TableItem [4]; itemCount = 0; - - /* - * Bug in GTK. In version 2.3.2, when the property fixed-height-mode - * is set and there are items in the list, OS.gtk_list_store_clear() - * segment faults. The fix is to create a new empty model instead. - */ auto selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); -// OS.gtk_list_store_clear (modelHandle); - auto oldModel = modelHandle; - auto types = getColumnTypes (Math.max (1,columnCount)); - auto newModel = OS.gtk_list_store_newv (types.length, types.ptr); - if (newModel is null) error (DWT.ERROR_NO_HANDLES); - OS.gtk_tree_view_set_model (handle, newModel); - OS.g_object_unref (oldModel); - modelHandle = cast(GtkWidget*)newModel; + OS.gtk_list_store_clear (modelHandle); OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); resetCustomDraw (); @@ -2485,7 +2485,7 @@ sendEvent (DWT.MeasureItem, event); gc.dispose (); contentWidth = event.width - imageWidth; - contentHeight = event.height; + if (contentHeight < event.height) contentHeight = event.height; if (width !is null) *width = contentWidth; if (height !is null) *height = contentHeight; } @@ -2562,6 +2562,7 @@ gc.setForeground (item.getForeground (columnIndex)); } gc.setFont (item.getFont (columnIndex)); + if ((style & DWT.MIRRORED) !is 0) rect.x = getClientWidth () - rect.width - rect.x; gc.setClipping (rect.x, rect.y, rect.width, rect.height); Event event = new Event (); event.item = item; @@ -2634,6 +2635,7 @@ gc.setForeground (foreground); } gc.setFont (item.getFont (columnIndex)); + if ((style & DWT.MIRRORED) !is 0) rect.x = getClientWidth () - rect.width - rect.x; gc.setClipping (rect.x, rect.y, rect.width, rect.height); Event event = new Event (); event.item = item; diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/TableItem.d --- a/dwt/widgets/TableItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/TableItem.d Mon May 12 19:13:01 2008 +0200 @@ -136,6 +136,79 @@ return control; } +Color _getBackground () { + void* ptr; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, Table.BACKGROUND_COLUMN, &ptr); + if (ptr is null) return parent.getBackground (); + GdkColor* gdkColor = new GdkColor (); + *gdkColor = *cast(GdkColor*) ptr; + return Color.gtk_new (display, gdkColor); +} + +Color _getBackground (int index) { + int count = Math.max (1, parent.columnCount); + if (0 > index || index > count - 1) return _getBackground (); + void* ptr; + int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Table.CELL_BACKGROUND, &ptr); + if (ptr is null) return _getBackground (); + GdkColor* gdkColor = new GdkColor (); + *gdkColor = *cast(GdkColor*) ptr; + return Color.gtk_new (display, gdkColor); +} + +bool _getChecked () { + void* ptr; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, Table.CHECKED_COLUMN, &ptr); + return ptr !is null; +} + +Color _getForeground () { + void* ptr; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, Table.FOREGROUND_COLUMN, &ptr); + if (ptr is null) return parent.getForeground (); + GdkColor* gdkColor = new GdkColor (); + *gdkColor = *cast(GdkColor*) ptr; + return Color.gtk_new (display, gdkColor); +} + +Color _getForeground (int index) { + int count = Math.max (1, parent.columnCount); + if (0 > index || index > count - 1) return _getForeground (); + void* ptr; + int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Table.CELL_FOREGROUND, &ptr); + if (ptr is null) return _getForeground (); + GdkColor* gdkColor = new GdkColor (); + *gdkColor = *cast(GdkColor*) ptr; + return Color.gtk_new (display, gdkColor); +} + +Image _getImage (int index) { + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return null; + void* ptr; + int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Table.CELL_PIXBUF, &ptr); + if (ptr is null) return null; + ImageList imageList = parent.imageList; + int imageIndex = imageList.indexOf (ptr); + if (imageIndex is -1) return null; + return imageList.get (imageIndex); +} + +String _getText (int index) { + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return ""; + void* ptr; + int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Table.CELL_TEXT, &ptr); + if (ptr is null) return ""; + char[] buffer = tango.stdc.stringz.fromStringz( cast(char*)ptr).dup; + OS.g_free (ptr); + return buffer; +} + protected override void checkSubclass () { if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS); } @@ -183,11 +256,7 @@ public Color getBackground () { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - void* ptr; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, Table.BACKGROUND_COLUMN, &ptr); - if (ptr is null) return parent.getBackground (); - GdkColor* gdkColor = cast(GdkColor*)ptr; - return Color.gtk_new (display, gdkColor); + return _getBackground (); } /** @@ -225,6 +294,7 @@ GdkRectangle rect; OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect); OS.gtk_tree_path_free (path); + if ((parent.getStyle () & DWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x; int right = rect.x + rect.width; int x, w; @@ -257,7 +327,8 @@ rect.width = Math.max (0, right - rect.x); } } - return new Rectangle (rect.x, rect.y, rect.width + 1, rect.height + 1); + int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0; + return new Rectangle (rect.x, rect.y, width, rect.height + 1); } /** @@ -276,14 +347,7 @@ public Color getBackground (int index) { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - int count = Math.max (1, parent.columnCount); - if (0 > index || index > count - 1) return getBackground (); - void* ptr; - int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Table.CELL_BACKGROUND, &ptr); - if (ptr is null) return getBackground (); - GdkColor* gdkColor = cast(GdkColor*)ptr; - return Color.gtk_new (display, gdkColor); + return _getBackground (index); } /** @@ -314,6 +378,7 @@ GdkRectangle rect; OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect); OS.gtk_tree_path_free (path); + if ((parent.getStyle () & DWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x; if (index is 0 && (parent.style & DWT.CHECK) !is 0) { if (OS.GTK_VERSION >= OS.buildVERSION (2, 1, 3)) { @@ -330,7 +395,8 @@ rect.width -= w + buffer; } } - return new Rectangle (rect.x, rect.y, rect.width + 1, rect.height + 1); + int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0; + return new Rectangle (rect.x, rect.y, width, rect.height + 1); } /** @@ -349,9 +415,7 @@ checkWidget(); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); if ((parent.style & DWT.CHECK) is 0) return false; - void* ptr; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, Table.CHECKED_COLUMN, &ptr); - return ptr !is null; + return _getChecked (); } /** @@ -410,11 +474,7 @@ public Color getForeground () { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - void* ptr; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, Table.FOREGROUND_COLUMN, &ptr); - if (ptr is null) return parent.getForeground (); - GdkColor* gdkColor = cast(GdkColor*)ptr; - return Color.gtk_new (display, gdkColor); + return _getForeground (); } /** @@ -434,14 +494,7 @@ public Color getForeground (int index) { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - int count = Math.max (1, parent.columnCount); - if (0 > index || index > count - 1) return getForeground (); - void* ptr; - int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Table.CELL_FOREGROUND, &ptr); - if (ptr is null) return getForeground (); - GdkColor* gdkColor = cast(GdkColor*)ptr; - return Color.gtk_new (display, gdkColor); + return _getForeground (index); } /** @@ -484,16 +537,7 @@ public Image getImage (int index) { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - int count = Math.max (1, parent.getColumnCount ()); - if (0 > index || index > count - 1) return null; - void* ptr; - int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Table.CELL_PIXBUF, &ptr); - if (ptr is null) return null; - ImageList imageList = parent.imageList; - int imageIndex = imageList.indexOf (ptr); - if (imageIndex is -1) return null; - return imageList.get (imageIndex); + return _getImage (index); } /** @@ -528,7 +572,7 @@ OS.gtk_widget_realize (parentHandle); OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect); OS.gtk_tree_path_free (path); - + if ((parent.getStyle () & DWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x; /* * The OS call gtk_cell_renderer_get_size() provides the width of image to be drawn * by the cell renderer. If there is no image in the cell, the width is zero. If the table contains @@ -549,7 +593,8 @@ OS.gtk_cell_renderer_get_size (pixbufRenderer, parentHandle, null, null, null, &w, null); rect.width = w; } - return new Rectangle (rect.x, rect.y, rect.width, rect.height + 1); + int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width : 0; + return new Rectangle (rect.x, rect.y, width, rect.height + 1); } /** @@ -612,15 +657,7 @@ public String getText (int index) { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - int count = Math.max (1, parent.getColumnCount ()); - if (0 > index || index > count - 1) return ""; - char* ptr; - int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Table.CELL_TEXT, cast(void**) &ptr); - if (ptr is null) return ""; - String res = tango.stdc.stringz.fromStringz( ptr ).dup; - OS.g_free (ptr); - return res; + return _getText (index); } /** @@ -668,6 +705,7 @@ GdkRectangle rect; OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect); OS.gtk_tree_path_free (path); + if ((parent.getStyle () & DWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x; int right = rect.x + rect.width; int x, w; @@ -699,7 +737,8 @@ rect.width = Math.max (0, right - rect.x); } } - return new Rectangle (rect.x, rect.y, rect.width + 1, rect.height + 1); + int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0; + return new Rectangle (rect.x, rect.y, width, rect.height + 1); } void redraw () { @@ -753,6 +792,7 @@ if (color !is null && color.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } + if (_getBackground ().opEquals (color)) return; GdkColor* gdkColor = color !is null ? color.handle : null; OS.gtk_list_store_set1 (parent.modelHandle, handle, Table.BACKGROUND_COLUMN, gdkColor); /* @@ -791,6 +831,7 @@ if (color !is null && color.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } + if (_getBackground (index).opEquals (color)) return; int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; @@ -848,6 +889,7 @@ public void setChecked (bool checked) { checkWidget(); if ((parent.style & DWT.CHECK) is 0) return; + if (_getChecked () is checked) return; OS.gtk_list_store_set1 (parent.modelHandle, handle, Table.CHECKED_COLUMN, cast(void*)cast(int)checked); /* * GTK+'s "inconsistent" state does not match DWT's concept of grayed. To @@ -880,9 +922,10 @@ if (font !is null && font.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } - if (this.font is font) return; - if (this.font !is null && this.font ==/*eq*/font ) return; + Font oldFont = this.font; + if (oldFont is font) return; this.font = font; + if (oldFont !is null && oldFont.opEquals (font)) return; auto fontHandle = font !is null ? font.handle : null; OS.gtk_list_store_set1 (parent.modelHandle, handle, Table.FONT_COLUMN, fontHandle); /* @@ -925,11 +968,13 @@ int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; if (cellFont is null) { + if (font is null) return; cellFont = new Font [count]; } - if (cellFont [index] is font) return; - if (cellFont [index] !is null && cellFont [index] ==/*eq*/ font) return; + Font oldFont = cellFont [index]; + if (oldFont is font) return; cellFont [index] = font; + if (oldFont !is null && oldFont.opEquals (font)) return; int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; auto fontHandle = font !is null ? font.handle : null; @@ -994,6 +1039,7 @@ if (color !is null && color.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } + if (_getForeground ().opEquals (color)) return; GdkColor* gdkColor = color !is null ? color.handle : null; OS.gtk_list_store_set1 (parent.modelHandle, handle, Table.FOREGROUND_COLUMN, gdkColor); /* @@ -1032,6 +1078,7 @@ if (color !is null && color.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } + if (_getForeground (index).opEquals (color)) return; int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; int modelIndex = parent.columnCount is 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex; @@ -1089,6 +1136,7 @@ public void setGrayed (bool grayed) { checkWidget(); if ((parent.style & DWT.CHECK) is 0) return; + if (this.grayed is grayed) return; this.grayed = grayed; /* * GTK+'s "inconsistent" state does not match DWT's concept of grayed. @@ -1119,6 +1167,9 @@ if (image !is null && image.isDisposed ()) { error(DWT.ERROR_INVALID_ARGUMENT); } + if (image !is null && image.type is DWT.ICON) { + if (image.opEquals (_getImage (index))) return; + } int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; void* pixbuf; @@ -1161,7 +1212,7 @@ * the style. */ auto style = OS.gtk_widget_get_modifier_style (parentHandle); - OS.gtk_widget_modify_style (parentHandle, style); + parent.modifyStyle (parentHandle, style); } } } @@ -1233,6 +1284,7 @@ public void setText (int index, String string) { checkWidget (); if (string is null) error (DWT.ERROR_NULL_ARGUMENT); + if (_getText (index).equals (string)) return; int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; char* buffer = tango.stdc.stringz.toStringz( string ); diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Text.d --- a/dwt/widgets/Text.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Text.d Mon May 12 19:13:01 2008 +0200 @@ -177,7 +177,7 @@ OS.gtk_container_add (cast(GtkContainer*)fixedHandle, scrolledHandle); OS.gtk_container_add (cast(GtkContainer*)scrolledHandle, handle); OS.gtk_text_view_set_editable (cast(GtkTextView*)handle, (style & DWT.READ_ONLY) is 0); - if ((style & DWT.WRAP) !is 0) OS.gtk_text_view_set_wrap_mode (cast(GtkTextView*)handle, OS.GTK_WRAP_WORD); + if ((style & DWT.WRAP) !is 0) OS.gtk_text_view_set_wrap_mode (cast(GtkTextView*)handle, OS.GTK_WRAP_WORD_CHAR); int hsp = (style & DWT.H_SCROLL) !is 0 ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER; int vsp = (style & DWT.V_SCROLL) !is 0 ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER; OS.gtk_scrolled_window_set_policy (cast(GtkScrolledWindow*)scrolledHandle, hsp, vsp); @@ -1323,6 +1323,14 @@ return result; } +override int /*long*/ gtk_populate_popup (GtkWidget* widget, GtkWidget* menu) { + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + OS.gtk_widget_set_direction (menu, OS.GTK_TEXT_DIR_RTL); + display.doSetDirectionProc (menu, OS.GTK_TEXT_DIR_RTL); + } + return 0; +} + override int /*long*/ gtk_text_buffer_insert_text (GtkTextBuffer *widget, GtkTextIter *iter, char *text, int len) { if (!hooks (DWT.Verify) && !filters (DWT.Verify)) return 0; GtkTextIter position = *iter; @@ -1356,10 +1364,12 @@ OS.g_signal_connect_closure (handle, OS.delete_text.ptr, display.closures [DELETE_TEXT], false); OS.g_signal_connect_closure (handle, OS.activate.ptr, display.closures [ACTIVATE], false); OS.g_signal_connect_closure (handle, OS.grab_focus.ptr, display.closures [GRAB_FOCUS], false); + OS.g_signal_connect_closure (handle, OS.populate_popup.ptr, display.closures [POPULATE_POPUP], false); } else { OS.g_signal_connect_closure (bufferHandle, OS.changed.ptr, display.closures [CHANGED], false); OS.g_signal_connect_closure (bufferHandle, OS.insert_text.ptr, display.closures [TEXT_BUFFER_INSERT_TEXT], false); OS.g_signal_connect_closure (bufferHandle, OS.delete_range.ptr, display.closures [DELETE_RANGE], false); + OS.g_signal_connect_closure (handle, OS.populate_popup.ptr, display.closures [POPULATE_POPUP], false); } auto imContext = imContext (); if (imContext !is null) { @@ -1371,7 +1381,10 @@ } GtkIMContext* imContext () { - return (style & DWT.SINGLE) !is 0 ? OS.GTK_ENTRY_IM_CONTEXT (cast(GtkEntry*)handle) : OS.GTK_TEXTVIEW_IM_CONTEXT (cast(GtkTextView*)handle); + if ((style & DWT.SINGLE) !is 0) { + return OS.gtk_editable_get_editable (handle) ? OS.GTK_ENTRY_IM_CONTEXT (handle) : null; + } + return OS.GTK_TEXTVIEW_IM_CONTEXT (cast(GtkTextView*)handle); } /** diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/ToolBar.d --- a/dwt/widgets/ToolBar.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/ToolBar.d Mon May 12 19:13:01 2008 +0200 @@ -333,6 +333,7 @@ auto topHandle = item.topHandle (); event.x = OS.GTK_WIDGET_X (topHandle); event.y = OS.GTK_WIDGET_Y (topHandle) + OS.GTK_WIDGET_HEIGHT (topHandle); + if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth() - OS.GTK_WIDGET_WIDTH(topHandle) - event.x; item.postEvent (DWT.Selection, event); return result; } @@ -342,6 +343,7 @@ case OS.GDK_Right: next = true; break; default: return result; } + if ((style & DWT.MIRRORED) !is 0) next= !next; int start = index, offset = next ? 1 : -1; while ((index = (index + offset + length) % length) !is start) { ToolItem item = items [index]; diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/ToolItem.d --- a/dwt/widgets/ToolItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/ToolItem.d Mon May 12 19:13:01 2008 +0200 @@ -339,6 +339,8 @@ width = OS.GTK_WIDGET_WIDTH (topHandle); height = OS.GTK_WIDGET_HEIGHT (topHandle); } + if ((parent.style & DWT.MIRRORED) !is 0) x = parent.getClientWidth () - width - x; + if ((style & DWT.SEPARATOR) !is 0 && control !is null) height = Math.max (height, 23); return new Rectangle (x, y, width, height); } @@ -525,11 +527,12 @@ OS.gdk_event_get_coords (eventPtr, &x_win, &y_win); int x = OS.GTK_WIDGET_X (arrowHandle) - OS.GTK_WIDGET_X (handle); int width = OS.GTK_WIDGET_WIDTH (arrowHandle); - if ((((state & DWT.RIGHT_TO_LEFT) is 0) && x <= cast(int)x_win) - || (((state & DWT.RIGHT_TO_LEFT) !is 0) && cast(int)x_win <= x + width)) { + if ((((parent.style & DWT.RIGHT_TO_LEFT) is 0) && x <= cast(int)x_win) + || (((parent.style & DWT.RIGHT_TO_LEFT) !is 0) && cast(int)x_win <= x + width)) { event.detail = DWT.ARROW; auto topHandle = topHandle (); event.x = OS.GTK_WIDGET_X (topHandle); + if ((parent.style & DWT.MIRRORED) !is 0) event.x = parent.getClientWidth () - OS.GTK_WIDGET_WIDTH (topHandle) - event.x; event.y = OS.GTK_WIDGET_Y (topHandle) + OS.GTK_WIDGET_HEIGHT (topHandle); } break; @@ -725,6 +728,7 @@ */ Rectangle itemRect = getBounds (); control.setSize (itemRect.width, itemRect.height); + OS.gtk_widget_set_size_request (handle, itemRect.width, itemRect.height); Rectangle rect = control.getBounds (); rect.x = itemRect.x + (itemRect.width - rect.width) / 2; rect.y = itemRect.y + (itemRect.height - rect.height) / 2; @@ -1034,7 +1038,9 @@ checkWidget(); if ((style & DWT.SEPARATOR) is 0) return; if (width < 0) return; - OS.gtk_widget_set_size_request (handle, width, -1); + bool isVertical = (parent.style & DWT.VERTICAL) !is 0; + OS.gtk_widget_set_size_request (separatorHandle, width, isVertical ? 6 : 15); + OS.gtk_widget_set_size_request (handle, width, isVertical ? 6 : 15); parent.relayout (); } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/ToolTip.d --- a/dwt/widgets/ToolTip.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/ToolTip.d Mon May 12 19:13:01 2008 +0200 @@ -173,6 +173,14 @@ w-1, h-6+t, w-2, h-5+t, w-2, h-4+t, w-4, h-2+t, w-5, h-2+t, w-6, h-1+t, 5, h-1+t, 4, h-2+t, 3, h-2+t, 1, h-4+t, 1, h-5+t, 0, h-6+t, 0, 5+t]; + if ((parent.style & DWT.MIRRORED) !is 0) { + x -= w - 36; + polyline[12] = w-36; + polyline[14] = w-16; + polyline[16] = w-15; + borderPolygon[12] = w-35; + borderPolygon[14] = borderPolygon[16] = w-16; + } OS.gtk_window_move (cast(GtkWindow*)handle, Math.max(0, x - 17), y); } else { polyline = [ @@ -189,6 +197,13 @@ 35, h-1, 17, h+TIP_HEIGHT-2, 17, h-1, 5, h-1, 4, h-2, 3, h-2, 1, h-4, 1, h-5, 0, h-6, 0, 5]; + if ((parent.style & DWT.MIRRORED) !is 0) { + x -= w - 36; + polyline [42] = polyline [44] = w-16; + polyline [46] = w-35; + borderPolygon[36] = borderPolygon[38] = w-17; + borderPolygon [40] = w-35; + } OS.gtk_window_move (cast(GtkWindow*)handle, Math.max(0, x - 17), y - h - TIP_HEIGHT); } } else { @@ -208,6 +223,13 @@ w-1, h-6+t, w-2, h-5+t, w-2, h-4+t, w-4, h-2+t, w-5, h-2+t, w-6, h-1+t, 5, h-1+t, 4, h-2+t, 3, h-2+t, 1, h-4+t, 1, h-5+t, 0, h-6+t, 0, 5+t]; + if ((parent.style & DWT.MIRRORED) !is 0) { + x += w - 35; + polyline [12] = polyline [14] = 16; + polyline [16] = 35; + borderPolygon[12] = borderPolygon[14] = 16; + borderPolygon [16] = 35; + } OS.gtk_window_move (cast(GtkWindow*)handle, Math.min(dest.width - w, x - w + 17), y); } else { polyline = [ @@ -224,6 +246,13 @@ w-17, h-1, w-17, h+TIP_HEIGHT-2, w-36, h-1, 5, h-1, 4, h-2, 3, h-2, 1, h-4, 1, h-5, 0, h-6, 0, 5]; + if ((parent.style & DWT.MIRRORED) !is 0) { + x += w - 35; + polyline [42] = 35; + polyline [44] = polyline [46] = 16; + borderPolygon[36] = 35; + borderPolygon[38] = borderPolygon [40] = 17; + } OS.gtk_window_move (cast(GtkWindow*)handle, Math.min(dest.width - w, x - w + 17), y - h - TIP_HEIGHT); } } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Tracker.d --- a/dwt/widgets/Tracker.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Tracker.d Mon May 12 19:13:01 2008 +0200 @@ -52,7 +52,8 @@ */ public class Tracker : Widget { Composite parent; - GdkCursor* cursor, lastCursor; + Cursor cursor; + GdkCursor* lastCursor; GdkDrawable* window; bool tracking, cancelled, grabbed, stippled; Rectangle [] rectangles, proportions; @@ -330,7 +331,9 @@ OS.gdk_gc_set_function (gc, OS.GDK_XOR); for (int i=0; i 0 && ((style & DWT.DOWN) is 0)) yChange = 0; if (xChange is 0 && yChange is 0) return; + if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) xChange *= -1; bounds.x += xChange; bounds.y += yChange; for (int i = 0; i < rectangles.length; i++) { rectangles [i].x += xChange; @@ -704,7 +713,7 @@ this.oldY = oldY ; grabbed = grab (); - lastCursor = cursor; + lastCursor = this.cursor !is null ? this.cursor.handle : null; /* Tracker behaves like a Dialog with its own OS event loop. */ GdkEvent* gdkEvent; @@ -812,6 +821,7 @@ void resizeRectangles (int xChange, int yChange) { if (bounds is null) return; + if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) xChange *= -1; /* * If the cursor orientation has not been set in the orientation of * this change then try to set it here. @@ -935,8 +945,7 @@ */ public void setCursor (Cursor value) { checkWidget (); - cursor = null; - if (value !is null) cursor = value.handle; + cursor = value; } /** diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Tree.d --- a/dwt/widgets/Tree.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Tree.d Mon May 12 19:13:01 2008 +0200 @@ -227,11 +227,17 @@ static int checkStyle (int style) { /* - * To be compatible with Windows, force the H_SCROLL - * and V_SCROLL style bits. On Windows, it is not - * possible to create a tree without scroll bars. + * Feature in Windows. Even when WS_HSCROLL or + * WS_VSCROLL is not specified, Windows creates + * trees and tables with scroll bars. The fix + * is to set H_SCROLL and V_SCROLL. + * + * NOTE: This code appears on all platforms so that + * applications have consistent scroll bar behavior. */ - style |= DWT.H_SCROLL | DWT.V_SCROLL; + if ((style & DWT.NO_SCROLL) is 0) { + style |= DWT.H_SCROLL | DWT.V_SCROLL; + } /* GTK is always FULL_SELECTION */ style |= DWT.FULL_SELECTION; return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0); @@ -429,7 +435,7 @@ addListener (DWT.Collapse, typedListener); } -int calculateWidth (GtkTreeViewColumn *column, GtkTreeIter* iter) { +int calculateWidth (GtkTreeViewColumn *column, GtkTreeIter* iter, bool recurse) { OS.gtk_tree_view_column_cell_set_cell_data (column, modelHandle, iter, false, false); /* * Bug in GTK. The width calculated by gtk_tree_view_column_cell_get_size() @@ -443,7 +449,16 @@ int width = 0; int w; + GtkTreePath* path = null; + if (OS.gtk_tree_view_get_expander_column (handle) is column) { + /* indent */ + GdkRectangle rect; + OS.gtk_widget_realize (handle); + path = OS.gtk_tree_model_get_path (modelHandle, iter); + OS.gtk_tree_view_get_cell_area (handle, path, column, &rect); + width += rect.x; + /* expander */ OS.gtk_widget_style_get1 (handle, OS.expander_size.ptr, &w); width += w + TreeItem.EXPANDER_EXTRA_PADDING; } @@ -461,6 +476,21 @@ temp = OS.g_list_next (temp); } OS.g_list_free (list); + + if (recurse) { + if (path is null) path = OS.gtk_tree_model_get_path (modelHandle, iter); + bool expanded = OS.gtk_tree_view_row_expanded (handle, path) !is 0; + if (expanded) { + GtkTreeIter childIter; + bool valid = OS.gtk_tree_model_iter_children (modelHandle, &childIter, iter) !is 0; + while (valid) { + width = Math.max (width, calculateWidth (column, &childIter, true)); + valid = OS.gtk_tree_model_iter_next (modelHandle, &childIter) !is 0; + } + } + } + + if (path !is null) OS.gtk_tree_path_free (path); return width; } @@ -939,6 +969,18 @@ if (checkRenderer !is null) display.removeWidget (cast(GtkWidget*)checkRenderer); } +public void deselect (TreeItem item) { + checkWidget (); + if (item is null) error (DWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + bool fixColumn = showFirstColumn (); + auto selection = OS.gtk_tree_view_get_selection (handle); + OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); + OS.gtk_tree_selection_unselect_iter (selection, item.handle); + OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); + if (fixColumn) hideFirstColumn (); +} + /** * Deselects all selected items in the receiver. * @@ -1124,6 +1166,13 @@ return new Rectangle (fixedX - binX , fixedY - binY , width, height); } +int getClientWidth () { + int w, h; + OS.gtk_widget_realize (handle); + OS.gdk_drawable_get_size(OS.gtk_tree_view_get_bin_window(handle), &w, &h); + return w; +} + /** * Returns the column at the given, zero-relative index in the * receiver. Throws an exception if the index is out of range. @@ -2303,37 +2352,9 @@ if (item !is null && !item.isDisposed ()) item.release (false); } items = new TreeItem[4]; - /* - * Bug in GTK. In version 2.3.2, when the property fixed-height-mode - * is set and there are items in the list, OS.gtk_tree_store_clear() - * segment faults. The fix is to create a new empty model instead. - */ auto selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); - /* - * Bug in GTK. In version 2.8, when gtk_tree_view_set_model() is called, GTK - * does not remove the timer used to show animation when expanding a node. This - * can cause two possible crashes. The first one happens when the timer expires and - * it accesses the expanding node which has been already destroyed. The second one - * happens if a new item is created and destroyed before the timer expires. The fix - * is to remove the timer by disposing the first item in the tree. - */ - if (OS.GTK_VERSION < OS.buildVERSION(2, 10, 0)) { - if (OS.gtk_tree_model_iter_n_children (modelHandle, null) !is 0) { - GtkTreeIter iter; - OS.gtk_tree_model_iter_nth_child (modelHandle, &iter, null, 0); - OS.gtk_tree_store_remove (modelHandle, &iter); - } - } - // TODO verify if true for tree store - //OS.gtk_tree_store_clear (modelHandle); - auto oldModel = modelHandle; - uint[] types = getColumnTypes (Math.max (1,columnCount)); - auto newModel = OS.gtk_tree_store_newv (types.length, types.ptr); - if (newModel is null) error (DWT.ERROR_NO_HANDLES); - OS.gtk_tree_view_set_model (handle, newModel); - OS.g_object_unref (oldModel); - modelHandle = newModel; + OS.gtk_tree_store_clear (modelHandle); OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); /* Disable searching when using VIRTUAL */ @@ -2458,7 +2479,7 @@ sendEvent (DWT.MeasureItem, event); gc.dispose (); contentWidth = event.width - imageWidth; - contentHeight = event.height; + if (contentHeight < event.height) contentHeight = event.height; if (width !is null) *width = contentWidth; if (height !is null) *height = contentHeight; } @@ -2529,6 +2550,7 @@ gc.setForeground (item.getForeground (columnIndex)); } gc.setFont (item.getFont (columnIndex)); + if ((style & DWT.MIRRORED) !is 0) rect.x = getClientWidth () - rect.width - rect.x; gc.setClipping (rect.x, rect.y, rect.width, rect.height); Event event = new Event (); event.item = item; @@ -2610,6 +2632,7 @@ gc.setForeground (foreground); } gc.setFont (item.getFont (columnIndex)); + if ((style & DWT.MIRRORED) !is 0) rect.x = getClientWidth () - rect.width - rect.x; gc.setClipping (rect.x, rect.y, rect.width, rect.height); Event event = new Event (); event.item = item; @@ -2663,7 +2686,7 @@ public void setInsertMark (TreeItem item, bool before) { checkWidget (); if (item is null) { - OS.gtk_tree_view_unset_rows_drag_dest(handle); + OS.gtk_tree_view_set_drag_dest_row(handle, null, OS.GTK_TREE_VIEW_DROP_BEFORE); return; } if (item.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT); @@ -2716,6 +2739,19 @@ count = Math.max (0, count); setItemCount (null, count); } + +public void select (TreeItem item) { + checkWidget (); + if (item is null) error (DWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + bool fixColumn = showFirstColumn (); + auto selection = OS.gtk_tree_view_get_selection (handle); + OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); + OS.gtk_tree_selection_select_iter (selection, item.handle); + OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udCHANGED); + if (fixColumn) hideFirstColumn (); +} + /** * Selects all of the items in the receiver. *

    @@ -2893,7 +2929,7 @@ */ if (((style & DWT.VIRTUAL) !is 0) && OS.GTK_VERSION < OS.buildVERSION (2, 3, 2)) return; int width = OS.gtk_tree_view_column_get_fixed_width (column); - int itemWidth = calculateWidth (column, cast(GtkTreeIter*)item.handle); + int itemWidth = calculateWidth (column, cast(GtkTreeIter*)item.handle, true); if (width < itemWidth) { OS.gtk_tree_view_column_set_fixed_width (column, itemWidth); } diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/TreeColumn.d --- a/dwt/widgets/TreeColumn.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/TreeColumn.d Mon May 12 19:13:01 2008 +0200 @@ -202,6 +202,7 @@ void createWidget (int index) { parent.createItem (this, index); + setOrientation (); hookEvents (); register (); text = ""; @@ -426,7 +427,7 @@ GtkTreeIter iter; if (OS.gtk_tree_model_get_iter_first (parent.modelHandle, &iter)) { do { - width = Math.max (width, parent.calculateWidth (cast(GtkTreeViewColumn*)handle, &iter)); + width = Math.max (width, parent.calculateWidth (cast(GtkTreeViewColumn*)handle, &iter, true)); } while (OS.gtk_tree_model_iter_next(parent.modelHandle, &iter)); } } @@ -576,6 +577,15 @@ OS.gtk_tree_view_column_set_reorderable (handle, moveable); } +void setOrientation() { + if ((parent.style & DWT.RIGHT_TO_LEFT) !is 0) { + if (buttonHandle !is null) { + OS.gtk_widget_set_direction (buttonHandle, OS.GTK_TEXT_DIR_RTL); + display.doSetDirectionProc(buttonHandle, OS.GTK_TEXT_DIR_RTL); + } + } +} + /** * Sets the resizable attribute. A column that is * not resizable cannot be dragged by the user but diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/TreeItem.d --- a/dwt/widgets/TreeItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/TreeItem.d Mon May 12 19:13:01 2008 +0200 @@ -221,6 +221,79 @@ if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS); } +Color _getBackground () { + void* ptr; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.BACKGROUND_COLUMN, &ptr); + if (ptr is null) return parent.getBackground (); + GdkColor* gdkColor = new GdkColor (); + *gdkColor = *cast(GdkColor*) ptr; + return Color.gtk_new (display, gdkColor); +} + +Color _getBackground (int index) { + int count = Math.max (1, parent.columnCount); + if (0 > index || index > count - 1) return _getBackground (); + void* ptr; + int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_BACKGROUND, &ptr); + if (ptr is null) return _getBackground (); + GdkColor* gdkColor = new GdkColor (); + *gdkColor = *cast(GdkColor*) ptr; + return Color.gtk_new (display, gdkColor); +} + +bool _getChecked () { + void* ptr; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.CHECKED_COLUMN, &ptr); + return ptr !is null; +} + +Color _getForeground () { + void* ptr; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.FOREGROUND_COLUMN, &ptr); + if (ptr is null) return parent.getForeground (); + GdkColor* gdkColor = new GdkColor (); + *gdkColor = *cast(GdkColor*) ptr; + return Color.gtk_new (display, gdkColor); +} + +Color _getForeground (int index) { + int count = Math.max (1, parent.columnCount); + if (0 > index || index > count - 1) return _getForeground (); + void* ptr; + int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_FOREGROUND, &ptr); + if (ptr is null) return _getForeground (); + GdkColor* gdkColor = new GdkColor (); + *gdkColor = *cast(GdkColor*) ptr; + return Color.gtk_new (display, gdkColor); +} + +Image _getImage (int index) { + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return null; + void* ptr; + int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_PIXBUF, &ptr); + if (ptr is null) return null; + ImageList imageList = parent.imageList; + int imageIndex = imageList.indexOf (ptr); + if (imageIndex is -1) return null; + return imageList.get (imageIndex); +} + +String _getText (int index) { + int count = Math.max (1, parent.getColumnCount ()); + if (0 > index || index > count - 1) return ""; + void* ptr; + int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; + OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_TEXT, &ptr); + if (ptr is null) return ""; //$NON-NLS-1$ + char[] buffer = tango.stdc.stringz.fromStringz( cast(char*)ptr).dup; + OS.g_free (ptr); + return buffer; +} + void clear () { if (parent.currentItem is this) return; if (cached || (parent.style & DWT.VIRTUAL) is 0) { @@ -318,11 +391,7 @@ public Color getBackground () { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - void* ptr; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.BACKGROUND_COLUMN, &ptr); - if (ptr is null) return parent.getBackground (); - GdkColor* gdkColor = cast(GdkColor*)ptr; - return Color.gtk_new (display, gdkColor); + return _getBackground (); } /** @@ -341,14 +410,7 @@ public Color getBackground (int index) { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - int count = Math.max (1, parent.columnCount); - if (0 > index || index > count - 1) return getBackground (); - void* ptr; - int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_BACKGROUND, &ptr); - if (ptr is null) return getBackground (); - GdkColor* gdkColor = cast(GdkColor*)ptr; - return Color.gtk_new (display, gdkColor); + return _getBackground (index); } /** @@ -381,7 +443,7 @@ OS.gtk_widget_realize (parentHandle); GdkRectangle rect; OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect); - OS.gtk_tree_path_free (path); + if ((parent.getStyle () & DWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x; if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 18) && OS.gtk_tree_view_get_expander_column (parentHandle) is column) { int buffer; @@ -392,6 +454,18 @@ rect.x += buffer; //rect.width -= buffer [0]; // TODO Is this required for some versions? } + /* + * Bug in GTK. In GTK 2.8.x, the cell area is left aligned even + * when the widget is mirrored. The fix is to sum up the indentation + * of the expanders. + */ + if ((parent.getStyle () & DWT.MIRRORED) !is 0 && (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0))) { + int depth = OS.gtk_tree_path_get_depth (path); + int expanderSize; + OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &expanderSize); + rect.x += depth * (expanderSize + TreeItem.EXPANDER_EXTRA_PADDING); + } + OS.gtk_tree_path_free (path); if (index is 0 && (parent.style & DWT.CHECK) !is 0) { if (OS.GTK_VERSION >= OS.buildVERSION (2, 1, 3)) { @@ -408,7 +482,8 @@ rect.width -= w + buffer; } } - return new Rectangle (rect.x, rect.y, rect.width + 1, rect.height + 1); + int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0; + return new Rectangle (rect.x, rect.y, width, rect.height + 1); } /** @@ -443,7 +518,7 @@ GdkRectangle rect; OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect); - OS.gtk_tree_path_free (path); + if ((parent.getStyle () & DWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x; int right = rect.x + rect.width; int x, w; @@ -456,6 +531,19 @@ OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &buffer); rect.x += buffer + TreeItem.EXPANDER_EXTRA_PADDING; } + /* + * Bug in GTK. In GTK 2.8.x, the cell area is left aligned even + * when the widget is mirrored. The fix is to sum up the indentation + * of the expanders. + */ + if ((parent.getStyle () & DWT.MIRRORED) !is 0 && (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0))) { + int depth = OS.gtk_tree_path_get_depth (path); + int expanderSize; + OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &expanderSize); + rect.x += depth * (expanderSize + TreeItem.EXPANDER_EXTRA_PADDING); + } + OS.gtk_tree_path_free (path); + OS.gtk_widget_style_get1 (parentHandle, OS.horizontal_separator.ptr, &buffer); int horizontalSeparator = buffer; rect.x += horizontalSeparator; @@ -476,7 +564,8 @@ rect.width = Math.max (0, right - rect.x); } } - return new Rectangle (rect.x, rect.y, rect.width + 1, rect.height + 1); + int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0; + return new Rectangle (rect.x, rect.y, width, rect.height + 1); } /** @@ -496,9 +585,7 @@ checkWidget(); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); if ((parent.style & DWT.CHECK) is 0) return false; - void* ptr; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.CHECKED_COLUMN, &ptr); - return ptr !is null; + return _getChecked (); } /** @@ -579,11 +666,7 @@ public Color getForeground () { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - void* ptr; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, Tree.FOREGROUND_COLUMN, &ptr); - if (ptr is null) return parent.getForeground (); - GdkColor* gdkColor = cast(GdkColor*)ptr; - return Color.gtk_new (display, gdkColor); + return _getForeground (); } /** @@ -603,14 +686,7 @@ public Color getForeground (int index) { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - int count = Math.max (1, parent.columnCount); - if (0 > index || index > count - 1) return getForeground (); - void* ptr; - int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_FOREGROUND, &ptr); - if (ptr is null) return getForeground (); - GdkColor* gdkColor = cast(GdkColor*)ptr; - return Color.gtk_new (display, gdkColor); + return _getForeground (index); } /** @@ -656,16 +732,7 @@ public Image getImage (int index) { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - int count = Math.max (1, parent.getColumnCount ()); - if (0 > index || index > count - 1) return null; - void* ptr; - int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_PIXBUF, &ptr); - if (ptr is null) return null; - ImageList imageList = parent.imageList; - int imageIndex = imageList.indexOf (ptr); - if (imageIndex is -1) return null; - return imageList.get (imageIndex); + return _getImage (index); } /** @@ -701,8 +768,7 @@ auto path = OS.gtk_tree_model_get_path (parent.modelHandle, handle); OS.gtk_widget_realize (parentHandle); OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect); - OS.gtk_tree_path_free (path); - + if ((parent.getStyle () & DWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x; if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 18) && OS.gtk_tree_view_get_expander_column (parentHandle) is column) { int buffer; OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &buffer); @@ -712,6 +778,18 @@ //int horizontalSeparator = buffer[0]; //rect.x += horizontalSeparator; } + /* + * Bug in GTK. In GTK 2.8.x, the cell area is left aligned even + * when the widget is mirrored. The fix is to sum up the indentation + * of the expanders. + */ + if ((parent.getStyle () & DWT.MIRRORED) !is 0 && (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0))) { + int depth = OS.gtk_tree_path_get_depth (path); + int expanderSize; + OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &expanderSize); + rect.x += depth * (expanderSize + TreeItem.EXPANDER_EXTRA_PADDING); + } + OS.gtk_tree_path_free (path); /* * The OS call gtk_cell_renderer_get_size() provides the width of image to be drawn @@ -733,7 +811,8 @@ OS.gtk_cell_renderer_get_size (pixbufRenderer, parentHandle, null, null, null, &w, null); rect.width = w; } - return new Rectangle (rect.x, rect.y, rect.width, rect.height + 1); + int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width : 0; + return new Rectangle (rect.x, rect.y, width, rect.height + 1); } /** @@ -874,15 +953,7 @@ public String getText (int index) { checkWidget (); if (!parent.checkData (this)) error (DWT.ERROR_WIDGET_DISPOSED); - int count = Math.max (1, parent.getColumnCount ()); - if (0 > index || index > count - 1) return ""; - void* ptr; - int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; - OS.gtk_tree_model_get1 (parent.modelHandle, handle, modelIndex + Tree.CELL_TEXT, &ptr); - if (ptr is null) return ""; //$NON-NLS-1$ - String res = tango.stdc.stringz.fromStringz( cast(char*)ptr ).dup; - OS.g_free (ptr); - return res; + return _getText (index); } /** @@ -928,7 +999,7 @@ GdkRectangle rect; OS.gtk_tree_view_get_cell_area (parentHandle, path, column, &rect); - OS.gtk_tree_path_free (path); + if ((parent.getStyle () & DWT.MIRRORED) !is 0) rect.x = parent.getClientWidth () - rect.width - rect.x; int right = rect.x + rect.width; int x, w; @@ -940,6 +1011,19 @@ OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &buffer); rect.x += buffer + TreeItem.EXPANDER_EXTRA_PADDING; } + /* + * Bug in GTK. In GTK 2.8.x, the cell area is left aligned even + * when the widget is mirrored. The fix is to sum up the indentation + * of the expanders. + */ + if ((parent.getStyle () & DWT.MIRRORED) !is 0 && (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0))) { + int depth = OS.gtk_tree_path_get_depth (path); + int expanderSize; + OS.gtk_widget_style_get1 (parentHandle, OS.expander_size.ptr, &expanderSize); + rect.x += depth * (expanderSize + TreeItem.EXPANDER_EXTRA_PADDING); + } + OS.gtk_tree_path_free (path); + OS.gtk_widget_style_get1 (parentHandle, OS.horizontal_separator.ptr, &buffer); int horizontalSeparator = buffer; rect.x += horizontalSeparator; @@ -959,7 +1043,8 @@ rect.width = Math.max (0, right - rect.x); } } - return new Rectangle (rect.x, rect.y, rect.width + 1, rect.height + 1); + int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0; + return new Rectangle (rect.x, rect.y, width, rect.height + 1); } /** @@ -1095,6 +1180,7 @@ if (color !is null && color.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } + if (_getBackground ().opEquals (color)) return; GdkColor* gdkColor = color !is null ? color.handle : null; OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.BACKGROUND_COLUMN, gdkColor); /* @@ -1134,6 +1220,7 @@ if (color !is null && color.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } + if (_getBackground (index).opEquals (color)) return; int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; @@ -1191,6 +1278,7 @@ public void setChecked (bool checked) { checkWidget(); if ((parent.style & DWT.CHECK) is 0) return; + if (_getChecked () is checked) return; OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.CHECKED_COLUMN, cast(void*)cast(int)checked); /* * GTK+'s "inconsistent" state does not match DWT's concept of grayed. To @@ -1252,10 +1340,11 @@ if (font !is null && font.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } - if (this.font is font) return; - if (this.font !is null && this.font ==/*eq*/font) return; + Font oldFont = this.font; + if (oldFont is font) return; this.font = font; - auto fontHandle = font !is null ? font.handle : null; + if (oldFont !is null && oldFont.opEquals (font)) return; + void* fontHandle = font !is null ? font.handle : null; OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.FONT_COLUMN, fontHandle); /* * Bug in GTK. When using fixed-height-mode, @@ -1297,11 +1386,13 @@ int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; if (cellFont is null) { + if (font is null) return; cellFont = new Font [count]; } - if (cellFont [index] is font) return; - if (cellFont [index] !is null && cellFont [index] ==/*eq*/font ) return; + Font oldFont = cellFont [index]; + if (oldFont is font) return; cellFont [index] = font; + if (oldFont !is null && oldFont.opEquals (font)) return; int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; auto fontHandle = font !is null ? font.handle : null; @@ -1369,6 +1460,7 @@ if (color !is null && color.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } + if (_getForeground ().opEquals (color)) return; GdkColor *gdkColor = color !is null ? color.handle : null; OS.gtk_tree_store_set1 (parent.modelHandle, cast(GtkTreeIter*)handle, Tree.FOREGROUND_COLUMN, gdkColor); /* @@ -1408,6 +1500,7 @@ if (color !is null && color.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } + if (_getForeground (index).opEquals (color)) return; int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; int modelIndex = parent.columnCount is 0 ? Tree.FIRST_COLUMN : parent.columns [index].modelIndex; @@ -1465,6 +1558,7 @@ public void setGrayed (bool grayed) { checkWidget(); if ((parent.style & DWT.CHECK) is 0) return; + if (this.grayed is grayed) return; this.grayed = grayed; /* * GTK+'s "inconsistent" state does not match DWT's concept of grayed. @@ -1497,6 +1591,9 @@ if (image !is null && image.isDisposed()) { error(DWT.ERROR_INVALID_ARGUMENT); } + if (image !is null && image.type is DWT.ICON) { + if (image.opEquals (_getImage (index))) return; + } int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; GdkPixbuf* pixbuf; @@ -1541,7 +1638,7 @@ * the style. */ auto style = OS.gtk_widget_get_modifier_style (parentHandle); - OS.gtk_widget_modify_style (parentHandle, style); + parent.modifyStyle (parentHandle, style); } } } @@ -1615,6 +1712,7 @@ public void setText (int index, String string) { checkWidget (); if (string is null) error (DWT.ERROR_NULL_ARGUMENT); + if (_getText (index).equals (string)) return; int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; char* buffer = tango.stdc.stringz.toStringz(string); diff -r 06a1f6829310 -r ce446666f5a2 dwt/widgets/Widget.d --- a/dwt/widgets/Widget.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Widget.d Mon May 12 19:13:01 2008 +0200 @@ -152,32 +152,33 @@ static const int MOTION_NOTIFY_EVENT_INVERSE = 34; static const int MOVE_FOCUS = 35; static const int OUTPUT = 36; - static const int POPUP_MENU = 37; - static const int PREEDIT_CHANGED = 38; - static const int REALIZE = 39; - static const int ROW_ACTIVATED = 40; - static const int SCROLL_CHILD = 41; - static const int SCROLL_EVENT = 42; - static const int SELECT = 43; - static const int SHOW = 44; - static const int SHOW_HELP = 45; - static const int SIZE_ALLOCATE = 46; - static const int STYLE_SET = 47; - static const int SWITCH_PAGE = 48; - static const int TEST_COLLAPSE_ROW = 49; - static const int TEST_EXPAND_ROW = 50; - static const int TEXT_BUFFER_INSERT_TEXT = 51; - static const int TOGGLED = 52; - static const int UNMAP = 53; - static const int UNMAP_EVENT = 54; - static const int UNREALIZE = 55; - static const int VALUE_CHANGED = 56; - static const int VISIBILITY_NOTIFY_EVENT = 57; - static const int WINDOW_STATE_EVENT = 58; - static const int ACTIVATE_INVERSE = 59; - static const int DAY_SELECTED = 60; - static const int MONTH_CHANGED = 61; - static const int LAST_SIGNAL = 62; + static const int POPULATE_POPUP = 37; + static const int POPUP_MENU = 38; + static const int PREEDIT_CHANGED = 39; + static const int REALIZE = 40; + static const int ROW_ACTIVATED = 41; + static const int SCROLL_CHILD = 42; + static const int SCROLL_EVENT = 43; + static const int SELECT = 44; + static const int SHOW = 45; + static const int SHOW_HELP = 46; + static const int SIZE_ALLOCATE = 47; + static const int STYLE_SET = 48; + static const int SWITCH_PAGE = 49; + static const int TEST_COLLAPSE_ROW = 50; + static const int TEST_EXPAND_ROW = 51; + static const int TEXT_BUFFER_INSERT_TEXT = 52; + static const int TOGGLED = 53; + static const int UNMAP = 54; + static const int UNMAP_EVENT = 55; + static const int UNREALIZE = 56; + static const int VALUE_CHANGED = 57; + static const int VISIBILITY_NOTIFY_EVENT = 58; + static const int WINDOW_STATE_EVENT = 59; + static const int ACTIVATE_INVERSE = 60; + static const int DAY_SELECTED = 61; + static const int MONTH_CHANGED = 62; + static const int LAST_SIGNAL = 63; template UD_Getter( String name ){ const String UD_Getter = "void* ud"~name~"(){ return getDisplay().getWindowProcUserData( "~name~"); }\n"; @@ -219,6 +220,7 @@ mixin ( UD_Getter!( "MOTION_NOTIFY_EVENT_INVERSE" )); mixin ( UD_Getter!( "MOVE_FOCUS" )); mixin ( UD_Getter!( "OUTPUT" )); + mixin ( UD_Getter!( "POPULATE_POPUP" )); mixin ( UD_Getter!( "POPUP_MENU" )); mixin ( UD_Getter!( "PREEDIT_CHANGED" )); mixin ( UD_Getter!( "REALIZE" )); @@ -385,6 +387,11 @@ } } style = checkBits (style, DWT.LEFT_TO_RIGHT, DWT.RIGHT_TO_LEFT, 0, 0, 0, 0); + /* Versions of GTK prior to 2.8 do not render RTL text properly */ + if (OS.GTK_VERSION < OS.buildVERSION (2, 8, 0)) { + style &= ~DWT.RIGHT_TO_LEFT; + style |= DWT.LEFT_TO_RIGHT; + } } /** @@ -612,6 +619,33 @@ return display; } +/** + * Returns an array of listeners who will be notified when an event + * of the given type occurs. The event type is one of the event constants + * defined in class DWT. + * + * @param eventType the type of event to listen for + * @return an array of listeners that will be notified when the event occurs + * + * @exception 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 Listener + * @see DWT + * @see #addListener(int, Listener) + * @see #removeListener(int, Listener) + * @see #notifyListeners + * + * @since 3.4 + */ +public Listener[] getListeners (int eventType) { + checkWidget(); + if (eventTable is null) return new Listener[0]; + return eventTable.getListeners(eventType); +} + String getName () { // String str = getClass ().getName (); // int index = str.lastIndexOf ('.'); @@ -788,6 +822,10 @@ return 0; } +int /*long*/ gtk_populate_popup (GtkWidget* widget, GtkWidget* menu) { + return 0; +} + int /*long*/ gtk_popup_menu (GtkWidget* widget) { return 0; } @@ -909,7 +947,15 @@ return 0; } +void fixedSizeAllocateProc(GtkWidget* widget, GtkAllocation* allocationPtr) { + return Display.oldFixedSizeAllocateProc(widget, allocationPtr); +} + char [] fixMnemonic (String str) { + return fixMnemonic (str, true); +} + +char [] fixMnemonic (String str, bool replace) { int len = str.length; String text = str[0 .. len].dup; int i = 0, j = 0; @@ -920,11 +966,15 @@ if (i + 1 < len && text [i + 1] is '&') { i++; } else { - text [i] = '_'; + if (replace) { + text [i] = '_'; + } else { + i++; + } } break; case '_': - result [j++] = '_'; + if (replace) result [j++] = '_'; break; default: } @@ -1019,6 +1069,10 @@ return keyval1 is keyval2; } +void modifyStyle (GtkWidget* handle, GtkRcStyle* style) { + OS.gtk_widget_modify_style (handle, style); +} + /** * Notifies all of the receiver's listeners for events * of the given type that one such event has occurred by @@ -1258,7 +1312,7 @@ return sendIMKeyEvent (type, keyEvent, chars) !is null; } -char [] sendIMKeyEvent (int type, GdkEventKey* keyEvent, char [] chars) { +char [] sendIMKeyEvent (int type, GdkEventKey* keyEvent, char [] chars) { int index = 0, count = 0, state = 0; GdkEvent* ptr = null; if (keyEvent is null) { @@ -1453,7 +1507,7 @@ flags = OS.gtk_rc_style_get_color_flags (style, OS.GTK_STATE_ACTIVE); flags = (color is null) ? flags & ~OS.GTK_RC_TEXT: flags | OS.GTK_RC_TEXT; OS.gtk_rc_style_set_color_flags (style, OS.GTK_STATE_ACTIVE, flags); - OS.gtk_widget_modify_style (handle, style); + modifyStyle (handle, style); } bool setInputState (Event event, int state) { @@ -1661,6 +1715,9 @@ case EVENT: trace( "EVENT" ); return gtk_event (handle, cast(GdkEvent*)arg0); + case POPULATE_POPUP: + trace( "POPULATE_POPUP" ); + return gtk_populate_popup (handle, cast(GtkWidget*)arg0); case EVENT_AFTER: trace( "EVENT_AFTER" ); return gtk_event_after (handle, cast(GdkEvent*)arg0);