All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.swt.widgets.Composite Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2000, 2020 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.widgets;


import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.cairo.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.internal.gtk3.*;
import org.eclipse.swt.internal.gtk4.*;

/**
 * Instances of this class are controls which are capable
 * of containing other controls.
 * 
*
Styles:
*
NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED
*
Events:
*
(none)
*
*

* Note: The NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, * and NO_REDRAW_RESIZE styles are intended for use with Canvas. * They can be used with Composite if you are drawing your own, but their * behavior is undefined if they are used with subclasses of Composite other * than Canvas. *

* Note: The CENTER style, although undefined for composites, has the * same value as EMBEDDED which is used to embed widgets from other * widget toolkits into SWT. On some operating systems (GTK), this may cause * the children of this composite to be obscured. *

* This class may be subclassed by custom control implementors * who are building controls that are constructed from aggregates * of other controls. *

* * @see Canvas * @see Composite snippets * @see Sample code and further information */ public class Composite extends Scrollable { /** * the handle to the OS resource * (Warning: This field is platform dependent) *

* IMPORTANT: This field is not part of the SWT * public API. It is marked public only so that it can be shared * within the packages provided by SWT. It is not available on all * platforms and should never be accessed from application code. *

* * @noreference This field is not intended to be referenced by clients. */ public long embeddedHandle; long imHandle, socketHandle; Layout layout; Control[] tabList; int layoutCount, backgroundMode; /** * When this field is set, it indicates that a child widget of this Composite * needs to have its clip set to its allocation. This is because on GTK3.20+ * some widgets (like Combo) have their clips merged with that of their parent. */ long fixClipHandle; /** * If fixClipHandle is set, then the fixClipMap HashMap contains children * of fixClipHandle that also need to have their clips adjusted. * *

Each key is a Control which needs to have its clip adjusted, and each value * is an array of handles (descendants of the Control) ordered by widget hierarchy. * This array will be traversed in-order to adjust the clipping of each element. * See bug 500703 and 535323.

*/ Map fixClipMap = new HashMap<> (); static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$ Shell popupChild; /** * If set to {@code true}, child widgets with negative y coordinate GTK allocation * will not be drawn. Only relevant if such child widgets are being * drawn via propagateDraw(), such as Tree/Table editing widgets. * * See bug 535978 and bug 547986. */ boolean noChildDrawing = false; /** * A HashMap of child widgets that keeps track of which child has had their * GdkWindow lowered/raised. Only relevant if such child widgets are being * drawn via propagateDraw(), such as Tree/Table editing widgets. * * See bug 535978. */ HashMap childrenLowered = new HashMap<>(); Composite () { /* Do nothing */ } /** * Constructs a new instance of this class given its parent * and a style value describing its behavior and appearance. *

* The style value is either one of the style constants defined in * class SWT which is applicable to instances of this * class, or must be built by bitwise OR'ing together * (that is, using the int "|" operator) two or more * of those SWT style constants. The class description * lists the style constants that are applicable to the class. * Style bits are also inherited from superclasses. *

* * @param parent a widget which will be the parent of the new instance (cannot be null) * @param style the style of widget to construct * * @exception IllegalArgumentException
    *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • *
* @exception SWTException
    *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
  • *
* * @see SWT#NO_BACKGROUND * @see SWT#NO_FOCUS * @see SWT#NO_MERGE_PAINTS * @see SWT#NO_REDRAW_RESIZE * @see SWT#NO_RADIO_GROUP * @see SWT#EMBEDDED * @see SWT#DOUBLE_BUFFERED * @see Widget#getStyle */ public Composite (Composite parent, int style) { super (parent, checkStyle (style)); /* * Cache the NO_BACKGROUND flag for use in the Cairo setRegion() * implementation. Only relevant to GTK3.10+, see bug 475784. */ if ((style & SWT.NO_BACKGROUND) != 0) { cachedNoBackground = true; } } static int checkStyle (int style) { style &= ~SWT.NO_BACKGROUND; style &= ~SWT.TRANSPARENT; return style; } Control[] _getChildren () { long parentHandle = parentingHandle(); if (GTK.GTK4) { ArrayList childrenList = new ArrayList<>(); for (long child = GTK4.gtk_widget_get_first_child(parentHandle); child != 0; child = GTK4.gtk_widget_get_next_sibling(child)) { Widget childWidget = display.getWidget(child); if (childWidget != null && childWidget instanceof Control && childWidget != this) { childrenList.add((Control)childWidget); } } return childrenList.toArray(new Control[childrenList.size()]); } else { long list = GTK3.gtk_container_get_children (parentHandle); if (list == 0) return new Control [0]; int count = OS.g_list_length (list); Control [] children = new Control [count]; int i = 0; long temp = list; while (temp != 0) { long handle = OS.g_list_data (temp); if (handle != 0) { Widget widget = display.getWidget (handle); if (widget != null && widget != this) { if (widget instanceof Control) { children [i++] = (Control) widget; } } } temp = OS.g_list_next (temp); } OS.g_list_free (list); if (i == count) return children; Control [] newChildren = new Control [i]; System.arraycopy (children, 0, newChildren, 0, i); return newChildren; } } Control [] _getTabList () { if (tabList == null) return tabList; int count = 0; for (int i=0; i *
  • ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed
  • *
  • ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver
  • * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @deprecated use {@link Composite#layout(Control[], int)} instead * @since 3.1 */ @Deprecated public void changed (Control[] changed) { layout(changed, SWT.DEFER); } @Override void checkBuffered () { if ((style & SWT.DOUBLE_BUFFERED) == 0 && (style & SWT.NO_BACKGROUND) != 0) { return; } super.checkBuffered(); } @Override protected void checkSubclass () { /* Do nothing - Subclassing is allowed */ } @Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) { checkWidget (); display.runSkin(); if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0; if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0; Point size; if (layout != null) { if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { changed |= (state & LAYOUT_CHANGED) != 0; size = DPIUtil.autoScaleUp(layout.computeSize (this, DPIUtil.autoScaleDown(wHint), DPIUtil.autoScaleDown(hHint), changed)); state &= ~LAYOUT_CHANGED; } else { size = new Point (wHint, hHint); } } else { size = minimumSize (wHint, hHint, changed); if (size.x == 0) size.x = DEFAULT_WIDTH; if (size.y == 0) size.y = DEFAULT_HEIGHT; } if (wHint != SWT.DEFAULT) size.x = wHint; if (hHint != SWT.DEFAULT) size.y = hHint; Rectangle trim = DPIUtil.autoScaleUp (computeTrim (0, 0, DPIUtil.autoScaleDown(size.x), DPIUtil.autoScaleDown(size.y))); return new Point (trim.width, trim.height); } @Override Widget [] computeTabList () { Widget result [] = super.computeTabList (); if (result.length == 0) return result; Control [] list = tabList != null ? _getTabList () : _getChildren (); for (int i=0; i= 4.") .printStackTrace (); } } else { socketHandle = GTK.gtk_socket_new (); if (socketHandle == 0) error (SWT.ERROR_NO_HANDLES); GTK3.gtk_container_add (handle, socketHandle); } } } if (!GTK.GTK4) { if ((style & SWT.NO_REDRAW_RESIZE) != 0 && (style & SWT.RIGHT_TO_LEFT) == 0) { GTK3.gtk_widget_set_redraw_on_allocate (handle, false); } /* * Bug in GTK. When a widget is double buffered and the back * pixmap is null, the double buffer pixmap is filled with the * background of the widget rather than the current contents of * the screen. If nothing is drawn during an expose event, * the pixels are altered. The fix is to clear double buffering * when NO_BACKGROUND is set and DOUBLE_BUFFERED * is not explicitly set. */ if ((style & SWT.DOUBLE_BUFFERED) == 0 && (style & SWT.NO_BACKGROUND) != 0) { GTK3.gtk_widget_set_double_buffered (handle, false); } } } /** * Iterates though the array of child widgets that need to have their clips * adjusted, and calls Control.adjustChildClipping() on it. * * The default implementation in Composite is: if a child has a negative clip, adjust it. * Also check if the child's allocation is negative, and adjust it as necessary. * *

    If the array is empty this method just returns. See bug 500703, and 539367.

    */ void fixClippings () { if (fixClipHandle == 0 || fixClipMap.isEmpty()) { return; } else { Control [] children = _getChildren(); for (Control child : children) { if (fixClipMap.containsKey(child)) { long [] childHandles = fixClipMap.get(child); for (long widget : childHandles) { child.adjustChildClipping(widget); } } } } } @Override void adjustChildClipping (long widget) { GtkRequisition minimumSize = new GtkRequisition (); GtkRequisition naturalSize = new GtkRequisition (); GtkAllocation clip = new GtkAllocation (); GtkAllocation allocation = new GtkAllocation (); GTK.gtk_widget_get_allocation(widget, allocation); GTK3.gtk_widget_get_clip(widget, clip); /* * If the clip is negative, add the x coordinate to the width * and set the x coordinate to 0. */ if (clip.x < 0) { /* * Some "transient" widgets like menus get allocations of * {-1, -1, 1, 1}. Check to make sure this isn't the case * before proceeding. */ if (allocation.x < -1 && (allocation.width > 1 || allocation.height > 1)) { // Adjust the allocation just like the clip, if it's negative allocation.width = allocation.width + allocation.x; allocation.x = 0; // Call gtk_widget_get_preferred_size() to prevent warnings GTK.gtk_widget_get_preferred_size(widget, minimumSize, naturalSize); // Allocate and queue a resize event gtk_widget_size_allocate(widget, allocation, -1); GTK.gtk_widget_queue_resize(widget); } } // Adjust the clip GTK3.gtk_widget_set_clip(widget, allocation); } @Override long gtk_draw (long widget, long cairo) { long context = GTK.gtk_widget_get_style_context(widget); GtkAllocation allocation = new GtkAllocation(); GTK.gtk_widget_get_allocation (widget, allocation); int width = (state & ZERO_WIDTH) != 0 ? 0 : allocation.width; int height = (state & ZERO_HEIGHT) != 0 ? 0 : allocation.height; // We specify a 0 value for x & y as we want the whole widget to be // colored, not some portion of it. GTK.gtk_render_background(context, cairo, 0, 0, width, height); // If fixClipHandle is set: iterate through the children of widget // and set their clips to be that of their allocation if (widget == fixClipHandle) fixClippings(); return super.gtk_draw(widget, cairo); } @Override boolean mustBeVisibleOnInitBounds() { // Bug 540298: if we return false, we will be invisible if the size is // not set, but our layout will not properly work, so that not all children // will be shown properly return true; } @Override void deregister () { super.deregister (); if (socketHandle != 0) display.removeWidget (socketHandle); } /** * Fills the interior of the rectangle specified by the arguments, * with the receiver's background. * *

    The offsetX and offsetY are used to map from * the gc origin to the origin of the parent image background. This is useful * to ensure proper alignment of the image background.

    * * @param gc the gc where the rectangle is to be filled * @param x the x coordinate of the rectangle to be filled * @param y the y coordinate of the rectangle to be filled * @param width the width of the rectangle to be filled * @param height the height of the rectangle to be filled * @param offsetX the image background x offset * @param offsetY the image background y offset * * @exception IllegalArgumentException
      *
    • ERROR_NULL_ARGUMENT - if the gc is null
    • *
    • ERROR_INVALID_ARGUMENT - if the gc has been disposed
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @since 3.6 */ public void drawBackground (GC gc, int x, int y, int width, int height, int offsetX, int offsetY) { checkWidget(); Rectangle rect = DPIUtil.autoScaleUp(new Rectangle (x, y, width, height)); offsetX = DPIUtil.autoScaleUp(offsetX); offsetY = DPIUtil.autoScaleUp(offsetY); drawBackgroundInPixels(gc, rect.x, rect.y, rect.width, rect.height, offsetX, offsetY); } void drawBackgroundInPixels (GC gc, int x, int y, int width, int height, int offsetX, int offsetY) { checkWidget (); if (gc == null) error (SWT.ERROR_NULL_ARGUMENT); if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); Control control = findBackgroundControl (); if (control != null) { GCData data = gc.getGCData (); long cairo = data.cairo; Cairo.cairo_save (cairo); if (control.backgroundImage != null) { Point pt = display.mapInPixels (this, control, 0, 0); Cairo.cairo_translate (cairo, -pt.x - offsetX, -pt.y - offsetY); x += pt.x + offsetX; y += pt.y + offsetY; long surface = control.backgroundImage.surface; if (surface == 0) error (SWT.ERROR_NO_HANDLES); Cairo.cairo_surface_reference(surface); long pattern = Cairo.cairo_pattern_create_for_surface (surface); if (pattern == 0) error (SWT.ERROR_NO_HANDLES); Cairo.cairo_pattern_set_extend (pattern, Cairo.CAIRO_EXTEND_REPEAT); if ((data.style & SWT.MIRRORED) != 0) { double[] matrix = {-1, 0, 0, 1, 0, 0}; Cairo.cairo_pattern_set_matrix(pattern, matrix); } Cairo.cairo_set_source (cairo, pattern); Cairo.cairo_surface_destroy (surface); Cairo.cairo_pattern_destroy (pattern); } else { GdkRGBA rgba = control.getBackgroundGdkRGBA (); Cairo.cairo_set_source_rgba (cairo, rgba.red, rgba.green, rgba.blue, rgba.alpha); } Cairo.cairo_rectangle (cairo, x, y, width, height); Cairo.cairo_fill (cairo); Cairo.cairo_restore (cairo); } else { gc.fillRectangle(DPIUtil.autoScaleDown(new Rectangle(x, y, width, height))); } } @Override void enableWidget (boolean enabled) { if ((state & CANVAS) != 0) return; super.enableWidget (enabled); } Composite findDeferredControl () { return layoutCount > 0 ? this : parent.findDeferredControl (); } @Override Menu [] findMenus (Control control) { if (control == this) return new Menu [0]; Menu result [] = super.findMenus (control); Control [] children = _getChildren (); for (int i=0; iSWT
    : * INHERIT_NONE, INHERIT_DEFAULT, * INHERIT_FORCE. * * @return the background mode * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see SWT * * @since 3.2 */ public int getBackgroundMode () { checkWidget (); return backgroundMode; } /** * Returns a (possibly empty) array containing the receiver's children. * Children are returned in the order that they are drawn. The topmost * control appears at the beginning of the array. Subsequent controls * draw beneath this control and appear later in the array. *

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

    * * @return an array of children * * @see Control#moveAbove * @see Control#moveBelow * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public Control [] getChildren () { checkWidget(); return _getChildren (); } int getChildrenCount () { int count = 0; if (GTK.GTK4) { for (long child = GTK4.gtk_widget_get_first_child(handle); child != 0; child = GTK4.gtk_widget_get_next_sibling(child)) { count++; } } else { /* * NOTE: The current implementation will count * non-registered children. */ long list = GTK3.gtk_container_get_children(handle); if (list != 0) { count = OS.g_list_length(list); OS.g_list_free(list); } } return count; } @Override Rectangle getClientAreaInPixels () { checkWidget(); if ((state & CANVAS) != 0) { if ((state & ZERO_WIDTH) != 0 && (state & ZERO_HEIGHT) != 0) { return new Rectangle (0, 0, 0, 0); } if(RESIZE_ON_GETCLIENTAREA) { forceResize (); } long clientHandle = clientHandle (); GtkAllocation allocation = new GtkAllocation(); GTK.gtk_widget_get_allocation (clientHandle, allocation); int width = (state & ZERO_WIDTH) != 0 ? 0 : allocation.width; int height = (state & ZERO_HEIGHT) != 0 ? 0 : allocation.height; return new Rectangle (0, 0, width, height); } return super.getClientAreaInPixels(); } /** * Returns layout which is associated with the receiver, or * null if one has not been set. * * @return the receiver's layout or null * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public Layout getLayout () { checkWidget(); return layout; } /** * Returns true if the receiver has deferred * the performing of layout, and false otherwise. * * @return the receiver's deferred layout state * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see #setLayoutDeferred(boolean) * @see #isLayoutDeferred() * * @since 3.1 */ public boolean getLayoutDeferred () { checkWidget (); return layoutCount > 0 ; } /** * Gets the (possibly empty) tabbing order for the control. * * @return tabList the ordered list of controls representing the tab order * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see #setTabList */ public Control [] getTabList () { checkWidget (); Control [] tabList = _getTabList (); if (tabList == null) { int count = 0; Control [] list =_getChildren (); for (int i=0; itrue if the receiver or any ancestor * up to and including the receiver's nearest ancestor shell * has deferred the performing of layouts. Otherwise, false * is returned. * * @return the receiver's deferred layout state * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see #setLayoutDeferred(boolean) * @see #getLayoutDeferred() * * @since 3.1 */ public boolean isLayoutDeferred () { checkWidget (); return findDeferredControl () != null; } @Override boolean isTabGroup() { if ((state & CANVAS) != 0) return true; return super.isTabGroup(); } /** * If the receiver has a layout, asks the layout to lay out * (that is, set the size and location of) the receiver's children. * If the receiver does not have a layout, do nothing. *

    * Use of this method is discouraged since it is the least-efficient * way to trigger a layout. The use of layout(true) * discards all cached layout information, even from controls which * have not changed. It is much more efficient to invoke * {@link Control#requestLayout()} on every control which has changed * in the layout than it is to invoke this method on the layout itself. *

    *

    * This is equivalent to calling layout(true). *

    *

    * Note: Layout is different from painting. If a child is * moved or resized such that an area in the parent is * exposed, then the parent will paint. If no child is * affected, the parent will not paint. *

    * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void layout () { checkWidget (); layout (true); } /** * If the receiver has a layout, asks the layout to lay out * (that is, set the size and location of) the receiver's children. * If the argument is true the layout must not rely * on any information it has cached about the immediate children. If it * is false the layout may (potentially) optimize the * work it is doing by assuming that none of the receiver's * children has changed state since the last layout. * If the receiver does not have a layout, do nothing. *

    * It is normally more efficient to invoke {@link Control#requestLayout()} * on every control which has changed in the layout than it is to invoke * this method on the layout itself. Clients are encouraged to use * {@link Control#requestLayout()} where possible instead of calling * this method. *

    *

    * If a child is resized as a result of a call to layout, the * resize event will invoke the layout of the child. The layout * will cascade down through all child widgets in the receiver's widget * tree until a child is encountered that does not resize. Note that * a layout due to a resize will not flush any cached information * (same as layout(false)). *

    *

    * Note: Layout is different from painting. If a child is * moved or resized such that an area in the parent is * exposed, then the parent will paint. If no child is * affected, the parent will not paint. *

    * * @param changed true if the layout must flush its caches, and false otherwise * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void layout (boolean changed) { checkWidget (); if (layout == null) return; layout (changed, false); } /** * If the receiver has a layout, asks the layout to lay out * (that is, set the size and location of) the receiver's children. * If the changed argument is true the layout must not rely * on any information it has cached about its children. If it * is false the layout may (potentially) optimize the * work it is doing by assuming that none of the receiver's * children has changed state since the last layout. * If the all argument is true the layout will cascade down * through all child widgets in the receiver's widget tree, regardless of * whether the child has changed size. The changed argument is applied to * all layouts. If the all argument is false, the layout will * not cascade down through all child widgets in the receiver's widget * tree. However, if a child is resized as a result of a call to layout, the * resize event will invoke the layout of the child. Note that * a layout due to a resize will not flush any cached information * (same as layout(false)). *

    * It is normally more efficient to invoke {@link Control#requestLayout()} * on every control which has changed in the layout than it is to invoke * this method on the layout itself. Clients are encouraged to use * {@link Control#requestLayout()} where possible instead of calling * this method. *

    *

    * Note: Layout is different from painting. If a child is * moved or resized such that an area in the parent is * exposed, then the parent will paint. If no child is * affected, the parent will not paint. *

    * * @param changed true if the layout must flush its caches, and false otherwise * @param all true if all children in the receiver's widget tree should be laid out, and false otherwise * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @since 3.1 */ public void layout (boolean changed, boolean all) { checkWidget (); if (layout == null && !all) return; markLayout (changed, all); updateLayout (all); } /** * Forces a lay out (that is, sets the size and location) of all widgets that * are in the parent hierarchy of the changed control up to and including the * receiver. The layouts in the hierarchy must not rely on any information * cached about the changed control or any of its ancestors. The layout may * (potentially) optimize the work it is doing by assuming that none of the * peers of the changed control have changed state since the last layout. * If an ancestor does not have a layout, skip it. *

    * It is normally more efficient to invoke {@link Control#requestLayout()} * on every control which has changed in the layout than it is to invoke * this method on the layout itself. Clients are encouraged to use * {@link Control#requestLayout()} where possible instead of calling * this method. *

    *

    * Note: Layout is different from painting. If a child is * moved or resized such that an area in the parent is * exposed, then the parent will paint. If no child is * affected, the parent will not paint. *

    * * @param changed a control that has had a state change which requires a recalculation of its size * * @exception IllegalArgumentException
      *
    • ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed
    • *
    • ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @since 3.1 */ public void layout (Control [] changed) { checkWidget (); if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT); layout (changed, SWT.NONE); } /** * Forces a lay out (that is, sets the size and location) of all widgets that * are in the parent hierarchy of the changed control up to and including the * receiver. *

    * The parameter flags may be a combination of: *

    *
    *
    SWT.ALL
    *
    all children in the receiver's widget tree should be laid out
    *
    SWT.CHANGED
    *
    the layout must flush its caches
    *
    SWT.DEFER
    *
    layout will be deferred
    *
    *

    * When the changed array is specified, the flags SWT.ALL * and SWT.CHANGED have no effect. In this case, the layouts in the * hierarchy must not rely on any information cached about the changed control or * any of its ancestors. The layout may (potentially) optimize the * work it is doing by assuming that none of the peers of the changed * control have changed state since the last layout. * If an ancestor does not have a layout, skip it. *

    *

    * When the changed array is not specified, the flag SWT.ALL * indicates that the whole widget tree should be laid out. And the flag * SWT.CHANGED indicates that the layouts should flush any cached * information for all controls that are laid out. *

    *

    * The SWT.DEFER flag always causes the layout to be deferred by * calling Composite.setLayoutDeferred(true) and scheduling a call * to Composite.setLayoutDeferred(false), which will happen when * appropriate (usually before the next event is handled). When this flag is set, * the application should not call Composite.setLayoutDeferred(boolean). *

    *

    * Note: Layout is different from painting. If a child is * moved or resized such that an area in the parent is * exposed, then the parent will paint. If no child is * affected, the parent will not paint. *

    * * @param changed a control that has had a state change which requires a recalculation of its size * @param flags the flags specifying how the layout should happen * * @exception IllegalArgumentException
      *
    • ERROR_INVALID_ARGUMENT - if any of the controls in changed is null or has been disposed
    • *
    • ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @since 3.6 */ public void layout (Control [] changed, int flags) { checkWidget (); if (changed != null) { for (int i=0; i=0; i--) { update [i].updateLayout (false); } } else { if (layout == null && (flags & SWT.ALL) == 0) return; markLayout ((flags & SWT.CHANGED) != 0, (flags & SWT.ALL) != 0); if (!display.externalEventLoop && (flags & SWT.DEFER) != 0) { setLayoutDeferred (true); display.addLayoutDeferred (this); } updateLayout ((flags & SWT.ALL) != 0); } } @Override void markLayout (boolean changed, boolean all) { if (layout != null) { state |= LAYOUT_NEEDED; if (changed) state |= LAYOUT_CHANGED; } if (all) { Control [] children = _getChildren (); for (int i=0; i 0) x = oldWidth - controlWidth - x; int clientWidth = getClientWidth (); x = clientWidth - controlWidth - x; if (!GTK.GTK4) { if (child.enableWindow != 0) { GDK.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 = new GtkRequisition (); gtk_widget_get_preferred_size (topHandle, requisition); allocation.x = x; allocation.y = y; gtk_widget_size_allocate(topHandle, allocation, -1); Control control = child.findBackgroundControl (); if (control != null && control.backgroundImage != null) { if (child.isVisible ()) child.redrawWidget (0, 0, 0, 0, true, true, true); } } } Point minimumSize (int wHint, int hHint, boolean changed) { Control [] children = _getChildren (); /* * Since getClientArea can be overridden by subclasses, we cannot * call getClientAreaInPixels directly. */ Rectangle clientArea = DPIUtil.autoScaleUp(getClientArea ()); int width = 0, height = 0; for (int i=0; i=0; --i) { Control child = children [i]; if (child.getVisible ()) { Point location = child.getLocationInPixels (); child.printWidget (gc, drawable, depth, x + location.x, y + location.y); } } gc.setClipping (oldClip); oldClip.dispose (); newClip.dispose (); } /** * Connects this widget's fixedHandle to the "draw" signal.
    * NOTE: only the "draw" (EXPOSE) signal is connected, not EXPOSE_EVENT_INVERSE. */ void connectFixedHandleDraw () { long paintHandle = fixedHandle; int paintMask = GDK.GDK_EXPOSURE_MASK; GTK3.gtk_widget_add_events (paintHandle, paintMask); OS.g_signal_connect_closure_by_id (paintHandle, display.signalIds [DRAW], 0, display.getClosure (DRAW), true); } /** *

    Propagates draw events from a parent container to its children using * gtk_container_propagate_draw(). This method only works if the fixedHandle * has been connected to the "draw" signal, and only propagates draw events * to other siblings of handle (i.e. other children of fixedHandle, but not * handle itself).

    * *

    It's useful to propagate draw events to other child widgets for things * like Table/Tree editors, or other scenarios where a widget is a child of * a non-standard container widget (i.e., not a direct child of a Composite).

    * * @param container the parent container, i.e. fixedHandle * @param cairo the cairo context provided by GTK */ void propagateDraw (long container, long cairo) { if (container == fixedHandle) { if (GTK.GTK4) { for (long child = GTK4.gtk_widget_get_first_child(container); child != 0; child = GTK4.gtk_widget_get_next_sibling(child)) { //TODO: GTK4 no gtk_container_propagate_draw. Possibly not required at all. } } else { long list = GTK3.gtk_container_get_children (container); long temp = list; while (temp != 0) { long child = OS.g_list_data (temp); if (child != 0) { Widget widget = display.getWidget (child); if (widget != this) { if (noChildDrawing) { Boolean childLowered = childrenLowered.get(widget); if (childLowered == null) { childrenLowered.put(widget, false); childLowered = false; } GtkAllocation allocation = new GtkAllocation (); GTK.gtk_widget_get_allocation(child, allocation); if (allocation.y < 0) { if (!childLowered) { long window = gtk_widget_get_window(child); GDK.gdk_window_lower(window); childrenLowered.put(widget, true); } } else { if (childLowered) { long window = gtk_widget_get_window(child); GDK.gdk_window_raise(window); childrenLowered.put(widget, false); } GTK3.gtk_container_propagate_draw(container, child, cairo); } } else { GTK3.gtk_container_propagate_draw(container, child, cairo); } } } temp = OS.g_list_next (temp); } OS.g_list_free (list); } } } @Override void redrawChildren () { super.redrawChildren (); Control [] children = _getChildren (); for (int i = 0; i < children.length; i++) { Control child = children [i]; if ((child.state & PARENT_BACKGROUND) != 0) { child.redrawWidget (0, 0, 0, 0, true, false, true); child.redrawChildren (); } } } @Override void register () { super.register (); if (socketHandle != 0) display.addWidget (socketHandle, this); } @Override void releaseChildren (boolean destroy) { try (ExceptionStash exceptions = new ExceptionStash ()) { for (Control child : _getChildren ()) { if (child == null || child.isDisposed ()) continue; try { child.release (false); } catch (Error | RuntimeException ex) { exceptions.stash (ex); } } super.releaseChildren (destroy); } } @Override void releaseHandle () { super.releaseHandle (); socketHandle = embeddedHandle = 0; } @Override void releaseWidget () { super.releaseWidget (); if (imHandle != 0) OS.g_object_unref (imHandle); imHandle = 0; layout = null; tabList = null; } void removeControl (Control control) { fixTabList (control); } @Override void reskinChildren (int flags) { super.reskinChildren (flags); Control [] children = _getChildren (); for (int i=0; iSWT: * INHERIT_NONE, INHERIT_DEFAULT, * INHERIT_FORCE. * * @param mode the new background mode * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see SWT * * @since 3.2 */ public void setBackgroundMode (int mode) { checkWidget (); backgroundMode = mode; Control[] children = _getChildren (); for (int i = 0; i < children.length; i++) { children [i].updateBackgroundMode (); } } @Override int setBounds (int x, int y, int width, int height, boolean move, boolean resize) { /* Bug 487757 * Deal with bug where for Gtk3.8+, ScrolledComposites appear empty or internal widgets don't * get sized properly. When resizing shell, widgets appear or grow into correct size. * * The issue is that upon widget creation ZERO_HEIGHT/WIDTH is assigned to widget's state (createWidget()); * then if you call setVisible(false), setVisible(true) before a layout operation, * in the setVisible(true) call, the widget is never shown. In Gtk3.8+ hidden widgets have a * size of 0x0, and as such allocation is not done correctly until you manually re-size the parent. * * To resolve the issue we check if widget is not HIDDEN on SWT side, but is hidden on GTK side. If it * is, then show it. This correctly initializes layout of internal widgets. * * Future note: If you observe non Composite widgets to have incorrect sizing on first display * but fix themselfes upon first resize by mouse, then * consider moving this fix higher into Control's setBound(...) method instead. */ long topHandle = topHandle (); if (fixedHandle != 0 && handle != 0 && getVisible() && !GTK.gtk_widget_get_visible(topHandle) //if SWT State is not HIDDEN, but widget is hidden on GTK side. && topHandle == fixedHandle && width > 0 && height > 0 && resize) { GTK.gtk_widget_show(topHandle); } int result = super.setBounds (x, y, width, height, move, resize); if ((result & RESIZED) != 0 && layout != null) { markLayout (false, false); updateLayout (false); } return result; } @Override public boolean setFocus () { checkWidget(); Control [] children = _getChildren (); for (int i=0; i *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • * */ public void setLayout (Layout layout) { checkWidget(); this.layout = layout; } /** * If the argument is true, causes subsequent layout * operations in the receiver or any of its children to be ignored. * No layout of any kind can occur in the receiver or any of its * children until the flag is set to false. * Layout operations that occurred while the flag was * true are remembered and when the flag is set to * false, the layout operations are performed in an * optimized manner. Nested calls to this method are stacked. * * @param defer the new defer state * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see #layout(boolean) * @see #layout(Control[]) * * @since 3.1 */ public void setLayoutDeferred (boolean defer) { checkWidget(); if (!defer) { if (--layoutCount == 0) { if ((state & LAYOUT_CHILD) != 0 || (state & LAYOUT_NEEDED) != 0) { updateLayout (true); } } } else { layoutCount++; } } @Override void setOrientation (boolean create) { super.setOrientation (create); if (!create) { int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT; int orientation = style & flags; Control [] children = _getChildren (); for (int i=0; i *
  • ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed
  • *
  • ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree
  • * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void setTabList (Control [] tabList) { checkWidget (); if (tabList != null) { for (int i=0; i




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy