Point minimumSize(int wHint, int hHint, boolean flushCache) { Control[] children = _getChildren(); int width = 0, height = 0; for (int i = 0; i < children.length; i++) { Control child = children[i]; int index = 0; int count = 0; long /*int*/ list = OS.gtk_container_get_children(handle); if (list != 0) { count = OS.g_list_length(list); OS.g_list_free(list); } while (index < count) { if (items[index].control == child) break; index++; } if (index == count) { Rectangle rect = child.getBounds(); width = Math.max(width, rect.x + rect.width); height = Math.max(height, rect.y + rect.height); } else { Point size = child.computeSize(wHint, hHint, flushCache); width = Math.max(width, size.x); height = Math.max(height, size.y); } } return new Point(width, height); }
void destroyItem(TabItem item) { int index = 0; int itemCount = getItemCount(); while (index < itemCount) { if (items[index] == item) break; index++; } if (index == itemCount) error(SWT.ERROR_ITEM_NOT_REMOVED); int oldIndex = OS.gtk_notebook_get_current_page(handle); OS.g_signal_handlers_block_matched(handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, SWITCH_PAGE); OS.gtk_notebook_remove_page(handle, index); OS.g_signal_handlers_unblock_matched(handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, SWITCH_PAGE); System.arraycopy(items, index + 1, items, index, --itemCount - index); items[itemCount] = null; if (index == oldIndex) { int newIndex = OS.gtk_notebook_get_current_page(handle); if (newIndex != -1) { Control control = items[newIndex].getControl(); if (control != null && !control.isDisposed()) { control.setBounds(getClientArea()); control.setVisible(true); } Event event = new Event(); event.item = items[newIndex]; sendSelectionEvent(SWT.Selection, event, true); // the widget could be destroyed at this point } } }
private void onDispose() { if (control == null) return; this.Release(); if (controlListener != null) { control.removeListener(SWT.Dispose, controlListener); control.removeListener(SWT.DragDetect, controlListener); } controlListener = null; control.setData(DND.DRAG_SOURCE_KEY, null); control = null; transferAgents = null; }
/** * Sets the control that is shown when the item is expanded. * * @param control the new control (or null) * @exception IllegalArgumentException * <ul> * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree * </ul> * * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setControl(Control control) { checkWidget(); if (control != null) { if (control.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); if (control.parent != parent) error(SWT.ERROR_INVALID_PARENT); } if (this.control == control) return; this.control = control; if (control != null) { control.setVisible(expanded); } parent.layoutItems(0, true); }
int setBounds(int x, int y, int width, int height, boolean move, boolean resize) { int result = super.setBounds(x, y, width, height, move, resize); if ((result & RESIZED) != 0) { int index = getSelectionIndex(); if (index != -1) { TabItem item = items[index]; Control control = item.control; if (control != null && !control.isDisposed()) { control.setBounds(getClientArea()); } } } return result; }
void setSelection(int index, boolean notify) { if (index < 0) return; int oldIndex = OS.gtk_notebook_get_current_page(handle); if (oldIndex == index) return; if (oldIndex != -1) { TabItem item = items[oldIndex]; Control control = item.control; if (control != null && !control.isDisposed()) { control.setVisible(false); } } OS.g_signal_handlers_block_matched(handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, SWITCH_PAGE); OS.gtk_notebook_set_current_page(handle, index); OS.g_signal_handlers_unblock_matched(handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, SWITCH_PAGE); int newIndex = OS.gtk_notebook_get_current_page(handle); if (newIndex != -1) { TabItem item = items[newIndex]; Control control = item.control; if (control != null && !control.isDisposed()) { control.setBounds(getClientArea()); control.setVisible(true); } if (notify) { Event event = new Event(); event.item = item; sendSelectionEvent(SWT.Selection, event, true); } } }
/** * Creates a new <code>DragSource</code> to handle dragging from the specified <code>Control * </code>. Creating an instance of a DragSource may cause system resources to be allocated * depending on the platform. It is therefore mandatory that the DragSource instance be disposed * when no longer required. * * @param control the <code>Control</code> that the user clicks on to initiate the drag * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of * DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK * @exception SWTException * <ul> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass * </ul> * * @exception SWTError * <ul> * <li>ERROR_CANNOT_INIT_DRAG - unable to initiate drag source; this will occur if more than * one drag source is created for a control or if the operating system will not allow * the creation of the drag source * </ul> * <p>NOTE: ERROR_CANNOT_INIT_DRAG should be an SWTException, since it is a recoverable error, * but can not be changed due to backward compatibility. * @see Widget#dispose * @see DragSource#checkSubclass * @see DND#DROP_NONE * @see DND#DROP_COPY * @see DND#DROP_MOVE * @see DND#DROP_LINK */ public DragSource(Control control, int style) { super(control, checkStyle(style)); this.control = control; if (control.getData(DND.DRAG_SOURCE_KEY) != null) { DND.error(DND.ERROR_CANNOT_INIT_DRAG); } control.setData(DND.DRAG_SOURCE_KEY, this); createCOMInterfaces(); this.AddRef(); controlListener = new Listener() { public void handleEvent(Event event) { if (event.type == SWT.Dispose) { if (!DragSource.this.isDisposed()) { DragSource.this.dispose(); } } if (event.type == SWT.DragDetect) { if (!DragSource.this.isDisposed()) { DragSource.this.drag(event); } } } }; control.addListener(SWT.Dispose, controlListener); control.addListener(SWT.DragDetect, controlListener); this.addListener( SWT.Dispose, new Listener() { public void handleEvent(Event e) { DragSource.this.onDispose(); } }); Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT); if (effect instanceof DragSourceEffect) { dragEffect = (DragSourceEffect) effect; } else if (control instanceof Tree) { dragEffect = new TreeDragSourceEffect((Tree) control); } else if (control instanceof Table) { dragEffect = new TableDragSourceEffect((Table) control); } }
void resizeControl() { if (control != null && !control.isDisposed()) { /* * Set the size and location of the control * separately to minimize flashing in the * case where the control does not resize * to the size that was requested. This * case can occur when the control is a * combo box. */ Rectangle itemRect = getBounds(); control.setSize(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; control.setLocation(rect.x, rect.y); } }
/** * Sets the control that is used to fill the bounds of the item when the item is a <code>SEPARATOR * </code>. * * @param control the new control * @exception IllegalArgumentException * <ul> * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree * </ul> * * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setControl(Control control) { checkWidget(); if (control != null) { if (control.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); if (control.parent != parent) error(SWT.ERROR_INVALID_PARENT); } if ((style & SWT.SEPARATOR) == 0) return; if (this.control == control) return; this.control = control; parent.relayout(); }
Widget[] computeTabList() { if (isTabGroup()) { if (getEnabled()) { if ((style & SWT.SEPARATOR) != 0) { if (control != null) return control.computeTabList(); } else { return new Widget[] {this}; } } } return new Widget[0]; }
void setBounds(int x, int y, int width, int height, boolean move, boolean size) { redraw(); int headerHeight = parent.getBandHeight(); if (move) { if (imageHeight > headerHeight) { y += (imageHeight - headerHeight); } this.x = x; this.y = y; redraw(); } if (size) { this.width = width; this.height = height; redraw(); } if (control != null && !control.isDisposed()) { if (move) control.setLocation(x + BORDER, y + headerHeight); if (size) control.setSize(Math.max(0, width - 2 * BORDER), Math.max(0, height - BORDER)); } }
void resizeControl(int yScroll) { if (control != null && !control.isDisposed()) { boolean visible = OS.gtk_expander_get_expanded(handle); if (visible) { int x = OS.GTK_WIDGET_X(clientHandle); int y = OS.GTK_WIDGET_Y(clientHandle); if (x != -1 && y != -1) { int width = OS.GTK_WIDGET_WIDTH(clientHandle); int height = OS.GTK_WIDGET_HEIGHT(clientHandle); int[] property = new int[1]; OS.gtk_widget_style_get(handle, OS.focus_line_width, property, 0); y += property[0] * 2; height -= property[0] * 2; /* * Feature in GTK. When the ExpandBar is resize too small the control * shows up on top of the vertical scrollbar. This happen because the * GtkExpander does not set the size of child smaller than the request * size of its parent and because the control is not parented in the * hierarchy of the GtkScrolledWindow. * The fix is calculate the width ourselves when the scrollbar is visible. */ ScrollBar vBar = parent.verticalBar; if (vBar != null) { if (OS.GTK_WIDGET_VISIBLE(vBar.handle)) { width = OS.GTK_WIDGET_WIDTH(parent.scrolledHandle) - parent.vScrollBarWidth() - 2 * parent.spacing; } } control.setBounds(x, y - yScroll, width, Math.max(0, height), true, true); } } control.setVisible(visible); } }
long /*int*/ gtk_switch_page(long /*int*/ widget, long /*int*/ page, long /*int*/ page_num) { int index = OS.gtk_notebook_get_current_page(handle); if (index != -1) { Control control = items[index].getControl(); if (control != null && !control.isDisposed()) { control.setVisible(false); } } TabItem item = items[(int) /*64*/ page_num]; Control control = item.getControl(); if (control != null && !control.isDisposed()) { control.setBounds(getClientArea()); control.setVisible(true); } Event event = new Event(); event.item = item; sendSelectionEvent(SWT.Selection, event, false); return 0; }
void scrollInPixels(int destX, int destY, int x, int y, int width, int height, boolean all) { forceResize(); boolean isFocus = caret != null && caret.isFocusCaret(); if (isFocus) caret.killFocus(); RECT sourceRect = new RECT(); OS.SetRect(sourceRect, x, y, x + width, y + height); RECT clientRect = new RECT(); OS.GetClientRect(handle, clientRect); if (OS.IntersectRect(clientRect, sourceRect, clientRect)) { if (OS.IsWinCE) { OS.UpdateWindow(handle); } else { int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN; OS.RedrawWindow(handle, null, 0, flags); } } int deltaX = destX - x, deltaY = destY - y; if (findImageControl() != null) { if (OS.IsWinCE) { OS.InvalidateRect(handle, sourceRect, true); } else { int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE; if (all) flags |= OS.RDW_ALLCHILDREN; OS.RedrawWindow(handle, sourceRect, 0, flags); } OS.OffsetRect(sourceRect, deltaX, deltaY); if (OS.IsWinCE) { OS.InvalidateRect(handle, sourceRect, true); } else { int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE; if (all) flags |= OS.RDW_ALLCHILDREN; OS.RedrawWindow(handle, sourceRect, 0, flags); } } else { int flags = OS.SW_INVALIDATE | OS.SW_ERASE; /* * Feature in Windows. If any child in the widget tree partially * intersects the scrolling rectangle, Windows moves the child * and copies the bits that intersect the scrolling rectangle but * does not redraw the child. * * Feature in Windows. When any child in the widget tree does not * intersect the scrolling rectangle but the parent does intersect, * Windows does not move the child. This is the documented (but * strange) Windows behavior. * * The fix is to not use SW_SCROLLCHILDREN and move the children * explicitly after scrolling. */ // if (all) flags |= OS.SW_SCROLLCHILDREN; OS.ScrollWindowEx(handle, deltaX, deltaY, sourceRect, null, 0, null, flags); } if (all) { Control[] children = _getChildren(); for (int i = 0; i < children.length; i++) { Control child = children[i]; Rectangle rect = child.getBoundsInPixels(); if (Math.min(x + width, rect.x + rect.width) >= Math.max(x, rect.x) && Math.min(y + height, rect.y + rect.height) >= Math.max(y, rect.y)) { child.setLocationInPixels(rect.x + deltaX, rect.y + deltaY); } } } if (isFocus) caret.setFocus(); }
/** * Sets the control that is used to fill the bounds of the item when the item is a <code>SEPARATOR * </code>. * * @param control the new control * @exception IllegalArgumentException * <ul> * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree * </ul> * * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setControl(Control control) { checkWidget(); if (control != null) { if (control.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); if (control.parent != parent) error(SWT.ERROR_INVALID_PARENT); } if ((style & SWT.SEPARATOR) == 0) return; this.control = control; /* * Feature in Windows. When a tool bar wraps, tool items * with the style BTNS_SEP are used as wrap points. This * means that controls that are placed on top of separator * items are not positioned properly. Also, vertical tool * bars are implemented using TB_SETROWS to set the number * of rows. When a control is placed on top of a separator, * the height of the separator does not grow. The fix in * both cases is to change the tool item style from BTNS_SEP * to BTNS_BUTTON, causing the item to wrap like a tool item * button. The new tool item button is disabled to avoid key * traversal and the image is set to I_IMAGENONE to avoid * getting the first image from the image list. */ if ((parent.style & (SWT.WRAP | SWT.VERTICAL)) != 0) { boolean changed = false; long /*int*/ hwnd = parent.handle; TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_STYLE | OS.TBIF_STATE; OS.SendMessage(hwnd, OS.TB_GETBUTTONINFO, id, info); if (control == null) { if ((info.fsStyle & OS.BTNS_SEP) == 0) { changed = true; info.fsStyle &= ~(OS.BTNS_BUTTON | OS.BTNS_SHOWTEXT); info.fsStyle |= OS.BTNS_SEP; if ((state & DISABLED) != 0) { info.fsState &= ~OS.TBSTATE_ENABLED; } else { info.fsState |= OS.TBSTATE_ENABLED; } } } else { if ((info.fsStyle & OS.BTNS_SEP) != 0) { changed = true; info.fsStyle &= ~OS.BTNS_SEP; info.fsStyle |= OS.BTNS_BUTTON | OS.BTNS_SHOWTEXT; info.fsState &= ~OS.TBSTATE_ENABLED; info.dwMask |= OS.TBIF_IMAGE; info.iImage = OS.I_IMAGENONE; } } if (changed) { OS.SendMessage(hwnd, OS.TB_SETBUTTONINFO, id, info); /* * Bug in Windows. When TB_SETBUTTONINFO changes the * style of a tool item from BTNS_SEP to BTNS_BUTTON * and the tool bar is wrapped, the tool bar does not * redraw properly. Windows uses separator items as * wrap points and sometimes draws etching above or * below and entire row. The fix is to redraw the * tool bar. */ if (OS.SendMessage(hwnd, OS.TB_GETROWS, 0, 0) > 1) { OS.InvalidateRect(hwnd, null, true); } } } resizeControl(); }
private void drag(Event dragEvent) { DNDEvent event = new DNDEvent(); event.widget = this; event.x = dragEvent.x; event.y = dragEvent.y; event.time = OS.GetMessageTime(); event.doit = true; notifyListeners(DND.DragStart, event); if (!event.doit || transferAgents == null || transferAgents.length == 0) return; int[] pdwEffect = new int[1]; int operations = opToOs(getStyle()); Display display = control.getDisplay(); String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; // $NON-NLS-1$ Object oldValue = display.getData(key); display.setData(key, Boolean.TRUE); ImageList imagelist = null; Image image = event.image; hwndDrag = 0; topControl = null; if (image != null) { imagelist = new ImageList(SWT.NONE); imagelist.add(image); topControl = control.getShell(); /* * Bug in Windows. The image is inverted if the shell is RIGHT_TO_LEFT. * The fix is to create a transparent window that covers the shell client * area and use it during the drag to prevent the image from being inverted. * On XP if the shell is RTL, the image is not displayed. */ int offsetX = event.offsetX; hwndDrag = topControl.handle; if ((topControl.getStyle() & SWT.RIGHT_TO_LEFT) != 0) { offsetX = image.getBounds().width - offsetX; RECT rect = new RECT(); OS.GetClientRect(topControl.handle, rect); hwndDrag = OS.CreateWindowEx( OS.WS_EX_TRANSPARENT | OS.WS_EX_NOINHERITLAYOUT, WindowClass, null, OS.WS_CHILD | OS.WS_CLIPSIBLINGS, 0, 0, rect.right - rect.left, rect.bottom - rect.top, topControl.handle, 0, OS.GetModuleHandle(null), null); OS.ShowWindow(hwndDrag, OS.SW_SHOW); } OS.ImageList_BeginDrag(imagelist.getHandle(), 0, offsetX, event.offsetY); /* * Feature in Windows. When ImageList_DragEnter() is called, * it takes a snapshot of the screen If a drag is started * when another window is in front, then the snapshot will * contain part of the other window, causing pixel corruption. * The fix is to force all paints to be delivered before * calling ImageList_DragEnter(). */ if (OS.IsWinCE) { OS.UpdateWindow(topControl.handle); } else { int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN; OS.RedrawWindow(topControl.handle, null, 0, flags); } POINT pt = new POINT(); pt.x = dragEvent.x; pt.y = dragEvent.y; OS.MapWindowPoints(control.handle, 0, pt, 1); RECT rect = new RECT(); OS.GetWindowRect(hwndDrag, rect); OS.ImageList_DragEnter(hwndDrag, pt.x - rect.left, pt.y - rect.top); } int result = COM.DRAGDROP_S_CANCEL; try { result = COM.DoDragDrop(iDataObject.getAddress(), iDropSource.getAddress(), operations, pdwEffect); } finally { // ensure that we don't leave transparent window around if (hwndDrag != 0) { OS.ImageList_DragLeave(hwndDrag); OS.ImageList_EndDrag(); imagelist.dispose(); if (hwndDrag != topControl.handle) OS.DestroyWindow(hwndDrag); hwndDrag = 0; topControl = null; } display.setData(key, oldValue); } int operation = osToOp(pdwEffect[0]); if (dataEffect == DND.DROP_MOVE) { operation = (operation == DND.DROP_NONE || operation == DND.DROP_COPY) ? DND.DROP_TARGET_MOVE : DND.DROP_MOVE; } else { if (dataEffect != DND.DROP_NONE) { operation = dataEffect; } } event = new DNDEvent(); event.widget = this; event.time = OS.GetMessageTime(); event.doit = (result == COM.DRAGDROP_S_DROP); event.detail = operation; notifyListeners(DND.DragEnd, event); dataEffect = DND.DROP_NONE; }