Mercurial > projects > dwt-linux
changeset 240:ce446666f5a2
Update to SWT 3.4M7
line wrap: on
line diff
--- 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). + * <p> + * The IME composition event is sent to allow + * custom text editors to implement in-line + * editing of international text. + * </p> + * + * The detail field indicates the action to be taken: + * <p><ul> + * <li>{@link DWT#COMPOSITION_CHANGED}</li> + * <li>{@link DWT#COMPOSITION_OFFSET}</li> + * <li>{@link DWT#COMPOSITION_SELECTION}</li> + * </ul></p> + * + * @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). + * <p> + * 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. + * + * <b>Used By:</b><ul> + * <li><code>Tree</code></li> + * <li><code>Table</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int NO_SCROLL = 1 << 4; + + /** * Style constant for bordered behavior (value is 1<<11). * <br>Note that this is a <em>HINT</em>. * <p><b>Used By:</b><ul> @@ -1298,7 +1382,15 @@ /** * Style constant for no focus from the mouse behavior (value is 1<<19). + * <p> + * Normally, when the user clicks on a control, focus is assigned to that + * control, providing the control has no children. Some controls, such as + * tool bars and sashes, don't normally take focus when the mouse is clicked + * or accept focus when assigned from within the program. This style allows + * Composites to implement "no focus" mouse behavior. + * * <br>Note that this is a <em>HINT</em>. + * </p> * <p><b>Used By:</b><ul> * <li><code>Composite</code></li> * </ul></p> @@ -1313,6 +1405,8 @@ * the DWT.Paint event is not sent. When it gets bigger, an DWT.Paint event is * sent with a GC clipped to only the new areas to be painted. Without this * style, the entire client area will be repainted. + * + * <br>Note that this is a <em>HINT</em>. * </p><p><b>Used By:</b><ul> * <li><code>Composite</code></li> * </ul></p> @@ -1321,6 +1415,8 @@ /** * Style constant for no paint event merging behavior (value is 1<<21). + * + * <br>Note that this is a <em>HINT</em>. * <p><b>Used By:</b><ul> * <li><code>Composite</code></li> * </ul></p> @@ -1418,16 +1514,104 @@ public static const int DOUBLE_BUFFERED = 1 << 29; /** + * Style constant for transparent behavior (value is 1<<30). + * <p> + * By default, before a widget paints, the client area is filled with the current background. + * When this style is specified, the background is not filled and widgets that are obscured + * will draw through. + * </p><p><b>Used By:</b><ul> + * <li><code>Composite</code></li> + * </ul></p> + * + * @since 3.4 + * + * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED + */ + public static const int TRANSPARENT = 1 << 30; + + /** * Style constant for align up behavior (value is 1<<7, * since align UP and align TOP are considered the same). * <p><b>Used By:</b><ul> * <li><code>Button</code> with <code>ARROW</code> style</li> * <li><code>Tracker</code></li> + * <li><code>Table</code></li> + * <li><code>Tree</code></li> * </ul></p> */ public static const int UP = 1 << 7; /** + * Style constant to indicate single underline (value is 0). + * <p><b>Used By:</b><ul> + * <li><code>TextStyle</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int UNDERLINE_SINGLE = 0; + + /** + * Style constant to indicate double underline (value is 1). + * <p><b>Used By:</b><ul> + * <li><code>TextStyle</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int UNDERLINE_DOUBLE = 1; + + /** + * Style constant to indicate error underline (value is 2). + * <p><b>Used By:</b><ul> + * <li><code>TextStyle</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int UNDERLINE_ERROR = 2; + + /** + * Style constant to indicate squiggle underline (value is 3). + * <p><b>Used By:</b><ul> + * <li><code>TextStyle</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int UNDERLINE_SQUIGGLE = 3; + + /** + * Style constant to indicate solid border (value is 1). + * <p><b>Used By:</b><ul> + * <li><code>TextStyle</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int BORDER_SOLID = 1; + + /** + * Style constant to indicate dashed border (value is 2). + * <p><b>Used By:</b><ul> + * <li><code>TextStyle</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int BORDER_DASH = 2; + + /** + * Style constant to indicate dotted border (value is 4). + * <p><b>Used By:</b><ul> + * <li><code>TextStyle</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int BORDER_DOT = 4; + + /** * Style constant for align top behavior (value is 1<<7, * since align UP and align TOP are considered the same). * <p><b>Used By:</b><ul> @@ -1442,6 +1626,8 @@ * <p><b>Used By:</b><ul> * <li><code>Button</code> with <code>ARROW</code> style</li> * <li><code>Tracker</code></li> + * <li><code>Table</code></li> + * <li><code>Tree</code></li> * </ul></p> */ public static const int DOWN = 1 << 10; @@ -2979,8 +3165,32 @@ public static const int IMAGE_GRAY = 2; /** + * Constant to indicate an error state (value is 1). + * <p><b>Used By:</b><ul> + * <li><code>ProgressBar</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int ERROR = 1; + + /** + * Constant to a indicate a paused state (value is 4). + * <p><b>Used By:</b><ul> + * <li><code>ProgressBar</code></li> + * </ul></p> + * + * @since 3.4 + */ + public static const int PAUSED = 1 << 2; + + /** * The font style constant indicating a normal weight, non-italic font - * (value is 0). + * (value is 0). This constant is also used with <code>ProgressBar</code> + * to indicate a normal state. + * <p><b>Used By:</b><ul> + * <li><code>ProgressBar</code></li> + * </ul></p> */ public static const int NORMAL = 0;
--- a/dwt/accessibility/AccessibleObject.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/accessibility/AccessibleObject.d Mon May 12 19:13:01 2008 +0200 @@ -472,8 +472,8 @@ case ACC.ROLE_SCROLLBAR: return ATK.ATK_ROLE_SCROLL_BAR; case ACC.ROLE_SEPARATOR: return ATK.ATK_ROLE_SEPARATOR; case ACC.ROLE_SLIDER: return ATK.ATK_ROLE_SLIDER; - case ACC.ROLE_TABLE: return ATK.ATK_ROLE_TABLE; - case ACC.ROLE_TABLECELL: return ATK.ATK_ROLE_TABLE_CELL; + case ACC.ROLE_TABLE: return ATK.ATK_ROLE_LIST; + case ACC.ROLE_TABLECELL: return ATK.ATK_ROLE_LIST_ITEM; case ACC.ROLE_TABLECOLUMNHEADER: return ATK.ATK_ROLE_TABLE_COLUMN_HEADER; case ACC.ROLE_TABLEROWHEADER: return ATK.ATK_ROLE_TABLE_ROW_HEADER; case ACC.ROLE_TABFOLDER: return ATK.ATK_ROLE_PAGE_TAB_LIST;
--- a/dwt/custom/CCombo.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/CCombo.d Mon May 12 19:13:01 2008 +0200 @@ -51,6 +51,7 @@ static import tango.text.Unicode; static import tango.text.convert.Format; import dwt.dwthelper.utils; +import dwt.dwthelper.Runnable; /** * The CCombo class represents a selectable user interface object @@ -152,7 +153,12 @@ return; } if (getShell () is event.widget) { - handleFocus (DWT.FocusOut); + getDisplay().asyncExec(new class() Runnable { + public void run() { + if (isDisposed()) return; + handleFocus (DWT.FocusOut); + } + }); } } }; @@ -165,13 +171,13 @@ } }; - int [] comboEvents = [DWT.Dispose, DWT.Move, DWT.Resize]; + int [] comboEvents = [DWT.Dispose, DWT.FocusIn, DWT.Move, DWT.Resize]; for (int i=0; i<comboEvents.length; i++) this.addListener (comboEvents [i], listener); - int [] textEvents = [DWT.KeyDown, DWT.KeyUp, DWT.MenuDetect, DWT.Modify, DWT.MouseDown, DWT.MouseUp, DWT.Traverse, DWT.FocusIn, DWT.Verify]; + int [] textEvents = [DWT.DefaultSelection, DWT.KeyDown, DWT.KeyUp, DWT.MenuDetect, DWT.Modify, DWT.MouseDown, DWT.MouseUp, DWT.MouseDoubleClick, DWT.MouseWheel, DWT.Traverse, DWT.FocusIn, DWT.Verify]; for (int i=0; i<textEvents.length; i++) text.addListener (textEvents [i], listener); - int [] arrowEvents = [DWT.Selection, DWT.FocusIn]; + int [] arrowEvents = [DWT.MouseDown, DWT.MouseUp, DWT.Selection, DWT.FocusIn]; for (int i=0; i<arrowEvents.length; i++) arrow.addListener (arrowEvents [i], listener); createPopup(null, -1); @@ -179,7 +185,7 @@ } static int checkStyle (int style) { int mask = DWT.BORDER | DWT.READ_ONLY | DWT.FLAT | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; - return style & mask; + return DWT.NO_FOCUS | (style & mask); } /** * Adds the argument to the end of the receiver's list. @@ -318,7 +324,30 @@ handleFocus (DWT.FocusIn); break; } + case DWT.MouseDown: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseDown, mouseEvent); + event.doit = mouseEvent.doit; + break; + } + case DWT.MouseUp: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseUp, mouseEvent); + event.doit = mouseEvent.doit; + break; + } case DWT.Selection: { + text.setFocus(); dropDown (!isDropped ()); break; } @@ -363,6 +392,15 @@ list = null; arrow = null; break; + case DWT.FocusIn: + Control focusControl = getDisplay ().getFocusControl (); + if (focusControl is arrow || focusControl is list) return; + if (isDropped()) { + list.setFocus(); + } else { + text.setFocus(); + } + break; case DWT.Move: dropDown (false); break; @@ -465,7 +503,12 @@ */ public void deselect (int index) { checkWidget (); - list.deselect (index); + if (0 <= index && index < list.getItemCount () && + index is list.getSelectionIndex() && + text.getText().equals(list.getItem(index))) { + text.setText(""); //$NON-NLS-1$ + list.deselect (index); + } } /** * Deselects all selected items in the receiver's list. @@ -483,13 +526,14 @@ */ public void deselectAll () { checkWidget (); + text.setText(""); //$NON-NLS-1$ list.deselectAll (); } void dropDown (bool drop) { if (drop is isDropped ()) return; if (!drop) { popup.setVisible (false); - if (!isDisposed ()&& arrow.isFocusControl()) { + if (!isDisposed () && isFocusControl()) { text.setFocus(); } return; @@ -527,7 +571,7 @@ if (x + width > displayRect.x + displayRect.width) x = displayRect.x + displayRect.width - listRect.width; popup.setBounds (x, y, width, height); popup.setVisible (true); - list.setFocus (); + if (isFocusControl()) list.setFocus (); } /* * Return the lowercase of the first non-'&' character following @@ -655,6 +699,29 @@ checkWidget (); return list.getItems (); } +/** + * Returns <code>true</code> if the receiver's list is visible, + * and <code>false</code> otherwise. + * <p> + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, this method + * may still indicate that it is considered visible even though + * it may not actually be showing. + * </p> + * + * @return the receiver's list's visibility state + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public bool getListVisible () { + checkWidget (); + return isDropped(); +} public override Menu getMenu() { return text.getMenu(); } @@ -905,7 +972,7 @@ public void getLocation (AccessibleControlEvent e) { Rectangle location = getBounds (); - Point pt = toDisplay (location.x, location.y); + Point pt = getParent().toDisplay (location.x, location.y); e.x = pt.x; e.y = pt.y; e.width = location.width; @@ -1002,6 +1069,12 @@ case DWT.TRAVERSE_ARROW_NEXT: event.doit = false; break; + case DWT.TRAVERSE_TAB_NEXT: + case DWT.TRAVERSE_TAB_PREVIOUS: + event.doit = text.traverse(event.detail); + event.detail = DWT.TRAVERSE_NONE; + if (event.doit) dropDown(false); + return; default: } Event e = new Event (); @@ -1093,8 +1166,10 @@ * we hide the popup in the deactivate event, the selection event will show * it again. To prevent the popup from showing again, we will let the selection * event of the arrow button hide the popup. + * In Windows, hiding the popup during the deactivate causes the deactivate + * to be called twice and the selection event to be disappear. */ - if ("gtk".equals(DWT.getPlatform())) { + if (!"carbon".equals(DWT.getPlatform())) { Point point = arrow.toControl(getDisplay().getCursorLocation()); Point size = arrow.getSize(); Rectangle rect = new Rectangle(0, 0, size.x, size.y); @@ -1317,6 +1392,7 @@ } public override bool setFocus () { checkWidget(); + if (!isEnabled () || !isVisible ()) return false; if (isFocusControl ()) return true; return text.setFocus (); } @@ -1394,6 +1470,28 @@ checkWidget (); return; } +/** + * Marks the receiver's list as visible if the argument is <code>true</code>, + * and marks it invisible otherwise. + * <p> + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + * </p> + * + * @param visible the new visibility state + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public void setListVisible (bool visible) { + checkWidget (); + dropDown(visible); +} public override void setMenu(Menu menu) { text.setMenu(menu); } @@ -1526,6 +1624,14 @@ handleFocus (DWT.FocusIn); break; } + case DWT.DefaultSelection: { + dropDown (false); + Event e = new Event (); + e.time = event.time; + e.stateMask = event.stateMask; + notifyListeners (DWT.DefaultSelection, e); + break; + } case DWT.KeyDown: { Event keyEvent = new Event (); keyEvent.time = event.time; @@ -1536,16 +1642,6 @@ if (isDisposed ()) break; event.doit = keyEvent.doit; if (!event.doit) break; - - if (event.character is DWT.CR) { - dropDown (false); - Event selectionEvent = new Event (); - selectionEvent.time = event.time; - selectionEvent.stateMask = event.stateMask; - notifyListeners (DWT.DefaultSelection, selectionEvent); - if (isDisposed ()) break; - } - if (event.keyCode is DWT.ARROW_UP || event.keyCode is DWT.ARROW_DOWN) { event.doit = false; if ((event.stateMask & DWT.ALT) !is 0) { @@ -1599,6 +1695,16 @@ break; } case DWT.MouseDown: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseDown, mouseEvent); + if (isDisposed ()) break; + event.doit = mouseEvent.doit; + if (!event.doit) break; if (event.button !is 1) return; if (text.getEditable ()) return; bool dropped = isDropped (); @@ -1608,14 +1714,60 @@ break; } case DWT.MouseUp: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseUp, mouseEvent); + if (isDisposed ()) break; + event.doit = mouseEvent.doit; + if (!event.doit) break; if (event.button !is 1) return; if (text.getEditable ()) return; text.selectAll (); break; } + case DWT.MouseDoubleClick: { + Event mouseEvent = new Event (); + mouseEvent.button = event.button; + mouseEvent.count = event.count; + mouseEvent.stateMask = event.stateMask; + mouseEvent.time = event.time; + mouseEvent.x = event.x; mouseEvent.y = event.y; + notifyListeners (DWT.MouseDoubleClick, mouseEvent); + break; + } + case DWT.MouseWheel: { + Event keyEvent = new Event (); + keyEvent.time = event.time; + keyEvent.keyCode = event.count > 0 ? DWT.ARROW_UP : DWT.ARROW_DOWN; + keyEvent.stateMask = event.stateMask; + notifyListeners (DWT.KeyDown, keyEvent); + if (isDisposed ()) break; + event.doit = keyEvent.doit; + if (!event.doit) break; + if (event.count !is 0) { + event.doit = false; + int oldIndex = getSelectionIndex (); + if (event.count > 0) { + select (Math.max (oldIndex - 1, 0)); + } else { + select (Math.min (oldIndex + 1, getItemCount () - 1)); + } + if (oldIndex !is getSelectionIndex ()) { + Event e = new Event(); + e.time = event.time; + e.stateMask = event.stateMask; + notifyListeners (DWT.Selection, e); + } + if (isDisposed ()) break; + } + break; + } case DWT.Traverse: { switch (event.detail) { - case DWT.TRAVERSE_RETURN: case DWT.TRAVERSE_ARROW_PREVIOUS: case DWT.TRAVERSE_ARROW_NEXT: // The enter causes default selection and @@ -1623,9 +1775,12 @@ // do not use them for traversal. event.doit = false; break; + case DWT.TRAVERSE_TAB_PREVIOUS: + event.doit = traverse(DWT.TRAVERSE_TAB_PREVIOUS); + event.detail = DWT.TRAVERSE_NONE; + return; default: } - Event e = new Event (); e.time = event.time; e.detail = event.detail;
--- a/dwt/custom/CLabel.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/CLabel.d Mon May 12 19:13:01 2008 +0200 @@ -33,6 +33,7 @@ import dwt.graphics.Image; import dwt.graphics.Point; import dwt.graphics.Rectangle; +import dwt.graphics.TextLayout; import dwt.widgets.Canvas; import dwt.widgets.Composite; import dwt.widgets.Control; @@ -797,25 +798,33 @@ int min = 0; int mid = (max+min)/2 - 1; if (mid <= 0) return t; + TextLayout layout = new TextLayout (getDisplay()); + layout.setText(t); + mid = validateOffset(layout, mid); while (min < mid && mid < max) { String s1 = t[0 .. mid].dup; - String s2 = t[l-mid .. l].dup; + String s2 = t.substring(validateOffset(layout, l-mid), l); int l1 = gc.textExtent(s1, DRAW_FLAGS).x; int l2 = gc.textExtent(s2, DRAW_FLAGS).x; if (l1+w+l2 > width) { max = mid; - mid = (max+min)/2; + mid = validateOffset(layout, (max+min)/2); } else if (l1+w+l2 < width) { min = mid; - mid = (max+min)/2; + mid = validateOffset(layout, (max+min)/2); } else { min = max; } } - if (mid is 0) return t; - return t[ 0 .. mid ] ~ ELLIPSIS ~ t[ l-mid .. l ]; + String result = mid is 0 ? t : t.substring(0, mid) ~ ELLIPSIS ~ t.substring(validateOffset(layout, l-mid), l); + layout.dispose(); + return result; } - +int validateOffset(TextLayout layout, int offset) { + int nextOffset = layout.getNextOffset(offset, DWT.MOVEMENT_CLUSTER); + if (nextOffset !is offset) return layout.getPreviousOffset(nextOffset, DWT.MOVEMENT_CLUSTER); + return offset; +} private String[] splitString(String text) { String[] lines = new String[1]; int start = 0, pos;
--- a/dwt/custom/CTabFolder.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/CTabFolder.d Mon May 12 19:13:01 2008 +0200 @@ -1543,6 +1543,8 @@ style &= ~(DWT.SINGLE | DWT.MULTI); style |= single ? DWT.SINGLE : DWT.MULTI; if (borderLeft !is 0) style |= DWT.BORDER; + style &= ~DWT.CLOSE; + if (showClose) style |= DWT.CLOSE; return style; } /** @@ -1717,20 +1719,26 @@ public void getLocation(AccessibleControlEvent e) { Rectangle location = null; + Point pt = null; int childID = e.childID; if (childID is ACC.CHILDID_SELF) { location = getBounds(); - } else if (childID >= 0 && childID < items.length) { - location = items[childID].getBounds(); - } else if (showChevron && childID is items.length + CHEVRON_CHILD_ID) { - location = chevronRect; - } else if (showMin && childID is items.length + MINIMIZE_CHILD_ID) { - location = minRect; - } else if (showMax && childID is items.length + MAXIMIZE_CHILD_ID) { - location = maxRect; + pt = getParent().toDisplay(location.x, location.y); + } else { + if (childID >= 0 && childID < items.length && items[childID].isShowing()) { + location = items[childID].getBounds(); + } else if (showChevron && childID is items.length + CHEVRON_CHILD_ID) { + location = chevronRect; + } else if (showMin && childID is items.length + MINIMIZE_CHILD_ID) { + location = minRect; + } else if (showMax && childID is items.length + MAXIMIZE_CHILD_ID) { + location = maxRect; + } + if (location !is null) { + pt = toDisplay(location.x, location.y); + } } - if (location !is null) { - Point pt = toDisplay(location.x, location.y); + if (location !is null && pt !is null) { e.x = pt.x; e.y = pt.y; e.width = location.width; @@ -2243,8 +2251,8 @@ CTabFolderListener listener = tabListeners[j]; listener.itemClosed(e); } - if (e.doit) { - item.dispose(); + if (e.doit) item.dispose(); + if (!isDisposed() && item.isDisposed()) { Display display = getDisplay(); Point pt = display.getCursorLocation(); pt = display.map(null, this, pt.x, pt.y); @@ -2782,7 +2790,7 @@ topRight.setBounds(topRightRect); } if (oldX !is topRightRect.x || oldWidth !is topRightRect.width || - oldY !is topRightRect.y || oldHeight !is topRightRect.height) { + oldY !is topRightRect.y || oldHeight !is topRightRect.height) { int left = Math.min(oldX, topRightRect.x); int right = Math.max(oldX + oldWidth, topRightRect.x + topRightRect.width); int top = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1; @@ -3287,22 +3295,25 @@ selection.closeImageState = NORMAL; selection.showing = false; - Control control = selection.control; - if (control !is null && !control.isDisposed()) { - control.setBounds(getClientArea()); - control.setVisible(true); + Control newControl = selection.control; + Control oldControl = null; + if (oldIndex !is -1) { + oldControl = items[oldIndex].control; } - if (oldIndex !is -1) { - control = items[oldIndex].control; - if (control !is null && !control.isDisposed()) { - control.setVisible(false); + if (newControl !is oldControl) { + if (newControl !is null && !newControl.isDisposed()) { + newControl.setBounds(getClientArea()); + newControl.setVisible(true); + } + if (oldControl !is null && !oldControl.isDisposed()) { + oldControl.setVisible(false); } } showItem(selection); redraw(); } -void setSelection(int index, bool notify) { +void setSelection(int index, bool notify) { int oldSelectedIndex = selectedIndex; setSelection(index); if (notify && selectedIndex !is oldSelectedIndex && selectedIndex !is -1) { @@ -4015,7 +4026,7 @@ } bool updateTabHeight(bool force){ int style = getStyle(); - if (fixedTabHeight is 0 && (style & DWT.FLAT) !is 0 && (style & DWT.BORDER) is 0) highlight_header = 0; + if (fixedTabHeight is 0 && (style & DWT.FLAT) !is 0 && (style & DWT.BORDER) is 0) highlight_header = 0; int oldHeight = tabHeight; if (fixedTabHeight !is DWT.DEFAULT) { tabHeight = fixedTabHeight is 0 ? 0 : fixedTabHeight + 1; // +1 for line drawn across top of tab
--- a/dwt/custom/CTabItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/CTabItem.d Mon May 12 19:13:01 2008 +0200 @@ -25,6 +25,7 @@ import dwt.graphics.Point; import dwt.graphics.RGB; import dwt.graphics.Rectangle; +import dwt.graphics.TextLayout; import dwt.widgets.Control; import dwt.widgets.Display; import dwt.widgets.Item; @@ -135,13 +136,10 @@ */ public this (CTabFolder parent, int style, int index) { closeRect = new Rectangle(0, 0, 0, 0); - super (parent, checkStyle(style)); + super (parent, style); showClose = (style & DWT.CLOSE) !is 0; parent.createItem (this, index); } -static int checkStyle(int style) { - return DWT.NONE; -} /* * Return whether to use ellipses or just truncate labels @@ -160,16 +158,19 @@ if (gc.textExtent(text, FLAGS).x <= width) return text; int ellipseWidth = gc.textExtent(ellipses, FLAGS).x; int length = text.length; - int end = length - 1; + TextLayout layout = new TextLayout(getDisplay()); + layout.setText(text); + int end = layout.getPreviousOffset(length, DWT.MOVEMENT_CLUSTER); while (end > 0) { text = text[ 0 .. end ]; int l = gc.textExtent(text, FLAGS).x; if (l + ellipseWidth <= width) { - return text ~ ellipses; + break; } - end--; + end = layout.getPreviousOffset(end, DWT.MOVEMENT_CLUSTER); } - return text[ 0 .. 1 ]; + layout.dispose(); + return end is 0 ? text.substring(0, 1) : text ~ ellipses; } public override void dispose() { @@ -768,6 +769,24 @@ return parent; } /** + * Returns <code>true</code> to indicate that the receiver's close button should be shown. + * Otherwise return <code>false</code>. The initial value is defined by the style (DWT.CLOSE) + * that was used to create the receiver. + * + * @return <code>true</code> if the close button should be shown + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public bool getShowClose() { + checkWidget(); + return showClose; +} +/** * Returns the receiver's tool tip text, or null if it has * not been set. * @@ -998,6 +1017,27 @@ parent.redrawTabs(); } } +/** + * Sets to <code>true</code> to indicate that the receiver's close button should be shown. + * If the parent (CTabFolder) was created with DWT.CLOSE style, changing this value has + * no effect. + * + * @param close the new state of the close button + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public void setShowClose(bool close) { + checkWidget(); + if (showClose is close) return; + showClose = close; + parent.updateItems(); + parent.redrawTabs(); +} public override void setText (String string) { checkWidget(); if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); @@ -1025,4 +1065,5 @@ checkWidget(); toolTipText = string; } + }
--- a/dwt/custom/LineBackgroundEvent.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/LineBackgroundEvent.d Mon May 12 19:13:01 2008 +0200 @@ -45,6 +45,7 @@ super(cast(Object)e); lineOffset = e.detail; lineText = e.text; + lineBackground = e.lineBackground; } }
--- a/dwt/custom/LineStyleEvent.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/LineStyleEvent.d Mon May 12 19:13:01 2008 +0200 @@ -89,6 +89,8 @@ public this(StyledTextEvent e) { super(cast(Object)e); + styles = e.styles; + ranges = e.ranges; lineOffset = e.detail; lineText = e.text; alignment = e.alignment;
--- a/dwt/custom/SashForm.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/SashForm.d Mon May 12 19:13:01 2008 +0200 @@ -111,6 +111,23 @@ //checkWidget(); return (sashStyle & DWT.VERTICAL) !is 0 ? DWT.HORIZONTAL : DWT.VERTICAL; } +/** + * Returns the width of the sashes when the controls in the SashForm are + * laid out. + * + * @return the width of the sashes + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public int getSashWidth() { + checkWidget(); + return SASH_WIDTH; +} public override int getStyle() { int style = super.getStyle(); style |= getOrientation() is DWT.VERTICAL ? DWT.VERTICAL : DWT.HORIZONTAL; @@ -360,6 +377,25 @@ } /** + * Specify the width of the sashes when the controls in the SashForm are + * laid out. + * + * @param width the width of the sashes + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public void setSashWidth(int width) { + checkWidget(); + if (SASH_WIDTH is width) return; + SASH_WIDTH = width; + layout(false); +} +/** * Specify the relative weight of each child in the SashForm. This will determine * what percent of the total width (if SashForm has Horizontal orientation) or * total height (if SashForm has Vertical orientation) each control will occupy.
--- a/dwt/custom/ScrolledComposite.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/ScrolledComposite.d Mon May 12 19:13:01 2008 +0200 @@ -17,14 +17,18 @@ import dwt.DWT; import dwt.DWTException; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.widgets.Composite; import dwt.widgets.Control; +import dwt.widgets.Display; import dwt.widgets.Event; import dwt.widgets.Layout; import dwt.widgets.Listener; import dwt.widgets.ScrollBar; +import dwt.widgets.Shell; import dwt.custom.ScrolledCompositeLayout; /** @@ -114,12 +118,14 @@ Control content; Listener contentListener; + Listener filter; int minHeight = 0; int minWidth = 0; bool expandHorizontal = false; bool expandVertical = false; bool alwaysShowScroll = false; + bool showFocusedControl = false; /** * Constructs a new instance of this class given its parent @@ -177,6 +183,20 @@ layout(false); } }; + + filter = new class() Listener { + public void handleEvent(Event event) { + if (auto control = cast(Control)event.widget ) { + if (contains(control)) showControl(control); + } + } + }; + + addDisposeListener(new class() DisposeListener { + public void widgetDisposed(DisposeEvent e) { + getDisplay().removeFilter(DWT.FocusIn, filter); + } + }); } static int checkStyle (int style) { @@ -184,6 +204,17 @@ return style & mask; } +bool contains(Control control) { + if (control is null || control.isDisposed()) return false; + + Composite parent = control.getParent(); + while (parent !is null && !( null !is cast(Shell)parent )) { + if (this is parent) return true; + parent = parent.getParent(); + } + return false; +} + /** * Returns the Always Show Scrollbars flag. True if the scrollbars are * always shown even if they are not required. False if the scrollbars are only @@ -278,6 +309,22 @@ return content; } +/** + * Returns <code>true</code> if the receiver automatically scrolls to a focused child control + * to make it visible. Otherwise, returns <code>false</code>. + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public bool getShowFocusedControl() { + checkWidget(); + return showFocusedControl; +} + void hScroll() { if (content is null) return; Point location = content.getLocation (); @@ -587,6 +634,66 @@ setMinSize(width, minHeight); } +/** + * Configure the receiver to automatically scroll to a focused child control + * to make it visible. + * + * If show is <code>false</code>, show a focused control is off. + * By default, show a focused control is off. + * + * @param show <code>true</code> to show a focused control. + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public void setShowFocusedControl(bool show) { + checkWidget(); + if (showFocusedControl is show) return; + Display display = getDisplay(); + display.removeFilter(DWT.FocusIn, filter); + showFocusedControl = show; + if (!showFocusedControl) return; + display.addFilter(DWT.FocusIn, filter); + Control control = display.getFocusControl(); + if (contains(control)) showControl(control); +} + +/** + * Scrolls the content of the receiver so that the control is visible. + * + * @param control the control to be shown + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the control is null</li> + * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public void showControl(Control control) { + checkWidget (); + if (control is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + if (control.isDisposed ()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + if (!contains(control)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + + Rectangle itemRect = getDisplay().map(control.getParent(), this, control.getBounds()); + Rectangle area = getClientArea(); + Point origin = getOrigin(); + if (itemRect.x < 0) origin.x = Math.max(0, origin.x + itemRect.x); + if (itemRect.y < 0) origin.y = Math.max(0, origin.y + itemRect.y); + if (area.width < itemRect.x + itemRect.width) origin.x = Math.max(0, origin.x + itemRect.x + itemRect.width - area.width); + if (area.height < itemRect.y + itemRect.height) origin.y = Math.max(0, origin.y + itemRect.y + itemRect.height - area.height); + setOrigin(origin); +} + void vScroll() { if (content is null) return; Point location = content.getLocation ();
--- a/dwt/custom/StyleRange.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/StyleRange.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 @@ -47,6 +47,13 @@ */ public int fontStyle = DWT.NORMAL; +/** + * Create a new style range with no styles + * + * @since 3.2 + */ +public this() { +} /++ + DWT extension for clone implementation +/ @@ -58,12 +65,14 @@ } /** - * Create a new style range with no styles + * Create a new style range from an existing text style. + * + *@param style the text style to copy * - * @since 3.2 + *@since 3.4 */ -public this() { - super(null, null, null); +public this(TextStyle style) { + super(style); } /** @@ -145,6 +154,7 @@ if (fontStyle !is DWT.NORMAL) return false; if (underline) return false; if (strikeout) return false; + if (borderStyle !is DWT.NONE) return false; return true; }
--- a/dwt/custom/StyledText.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/StyledText.d Mon May 12 19:13:01 2008 +0200 @@ -56,6 +56,7 @@ import dwt.widgets.Control; import dwt.widgets.Display; import dwt.widgets.Event; +import dwt.widgets.IME; import dwt.widgets.Label; import dwt.widgets.Listener; import dwt.widgets.ScrollBar; @@ -195,8 +196,8 @@ Point doubleClickSelection; // selection after last mouse double click bool editable = true; bool wordWrap = false; - bool doubleClickEnabled = true; // see getDoubleClickEnabled - bool overwrite = false; // insert/overwrite edit mode + bool doubleClickEnabled = true; // see getDoubleClickEnabled + bool overwrite = false; // insert/overwrite edit mode int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default. int[int] keyActionMap; Color background = null; // workaround for bug 4791 @@ -212,14 +213,16 @@ int lastTextChangeReplaceCharCount; int lastLineBottom; // the bottom pixel of the last line been replaced bool isMirrored_; - bool bidiColoring = false; // apply the BIDI algorithm on text segments of the same color + bool bidiColoring = false; // apply the BIDI algorithm on text segments of the same color Image leftCaretBitmap = null; Image rightCaretBitmap = null; int caretDirection = DWT.NULL; + int caretWidth = 0; Caret defaultCaret = null; bool updateCaretDirection = true; bool fixedLineHeight; bool dragDetect_ = true; + IME ime; int alignment; bool justify; @@ -259,9 +262,9 @@ int endPage; // last page to print int startLine; // first (wrapped) line to print int endLine; // last (wrapped) line to print - bool singleLine; // widget single line mode + bool singleLine; // widget single line mode Point selection = null; // selected text - bool mirrored; // indicates the printing gc should be mirrored + bool mirrored; // indicates the printing gc should be mirrored int lineSpacing; int printMargin; @@ -525,11 +528,24 @@ printLayout.setFont(printerFont); } if (printOptions.printLineNumbers) { + int numberingWidth = 0; int count = endLine - startLine + 1; - StringBuffer buffer = new StringBuffer("0"); - while ((count /= 10) > 0) buffer.append("0"); - printLayout.setText(buffer.toString()); - int numberingWidth = printLayout.getBounds().width + printMargin; + String[] lineLabels = printOptions.lineLabels; + if (lineLabels !is null) { + for (int i = startLine; i < Math.min(count, lineLabels.length); i++) { + if (lineLabels[i] !is null) { + printLayout.setText(lineLabels[i]); + int lineWidth = printLayout.getBounds().width; + numberingWidth = Math.max(numberingWidth, lineWidth); + } + } + } else { + StringBuffer buffer = new StringBuffer("0"); + while ((count /= 10) > 0) buffer.append("0"); + printLayout.setText(buffer.toString()); + numberingWidth = printLayout.getBounds().width; + } + numberingWidth += printMargin; if (numberingWidth > width) numberingWidth = width; paintX += numberingWidth; width -= numberingWidth; @@ -567,8 +583,9 @@ } else { //draw paragraph top in the current page and paragraph bottom in the next int height = paragraphBottom - paintY; - gc.setClipping(paintX, paintY, width, height); + gc.setClipping(clientArea.x, paintY, clientArea.width, height); printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); + gc.setClipping(cast(Rectangle)null); printDecoration(page, false, printLayout); printer.endPage(); page++; @@ -577,16 +594,16 @@ printDecoration(page, true, printLayout); paintY = clientArea.y - height; int layoutHeight = layout.getBounds().height; - gc.setClipping(paintX, clientArea.y, width, layoutHeight - height); + gc.setClipping(clientArea.x, clientArea.y, clientArea.width, layoutHeight - height); printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); + gc.setClipping(cast(Rectangle)null); paintY += layoutHeight; } - gc.setClipping(cast(Rectangle)null); } } printerRenderer.disposeTextLayout(layout); } - if (paintY > clientArea.y) { + if (page <= endPage && paintY > clientArea.y) { // close partial page printDecoration(page, false, printLayout); printer.endPage(); @@ -673,9 +690,18 @@ } if (printOptions.printLineNumbers) { FontMetrics metrics = layout.getLineMetrics(0); - printLayout.setAscent(metrics.getAscent() + metrics.getDescent()); + printLayout.setAscent(metrics.getAscent() + metrics.getLeading()); printLayout.setDescent(metrics.getDescent()); - printLayout.setText( to!(String)(index) ); + String[] lineLabels = printOptions.lineLabels; + if (lineLabels !is null) { + if (0 <= index && index < lineLabels.length && lineLabels[index] !is null) { + printLayout.setText(lineLabels[index]); + } else { + printLayout.setText(""); + } + } else { + printLayout.setText(to!(String)(index)); + } int paintX = x - printMargin - printLayout.getBounds().width; printLayout.draw(gc, paintX, y); printLayout.setAscent(-1); @@ -1311,7 +1337,8 @@ renderer = new StyledTextRenderer(getDisplay(), this); renderer.setContent(content); renderer.setFont(getFont(), tabLength); - defaultCaret = new Caret(this, DWT.NULL); + ime = new IME(this, DWT.NONE); + defaultCaret = new Caret(this, DWT.NONE); if ((style & DWT.WRAP) !is 0) { setWordWrap(true); } @@ -1326,7 +1353,7 @@ setCaretLocation(newCaretPos, direction); } }; - BidiUtil.addLanguageListener(handle, runnable); + BidiUtil.addLanguageListener(this, runnable); } setCaret(defaultCaret); calculateScrollBars(); @@ -1750,10 +1777,12 @@ int maxHeight = display.getClientArea().height; for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) { TextLayout layout = renderer.getTextLayout(lineIndex); + int wrapWidth = layout.getWidth(); if (wordWrap) layout.setWidth(wHint is 0 ? 1 : wHint); Rectangle rect = layout.getBounds(); height += rect.height; width = Math.max(width, rect.width); + layout.setWidth(wrapWidth); renderer.disposeTextLayout(layout); if (isFixedLineHeight() && height > maxHeight) break; } @@ -1940,8 +1969,8 @@ if (event.button !is 1) return false; } if (selection.x is selection.y) return false; - int offset = getOffsetAtPoint(event.x, event.y); - if (offset > selection.x && offset < selection.y) { + int offset = getOffsetAtPoint(event.x, event.y, null, true); + if (selection.x <= offset && offset < selection.y) { return dragDetect(event); } return false; @@ -2233,10 +2262,6 @@ * @param key the character typed by the user */ void doContent(dchar key) { - if (textLimit > 0 && - content.getCharCount() - (selection.y - selection.x) >= textLimit) { - return; - } Event event = new Event(); event.start = selection.x; event.end = selection.y; @@ -2263,6 +2288,9 @@ event.text = dcharToString( key ); } if (event.text !is null) { + if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) { + return; + } sendKeyEvent(event); } } @@ -2527,8 +2555,7 @@ int oldCaretAlignment = caretAlignment; int newCaretOffset = getOffsetAtPoint(x, y); - if (clickCount > 1) { - // double click word select the previous/next word. fixes bug 15610 + if (doubleClickEnabled && clickCount > 1) { newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); } @@ -3244,21 +3271,27 @@ } Rectangle getBoundsAtOffset(int offset) { int lineIndex = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(lineIndex); String line = content.getLine(lineIndex); Rectangle bounds; if (line.length !is 0) { - int offsetInLine = offset - content.getOffsetAtLine(lineIndex); + int offsetInLine = offset - lineOffset; TextLayout layout = renderer.getTextLayout(lineIndex); bounds = layout.getBounds(offsetInLine, offsetInLine); renderer.disposeTextLayout(layout); } else { bounds = new Rectangle (0, 0, 0, renderer.getLineHeight()); } + if (offset is caretOffset) { + int lineEnd = lineOffset + line.length; + if (offset is lineEnd && caretAlignment is PREVIOUS_OFFSET_TRAILING) { + bounds.width += getCaretWidth(); + } + } bounds.x += leftMargin - horizontalScrollOffset; bounds.y += getLinePixel(lineIndex); return bounds; } - /** * Returns the caret position relative to the start of the text. * @@ -3305,11 +3338,11 @@ return offset; } /** - * Returns the content implementation that is used for text storage - * or null if no user defined content implementation has been set. - * - * @return content implementation that is used for text storage or null - * if no user defined content implementation has been set. + * Returns the content implementation that is used for text storage. + * + * @return content the user defined content implementation that is used for + * text storage or the default content implementation if no user defined + * content implementation has been set. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -3466,6 +3499,32 @@ return content.getCharCount(); } /** + * Returns the line at the given line index without delimiters. + * Index 0 is the first line of the content. When there are not + * any lines, getLine(0) is a valid call that answers an empty string. + * <p> + * + * @param lineIndex index of the line to return. + * @return the line text without delimiters + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> + * </ul> + * @since 3.4 + */ +public String getLine(int lineIndex) { + checkWidget(); + if (lineIndex < 0 || + (lineIndex > 0 && lineIndex >= content.getLineCount())) { + DWT.error(DWT.ERROR_INVALID_RANGE); + } + return content.getLine(lineIndex); +} +/** * Returns the alignment of the line at the given index. * * @param index the index of the line @@ -3857,7 +3916,7 @@ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @exception IllegalArgumentException <ul> - * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> + * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> * </ul> * @since 2.0 */ @@ -3897,32 +3956,12 @@ if (point is null) { DWT.error(DWT.ERROR_NULL_ARGUMENT); } - // is y above first line or is x before first column? - if (point.y + getVerticalScrollOffset() < 0 || point.x + horizontalScrollOffset < 0) { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - int bottomIndex = getLineIndex(clientAreaHeight); - int height = getLinePixel(bottomIndex) + renderer.getLineHeight(bottomIndex); - if (point.y > height) { + int[] trailing = new int[1]; + int offset = getOffsetAtPoint(point.x, point.y, trailing, true); + if (offset is -1) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); } - int lineIndex = getLineIndex(point.y); - int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); - int[] trailing = new int[1]; - int x = point.x + horizontalScrollOffset - leftMargin ; - int y = point.y - getLinePixel(lineIndex); - int offsetInLine = layout.getOffset(x, y, trailing); - String line = content.getLine(lineIndex); - if (offsetInLine !is line.length - 1) { - offsetInLine = Math.min(line.length, offsetInLine + trailing[0]); - } - Rectangle rect = layout.getLineBounds(layout.getLineIndex(offsetInLine)); - renderer.disposeTextLayout(layout); - if (x > rect.x + rect.width) { - DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } - return lineOffset + offsetInLine; + return offset + trailing[0]; } int getOffsetAtPoint(int x, int y) { int lineIndex = getLineIndex(y); @@ -3945,7 +3984,6 @@ caretAlignment = OFFSET_LEADING; if (trailing[0] !is 0) { int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]); - //TODO handle bidi text int lineStart = layout.getLineOffsets()[lineInParagraph]; if (offsetInLine + trailing[0] is lineStart) { offsetInLine += trailing[0]; @@ -3972,6 +4010,28 @@ renderer.disposeTextLayout(layout); return offsetInLine + content.getOffsetAtLine(lineIndex); } +int getOffsetAtPoint(int x, int y, int[] trailing, bool inTextOnly) { + if (inTextOnly && y + getVerticalScrollOffset() < 0 || x + horizontalScrollOffset < 0) { + return -1; + } + int bottomIndex = getPartialBottomIndex(); + int height = getLinePixel(bottomIndex + 1); + if (inTextOnly && y > height) { + return -1; + } + int lineIndex = getLineIndex(y); + int lineOffset = content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + x += horizontalScrollOffset - leftMargin ; + y -= getLinePixel(lineIndex); + int offset = layout.getOffset(x, y, trailing); + Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset)); + renderer.disposeTextLayout(layout); + if (inTextOnly && !(rect.x <= x && x <= rect.x + rect.width)) { + return -1; + } + return offset + lineOffset; +} /** * Returns the orientation of the receiver. * @@ -3997,7 +4057,7 @@ if (isFixedLineHeight()) { int lineHeight = renderer.getLineHeight(); int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight); - return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1; + return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1); } return getLineIndex(clientAreaHeight - bottomMargin); } @@ -4594,12 +4654,15 @@ for (int i = lineStart; i <= lineEnd; i++) { int lineOffset = content.getOffsetAtLine(i); TextLayout layout = renderer.getTextLayout(i); - if (layout.getText().length > 0) { - if (i is lineStart && i is lineEnd) { - rect = layout.getBounds(start - lineOffset, end - lineOffset); - } else if (i is lineStart) { - String line = content.getLine(i); - rect = layout.getBounds(start - lineOffset, line.length); + int length = layout.getText().length; + if (length > 0) { + if (i is lineStart) { + if (i is lineEnd) { + rect = layout.getBounds(start - lineOffset, end - lineOffset); + } else { + rect = layout.getBounds(start - lineOffset, length); + } + y += rect.y; } else if (i is lineEnd) { rect = layout.getBounds(0, end - lineOffset); } else { @@ -4724,6 +4787,7 @@ } int getCaretDirection() { if (!isBidiCaret()) return DWT.DEFAULT; + if (ime.getCompositionOffset() !is -1) return DWT.DEFAULT; if (!updateCaretDirection && caretDirection !is DWT.NULL) return caretDirection; updateCaretDirection = false; int caretLine = getCaretLine(); @@ -4751,7 +4815,7 @@ } int getWrapWidth () { if (wordWrap && !isSingleLine()) { - int width = clientAreaWidth - leftMargin - rightMargin; + int width = clientAreaWidth - leftMargin - rightMargin - getCaretWidth(); return width > 0 ? width : 1; } return -1; @@ -4932,6 +4996,15 @@ addListener(DWT.Paint, listener); addListener(DWT.Resize, listener); addListener(DWT.Traverse, listener); + ime.addListener(DWT.ImeComposition, new class() Listener { + public void handleEvent(Event event) { + switch (event.detail) { + case DWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break; + case DWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break; + case DWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break; + } + } + }); if (verticalBar !is null) { verticalBar.addListener(DWT.Selection, new class() Listener { public void handleEvent(Event event) { @@ -5035,6 +5108,39 @@ super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false); } } +void handleCompositionOffset (Event event) { + int[] trailing = new int [1]; + event.index = getOffsetAtPoint(event.x, event.y, trailing, true); + event.count = trailing[0]; +} +void handleCompositionSelection (Event event) { + event.start = selection.x; + event.end = selection.y; + event.text = getSelectionText(); +} +void handleCompositionChanged(Event event) { + String text = event.text; + int start = event.start; + int end = event.end; + int length = text.length; + if (length is ime.getCommitCount()) { + content.replaceTextRange(start, end - start, ""); + caretOffset = start; + caretWidth = 0; + caretDirection = DWT.NULL; + } else { + content.replaceTextRange(start, end - start, text); + caretOffset = ime.getCaretOffset(); + if (ime.getWideCaret()) { + int lineIndex = getCaretLine(); + int lineOffset = content.getOffsetAtLine(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); + caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width; + renderer.disposeTextLayout(layout); + } + } + showCaret(); +} /** * Frees resources. */ @@ -5065,7 +5171,7 @@ rightCaretBitmap = null; } if (isBidiCaret()) { - BidiUtil.removeLanguageListener(handle); + BidiUtil.removeLanguageListener(this); } selectionBackground = null; selectionForeground = null; @@ -5247,8 +5353,8 @@ start = lineOffset; end = lineEnd; } - selection.x = selection.y = start; - selectionAnchor = -1; + caretOffset = start; + resetSelection(); caretOffset = end; showCaret(); doMouseSelection(); @@ -5393,6 +5499,10 @@ * the content change. */ void handleTextChanged(TextChangedEvent event) { + int offset = ime.getCompositionOffset(); + if (offset !is -1 && lastTextChangeStart < offset) { + ime.setCompositionOffset(offset + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount); + } int firstLine = content.getLineAtOffset(lastTextChangeStart); resetCache(firstLine, 0); if (!isFixedLineHeight() && topIndex > firstLine) { @@ -5783,7 +5893,7 @@ * Temporary until DWT provides this */ bool isBidi() { - return IS_GTK || BidiUtil.isBidiPlatform() || isMirrored_; + return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored_; } bool isBidiCaret() { return BidiUtil.isBidiPlatform(); @@ -6510,9 +6620,7 @@ } } horizontalScrollOffset += pixels; - int oldColumnX = columnX; setCaretLocation(); - columnX = oldColumnX; return true; } /** @@ -6565,9 +6673,7 @@ calculateTopIndex(pixels); super.redraw(); } - int oldColumnX = columnX; setCaretLocation(); - columnX = oldColumnX; return true; } void scrollText(int srcY, int destY) { @@ -6702,6 +6808,10 @@ /** * Sets the alignment of the widget. The argument should be one of <code>DWT.LEFT</code>, * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. The alignment applies for all lines. + * </p><p> + * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set + * in order to stabilize the right edge before setting alignment. + * </p> * * @param alignment the new alignment * @@ -6729,6 +6839,7 @@ public override void setBackground(Color color) { checkWidget(); background = color; + super.setBackground(color); super.redraw(); } /** @@ -6798,7 +6909,7 @@ location.x -= (caret.getSize().x - 1); } if (isDefaultCaret) { - caret.setBounds(location.x, location.y, 0, caretHeight); + caret.setBounds(location.x, location.y, caretWidth, caretHeight); } else { caret.setLocation(location); } @@ -6852,6 +6963,7 @@ } caretOffset = offset; } + caretAlignment = PREVIOUS_OFFSET_TRAILING; // clear the selection if the caret is moved. // don't notify listeners about the selection change. clearSelection(false); @@ -7181,7 +7293,10 @@ /** * Sets the alignment of the specified lines. The argument should be one of <code>DWT.LEFT</code>, * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. - * <p> + * <p><p> + * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set + * in order to stabilize the right edge before setting alignment. + * </p> * Should not be called if a LineStyleListener has been set since the listener * maintains the line attributes. * </p><p> @@ -7487,7 +7602,7 @@ if ((orientation & DWT.LEFT_TO_RIGHT) !is 0 && !isMirrored()) { return; } - if (!BidiUtil.setOrientation(handle, orientation)) { + if (!BidiUtil.setOrientation(this, orientation)) { return; } isMirrored_ = (orientation & DWT.RIGHT_TO_LEFT) !is 0; @@ -7705,6 +7820,7 @@ selectionAnchor = selection.x = start; caretOffset = selection.y = end; } + caretAlignment = PREVIOUS_OFFSET_TRAILING; internalRedrawRange(selection.x, selection.y - selection.x); } } @@ -8004,12 +8120,8 @@ checkWidget(); tabLength = tabs; renderer.setFont(null, tabs); - if (caretOffset > 0) { - caretOffset = 0; - showCaret(); - clearSelection(false); - } resetCache(0, content.getLineCount()); + setCaretLocation(); super.redraw(); } /**
--- a/dwt/custom/StyledTextDropTargetEffect.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/StyledTextDropTargetEffect.d Mon May 12 19:13:01 2008 +0200 @@ -18,6 +18,8 @@ import dwt.dnd.DropTargetAdapter; import dwt.dnd.DropTargetEffect; import dwt.dnd.DropTargetEvent; +import dwt.graphics.FontMetrics; +import dwt.graphics.GC; import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.widgets.Event; @@ -30,7 +32,7 @@ /** * This adapter class provides a default drag under effect (eg. select and scroll) - * when a drag occurs over a <code>Table</code>. + * when a drag occurs over a <code>StyledText</code>. * * <p>Classes that wish to provide their own drag under effect for a <code>StyledText</code> * can extend this class, override the <code>StyledTextDropTargetEffect.dragOver</code> @@ -171,37 +173,27 @@ pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) { if (System.currentTimeMillis() >= scrollBeginTime) { Rectangle area = text.getClientArea(); - Rectangle bounds = text.getTextBounds(0, 0); - int charWidth = bounds.width; + GC gc = new GC(text); + FontMetrics fm = gc.getFontMetrics(); + gc.dispose(); + int charWidth = fm.getAverageCharWidth(); int scrollAmount = 10*charWidth; if (pt.x < area.x + 3*charWidth) { int leftPixel = text.getHorizontalPixel(); text.setHorizontalPixel(leftPixel - scrollAmount); - if (text.getHorizontalPixel() !is leftPixel) { - text.redraw(); - } } if (pt.x > area.width - 3*charWidth) { int leftPixel = text.getHorizontalPixel(); text.setHorizontalPixel(leftPixel + scrollAmount); - if (text.getHorizontalPixel() !is leftPixel) { - text.redraw(); - } } - int lineHeight = bounds.height; + int lineHeight = text.getLineHeight(); if (pt.y < area.y + lineHeight) { int topPixel = text.getTopPixel(); text.setTopPixel(topPixel - lineHeight); - if (text.getTopPixel() !is topPixel) { - text.redraw(); - } } if (pt.y > area.height - lineHeight) { int topPixel = text.getTopPixel(); text.setTopPixel(topPixel + lineHeight); - if (text.getTopPixel() !is topPixel) { - text.redraw(); - } } scrollBeginTime = 0; scrollX = scrollY = -1; @@ -215,53 +207,10 @@ } if ((effect & DND.FEEDBACK_SELECT) !is 0) { - StyledTextContent content = text.getContent(); - int newOffset = -1; - try { - newOffset = text.getOffsetAtLocation(pt); - } catch ( tango.core.Exception.IllegalArgumentException ex1) { - int maxOffset = content.getCharCount(); - Point maxLocation = text.getLocationAtOffset(maxOffset); - if (pt.y >= maxLocation.y) { - try { - newOffset = text.getOffsetAtLocation(new Point(pt.x, maxLocation.y)); - } catch (tango.core.Exception.IllegalArgumentException ex2) { - newOffset = maxOffset; - } - } else { - try { - int startOffset = text.getOffsetAtLocation(new Point(0, pt.y)); - int endOffset = maxOffset; - int line = content.getLineAtOffset(startOffset); - int lineCount = content.getLineCount(); - if (line + 1 < lineCount) { - endOffset = content.getOffsetAtLine(line + 1) - 1; - } - int lineHeight = text.getLineHeight(startOffset); - for (int i = endOffset; i >= startOffset; i--) { - Point p = text.getLocationAtOffset(i); - if (p.x < pt.x && p.y < pt.y && p.y + lineHeight > pt.y) { - newOffset = i; - break; - } - } - } catch (tango.core.Exception.IllegalArgumentException ex2) { - newOffset = -1; - } - } - } - if (newOffset !is -1 && newOffset !is currentOffset) { - // check if offset is line delimiter - // see StyledText.isLineDelimiter() - int line = content.getLineAtOffset(newOffset); - int lineOffset = content.getOffsetAtLine(line); - int offsetInLine = newOffset - lineOffset; - // offsetInLine will be greater than line length if the line - // delimiter is longer than one character and the offset is set - // in between parts of the line delimiter. - if (offsetInLine > content.getLine(line).length) { - newOffset = Math.max(0, newOffset - 1); - } + int[] trailing = new int [1]; + int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false); + newOffset += trailing [0]; + if (newOffset !is currentOffset) { refreshCaret(text, currentOffset, newOffset); currentOffset = newOffset; }
--- a/dwt/custom/StyledTextPrintOptions.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/StyledTextPrintOptions.d Mon May 12 19:13:01 2008 +0200 @@ -95,5 +95,11 @@ */ public bool printLineNumbers = false; + /** + * Labels used for printing line numbers. + * + * @since 3.4 + */ + public String[] lineLabels = null; }
--- a/dwt/custom/StyledTextRenderer.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/StyledTextRenderer.d Mon May 12 19:13:01 2008 +0200 @@ -27,6 +27,7 @@ import dwt.graphics.TextLayout; import dwt.graphics.TextStyle; import dwt.widgets.Display; +import dwt.widgets.IME; import dwt.widgets.ScrollBar; import dwt.custom.StyledText; import dwt.custom.Bullet; @@ -391,16 +392,19 @@ int selectionStart = selection.x - lineOffset; int selectionEnd = selection.y - lineOffset; Rectangle client = styledText.getClientArea(); - Color lineBackground = getLineBackground(lineIndex, widgetBackground); + Color lineBackground = getLineBackground(lineIndex, null); StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line); if (event !is null && event.lineBackground !is null) lineBackground = event.lineBackground; int height = layout.getBounds().height; - gc.setBackground(lineBackground); - styledText.drawBackground(gc, client.x, paintY, client.width, height); - + if (lineBackground !is null) { + gc.setBackground(lineBackground); + gc.fillRectangle(client.x, paintY, client.width, height); + } else { + gc.setBackground(widgetBackground); + styledText.drawBackground(gc, client.x, paintY, client.width, height); + } gc.setForeground(widgetForeground); - gc.setBackground(lineBackground); if (selectionStart is selectionEnd || (selectionEnd <= 0 && selectionStart > lineLength - 1)) { layout.draw(gc, paintX, paintY); } else { @@ -663,8 +667,14 @@ } style = newStyles[newStyles.length - 1]; if (end < style.start + style.length - 1) { - if (!includeRanges || ranges is null) newStyles[newStyles.length - 1] = style = cast(StyleRange)style.clone(); - style.length = end - style.start + 1; + if (end < style.start) { + StyleRange[] tmp = new StyleRange[newStyles.length - 1]; + System.arraycopy(newStyles, 0, tmp, 0, newStyles.length - 1); + newStyles = tmp; + } else { + if (!includeRanges || ranges is null) newStyles[newStyles.length - 1] = style = cast(StyleRange)style.clone(); + style.length = end - style.start + 1; + } } return newStyles; } @@ -868,6 +878,58 @@ } } if (lastOffset < length) layout.setStyle(null, lastOffset, length); + if (styledText !is null && styledText.ime !is null) { + IME ime = styledText.ime; + int compositionOffset = ime.getCompositionOffset(); + if (compositionOffset !is -1) { + int commitCount = ime.getCommitCount(); + int compositionLength = ime.getText().length; + if (compositionLength !is commitCount) { + int compositionLine = content.getLineAtOffset(compositionOffset); + if (compositionLine is lineIndex) { + int[] imeRanges = ime.getRanges(); + TextStyle[] imeStyles = ime.getStyles(); + if (imeRanges.length > 0) { + for (int i = 0; i < imeStyles.length; i++) { + int start = imeRanges[i*2] - lineOffset; + int end = imeRanges[i*2+1] - lineOffset; + TextStyle imeStyle = imeStyles[i], userStyle; + for (int j = start; j <= end; j++) { + userStyle = layout.getStyle(j); + if (userStyle is null && j > 0) userStyle = layout.getStyle(j - 1); + if (userStyle is null && j + 1 < length) userStyle = layout.getStyle(j + 1); + if (userStyle is null) { + layout.setStyle(imeStyle, j, j); + } else { + TextStyle newStyle = new TextStyle(imeStyle); + if (newStyle.font is null) newStyle.font = userStyle.font; + if (newStyle.foreground is null) newStyle.foreground = userStyle.foreground; + if (newStyle.background is null) newStyle.background = userStyle.background; + layout.setStyle(newStyle, j, j); + } + } + } + } else { + int start = compositionOffset - lineOffset; + int end = start + compositionLength - 1; + TextStyle userStyle = layout.getStyle(start); + if (userStyle is null) { + if (start > 0) userStyle = layout.getStyle(start - 1); + if (userStyle is null && end + 1 < length) userStyle = layout.getStyle(end + 1); + if (userStyle !is null) { + TextStyle newStyle = new TextStyle(); + newStyle.font = userStyle.font; + newStyle.foreground = userStyle.foreground; + newStyle.background = userStyle.background; + layout.setStyle(newStyle, start, end); + } + } + } + } + } + } + } + if (styledText !is null && styledText.isFixedLineHeight()) { int index = -1; int lineCount = layout.getLineCount();
--- a/dwt/custom/TableCursor.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/TableCursor.d Mon May 12 19:13:01 2008 +0200 @@ -161,6 +161,9 @@ TableColumn column = null; Listener tableListener, resizeListener, disposeItemListener, disposeColumnListener; + Color background = null; + Color foreground = null; + // By default, invert the list selection colors static final int BACKGROUND = DWT.COLOR_LIST_SELECTION_TEXT; static final int FOREGROUND = DWT.COLOR_LIST_SELECTION; @@ -254,6 +257,7 @@ disposeItemListener = new class() Listener { public void handleEvent(Event event) { + unhookRowColumnListeners(); row = null; column = null; _resize(); @@ -261,6 +265,7 @@ }; disposeColumnListener = new class() Listener { public void handleEvent(Event event) { + unhookRowColumnListeners(); row = null; column = null; _resize(); @@ -320,16 +325,7 @@ void dispose(Event event) { table.removeListener(DWT.FocusIn, tableListener); table.removeListener(DWT.MouseDown, tableListener); - if (column !is null) { - column.removeListener(DWT.Dispose, disposeColumnListener); - column.removeListener(DWT.Move, resizeListener); - column.removeListener(DWT.Resize, resizeListener); - column = null; - } - if (row !is null) { - row.removeListener(DWT.Dispose, disposeItemListener); - row = null; - } + unhookRowColumnListeners(); ScrollBar hBar = table.getHorizontalBar(); if (hBar !is null) { hBar.removeListener(DWT.Selection, resizeListener); @@ -493,10 +489,11 @@ } void tableFocusIn(Event event) { - if (isDisposed()) - return; - if (isVisible()) + if (isDisposed()) return; + if (isVisible()) { + if (row is null && column is null) return; setFocus(); + } } void tableMouseDown(Event event) { @@ -523,7 +520,14 @@ } TableColumn newColumn = null; int columnCount = table.getColumnCount(); - if (columnCount > 0) { + if (columnCount is 0) { + if ((table.getStyle() & DWT.FULL_SELECTION) is 0) { + Rectangle rect = item.getBounds(0); + rect.width += lineWidth; + rect.height += lineWidth; + if (!rect.contains(pt)) return; + } + } else { for (int i = 0; i < columnCount; i++) { Rectangle rect = item.getBounds(i); rect.width += lineWidth; @@ -534,6 +538,7 @@ } } if (newColumn is null) { + if ((table.getStyle() & DWT.FULL_SELECTION) is 0) return; newColumn = table.getColumn(0); } } @@ -639,6 +644,30 @@ return column is null ? 0 : table.indexOf(column); } /** + * Returns the background color that the receiver will use to draw. + * + * @return the receiver's background color + */ +public Color getBackground() { + checkWidget(); + if (background is null) { + return getDisplay().getSystemColor(BACKGROUND); + } + return background; +} +/** + * Returns the foreground color that the receiver will use to draw. + * + * @return the receiver's foreground color + */ +public Color getForeground() { + checkWidget(); + if (foreground is null) { + return getDisplay().getSystemColor(FOREGROUND); + } + return foreground; +} +/** * Returns the row over which the TableCursor is positioned. * * @return the item for the current position @@ -652,14 +681,49 @@ checkWidget(); return row; } +/** + * Sets the receiver's background color to the color specified + * by the argument, or to the default system color for the control + * if the argument is null. + * <p> + * Note: This operation is a hint and may be overridden by the platform. + * For example, on Windows the background of a Button cannot be changed. + * </p> + * @param color the new color (or null) + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ public override void setBackground (Color color) { - if (color is null) color = getDisplay().getSystemColor(BACKGROUND); - super.setBackground(color); + background = color; + super.setBackground(getBackground()); redraw(); } +/** + * Sets the receiver's foreground color to the color specified + * by the argument, or to the default system color for the control + * if the argument is null. + * <p> + * Note: This operation is a hint and may be overridden by the platform. + * </p> + * @param color the new color (or null) + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ public override void setForeground (Color color) { - if (color is null) color = getDisplay().getSystemColor(FOREGROUND); - super.setForeground(color); + foreground = color; + super.setForeground(getForeground()); redraw(); } /** @@ -708,4 +772,16 @@ DWT.error(DWT.ERROR_INVALID_ARGUMENT); setRowColumn(table.indexOf(row), column, false); } +void unhookRowColumnListeners() { + if (column !is null) { + column.removeListener(DWT.Dispose, disposeColumnListener); + column.removeListener(DWT.Move, resizeListener); + column.removeListener(DWT.Resize, resizeListener); + column = null; + } + if (row !is null) { + row.removeListener(DWT.Dispose, disposeItemListener); + row = null; + } } +}
--- a/dwt/custom/TableTreeItem.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/custom/TableTreeItem.d Mon May 12 19:13:01 2008 +0200 @@ -206,7 +206,7 @@ */ if (parent.sizeImage is null) { int itemHeight = parent.getItemHeight(); - parent.sizeImage = new Image(null, itemHeight, itemHeight); + parent.sizeImage = new Image(parent.getDisplay(), itemHeight, itemHeight); GC gc = new GC (parent.sizeImage); gc.setBackground(parent.getBackground()); gc.fillRectangle(0, 0, itemHeight, itemHeight);
--- a/dwt/dnd/ClipboardProxy.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/ClipboardProxy.d Mon May 12 19:13:01 2008 +0200 @@ -144,7 +144,7 @@ return 1; } -bool setData(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipboards) { +bool setData(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipboards) { GtkTargetEntry*[] entries; GtkTargetEntry* pTargetsList; try {
--- a/dwt/dnd/DND.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/DND.d Mon May 12 19:13:01 2008 +0200 @@ -115,7 +115,7 @@ /** * DropTarget Event: the cursor has left the drop target boundaries OR the drop * operation has been cancelled (such as by hitting ECS) OR the drop is about to - * happen (user has released the mous ebutotn over this target) (value is 2003). + * happen (user has released the mouse button over this target) (value is 2003). */ public static const int DragLeave = 2003; @@ -201,6 +201,25 @@ */ public static const int ERROR_INVALID_DATA = 2003; + /** + * DropTarget Key: The string constant for looking up the drop target + * for a control using <code>getData(String)</code>. When a drop target + * is created for a control, it is stored as a property in the control + * using <code>setData(String, Object)</code>. + * + * @since 3.4 + */ + public static final String DROP_TARGET_KEY = "DropTarget"; //$NON-NLS-1$ + + /** + * DragSource Key: The string constant for looking up the drag source + * for a control using <code>getData(String)</code>. When a drag source + * is created for a control, it is stored as a property in the control + * using <code>setData(String, Object)</code>. + * + * @since 3.4 + */ + public static final String DRAG_SOURCE_KEY = "DragSource"; //$NON-NLS-1$ static const String INIT_DRAG_MESSAGE = "Cannot initialize Drag"; //$NON-NLS-1$ static const String INIT_DROP_MESSAGE = "Cannot initialize Drop"; //$NON-NLS-1$
--- a/dwt/dnd/DragSource.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/DragSource.d Mon May 12 19:13:01 2008 +0200 @@ -130,7 +130,6 @@ bool moveData = false; static const String DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; //$NON-NLS-1$ - static const String DRAGSOURCEID = "DragSource"; //$NON-NLS-1$ // static Callback DragGetData; // static Callback DragEnd; @@ -179,10 +178,10 @@ // if (DragGetData is null || DragEnd is null || DragDataDelete is null) { // DND.error(DND.ERROR_CANNOT_INIT_DRAG); // } - if (control.getData(DRAGSOURCEID) !is null) { + if (control.getData(DND.DRAG_SOURCE_KEY) !is null) { DND.error(DND.ERROR_CANNOT_INIT_DRAG); } - control.setData(DRAGSOURCEID, this); + control.setData(DND.DRAG_SOURCE_KEY, this); OS.g_signal_connect(control.handle, OS.drag_data_get.ptr, cast(GCallback)&DragGetData, null); OS.g_signal_connect(control.handle, OS.drag_end.ptr, cast(GCallback)&DragEnd, null); @@ -267,7 +266,7 @@ if (display is null || display.isDisposed()) return null; Widget widget = display.findWidget(handle); if (widget is null) return null; - return cast(DragSource)widget.getData(DRAGSOURCEID); + return cast(DragSource)widget.getData(DND.DRAG_SOURCE_KEY); } /** @@ -432,6 +431,41 @@ } /** + * Returns an array of listeners who will be notified when a drag and drop + * operation is in progress, by sending it one of the messages defined in + * the <code>DragSourceListener</code> interface. + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see DragSourceListener + * @see #addDragListener + * @see #removeDragListener + * @see DragSourceEvent + * + * @since 3.4 + */ +public DragSourceListener[] getDragListeners() { + Listener[] listeners = getListeners(DND.DragStart); + int length = listeners.length; + DragSourceListener[] dragListeners = new DragSourceListener[length]; + int count = 0; + for (int i = 0; i < length; i++) { + Listener listener = listeners[i]; + if ( auto l = cast(DNDListener)listener ) { + dragListeners[count] = cast(DragSourceListener) (l.getEventListener()); + count++; + } + } + if (count is length) return dragListeners; + DragSourceListener[] result = new DragSourceListener[count]; + SimpleType!(DragSourceListener).arraycopy(dragListeners, 0, result, 0, count); + return result; +} + +/** * Returns the drag effect that is registered for this DragSource. This drag * effect will be used during a drag and drop operation. * @@ -463,7 +497,7 @@ control.removeListener(DWT.DragDetect, controlListener); } controlListener = null; - control.setData(DRAGSOURCEID, null); + control.setData(DND.DRAG_SOURCE_KEY, null); control = null; transferAgents = null; }
--- a/dwt/dnd/DropTarget.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/DropTarget.d Mon May 12 19:13:01 2008 +0200 @@ -19,6 +19,7 @@ import dwt.DWTException; import dwt.graphics.Point; import dwt.internal.gtk.OS; +import dwt.widgets.Combo; import dwt.widgets.Control; import dwt.widgets.Display; import dwt.widgets.Event; @@ -117,7 +118,6 @@ int drag_drop_handler; static const String DEFAULT_DROP_TARGET_EFFECT = "DEFAULT_DROP_TARGET_EFFECT"; //$NON-NLS-1$ - static const String DROPTARGETID = "DropTarget"; //$NON-NLS-1$ static const int DRAGOVER_HYSTERESIS = 50; // static Callback Drag_Motion; @@ -173,10 +173,10 @@ // if (Drag_Motion is null || Drag_Leave is null || Drag_Data_Received is null || Drag_Drop is null) { // DND.error(DND.ERROR_CANNOT_INIT_DROP); // } - if (control.getData(DROPTARGETID) !is null) { + if (control.getData(DND.DROP_TARGET_KEY) !is null) { DND.error(DND.ERROR_CANNOT_INIT_DROP); } - control.setData(DROPTARGETID, this); + control.setData(DND.DROP_TARGET_KEY, this); drag_motion_handler = OS.g_signal_connect(control.handle, OS.drag_motion.ptr, cast(GCallback)&Drag_Motion, null); drag_leave_handler = OS.g_signal_connect(control.handle, OS.drag_leave.ptr, cast(GCallback)&Drag_Leave, null); @@ -321,7 +321,7 @@ if (display is null || display.isDisposed()) return null; Widget widget = display.findWidget(handle); if (widget is null) return null; - return cast(DropTarget)widget.getData(DROPTARGETID); + return cast(DropTarget)widget.getData(DND.DROP_TARGET_KEY); } /** @@ -579,6 +579,41 @@ } /** + * Returns an array of listeners who will be notified when a drag and drop + * operation is in progress, by sending it one of the messages defined in + * the <code>DropTargetListener</code> interface. + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see DropTargetListener + * @see #addDropListener + * @see #removeDropListener + * @see DropTargetEvent + * + * @since 3.4 + */ +public DropTargetListener[] getDropListeners() { + Listener[] listeners = getListeners(DND.DragEnter); + int length = listeners.length; + DropTargetListener[] dropListeners = new DropTargetListener[length]; + int count = 0; + for (int i = 0; i < length; i++) { + Listener listener = listeners[i]; + if ( auto l = cast(DNDListener)listener ) { + dropListeners[count] = cast(DropTargetListener) (l.getEventListener()); + count++; + } + } + if (count is length) return dropListeners; + DropTargetListener[] result = new DropTargetListener[count]; + SimpleType!(DropTargetListener).arraycopy(dropListeners, 0, result, 0, count); + return result; +} + +/** * Returns the drop effect for this DropTarget. This drop effect will be * used during a drag and drop to display the drag under effect on the * target widget. @@ -622,7 +657,7 @@ transferAgents = null; if (controlListener !is null) control.removeListener(DWT.Dispose, controlListener); - control.setData(DROPTARGETID, null); + control.setData(DND.DROP_TARGET_KEY, null); control = null; controlListener = null; } @@ -723,6 +758,14 @@ } int actions = opToOsOp(getStyle()); + if ( auto c = cast(Combo)control ) { + if ((control.getStyle() & DWT.READ_ONLY) is 0) { + auto entryHandle = OS.gtk_bin_get_child (control.handle); + if (entryHandle !is null) { + OS.gtk_drag_dest_unset(entryHandle); + } + } + } OS.gtk_drag_dest_set(control.handle, 0, pTargets, targets.length, actions); for (int i = 0; i < targets.length; i++) {
--- a/dwt/dnd/DropTargetEffect.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/DropTargetEffect.d Mon May 12 19:13:01 2008 +0200 @@ -17,8 +17,8 @@ import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.widgets.Control; -import dwt.widgets.Item; import dwt.widgets.Table; +import dwt.widgets.TableItem; import dwt.widgets.Tree; import dwt.widgets.TreeItem; import dwt.widgets.Widget; @@ -107,38 +107,39 @@ Widget getItem(Table table, int x, int y) { Point coordinates = new Point(x, y); coordinates = table.toControl(coordinates); - Item item = table.getItem(coordinates); - if (item is null) { - Rectangle area = table.getClientArea(); - if (area.contains(coordinates)) { - // Scan across the width of the table. - for (int x1 = area.x; x1 < area.x + area.width; x1++) { - Point pt = new Point(x1, coordinates.y); - item = table.getItem(pt); - if (item !is null) { - break; - } - } - } + TableItem item = table.getItem(coordinates); + if (item !is null) return item; + Rectangle area = table.getClientArea(); + int tableBottom = area.y + area.height; + int itemCount = table.getItemCount(); + for (int i=table.getTopIndex(); i<itemCount; i++) { + item = table.getItem(i); + Rectangle rect = item.getBounds(); + rect.x = area.x; + rect.width = area.width; + if (rect.contains(coordinates)) return item; + if (rect.y > tableBottom) break; } - return item; + return null; } Widget getItem(Tree tree, int x, int y) { - Point coordinates = new Point(x, y); - coordinates = tree.toControl(coordinates); - Item item = tree.getItem(coordinates); + Point point = new Point(x, y); + point = tree.toControl(point); + TreeItem item = tree.getItem(point); if (item is null) { Rectangle area = tree.getClientArea(); - if (area.contains(coordinates)) { - // Scan across the width of the tree. - for (int x1 = area.x; x1 < area.x + area.width; x1++) { - Point pt = new Point(x1, coordinates.y); - item = tree.getItem(pt); - if (item !is null) { - break; - } + if (area.contains(point)) { + int treeBottom = area.y + area.height; + item = tree.getTopItem(); + while (item !is null) { + Rectangle rect = item.getBounds(); + int itemBottom = rect.y + rect.height; + if (rect.y <= point.y && point.y < itemBottom) return item; + if (itemBottom > treeBottom) break; + item = nextItem(tree, item); } + return null; } } return item; @@ -146,7 +147,7 @@ TreeItem nextItem(Tree tree, TreeItem item) { if (item is null) return null; - if (item.getExpanded()) return item.getItem(0); + if (item.getExpanded() && item.getItemCount() > 0) return item.getItem(0); TreeItem childItem = item; TreeItem parentItem = childItem.getParentItem(); int index = parentItem is null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
--- a/dwt/dnd/FileTransfer.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/FileTransfer.d Mon May 12 19:13:01 2008 +0200 @@ -84,7 +84,7 @@ if (string.ptr is null) continue; if (string.length is 0) continue; GError* error; - auto localePtr = OS.g_locale_from_utf8(string.ptr, -1, null, null, &error); + auto localePtr = OS.g_filename_from_utf8(string.ptr, -1, null, null, &error); if (error !is null || localePtr is null) continue; auto uriPtr = OS.g_filename_to_uri(localePtr, null, &error); OS.g_free(localePtr); @@ -159,7 +159,7 @@ auto localePtr = OS.g_filename_from_uri(files[i], null, &error); OS.g_free(files[i]); if (error !is null || localePtr is null) continue; - auto utf8Ptr = OS.g_locale_to_utf8(localePtr, -1, null, null, &error); + auto utf8Ptr = OS.g_filename_to_utf8(localePtr, -1, null, null, &error); OS.g_free(localePtr); if (error !is null || utf8Ptr is null) continue; String buffer = tango.stdc.stringz.fromStringz( utf8Ptr ).dup;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/ImageTransfer.d Mon May 12 19:13:01 2008 +0200 @@ -0,0 +1,194 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.dnd.ImageTransfer; + +import dwt.DWT; +import dwt.graphics.Image; +import dwt.graphics.ImageData; +import dwt.internal.Converter; +import dwt.internal.gtk.OS; +import dwt.widgets.Display; +import dwt.dnd.ByteArrayTransfer; +import dwt.dnd.TransferData; +import dwt.dnd.DND; + +import dwt.dwthelper.utils; + +/** + * The class <code>ImageTransfer</code> provides a platform specific mechanism + * for converting a Image represented as a java <code>ImageData</code> to a + * platform specific representation of the data and vice versa. + * See <code>Transfer</code> for additional information. + * + * <p>An example of a java <code>ImageData</code> is shown + * below:</p> + * + * <code><pre> + * Image image = new Image("C:\temp\img1.gif"); + * ImageData imgData = image.getImageData(); + * </code></pre> + */ +public class ImageTransfer : ByteArrayTransfer { + + private static ImageTransfer _instance; + + private static const String JPEG = "image/jpge"; //$NON-NLS-1$ + private static int JPEG_ID; + private static const String PNG = "image/png"; //$NON-NLS-1$ + private static int PNG_ID; + private static const String BMP = "image/bmp"; //$NON-NLS-1$ + private static int BMP_ID; + private static const String EPS = "image/eps"; //$NON-NLS-1$ + private static int EPS_ID; + private static const String PCX = "image/pcx"; //$NON-NLS-1$ + private static int PCX_ID; + private static const String PPM = "image/ppm"; //$NON-NLS-1$ + private static int PPM_ID; + private static const String RGB = "image/ppm"; //$NON-NLS-1$ + private static int RGB_ID; + private static const String TGA = "image/tga"; //$NON-NLS-1$ + private static int TGA_ID; + private static const String XBM = "image/xbm"; //$NON-NLS-1$ + private static int XBM_ID; + private static const String XPM = "image/xpm"; //$NON-NLS-1$ + private static int XPM_ID; + private static const String XV = "image/xv"; //$NON-NLS-1$ + private static int XV_ID; + +static this(){ + JPEG_ID = registerType(JPEG); + PNG_ID = registerType(PNG); + BMP_ID = registerType(BMP); + EPS_ID = registerType(EPS); + PCX_ID = registerType(PCX); + PPM_ID = registerType(PPM); + RGB_ID = registerType(RGB); + TGA_ID = registerType(TGA); + XBM_ID = registerType(XBM); + XPM_ID = registerType(XPM); + XV_ID = registerType(XV); + _instance = new ImageTransfer(); +} + +private this() { +} + +/** + * Returns the singleton instance of the ImageTransfer class. + * + * @return the singleton instance of the ImageTransfer class + */ +public static ImageTransfer getInstance () { + return _instance; +} + +/** + * This implementation of <code>javaToNative</code> converts an ImageData object represented + * by java <code>ImageData</code> to a platform specific representation. + * For additional information see <code>Transfer#javaToNative</code>. + * + * @param object a java <code>ImageData</code> containing the ImageData to be + * converted + * @param transferData an empty <code>TransferData</code> object; this + * object will be filled in on return with the platform specific format of the data + */ +public void javaToNative(Object object, TransferData transferData) { + if (!checkImage(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + if (OS.GTK_VERSION < OS.buildVERSION (2, 4, 0)) return; + + ImageData imgData = cast(ImageData)object; + if (imgData is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + Image image = new Image(Display.getCurrent(), imgData); + auto pixmap = image.pixmap; + int width = imgData.width; + int height = imgData.height; + auto pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, true, 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, pixmap, colormap, 0, 0, 0, 0, width, height); + + String typeStr = ""; + if (transferData.type is cast(void*)JPEG_ID) typeStr = "jpeg"; + if (transferData.type is cast(void*)PNG_ID) typeStr = "png"; + if (transferData.type is cast(void*)BMP_ID) typeStr = "bmp"; + if (transferData.type is cast(void*)EPS_ID) typeStr = "eps"; + if (transferData.type is cast(void*)PCX_ID) typeStr = "pcx"; + if (transferData.type is cast(void*)PPM_ID) typeStr = "ppm"; + if (transferData.type is cast(void*)RGB_ID) typeStr = "rgb"; + if (transferData.type is cast(void*)TGA_ID) typeStr = "tga"; + if (transferData.type is cast(void*)XBM_ID) typeStr = "xbm"; + if (transferData.type is cast(void*)XPM_ID) typeStr = "xpm"; + if (transferData.type is cast(void*)XV_ID) typeStr = "xv"; + char* type = typeStr.ptr; + char* buffer; + uint len; + if (type is null) return; + OS.gdk_pixbuf_save_to_buffer0(pixbuf, &buffer, &len, type, null); + OS.g_object_unref(pixbuf); + image.dispose(); + transferData.pValue = buffer; + transferData.length = (len + 3) / 4 * 4; + transferData.result = 1; + transferData.format = 32; +} + +/** + * This implementation of <code>nativeToJava</code> converts a platform specific + * representation of an <code>ImageData</code> to java. + * For additional information see <code>Transfer#nativeToJava</code>. + * + * @param transferData the platform specific representation of the data to be + * been converted + * @return a java <code>ImageData</code> the imageData of the image if + * conversion was successful; otherwise null + */ +public Object nativeToJava(TransferData transferData) { + ImageData imgData = null; + if (transferData.length > 0) + { + auto loader = OS.gdk_pixbuf_loader_new(); + OS.gdk_pixbuf_loader_write(loader, transferData.pValue, transferData.length, null); + OS.gdk_pixbuf_loader_close(loader, null); + auto pixbuf = OS.gdk_pixbuf_loader_get_pixbuf(loader); + if (pixbuf !is null) { + OS.g_object_ref(pixbuf); + GdkPixmap* pixmap_return; + OS.gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap_return, null, 0); + auto handle = pixmap_return; + if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); + OS.g_object_unref(loader); + Image img = Image.gtk_new(Display.getCurrent(), DWT.BITMAP, handle, null); + imgData = img.getImageData(); + img.dispose(); + } + } + return imgData; +} + +protected int[] getTypeIds(){ + return [JPEG_ID, PNG_ID, BMP_ID, EPS_ID, PCX_ID, PPM_ID, RGB_ID, TGA_ID, XBM_ID, XPM_ID, XV_ID]; +} + +protected String[] getTypeNames(){ + return [JPEG, PNG, BMP, EPS, PCX, PPM, RGB, TGA, XBM, XPM, XV]; +} + +bool checkImage(Object object) { + if (object is null || !( null !is cast(ImageData)object )) return false; + return true; +} + +protected bool validate(Object object) { + return checkImage(object); +} +}
--- a/dwt/dnd/TableDragSourceEffect.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/TableDragSourceEffect.d Mon May 12 19:13:01 2008 +0200 @@ -88,6 +88,8 @@ Table table = cast(Table) control; if (OS.GTK_VERSION < OS.buildVERSION (2, 2, 0)) return null; + //TEMPORARY CODE + if (table.isListening(DWT.EraseItem) || table.isListening (DWT.PaintItem)) return null; /* * Bug in GTK. gtk_tree_selection_get_selected_rows() segmentation faults * in versions smaller than 2.2.4 if the model is NULL. The fix is
--- a/dwt/dnd/TableDropTargetEffect.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/TableDropTargetEffect.d Mon May 12 19:13:01 2008 +0200 @@ -110,7 +110,7 @@ public override void dragLeave(DropTargetEvent event) { Table table = cast(Table) control; auto handle = table.handle; - 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); scrollBeginTime = 0; scrollIndex = -1; @@ -181,10 +181,10 @@ if (position !is 0) { OS.gtk_tree_view_set_drag_dest_row(handle, path, OS.GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); } else { - 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); } } else { - 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); } if (path !is null) OS.gtk_tree_path_free (path ); }
--- a/dwt/dnd/TransferData.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/TransferData.d Mon May 12 19:13:01 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0
--- a/dwt/dnd/TreeDragSourceEffect.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/TreeDragSourceEffect.d Mon May 12 19:13:01 2008 +0200 @@ -87,6 +87,8 @@ Tree tree = cast(Tree) control; if (OS.GTK_VERSION < OS.buildVERSION (2, 2, 0)) return null; + //TEMPORARY CODE + if (tree.isListening(DWT.EraseItem) || tree.isListening (DWT.PaintItem)) return null; /* * Bug in GTK. gtk_tree_selection_get_selected_rows() segmentation faults * in versions smaller than 2.2.4 if the model is NULL. The fix is
--- a/dwt/dnd/TreeDropTargetEffect.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/dnd/TreeDropTargetEffect.d Mon May 12 19:13:01 2008 +0200 @@ -118,7 +118,7 @@ public override void dragLeave(DropTargetEvent event) { Tree tree = cast(Tree) control; auto handle = tree.handle; - 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); scrollBeginTime = 0; scrollIndex = -1; @@ -214,10 +214,10 @@ if (position !is -1) { OS.gtk_tree_view_set_drag_dest_row(handle, path, position); } else { - 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); } } else { - 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); } if (path !is null) OS.gtk_tree_path_free (path );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/URLTransfer.d Mon May 12 19:13:01 2008 +0200 @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.dnd.URLTransfer; + +import dwt.internal.gtk.OS; + +import dwt.dnd.ByteArrayTransfer; +import dwt.dnd.TransferData; +import dwt.dnd.DND; + +import dwt.dwthelper.utils; + +/** + * The class <code>URLTransfer</code> provides a platform specific mechanism + * for converting text in URL format represented as a java <code>String</code> + * to a platform specific representation of the data and vice versa. See + * <code>Transfer</code> for additional information. The string + * must be a fully specified url. + * + * <p>An example of a java <code>String[]</code> containing a URL is shown + * below:</p> + * + * <code><pre> + * String urlData = "http://www.eclipse.org"; + * </code></pre> + */ +public class URLTransfer : ByteArrayTransfer { + + static URLTransfer _instance; + private static const String TEXT_UNICODE = "text/unicode"; //$NON-NLS-1$ + private static const String TEXT_XMOZURL = "text/x-moz-url"; //$NON-NLS-1$ + private static int TEXT_UNICODE_ID; + private static int TEXT_XMOZURL_ID; + +static this(){ + TEXT_UNICODE_ID = registerType(TEXT_UNICODE); + TEXT_XMOZURL_ID = registerType(TEXT_XMOZURL); + _instance = new URLTransfer(); +} + +private this() {} + +/** + * Returns the singleton instance of the URLTransfer class. + * + * @return the singleton instance of the URLTransfer class + */ +public static URLTransfer getInstance () { + return _instance; +} + +/** + * This implementation of <code>javaToNative</code> converts a URL + * represented by a java <code>String</code> to a platform specific representation. + * For additional information see <code>Transfer#javaToNative</code>. + * + * @param object a java <code>String</code> containing a URL + * @param transferData an empty <code>TransferData</code> object; this + * object will be filled in on return with the platform specific format of the data + */ +public void javaToNative (Object object, TransferData transferData){ + transferData.result = 0; + if (!checkURL(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + String string = (cast(ArrayWrapperString)object).array; + char* pValue = cast(char*)OS.g_malloc(string.length+1); + if (pValue is null) return; + pValue[ 0 .. string.length ] = string[]; + pValue[ string.length ] = '\0'; + transferData.length = string.length; + transferData.format = 8; + transferData.pValue = pValue; + transferData.result = 1; +} + +/** + * This implementation of <code>nativeToJava</code> converts a platform specific + * representation of a URL <code>String</code>. + * For additional information see <code>Transfer#nativeToJava</code>. + * + * @param transferData the platform specific representation of the data to be + * converted + * @return a java <code>String</code> containing a URL if the + * conversion was successful; otherwise null + */ +public Object nativeToJava(TransferData transferData){ + if (!isSupportedType(transferData) || transferData.pValue is null) return null; + int size = (transferData.format * transferData.length / 8); + if (size <= 0) return null; + String string = tango.stdc.stringz.fromStringz(cast(char*)transferData.pValue).dup; + int end = string.indexOf('\0'); + return new ArrayWrapperString((end is -1) ? string : string.substring(0, end)); +} + +protected int[] getTypeIds(){ + return [TEXT_XMOZURL_ID, TEXT_UNICODE_ID]; +} + +protected String[] getTypeNames(){ + return [TEXT_XMOZURL, TEXT_UNICODE]; +} + +bool checkURL(Object object) { + return object !is null && (null !is cast(ArrayWrapperString)object) && (cast(ArrayWrapperString)object).array.length > 0; +} + +protected bool validate(Object object) { + return checkURL(object); +} +}
--- a/dwt/graphics/Color.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Color.d Mon May 12 19:13:01 2008 +0200 @@ -39,6 +39,7 @@ * @see Device#getSystemColor */ public final class Color : Resource { + alias Resource.init_ init_; /** * the handle to the OS color resource * (Warning: This field is platform dependent) @@ -51,7 +52,8 @@ */ public GdkColor* handle; -this() { +this(Device device) { + super(device); } /** @@ -79,10 +81,9 @@ * @see #dispose */ public this(Device device, int red, int green, int blue) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, red, green, blue); - if (device.tracking) device.new_Object(this); + super(device); + init_(red, green, blue); + init_(); } /** @@ -108,21 +109,13 @@ * @see #dispose */ public this(Device device, RGB rgb) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (rgb is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, rgb.red, rgb.green, rgb.blue); - if (device.tracking) device.new_Object(this); + init_(rgb.red, rgb.green, rgb.blue); + init_(); } -/** - * Disposes of the operating system resources associated with - * the color. Applications must dispose of all colors which - * they allocate. - */ -public override void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { int pixel = handle.pixel; if (device.colorRefCount !is null) { /* If this was the last reference, remove the color from the list */ @@ -133,8 +126,6 @@ auto colormap = OS.gdk_colormap_get_system(); OS.gdk_colormap_free_colors(colormap, handle, 1); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -245,15 +236,12 @@ * @private */ public static Color gtk_new(Device device, GdkColor* gdkColor) { - if (device is null) device = Device.getDevice(); - Color color = new Color(); + Color color = new Color(device); color.handle = gdkColor; - color.device = device; return color; } -void init_(Device device, int red, int green, int blue) { - this.device = device; +void init_(int red, int green, int blue) { if ((red > 255) || (red < 0) || (green > 255) || (green < 0) || (blue > 255) || (blue < 0)) {
--- a/dwt/graphics/Cursor.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Cursor.d Mon May 12 19:13:01 2008 +0200 @@ -90,7 +90,8 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; -this () { +this (Device device) { + super(device); } /** @@ -135,9 +136,7 @@ * @see DWT#CURSOR_HAND */ public this(Device device, int style) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); int shape = 0; switch (style) { case DWT.CURSOR_APPSTARTING: break; @@ -171,7 +170,7 @@ handle = OS.gdk_cursor_new(shape); } if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } /** @@ -206,9 +205,7 @@ * </ul> */ public this(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (mask is null) { if (!(source.getTransparencyType() is DWT.TRANSPARENCY_MASK)) DWT.error(DWT.ERROR_NULL_ARGUMENT); @@ -260,7 +257,7 @@ maskData = ImageData.convertPad(maskData, mask.width, mask.height, mask.depth, mask.scanlinePad, 1); handle = createCursor(maskData, sourceData, source.width, source.height, hotspotX, hotspotY, true); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } /** @@ -291,9 +288,7 @@ * @since 3.0 */ public this(Device device, ImageData source, int hotspotX, int hotspotY) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (hotspotX >= source.width || hotspotX < 0 || hotspotY >= source.height || hotspotY < 0) { @@ -438,7 +433,7 @@ handle = createCursor(sourceData, maskData, source.width, source.height, hotspotX, hotspotY, false); } if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } GdkCursor* createCursor(byte[] sourceData, byte[] maskData, int width, int height, int hotspotX, int hotspotY, bool reverse) { @@ -457,18 +452,9 @@ return cursor; } -/** - * Disposes of the operating system resources associated with - * the cursor. Applications must dispose of all cursors which - * they allocate. - */ -public override void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { OS.gdk_cursor_destroy(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -505,10 +491,8 @@ * @private */ public static Cursor gtk_new(Device device, GdkCursor* handle) { - if (device is null) device = Device.getDevice(); - Cursor cursor = new Cursor(); + Cursor cursor = new Cursor(device); cursor.handle = handle; - cursor.device = device; return cursor; }
--- a/dwt/graphics/Device.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Device.d Mon May 12 19:13:01 2008 +0200 @@ -57,6 +57,7 @@ bool tracking; Exception [] errors; Object [] objects; + Object trackingLock; /* Colormap and reference count */ GdkColor *[] gdkColors; @@ -99,8 +100,6 @@ static bool CAIRO_LOADED; -// static Object CREATE_LOCK; - /* * TEMPORARY CODE. When a graphics object is * created and the device parameter is null, @@ -157,7 +156,6 @@ * @see #init * @see DeviceData */ - public this(DeviceData data) { handler_ids = new int [log_domains.length]; debugging = DEBUG; @@ -171,13 +169,11 @@ if (tracking) { errors = new Exception [128]; objects = new Object [128]; + trackingLock = new Object (); } create (data); init_ (); register (this); - - /* Initialize the system font slot */ - systemFont = getSystemFont (); } } @@ -236,25 +232,32 @@ * @see #checkDevice */ public void dispose () { - if (isDisposed()) return; - checkDevice (); - release (); - destroy (); - deregister (this); - xDisplay = null; - disposed = true; - if (tracking) { - objects = null; - errors = null; + synchronized (Device.classinfo) { + if (isDisposed()) return; + checkDevice (); + release (); + destroy (); + deregister (this); + xDisplay = null; + disposed = true; + if (tracking) { + synchronized (trackingLock) { + objects = null; + errors = null; + trackingLock = null; + } + } } } void dispose_Object (Object object) { - for (int i=0; i<objects.length; i++) { - if (objects [i] is object) { - objects [i] = null; - errors [i] = null; - return; + synchronized (trackingLock) { + for (int i=0; i<objects.length; i++) { + if (objects [i] is object) { + objects [i] = null; + errors [i] = null; + return; + } } } } @@ -324,20 +327,26 @@ DeviceData data = new DeviceData (); data.debugging = debugging; data.tracking = tracking; - int count = 0, length = 0; - if (tracking) length = objects.length; - for (int i=0; i<length; i++) { - if (objects [i] !is null) count++; - } - int index = 0; - data.objects = new Object [count]; - data.errors = new Exception [count]; - for (int i=0; i<length; i++) { - if (objects [i] !is null) { - data.objects [index] = objects [i]; - data.errors [index] = errors [i]; - index++; + if (tracking) { + synchronized (trackingLock) { + int count = 0, length = objects.length; + for (int i=0; i<length; i++) { + if (objects [i] !is null) count++; + } + int index = 0; + data.objects = new Object [count]; + data.errors = new Exception [count]; + for (int i=0; i<length; i++) { + if (objects [i] !is null) { + data.objects [index] = objects [i]; + data.errors [index] = errors [i]; + index++; + } + } } + } else { + data.objects = null; + data.errors = null; } return data; } @@ -611,6 +620,9 @@ shellHandle = OS.gtk_window_new(OS.GTK_WINDOW_TOPLEVEL); if (shellHandle is null) DWT.error(DWT.ERROR_NO_HANDLES); OS.gtk_widget_realize(shellHandle); + + /* Initialize the system font slot */ + systemFont = getSystemFont (); } /** @@ -654,7 +666,9 @@ * @return <code>true</code> when the device is disposed and <code>false</code> otherwise */ public bool isDisposed () { - return disposed; + synchronized (Device.classinfo) { + return disposed; + } } /** @@ -693,21 +707,23 @@ } void new_Object (Object object) { - for (int i=0; i<objects.length; i++) { - if (objects [i] is null) { - objects [i] = object; - errors [i] = new Exception (""); - return; + synchronized (trackingLock) { + for (int i=0; i<objects.length; i++) { + if (objects [i] is null) { + objects [i] = object; + errors [i] = new Exception (""); + return; + } } + Object [] newObjects = new Object [objects.length + 128]; + System.arraycopy (objects, 0, newObjects, 0, objects.length); + newObjects [objects.length] = object; + objects = newObjects; + Exception [] newErrors = new Exception [errors.length + 128]; + System.arraycopy (errors, 0, newErrors, 0, errors.length); + newErrors [errors.length] = new Exception (""); + errors = newErrors; } - Object [] newObjects = new Object [objects.length + 128]; - System.arraycopy (objects, 0, newObjects, 0, objects.length); - newObjects [objects.length] = object; - objects = newObjects; - Exception [] newErrors = new Exception [errors.length + 128]; - System.arraycopy (errors, 0, newErrors, 0, errors.length); - newErrors [errors.length] = new Exception (""); - errors = newErrors; } static synchronized void register (Device device) {
--- a/dwt/graphics/Font.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Font.d Mon May 12 19:13:01 2008 +0200 @@ -39,6 +39,8 @@ * @see FontData */ public final class Font : Resource { + + alias Resource.init_ init_; /** * the handle to the OS font resource * (Warning: This field is platform dependent) @@ -51,7 +53,8 @@ */ public PangoFontDescription* handle; -this() { +this(Device device) { + super(device); } /** @@ -73,11 +76,10 @@ * </ul> */ public this(Device device, FontData fd) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (fd is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, fd.getName(), fd.getHeightF(), fd.getStyle(), fd.str); - if (device.tracking) device.new_Object(this); + init_(fd.getName(), fd.getHeightF(), fd.getStyle(), fd.str); + init_(); } /** @@ -104,16 +106,15 @@ * @since 2.1 */ public this(Device device, FontData[] fds) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (fds is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (fds.length is 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); for (int i=0; i<fds.length; i++) { if (fds[i] is null) DWT.error(DWT.ERROR_INVALID_ARGUMENT); } FontData fd = fds[0]; - init_(device,fd.getName(), fd.getHeightF(), fd.getStyle(), fd.str); - if (device.tracking) device.new_Object(this); + init_(fd.getName(), fd.getHeightF(), fd.getStyle(), fd.str); + init_(); } /** @@ -139,31 +140,20 @@ * </ul> */ public this(Device device, String name, int height, int style) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, name, height, style, null); - if (device.tracking) device.new_Object(this); + super(device); + init_(name, height, style, null); + init_(); } /*public*/ this(Device device, String name, float height, int style) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, name, height, style, null); - if (device.tracking) device.new_Object(this); + super(device); + init_(name, height, style, null); + init_(); } -/** - * Disposes of the operating system resources associated with - * the font. Applications must dispose of all fonts which - * they allocate. - */ -public override void dispose() { - if (handle is null ) return; - if (device.isDisposed()) return; +void destroy() { OS.pango_font_description_free(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -233,10 +223,8 @@ * @private */ public static Font gtk_new(Device device, PangoFontDescription* handle) { - if (device is null) device = Device.getDevice(); - Font font = new Font(); + Font font = new Font(device); font.handle = handle; - font.device = device; return font; } @@ -254,10 +242,9 @@ return cast(hash_t)/*64*/handle; } -void init_(Device device, String name, float height, int style, String fontString) { +void init_(String name, float height, int style, char[] fontString) { if (name is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - this.device = device; if (fontString !is null) { handle = OS.pango_font_description_from_string (toStringz(fontString)); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); @@ -266,7 +253,9 @@ if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); //byte[] buffer = Converter.wcsToMbcs(null, name, true); OS.pango_font_description_set_family(handle, toStringz(name) ); - OS.pango_font_description_set_size(handle, cast(int)(0.5f + height * OS.PANGO_SCALE)); + if (height > 0) { + OS.pango_font_description_set_size(handle, cast(int)(0.5f + height * OS.PANGO_SCALE)); + } OS.pango_font_description_set_stretch(handle, OS.PANGO_STRETCH_NORMAL); int pangoStyle = OS.PANGO_STYLE_NORMAL; int pangoWeight = OS.PANGO_WEIGHT_NORMAL;
--- a/dwt/graphics/GC.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/GC.d Mon May 12 19:13:01 2008 +0200 @@ -78,6 +78,9 @@ * @see dwt.events.PaintEvent */ public final class GC : Resource { + + alias Resource.init_ init_; + /** * the handle to the OS device context * (Warning: This field is platform dependent) @@ -180,8 +183,8 @@ if (device is null) device = Device.getDevice(); if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); this.device = data.device = device; - init(drawable, data, gdkGC); - if (device.tracking) device.new_Object(this); + init_(drawable, data, gdkGC); + init_(); } static void addCairoString(cairo_t* cairo, String str, float x, float y, Font font) { @@ -191,7 +194,11 @@ if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES); OS.pango_layout_set_text(layout, buffer, -1); OS.pango_layout_set_font_description(layout, font.handle); - Cairo.cairo_move_to(cairo, x, y); + double currentX, currentY; + Cairo.cairo_get_current_point(cairo, ¤tX, ¤tY); + if (currentX !is x || currentY !is y) { + Cairo.cairo_move_to(cairo, x, y); + } OS.pango_cairo_layout_path(cairo, layout); OS.g_object_unref(layout); } else { @@ -209,11 +216,18 @@ return style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT); } +public static GC gtk_new(GdkGC* handle, GCData data) { + GC gc = new GC(); + gc.device = data.device; + gc.init_(null, data, handle); + return gc; +} + public static GC gtk_new(Drawable drawable, GCData data) { GC gc = new GC(); auto gdkGC = drawable.internal_new_GC(data); gc.device = data.device; - gc.init(drawable, data, gdkGC); + gc.init_(drawable, data, gdkGC); return gc; } @@ -237,14 +251,25 @@ data.state &= ~FOREGROUND; } if (pattern !is null) { - Cairo.cairo_set_source(cairo, pattern.handle); + if ((data.style & DWT.MIRRORED) !is 0 && pattern.surface !is null) { + auto newPattern = Cairo.cairo_pattern_create_for_surface(pattern.surface); + if (newPattern is null) DWT.error(DWT.ERROR_NO_HANDLES); + Cairo.cairo_pattern_set_extend(newPattern, Cairo.CAIRO_EXTEND_REPEAT); + double[6] matrix; matrix[0] = -1; matrix[1] = 0; matrix[2] = 0; matrix[3] = 1; matrix[4] = 0; matrix[5] = 0; + Cairo.cairo_pattern_set_matrix(newPattern, cast(cairo_matrix_t*) matrix.ptr); + Cairo.cairo_set_source(cairo, newPattern); + Cairo.cairo_pattern_destroy(newPattern); + } else { + Cairo.cairo_set_source(cairo, pattern.handle); + } } else { 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); } } if ((state & FONT) !is 0) { if (data.layout !is null) { - OS.pango_layout_set_font_description(data.layout, data.font); + Font font = data.font; + OS.pango_layout_set_font_description(data.layout, font.handle); } if (OS.GTK_VERSION < OS.buildVERSION(2, 8, 0)) { setCairoFont(cairo, data.font); @@ -312,13 +337,16 @@ data.cairoXoffset = data.cairoYoffset = 0; double[] matrix = new double[6]; Cairo.cairo_get_matrix(cairo,cast(cairo_matrix_t*) matrix.ptr); - double scaling = matrix[0]; + double dx = 1; + double dy = 1; + Cairo.cairo_user_to_device_distance(cairo, &dx, &dy); + double scaling = dx; if (scaling < 0) scaling = -scaling; double strokeWidth = data.lineWidth * scaling; if (strokeWidth is 0 || (cast(int)strokeWidth % 2) is 1) { data.cairoXoffset = 0.5 / scaling; } - scaling = matrix[3]; + scaling = dy; if (scaling < 0) scaling = -scaling; strokeWidth = data.lineWidth * scaling; if (strokeWidth is 0 || (cast(int)strokeWidth % 2) is 1) { @@ -344,7 +372,8 @@ } if ((state & FONT) !is 0) { if (data.layout !is null) { - OS.pango_layout_set_font_description(data.layout, data.font); + Font font = data.font; + OS.pango_layout_set_font_description(data.layout, font.handle); } } if ((state & (LINE_CAP | LINE_JOIN | LINE_STYLE | LINE_WIDTH)) !is 0) { @@ -544,7 +573,7 @@ if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES); data.layout = layout; OS.pango_context_set_language(context, OS.gtk_get_default_language()); - OS.pango_context_set_base_dir(context, OS.PANGO_DIRECTION_LTR); + OS.pango_context_set_base_dir(context, (data.style & DWT.MIRRORED) !is 0 ? OS.PANGO_DIRECTION_RTL : OS.PANGO_DIRECTION_LTR); OS.gdk_pango_context_set_colormap(context, OS.gdk_colormap_get_system()); if (OS.GTK_VERSION >= OS.buildVERSION(2, 4, 0)) { OS.pango_layout_set_auto_dir(layout, false); @@ -559,19 +588,7 @@ data.context = null; } -/** - * Disposes of the operating system resources associated with - * the graphics context. Applications must dispose of all GCs - * which they allocate. - * - * @exception DWTError <ul> - * <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li> - * </ul> - */ -public override void dispose() { - if (handle is null) return; - if (data.device.isDisposed()) return; - +void destroy() { if (data.disposeCairo) { auto cairo = data.cairo; if (cairo !is null) Cairo.cairo_destroy(cairo); @@ -590,17 +607,15 @@ disposeLayout(); /* Dispose the GC */ - Device device = data.device; - drawable.internal_dispose_GC(handle, data); - + if (drawable !is null) { + drawable.internal_dispose_GC(handle, data); + } data.drawable = null; data.clipRgn = null; drawable = null; handle = null; data.image = null; data.str = null; - if (device.tracking) device.dispose_Object(this); - data.device = null; data = null; } @@ -808,6 +823,10 @@ if (data.alpha !is 0) { srcImage.createSurface(); Cairo.cairo_save(cairo); + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_scale(cairo, -1f, 1); + Cairo.cairo_translate(cairo, - 2 * destX - destWidth, 0); + } Cairo.cairo_rectangle(cairo, destX , destY, destWidth, destHeight); Cairo.cairo_clip(cairo); Cairo.cairo_translate(cairo, destX - srcX, destY - srcY); @@ -1054,7 +1073,7 @@ void drawImageXRender(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple, int imgWidth, int imgHeight, GdkDrawable* maskPixmap, int maskType) { int translateX = 0, translateY = 0; auto drawable = data.drawable; - if (data.image is null) { + if (data.image is null && !data.realDrawable) { int x, y; GdkDrawable* real_drawable; OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y); @@ -1448,21 +1467,25 @@ if (nah < 0) nah = 0 - nah; auto cairo = data.cairo; if (cairo !is null) { - float naw2 = naw / 2f; - float nah2 = nah / 2f; - float fw = nw / naw2; - float fh = nh / nah2; - Cairo.cairo_save(cairo); double xOffset = data.cairoXoffset, yOffset = data.cairoYoffset; - Cairo.cairo_translate(cairo, nx + xOffset, ny + yOffset); - Cairo.cairo_scale(cairo, naw2, nah2); - Cairo.cairo_move_to(cairo, fw - 1, 0); - Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0); - Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0); - Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI); - Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0); - Cairo.cairo_close_path(cairo); - Cairo.cairo_restore(cairo); + if (naw is 0 || nah is 0) { + Cairo.cairo_rectangle(cairo, x + xOffset, y + yOffset, width, height); + } else { + float naw2 = naw / 2f; + float nah2 = nah / 2f; + float fw = nw / naw2; + float fh = nh / nah2; + Cairo.cairo_save(cairo); + Cairo.cairo_translate(cairo, nx + xOffset, ny + yOffset); + Cairo.cairo_scale(cairo, naw2, nah2); + Cairo.cairo_move_to(cairo, fw - 1, 0); + Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0); + Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0); + Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI); + Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0); + Cairo.cairo_close_path(cairo); + Cairo.cairo_restore(cairo); + } Cairo.cairo_stroke(cairo); return; } @@ -1653,8 +1676,19 @@ Cairo.cairo_fill(cairo); } checkGC(FOREGROUND | FONT); + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_save(cairo); + int width, height; + OS.pango_layout_get_size(data.layout, &width, &height); + Cairo.cairo_scale(cairo, -1f, 1); + Cairo.cairo_translate(cairo, -2 * x - OS.PANGO_PIXELS(width), 0); + } Cairo.cairo_move_to(cairo, x, y); OS.pango_cairo_show_layout(cairo, data.layout); + if ((data.style & DWT.MIRRORED) !is 0) { + Cairo.cairo_restore(cairo); + } + Cairo.cairo_new_path(cairo); return; } checkGC(FOREGROUND | FONT | BACKGROUND_BG); @@ -2055,20 +2089,24 @@ if (nah < 0) nah = 0 - nah; auto cairo = data.cairo; if (cairo !is null) { - float naw2 = naw / 2f; - float nah2 = nah / 2f; - float fw = nw / naw2; - float fh = nh / nah2; - Cairo.cairo_save(cairo); - Cairo.cairo_translate(cairo, nx, ny); - Cairo.cairo_scale(cairo, naw2, nah2); - Cairo.cairo_move_to(cairo, fw - 1, 0); - Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0); - Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0); - Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI); - Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0); - Cairo.cairo_close_path(cairo); - Cairo.cairo_restore(cairo); + if (naw is 0 || nah is 0) { + Cairo.cairo_rectangle(cairo, x, y, width, height); + } else { + float naw2 = naw / 2f; + float nah2 = nah / 2f; + float fw = nw / naw2; + float fh = nh / nah2; + Cairo.cairo_save(cairo); + Cairo.cairo_translate(cairo, nx, ny); + Cairo.cairo_scale(cairo, naw2, nah2); + Cairo.cairo_move_to(cairo, fw - 1, 0); + Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0); + Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0); + Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI); + Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0); + Cairo.cairo_close_path(cairo); + Cairo.cairo_restore(cairo); + } Cairo.cairo_fill(cairo); return; } @@ -2283,10 +2321,15 @@ if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); /* Calculate visible bounds in device space */ int x = 0, y = 0, width = 0, height = 0; - int w, h; - OS.gdk_drawable_get_size(data.drawable, &w, &h); - width = w; - height = h; + if (data.width !is -1 && data.height !is -1) { + width = data.width; + height = data.height; + } else { + int w, h; + OS.gdk_drawable_get_size(data.drawable, &w, &h); + width = w; + height = h; + } /* Intersect visible bounds with clipping in device space and then convert then to user space */ auto cairo = data.cairo; auto clipRgn = data.clipRgn; @@ -2353,11 +2396,16 @@ auto cairo = data.cairo; auto clipRgn = data.clipRgn; if (clipRgn is null) { - int width,height; - OS.gdk_drawable_get_size(data.drawable, &width, &height); GdkRectangle rect; - rect.width = width; - rect.height = height; + if (data.width !is -1 && data.height !is -1) { + rect.width = data.width; + rect.height = data.height; + } else { + int width, height; + OS.gdk_drawable_get_size(data.drawable, &width, &height); + rect.width = width; + rect.height = height; + } OS.gdk_region_union_with_rect(clipping, &rect); } else { /* Convert clipping to device space if needed */ @@ -2415,7 +2463,7 @@ */ public Font getFont() { if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); - return Font.gtk_new(data.device, data.font); + return data.font; } /** @@ -2433,9 +2481,10 @@ if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); if (data.context is null) createLayout(); checkGC(FONT); + Font font = data.font; auto context = data.context; auto lang = OS.pango_context_get_language(context); - auto metrics = OS.pango_context_get_metrics(context, data.font, lang); + auto metrics = OS.pango_context_get_metrics(context, font.handle, lang); FontMetrics fm = new FontMetrics(); fm.ascent = OS.PANGO_PIXELS(OS.pango_font_metrics_get_ascent(metrics)); fm.descent = OS.PANGO_PIXELS(OS.pango_font_metrics_get_descent(metrics)); @@ -2723,6 +2772,9 @@ auto cairo = data.cairo; if (cairo !is null) { Cairo.cairo_get_matrix(cairo, cast(cairo_matrix_t*)transform.handle.ptr); + double[] identity = identity(); + Cairo.cairo_matrix_invert(cast(cairo_matrix_t*)identity.ptr); + Cairo.cairo_matrix_multiply(cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)identity.ptr); } else { transform.setElements(1, 0, 0, 1, 0, 0); } @@ -2765,7 +2817,19 @@ return cast(hash_t)/*64*/handle; } -void init(Drawable drawable, GCData data, GdkGC* gdkGC) { +double[] identity() { + double[] identity = new double[6]; + if ((data.style & DWT.MIRRORED) !is 0) { + int w, h; + OS.gdk_drawable_get_size(data.drawable, &w, &h); + Cairo.cairo_matrix_init(cast(cairo_matrix_t*)identity.ptr, -1, 0, 0, 1, w, 0); + } else { + Cairo.cairo_matrix_init_identity(cast(cairo_matrix_t*)identity.ptr); + } + return identity; +} + +void init_(Drawable drawable, GCData data, GdkGC* gdkGC) { if (data.foreground !is null) data.state &= ~FOREGROUND; if (data.background !is null) data.state &= ~(BACKGROUND | BACKGROUND_BG); if (data.font !is null) data.state &= ~FONT; @@ -2783,6 +2847,11 @@ this.drawable = drawable; this.data = data; handle = gdkGC; + if ((data.style & DWT.MIRRORED) !is 0) { + initCairo(); + auto cairo = data.cairo; + Cairo.cairo_set_matrix(cairo, cast(cairo_matrix_t*) identity().ptr); + } } void initCairo() { @@ -2797,12 +2866,14 @@ if (data.image !is null) { xDrawable = OS.GDK_PIXMAP_XID(drawable); } else { - int x, y; - GdkDrawable* real_drawable; - OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y); - xDrawable = OS.gdk_x11_drawable_get_xid(real_drawable); - translateX = -x; - translateY = -y; + if (!data.realDrawable) { + int x, y; + GdkDrawable* real_drawable; + OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y); + xDrawable = OS.gdk_x11_drawable_get_xid(real_drawable); + translateX = -x; + translateY = -y; + } } int w, h; OS.gdk_drawable_get_size(drawable, &w, &h); @@ -2901,6 +2972,19 @@ */ public void setAdvanced(bool advanced) { if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + if ((data.style & DWT.MIRRORED) !is 0) { + if (!advanced) { + setAlpha(0xFF); + setAntialias(DWT.DEFAULT); + setBackgroundPattern(null); + setClipping(cast(GdkRegion*)null); + setForegroundPattern(null); + setInterpolation(DWT.DEFAULT); + setTextAntialias(DWT.DEFAULT); + setTransform(null); + } + return; + } if (advanced && data.cairo !is null) return; if (advanced) { try { @@ -3268,9 +3352,8 @@ */ public void setFont(Font font) { if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); - if (font is null) font = data.device.systemFont; - if (font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - data.font = font.handle; + if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + data.font = font !is null ? font : data.device.systemFont; data.state &= ~FONT; data.stringWidth = data.stringHeight = -1; } @@ -3469,7 +3552,7 @@ DWT.error(DWT.ERROR_INVALID_ARGUMENT); } } - int cap = attributes.join; + int cap = attributes.cap; if (cap !is data.lineCap) { mask |= LINE_CAP; switch (cap) { @@ -3810,11 +3893,11 @@ if (data.cairo is null && transform is null) return; initCairo(); auto cairo = data.cairo; + double[] identity = identity(); if (transform !is null) { - Cairo.cairo_set_matrix(cairo,cast(cairo_matrix_t*) transform.handle.ptr); - } else { - Cairo.cairo_identity_matrix(cairo); + Cairo.cairo_matrix_multiply(cast(cairo_matrix_t*)identity.ptr, cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)identity.ptr); } + Cairo.cairo_set_matrix(cairo, cast(cairo_matrix_t*)identity.ptr); data.state &= ~DRAW_OFFSET; }
--- a/dwt/graphics/GCData.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/GCData.d Mon May 12 19:13:01 2008 +0200 @@ -19,6 +19,7 @@ import dwt.graphics.Device; import dwt.graphics.Pattern; import dwt.graphics.Image; +import dwt.graphics.Font; /** * Instances of this class are descriptions of GCs in terms @@ -35,7 +36,7 @@ public int style, state = -1; public GdkColor* foreground; public GdkColor* background; - public PangoFontDescription* font; + public Font font; public Pattern foregroundPattern; public Pattern backgroundPattern; public GdkRegion* clipRgn; @@ -63,5 +64,7 @@ public int stringWidth = -1; public int stringHeight = -1; public int drawFlags; + public bool realDrawable; + public int width = -1, height = -1; }
--- a/dwt/graphics/Image.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/graphics/Image.d Mon May 12 19:13:01 2008 +0200 @@ -83,7 +83,7 @@ * @see ImageLoader */ public final class Image : Resource, Drawable { - + alias Resource.init_ init_; /** * specifies whether the receiver is a bitmap or an icon * (one of <code>DWT.BITMAP</code>, <code>DWT.ICON</code>) @@ -158,7 +158,8 @@ */ static const int DEFAULT_SCANLINE_PAD = 4; -this() { +this(Device device) { + super(device); } /** @@ -192,10 +193,9 @@ * </ul> */ 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 @@ * </ul> */ 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<height; y++) { + /* 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<height; y++) { + memmove(line.ptr, pixels + (y * stride), stride); + for (int x=0; x<width; x++) { + int offset = x*3; + int red = line[offset] & 0xFF; + int green = line[offset+1] & 0xFF; + int blue = line[offset+2] & 0xFF; + int intensity = red * red + green * green + blue * blue; + if (intensity < 98304) { + line[offset] = zeroRed; + line[offset+1] = zeroGreen; + line[offset+2] = zeroBlue; + } else { + line[offset] = oneRed; + line[offset+1] = oneGreen; + line[offset+2] = oneBlue; + } + } + memmove(pixels + (y * stride), line.ptr, stride); + } + break; + } + case DWT.IMAGE_GRAY: { + byte[] line = new byte[stride]; + for (int y=0; y<height; y++) { memmove(line.ptr, pixels + (y * stride), stride); - for (int x=0; x<width; x++) { - int offset = x*3; - int red = line[offset] & 0xFF; - int green = line[offset+1] & 0xFF; - int blue = line[offset+2] & 0xFF; - int intensity = red * red + green * green + blue * blue; - if (intensity < 98304) { - line[offset] = zeroRed; - line[offset+1] = zeroGreen; - line[offset+2] = zeroBlue; - } else { - line[offset] = oneRed; - line[offset+1] = oneGreen; - line[offset+2] = oneBlue; + for (int x=0; x<width; x++) { + int offset = x*3; + int red = line[offset] & 0xFF; + int green = line[offset+1] & 0xFF; + int blue = line[offset+2] & 0xFF; + byte intensity = cast(byte)((red+red+green+green+green+green+green+blue) >> 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<height; y++) { - memmove(line.ptr, pixels + (y * stride), stride); - for (int x=0; x<width; x++) { - int offset = x*3; - int red = line[offset] & 0xFF; - int green = line[offset+1] & 0xFF; - int blue = line[offset+2] & 0xFF; - byte intensity = cast(byte)((red+red+green+green+green+green+green+blue) >> 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 @@ * </ul> */ 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 @@ * </ul> */ 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 @@ * </ul> */ 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 @@ * </ul> */ 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 @@ * </ul> */ 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;
--- 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 <ul> * <li>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</li> + * one of 1, 2, 4, 8, 16, 24 or 32, or the data array is too small to contain the image data</li> * <li>ERROR_NULL_ARGUMENT - if the palette or data is null</li> * <li>ERROR_CANNOT_BE_ZERO - if the scanlinePad is zero</li> * </ul> @@ -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,
--- 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); + } + } } /**
--- 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; } /**
--- 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);
--- 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 <code>Device</code> where this resource was @@ -67,6 +85,10 @@ return device; } +void init_() { + if (device.tracking) device.new_Object(this); +} + /** * Returns <code>true</code> if the resource has been disposed, * and <code>false</code> otherwise.
--- 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<nRects; j++) { + rect = rects[j]; + Cairo.cairo_rectangle(cairo, rect.x + 0.5, rect.y + 0.5, rect.width - 1, rect.height - 1); + } + Cairo.cairo_stroke(cairo); + } else { + if (gcValues is null) { + gcValues = new GdkGCValues(); + OS.gdk_gc_get_values(gdkGC, gcValues); + } + OS.gdk_gc_set_foreground(gdkGC, color); + int cap_style = OS.GDK_CAP_BUTT; + int join_style = OS.GDK_JOIN_MITER; + int line_style = 0; + if (dashes !is null) { + byte[] dash_list = new byte[dashes.length]; + for (int j = 0; j < dash_list.length; j++) { + dash_list[j] = cast(byte)(width is 0 || data.lineStyle is DWT.LINE_CUSTOM ? dashes[j] : dashes[j] * width); + } + OS.gdk_gc_set_dashes(gdkGC, 0, cast(char*)dash_list.ptr, dash_list.length); + line_style = OS.GDK_LINE_ON_OFF_DASH; + } else { + line_style = OS.GDK_LINE_SOLID; + } + OS.gdk_gc_set_line_attributes(gdkGC, width, line_style, cap_style, join_style); + for (int j=0; j<nRects; j++) { + rect = rects[j]; + OS.gdk_draw_rectangle(data.drawable, gdkGC, 0, rect.x, rect.y, rect.width - 1, rect.height - 1); + } + } + if (rects !is null) OS.g_free(rects); + OS.gdk_region_destroy(rgn); + } + } + + bool drawUnderline = false; + if (style.underline && style.underlineColor !is null) drawUnderline = true; + if (style.underline && (style.underlineStyle is DWT.UNDERLINE_ERROR || style.underlineStyle is DWT.UNDERLINE_SQUIGGLE)&& OS.GTK_VERSION < OS.buildVERSION(2, 4, 0)) drawUnderline = true; + if (drawUnderline && !style.isAdherentUnderline(styles[i+1].style)) { + int start = styles[i].start; + for (int j = i; 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<nRects; j++) { + rect = rects[j]; + int offset = getOffset(rect.x - x, rect.y - y, null); + int lineIndex = getLineIndex(offset); + FontMetrics metrics = getLineMetrics(lineIndex); + int underlineY = rect.y + metrics.ascent - underlinePosition - style.rise; + switch (style.underlineStyle) { + case DWT.UNDERLINE_SQUIGGLE: + case DWT.UNDERLINE_ERROR: { + int squigglyThickness = underlineThickness; + int squigglyHeight = 2 * squigglyThickness; + int squigglyY = Math.min(underlineY, rect.y + rect.height - squigglyHeight - 1); + int[] points = computePolyline(rect.x, squigglyY, rect.x + rect.width, squigglyY + squigglyHeight); + if (cairo !is null && OS.GTK_VERSION >= 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<nRects; j++) { + rect = rects[j]; + int strikeoutY = rect.y + rect.height / 2 - style.rise; + if (OS.GTK_VERSION >= 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<styles.length; i++) { StyleItem item = styles[i]; if (item.start > 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)); } + +}
--- 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 <code>DWT.UNDERLINE_SINGLE</code>. + * * * @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 + * <code>underline</code> is false. + * <p> + * This value should be one of <code>DWT.UNDERLINE_SINGLE</code>, + * <code>DWT.UNDERLINE_DOUBLE</code>, <code>DWT.UNDERLINE_ERROR</code>, + * or <code>DWT.UNDERLINE_SQUIGGLE</code>. + * </p> + * + * @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 <code>DWT.NONE</code>. + * <p> + * This value should be one of <code>DWT.BORDER_SOLID</code>, + * <code>DWT.BORDER_DASH</code>,<code>DWT.BORDER_DOT</code> or + * <code>DWT.NONE</code>. + * </p> + * + * @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 <em>same</em> 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.
--- 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
--- 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; } +}
--- 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 <code>null</code> + * @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
--- 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}
--- 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;
--- 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;
--- 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 }
--- 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();
--- 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; }
--- 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 &&
--- 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;
--- 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); }
--- 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; //<RETURN> if ((signature[5] & 0xFF) !is 10) return false; //<LINEFEED> if ((signature[6] & 0xFF) !is 26) return false; //<CTRL/Z> - if ((signature[7] & 0xFF) !is 10) return false; //<LINEFEED> + if ((signature[7] & 0xFF) !is 10) return false; //<LINEFEED> 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); }
--- 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;
--- 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);
--- 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;
--- 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
--- 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.
--- 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<count; i++) { @@ -325,7 +336,13 @@ } for (int j=last; j<=i; j++) { if (justify) bounds [j].x += (space * (j - last + 1)) + margin; - if (fill) bounds [j].height = wraps [i]; + if (fill) { + bounds [j].height = wraps [i]; + } else { + if (center) { + bounds [j].y += Math.max (0, (wraps [i] - bounds [j].height) / 2); + } + } } last = i + 1; } @@ -335,7 +352,13 @@ for (int i=0; i<count; i++) { if (!wrapped) { if (justify) bounds [i].x += (space * (i + 1)) + margin; - if (fill) bounds [i].height = maxHeight; + if (fill) { + bounds [i].height = maxHeight; + } else { + if (center) { + bounds [i].y += Math.max (0, (maxHeight - bounds [i].height) / 2); + } + } } children [i].setBounds (bounds [i]); } @@ -375,7 +398,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]; } @@ -389,17 +412,17 @@ } if (wrap && (i !is 0) && (y + childHeight > 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<count; i++) { @@ -432,7 +455,13 @@ } for (int j=last; j<=i; j++) { if (justify) bounds [j].y += (space * (j - last + 1)) + margin; - if (fill) bounds [j].width = wraps [i]; + if (fill) { + bounds [j].width = wraps [i]; + } else { + if (center) { + bounds [j].x += Math.max (0, (wraps [i] - bounds [j].width) / 2); + } + } } last = i + 1; } @@ -442,7 +471,14 @@ for (int i=0; i<count; i++) { if (!wrapped) { if (justify) bounds [i].y += (space * (i + 1)) + margin; - if (fill) bounds [i].width = maxWidth; + if (fill) { + bounds [i].width = maxWidth; + } else { + if (center) { + bounds [i].x += Math.max (0, (maxWidth - bounds [i].width) / 2); + } + } + } children [i].setBounds (bounds [i]); }
--- a/dwt/printing/PrintDialog.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/printing/PrintDialog.d Mon May 12 19:13:01 2008 +0200 @@ -16,6 +16,7 @@ import dwt.DWT; import dwt.DWTException; +import dwt.internal.LONG; import dwt.internal.gtk.OS; import dwt.widgets.Dialog; import dwt.widgets.Display; @@ -39,6 +40,7 @@ * </p> */ 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
--- 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. */
--- 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 <code>PrintDialog</code>. + * On GTK, this contains a copy of the print_settings and page_setup + * returned from the <code>PrintDialog</code>. + * On OS X Carbon, this contains a copy of the PrintSettings and PageFormat + * returned from the <code>PrintDialog</code>. * This field is not currently used on the X/Window System. */ char [] otherData;
--- 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 {
--- 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 * <code>null</code> 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; }
--- 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;
--- 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); }
--- 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);
--- 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; } }
--- 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 ();
--- 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. * <p> @@ -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 <em>keyboard focus</em>, 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. * <p> @@ -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; }
--- 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);
--- 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);
--- 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. * <p> @@ -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. + * <p> + * This is the recommended way to set the date, because setting the year, + * month, and day separately may result in invalid intermediate dates. + * </p> + * + * @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 <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @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. * <p> * 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 <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @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. * <p> * The first year is 1752 and the last year is 9999.
--- 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 <code>DWTError.error</code> to handle the error.
--- 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 @@ * </ul> */ 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 @@ * </ul> */ 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;
--- 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<Displays.length; i++) { - if (Displays [i] !is null) { - if (!multiple) DWT.error (DWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]"); - if (Displays [i].thread is thread) DWT.error (DWT.ERROR_THREAD_INVALID_ACCESS); +static void checkDisplay (Thread thread, bool multiple) { + synchronized (Device.classinfo) { + for (int i=0; i<Displays.length; i++) { + if (Displays [i] !is null) { + if (!multiple) DWT.error (DWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]"); //$NON-NLS-1$ + if (Displays [i].thread is thread) DWT.error (DWT.ERROR_THREAD_INVALID_ACCESS); + } } } } @@ -848,6 +859,22 @@ //PORTING_TODO if (!isValidClass (getClass ())) error (DWT.ERROR_INVALID_SUBCLASS); } +void clearModal (Shell shell) { + if (modalShells is null) return; + int index = 0, length_ = modalShells.length; + while (index < length_) { + if (modalShells [index] is shell) break; + if (modalShells [index] is null) return; + index++; + } + if (index is length_) return; + System.arraycopy (modalShells, index + 1, modalShells, index, --length_ - index); + modalShells [length_] = null; + if (index is 0 && modalShells [0] is null) modalShells = null; + Shell [] shells = getShells (); + for (int i=0; i<shells.length; i++) shells [i].updateModal (); +} + /** * Requests that the connection between DWT and the underlying * operating system be closed. @@ -884,7 +911,7 @@ checkSubclass (); checkDisplay(thread = Thread.getThis (), false); createDisplay (data); - register (); + register (this); if (Default is null) Default = this; } @@ -895,7 +922,7 @@ return 0; } -synchronized void createDisplay (DeviceData data) { +void createDisplay (DeviceData data) { /* Required for g_main_context_wakeup */ if (!OS.g_thread_supported ()) { OS.g_thread_init (null); @@ -905,7 +932,6 @@ char*[] args = [ "name".ptr, "--sync".ptr, null ]; char** a = args.ptr; if (!OS.gtk_init_check (&cnt, &a )) { - DWT.error (DWT.ERROR_NO_HANDLES, null, " [gtk_init_check() failed]"); } assert( cnt is 1 ); if (OS.GDK_WINDOWING_X11 ()) xDisplay = cast(void*) OS.GDK_DISPLAY (); @@ -1077,9 +1103,11 @@ return pixbuf; } -synchronized void deregister () { - for (int i=0; i<Displays.length; i++) { - if (this is Displays [i]) Displays [i] = null; +static void deregister (Display display) { + synchronized (Device.classinfo) { + for (int i=0; i<Displays.length; i++) { + if (display is Displays [i]) Displays [i] = null; + } } } @@ -1095,13 +1123,25 @@ */ protected override void destroy () { if (this is Default) Default = null; - deregister (); + deregister (this); destroyDisplay (); } void destroyDisplay () { } +static extern(C) int /*long*/ emissionFunc (GSignalInvocationHint* ihint, uint n_param_values, GValue* param_values, void* data) { + auto cb = cast(CallbackData*)data; + return cb.display.emissionProc( ihint, n_param_values, param_values, cb.data ); +} + +int /*long*/ emissionProc (GSignalInvocationHint* ihint, uint n_param_values, GValue* param_values, void* data) { + if (OS.gtk_widget_get_toplevel (OS.g_value_peek_pointer(param_values)) is data) { + OS.gtk_widget_set_direction (OS.g_value_peek_pointer(param_values), OS.GTK_TEXT_DIR_RTL); + } + return 1; +} + /** * Returns the display which the given thread is the * user-interface thread for, or null if the given thread @@ -1112,14 +1152,16 @@ * @param thread the user-interface thread * @return the display for the given thread */ -public static synchronized Display findDisplay (Thread thread) { - for (int i=0; i<Displays.length; i++) { - Display display = Displays [i]; - if (display !is null && display.thread is thread) { - return display; +public static Display findDisplay (Thread thread) { + synchronized (Device.classinfo) { + for (int i=0; i<Displays.length; i++) { + Display display = Displays [i]; + if (display !is null && display.thread is thread) { + return display; + } } + return null; } - return null; } /** @@ -1200,61 +1242,8 @@ addGdkEvent (OS.gdk_event_copy (event)); return 0; } - /* - * Feature in GTK. GTK implements modality by adding a grab - * to the GTK top level window. Normally, all mouse and - * keyboard events are delivered to child widgets and the - * shell when the grab is active. When an override redirect - * shell is created as a child of a dialog, then events are - * grabbed by the dialog instead of the override redirect - * shell. The fix is to add a temporary grab to the override - * redirect window when there is not already a grab in a - * child widget of the override redirect shell (for example, - * in a scroll bar). - */ - Shell shell = null; - Control control = null; - auto grabHandle = OS.gtk_grab_get_current (); - if (grabHandle !is null && OS.GTK_IS_WINDOW (cast(GTypeInstance*)grabHandle) && OS.gtk_window_get_modal (cast(GtkWindow*)grabHandle)) { - switch (eventType) { - case OS.GDK_KEY_PRESS: - case OS.GDK_KEY_RELEASE: - case OS.GDK_ENTER_NOTIFY: - case OS.GDK_LEAVE_NOTIFY: - case OS.GDK_BUTTON_PRESS: - case OS.GDK_2BUTTON_PRESS: - case OS.GDK_3BUTTON_PRESS: - case OS.GDK_BUTTON_RELEASE: - case OS.GDK_MOTION_NOTIFY: { - auto window = OS.GDK_EVENT_WINDOW (cast(GdkEventAny*)event); - do { - GtkWidget* handle; - OS.gdk_window_get_user_data (window, cast(void**) &handle); - if (handle !is null) { - Widget widget = getWidget (handle); - if (widget !is null && (null !is cast(Control)widget)) { - control = cast(Control) widget; - break; - } - } - } while ((window = OS.gdk_window_get_parent (window)) !is null); - default: - } - } - if (control !is null) { - shell = control.getShell (); - if ((shell.style & DWT.ON_TOP) !is 0) { - OS.gtk_grab_add (shell.shellHandle); - } - } - } OS.gtk_main_do_event (event); if (dispatchEvents is null) putGdkEvents (); - if (control !is null) { - if (shell !is null && !shell.isDisposed () && (shell.style & DWT.ON_TOP) !is 0) { - OS.gtk_grab_remove (shell.shellHandle); - } - } return 0; } @@ -1325,7 +1314,7 @@ * * @since 3.3 */ -public Widget findWidget (Widget widget, int id) { +public Widget findWidget (Widget widget, int /*long*/ id) { checkDevice (); return null; } @@ -1334,6 +1323,8 @@ version(LOG) Stderr.formatln( "Display {}:", __LINE__ ).flush; GtkWidgetClass* klass = cast(GtkWidgetClass*)g_class; klass.map = &fixedMapProcFunc; + oldFixedSizeAllocateProc = klass.size_allocate; + klass.size_allocate = &fixedSizeAllocateProc; } private static extern(C) void fixedMapProcFunc (GtkWidget * handle) { @@ -1343,11 +1334,19 @@ if (widget !is null) widget.fixedMapProc (handle); } +private static extern(C) static void fixedSizeAllocateProc (GtkWidget* handle, GtkAllocation* allocation) { + Display display = getCurrent (); + Widget widget = display.getWidget (handle); + if (widget !is null) return widget.fixedSizeAllocateProc (handle, allocation); + return oldFixedSizeAllocateProc(handle, allocation); +} + private static extern(C) void rendererClassInitProcFunc (void* g_class, void* class_data) { version(LOG) Stderr.formatln( "Display {}:", __LINE__ ).flush; GtkCellRendererClass* klass = cast(GtkCellRendererClass*)g_class; klass.render = &rendererRenderProcFunc; klass.get_size = &rendererGetSizeProcFunc; + } private static extern(C) void rendererGetSizeProcFunc( GtkCellRenderer *cell, @@ -1423,13 +1422,8 @@ * * @return the current display */ -public static synchronized Display getCurrent () { - Thread current = Thread.getThis (); - for (int i=0; i<Displays.length; i++) { - Display display = Displays [i]; - if (display !is null && display.thread is current) return display; - } - return null; +public static Display getCurrent () { + return findDisplay (Thread.getThis ()); } int getCaretBlinkTime () { @@ -1464,10 +1458,41 @@ public Control getCursorControl () { checkDevice(); int x, y; + GtkWidget* handle; + GtkWidget* user_data; auto window = OS.gdk_window_at_pointer (&x, &y); - if (window is null) return null; - GtkWidget* handle; - OS.gdk_window_get_user_data (window, cast(void**)&handle); + if (window !is null) { + OS.gdk_window_get_user_data (window, cast(void**)&user_data); + handle = user_data; + } else { + /* + * Feature in GTK. gdk_window_at_pointer() will not return a window + * if the pointer is over a foreign embedded window. The fix is to use + * XQueryPointer to find the containing GDK window. + */ + if (!OS.GDK_WINDOWING_X11 ()) return null; + OS.gdk_error_trap_push (); + int unusedInt; + uint unusedUInt; + uint unusedPtr; + uint buffer; + uint xWindow, xParent = OS.XDefaultRootWindow (xDisplay); + do { + if (OS.XQueryPointer (xDisplay, xParent, &unusedPtr, &buffer, &unusedInt, &unusedInt, &unusedInt, &unusedInt, &unusedUInt) is 0) { + handle = null; + break; + } + if ((xWindow = buffer) !is 0) { + xParent = xWindow; + auto gdkWindow = OS.gdk_window_lookup (xWindow); + if (gdkWindow !is null) { + OS.gdk_window_get_user_data (gdkWindow, cast(void**)&user_data); + if (user_data !is null) handle = user_data; + } + } + } while (xWindow !is 0); + OS.gdk_error_trap_pop (); + } if (handle is null) return null; do { Widget widget = getWidget (handle); @@ -1587,12 +1612,21 @@ public Object getData (String key) { checkDevice (); if (key is null) error (DWT.ERROR_NULL_ARGUMENT); - if (key ==/*eq*/ DISPATCH_EVENT_KEY) { + if (key.equals (DISPATCH_EVENT_KEY)) { return new ArrayWrapperInt(dispatchEvents); } + if (key.equals (GET_MODAL_DIALOG)) { + return modalDialog; + } + if (key.equals (GET_DIRECTION_PROC_KEY)) { + return new LONG (cast(int) &setDirectionProcFunc); + } + if (key.equals (GET_EMISSION_PROC_KEY)) { + return new LONG (cast(int) &emissionFunc); + } if (keys is null) return null; for (int i=0; i<keys.length; i++) { - if (keys [i] ==/*eq*/ key) return values [i]; + if (keys [i].equals(key)) return values [i]; } return null; } @@ -1667,9 +1701,11 @@ * * @return the default display */ -public static synchronized Display getDefault () { - if (Default is null) Default = new Display (); - return Default; +public static Display getDefault () { + synchronized (Device.classinfo) { + if (Default is null) Default = new Display (); + return Default; + } } // /+static bool isValidClass (Class clazz) { @@ -1826,6 +1862,10 @@ return synchronizer.getMessageCount (); } +Dialog getModalDialog () { + return modalDialog; +} + /** * Returns the work area, an EWMH property to store the size * and position of the screen not covered by dock and panel @@ -1972,6 +2012,23 @@ } /** + * Gets the synchronizer used by the display. + * + * @return the receiver's synchronizer + * + * @exception DWTException <ul> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> + * </ul> + * + * @since 3.4 + */ +public Synchronizer getSynchronizer () { + checkDevice (); + return synchronizer; +} + +/** * Returns the thread that has invoked <code>syncExec</code> * or null if no such runnable is currently being invoked by * the user-interface thread. @@ -1987,8 +2044,10 @@ * </ul> */ 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 @@ * </ul> */ 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<Displays.length; i++) { - if (Displays [i] is null) { - Displays [i] = this; - return; +static void register (Display display) { + synchronized (Device.classinfo) { + for (int i=0; i<Displays.length; i++) { + if (Displays [i] is null) { + Displays [i] = display; + return; + } } + Display [] newDisplays = new Display [Displays.length + 4]; + System.arraycopy (Displays, 0, newDisplays, 0, Displays.length); + newDisplays [Displays.length] = display; + Displays = newDisplays; } - Display [] newDisplays = new Display [Displays.length + 4]; - System.arraycopy (Displays, 0, newDisplays, 0, Displays.length); - newDisplays [Displays.length] = this; - Displays = newDisplays; } /** @@ -3070,6 +3145,7 @@ void releaseDisplay () { /* Dispose xfilter callback */ + OS.gdk_window_remove_filter(null, &filterProcFunc, null); /* Dispose checkIfEvent callback */ @@ -3091,6 +3167,8 @@ /* Dispose the set direction callback */ + /* Dispose the emission proc callback */ + /* Dispose the set direction callback */ /* Dispose the caret callback */ @@ -3146,6 +3224,8 @@ COLOR_WIDGET_DARK_SHADOW = COLOR_WIDGET_NORMAL_SHADOW = COLOR_WIDGET_LIGHT_SHADOW = COLOR_WIDGET_HIGHLIGHT_SHADOW = COLOR_WIDGET_BACKGROUND = COLOR_WIDGET_BORDER = COLOR_LIST_FOREGROUND = COLOR_LIST_BACKGROUND = COLOR_LIST_SELECTION = COLOR_LIST_SELECTION_TEXT = + COLOR_WIDGET_FOREGROUND = COLOR_TITLE_FOREGROUND = COLOR_TITLE_BACKGROUND = COLOR_TITLE_BACKGROUND_GRADIENT = + COLOR_TITLE_INACTIVE_FOREGROUND = COLOR_TITLE_INACTIVE_BACKGROUND = COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT = COLOR_INFO_BACKGROUND = COLOR_INFO_FOREGROUND = null; /* Dispose the event callback */ @@ -3166,10 +3246,21 @@ /* Release references */ popups = null; thread = null; - activeShell = null; - lastWidget = null; - indexTable = null; - widgetTable = null; + lastWidget = activeShell = null; + //flushData = null; + closures = null; + indexTable = signalIds = treeSelection = null; + widgetTable = modalShells = null; + data = null; + values = null; + keys = null; + windowManager = null; + eventTable = filterTable = null; + modalDialog = null; + flushRect = null; + exposeEvent = null; + visibilityEvent = null; + idleLock = null; } /** @@ -3219,7 +3310,7 @@ } void removeIdleProc () { - synchronized(idleLock) { + synchronized (idleLock) { if (idleHandle !is 0) OS.g_source_remove (idleHandle); idleNeeded = false; idleHandle = 0; @@ -3455,8 +3546,12 @@ return; } } - - if (key==/*eq*/ ADD_WIDGET_KEY) { + if (key.equals (SET_MODAL_DIALOG)) { + setModalDialog (cast(Dialog) data); + return; + } + + if (key.equals (ADD_WIDGET_KEY)) { auto wrap = cast(ArrayWrapperObject) value; if( wrap is null ) DWT.error(DWT.ERROR_INVALID_ARGUMENT, null, " []"); Object [] data = wrap.array; @@ -3564,12 +3659,43 @@ } int /*long*/ setDirectionProc (GtkWidget* widget, int /*long*/ direction) { OS.gtk_widget_set_direction (widget, direction); + if (OS.GTK_IS_MENU_ITEM (widget)) { + auto submenu = OS.gtk_menu_item_get_submenu (widget); + if (submenu !is null) { + OS.gtk_widget_set_direction (submenu, cast(int)/*64*/ direction); + OS.gtk_container_forall (cast(GtkContainer*)submenu, cast(GtkCallback)&setDirectionProcFunc, cast(void*)direction); + } + } if (OS.GTK_IS_CONTAINER (cast(GTypeInstance*)widget)) { OS.gtk_container_forall (cast(GtkContainer*)widget, cast(GtkCallback)&setDirectionProcFunc, cast(void*)direction); } return 0; } +void setModalDialog (Dialog modalDailog) { + this.modalDialog = modalDailog; + Shell [] shells = getShells (); + for (int i=0; i<shells.length; i++) shells [i].updateModal (); +} + +void setModalShell (Shell shell) { + if (modalShells is null) modalShells = new Shell [4]; + int index = 0, length = modalShells.length; + while (index < length) { + if (modalShells [index] is shell) return; + if (modalShells [index] is null) break; + index++; + } + if (index is length) { + Shell [] newModalShells = new Shell [length + 4]; + System.arraycopy (modalShells, 0, newModalShells, 0, length); + modalShells = newModalShells; + } + modalShells [index] = shell; + Shell [] shells = getShells (); + for (int i=0; i<shells.length; i++) shells [i].updateModal (); +} + /** * Sets the synchronizer used by the display to be * the argument, which can not be null. @@ -3588,10 +3714,15 @@ public void setSynchronizer (Synchronizer synchronizer) { checkDevice (); if (synchronizer is null) error (DWT.ERROR_NULL_ARGUMENT); - if (this.synchronizer !is null) { - this.synchronizer.runAsyncMessages(true); + if (synchronizer is this.synchronizer) return; + Synchronizer oldSynchronizer; + synchronized (Device.classinfo) { + oldSynchronizer = this.synchronizer; + this.synchronizer = synchronizer; } - this.synchronizer = synchronizer; + if (oldSynchronizer !is null) { + oldSynchronizer.runAsyncMessages(true); + } } void showIMWindow (Control control) { @@ -3965,14 +4096,18 @@ * @see #asyncExec */ public void syncExec (Runnable runnable) { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - synchronized (idleLock) { - if (idleNeeded && idleHandle is 0) { - //NOTE: calling unlocked function in OS + Synchronizer synchronizer; + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + synchronizer = this.synchronizer; + synchronized (idleLock) { + if (idleNeeded && idleHandle is 0) { + //NOTE: calling unlocked function in OS idleProcCallbackData.display = this; idleProcCallbackData.data = cast(void*)0; //PORTING_TODO: was _g_idle_add, calling directly idleHandle = OS.g_idle_add (&idleProcFunc, &idleProcCallbackData); + } } } synchronizer.syncExec (runnable); @@ -4021,9 +4156,11 @@ * @see #sleep */ public void wake () { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - if (thread is Thread.getThis ()) return; - wakeThread (); + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + if (thread is Thread.getThis ()) return; + wakeThread (); + } } void wakeThread () {
--- a/dwt/widgets/Event.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/Event.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
--- a/dwt/widgets/EventTable.d Mon May 12 15:36:37 2008 +0200 +++ b/dwt/widgets/EventTable.d Mon May 12 19:13:01 2008 +0200 @@ -32,10 +32,28 @@ int [] types; Listener [] listeners; int level; + static final int GROW_SIZE = 4; + +public Listener [] getListeners (int eventType) { + if (types is null) return new Listener [0]; + int count = 0; + for (int i=0; i<types.length; i++) { + if (types [i] is eventType) count++; + } + if (count is 0) return new Listener [0]; + Listener [] result = new Listener [count]; + count = 0; + for (int i=0; i<types.length; i++) { + if (types [i] is eventType) { + result [count++] = listeners [i]; + } + } + return result; +} public void hook (int eventType, Listener listener) { - if (types is null) types = new int [4]; - if (listeners is null) listeners = new Listener [4]; + if (types is null) types = new int [GROW_SIZE]; + if (listeners is null) listeners = new Listener [GROW_SIZE]; int length = types.length, index = length - 1; while (index >= 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; }
--- 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)) {
--- 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 @@ * </ul> */ 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 @@ * </ul> */ 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. + * <p> + * This is an index into the FilterExtensions array and + * the FilterNames array. + * </p> + * + * @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. + * <p> + * This is an index into the FilterExtensions array and + * the FilterNames array. + * </p> + * + * @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; } +}
--- 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 @@ * </ul> */ 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 @@ * </ul> */ 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);
--- /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; + } +} + +}
--- 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);
--- 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++) {
--- 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) {
--- 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 <code>Menu</code>. * @@ -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;
--- 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 @@ * </ul> */ 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() {
--- 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 */
--- 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;
--- 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;
--- 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 <code>true</code> if the receiver is enabled, and * <code>false</code> 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); + } } }
--- 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; }
--- 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); + } }
--- 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); }
--- 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. + * <p> + * Note that this value is platform dependent, based upon + * the native widget implementation. + * </p> + */ + 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. * <p> @@ -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++;
--- 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 {
--- 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. *
--- 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
--- 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;
--- 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 );
--- 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); } /**
--- 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];
--- 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 (); }
--- 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); } }
--- 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<rects.length; i++) { Rectangle rect = rects [i]; - OS.gdk_draw_rectangle (window, gc, 0, rect.x, rect.y, rect.width, rect.height); + int x = rect.x; + if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) x = parent.getClientWidth () - rect.width - x; + OS.gdk_draw_rectangle (window, gc, 0, x, rect.y, rect.width, rect.height); } OS.g_object_unref (gc); } @@ -373,6 +376,7 @@ } bool grab () { + auto cursor = this.cursor !is null ? this.cursor.handle : null; int result = OS.gdk_pointer_grab (window, false, OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_RELEASE_MASK, window, cursor, OS.GDK_CURRENT_TIME); return result is OS.GDK_GRAB_SUCCESS; } @@ -417,6 +421,9 @@ Event event = new Event (); event.x = oldX + xChange; event.y = oldY + yChange; + if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) { + event.x = parent.getClientWidth () - event.width - event.x; + } if ((style & DWT.RESIZE) !is 0) { resizeRectangles (xChange, yChange); sendEvent (DWT.Resize, event); @@ -513,6 +520,7 @@ } override int gtk_motion_notify_event (GtkWidget* widget, GdkEventMotion* eventPtr) { + auto cursor = this.cursor !is null ? this.cursor.handle : null; if (cursor !is lastCursor) { ungrab (); grabbed = grab (); @@ -640,6 +648,7 @@ if (yChange < 0 && ((style & DWT.UP) is 0)) yChange = 0; if (yChange > 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; } /**
--- 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. * <p> @@ -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); }
--- 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
--- 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);
--- 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 <code>DWT</code>. + * + * @param eventType the type of event to listen for + * @return an array of listeners that will be notified when the event occurs + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @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);