/******************************************************************************* * 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 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.widgets; import org.eclipse.swt.internal.motif.*; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; /** * This class is the abstract superclass of all classes which * represent controls that have standard scroll bars. *
*
Styles:
*
H_SCROLL, V_SCROLL
*
Events: *
(none)
*
*

* IMPORTANT: This class is intended to be subclassed only * within the SWT implementation. *

*/ public abstract class Scrollable extends Control { int scrolledHandle, formHandle; ScrollBar horizontalBar, verticalBar; Scrollable () { /* 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 composite control which will be the parent of the new instance (cannot be null) * @param style the style of control to construct * * @exception IllegalArgumentException * @exception SWTException * * @see SWT#H_SCROLL * @see SWT#V_SCROLL * @see Widget#checkSubclass * @see Widget#getStyle */ public Scrollable (Composite parent, int style) { super (parent, style); } /** * Given a desired client area for the receiver * (as described by the arguments), returns the bounding * rectangle which would be required to produce that client * area. *

* In other words, it returns a rectangle such that, if the * receiver's bounds were set to that rectangle, the area * of the receiver which is capable of displaying data * (that is, not covered by the "trimmings") would be the * rectangle described by the arguments (relative to the * receiver's parent). *

* * @param x the desired x coordinate of the client area * @param y the desired y coordinate of the client area * @param width the desired width of the client area * @param height the desired height of the client area * @return the required bounds to produce the given client area * * @exception SWTException * * @see #getClientArea */ public Rectangle computeTrim (int x, int y, int width, int height) { checkWidget(); int border = getBorderWidth (); int trimX = x - border, trimY = y - border; int trimWidth = width + (border * 2), trimHeight = height + (border * 2); if (horizontalBar != null) { trimY -= display.scrolledInsetY; trimHeight += display.scrolledInsetY + display.scrolledMarginY; if (verticalBar == null) { trimX -= display.scrolledInsetX; trimWidth += display.scrolledInsetX * 2; trimHeight -= display.scrolledInsetY * 2; } } if (verticalBar != null) { trimX -= display.scrolledInsetX; trimWidth += display.scrolledInsetX + display.scrolledMarginX; if (horizontalBar == null) { trimY -= display.scrolledInsetY; trimHeight += display.scrolledInsetY * 2; trimWidth -= display.scrolledInsetX * 2; } } return new Rectangle (trimX, trimY, trimWidth, trimHeight); } ScrollBar createScrollBar (int type) { return new ScrollBar (this, type); } ScrollBar createStandardBar (int style) { if (scrolledHandle == 0) return null; ScrollBar bar = new ScrollBar (); bar.parent = this; bar.style = style; bar.display = display; int [] argList = {OS.XmNhorizontalScrollBar, 0, OS.XmNverticalScrollBar, 0}; OS.XtGetValues (scrolledHandle, argList, argList.length / 2); if (style == SWT.H_SCROLL) bar.handle = argList [1]; if (style == SWT.V_SCROLL) bar.handle = argList [3]; bar.hookEvents (); bar.register (); return bar; } void createWidget (int index) { super.createWidget (index); if ((style & SWT.H_SCROLL) != 0) horizontalBar = createScrollBar (SWT.H_SCROLL); if ((style & SWT.V_SCROLL) != 0) verticalBar = createScrollBar (SWT.V_SCROLL); } void deregister () { super.deregister (); if (formHandle != 0) display.removeWidget (formHandle); if (scrolledHandle != 0) display.removeWidget (scrolledHandle); } void enableWidget (boolean enabled) { super.enableWidget (enabled); if (formHandle != 0) enableHandle (enabled, formHandle); if (scrolledHandle != 0) enableHandle (enabled, scrolledHandle); } /** * Returns a rectangle which describes the area of the * receiver which is capable of displaying data (that is, * not covered by the "trimmings"). * * @return the client area * * @exception SWTException * * @see #computeTrim */ public Rectangle getClientArea () { checkWidget(); int [] argList = {OS.XmNwidth, 0, OS.XmNheight, 0}; OS.XtGetValues (handle, argList, argList.length / 2); return new Rectangle (0, 0, argList [1], argList [3]); } /** * Returns the receiver's horizontal scroll bar if it has * one, and null if it does not. * * @return the horizontal scroll bar (or null) * * @exception SWTException */ public ScrollBar getHorizontalBar () { checkWidget(); return horizontalBar; } /** * Returns the receiver's vertical scroll bar if it has * one, and null if it does not. * * @return the vertical scroll bar (or null) * * @exception SWTException */ public ScrollBar getVerticalBar () { checkWidget(); return verticalBar; } void manageChildren () { if (scrolledHandle != 0) { OS.XtSetMappedWhenManaged (scrolledHandle, false); OS.XtManageChild (scrolledHandle); } if (formHandle != 0) { OS.XtSetMappedWhenManaged (formHandle, false); OS.XtManageChild (formHandle); } super.manageChildren (); if (formHandle != 0) { int [] argList = {OS.XmNborderWidth, 0}; OS.XtGetValues (formHandle, argList, argList.length / 2); OS.XtResizeWidget (formHandle, 1, 1, argList [1]); OS.XtSetMappedWhenManaged (formHandle, true); } if (scrolledHandle != 0) { int [] argList = {OS.XmNborderWidth, 0}; OS.XtGetValues (scrolledHandle, argList, argList.length / 2); OS.XtResizeWidget (scrolledHandle, 1, 1, argList [1]); OS.XtSetMappedWhenManaged (scrolledHandle, true); } } void propagateWidget (boolean enabled) { super.propagateWidget (enabled); if (formHandle != 0) propagateHandle (enabled, formHandle, OS.None); if (scrolledHandle != 0) { propagateHandle (enabled, scrolledHandle, OS.None); if (horizontalBar != null) horizontalBar.propagateWidget (enabled); if (verticalBar != null) verticalBar.propagateWidget (enabled); } } void register () { super.register (); if (formHandle != 0) display.addWidget (formHandle, this); if (scrolledHandle != 0) display.addWidget (scrolledHandle, this); } void releaseChildren (boolean destroy) { if (horizontalBar != null) { horizontalBar.release (false); horizontalBar = null; } if (verticalBar != null) { verticalBar.release (false); verticalBar = null; } super.releaseChildren (destroy); } void releaseHandle () { super.releaseHandle (); scrolledHandle = formHandle = 0; } void setBackgroundPixel (int pixel) { super.setBackgroundPixel (pixel); /* * Uncomment this code to force scrollbars to change color. */ // if (scrolledHandle != 0) { // int [] argList1 = { // OS.XmNhorizontalScrollBar, 0, // OS.XmNverticalScrollBar, 0, // }; // OS.XtGetValues (scrolledHandle, argList1, argList1.length / 2); // if (argList1 [1] != 0) OS.XmChangeColor (argList1 [1], pixel); // if (argList1 [3] != 0) OS.XmChangeColor (argList1 [3], pixel); // } } void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) { super.redrawWidget (x, y, width, height, redrawAll, allChildren, trim); if (!trim) return; if (formHandle == 0 && scrolledHandle == 0) return; short [] root_x = new short [1], root_y = new short [1]; OS.XtTranslateCoords (handle, (short) x, (short) y, root_x, root_y); if (formHandle != 0) { short [] form_x = new short [1], form_y = new short [1]; OS.XtTranslateCoords (formHandle, (short) 0, (short) 0, form_x, form_y); redrawHandle (root_x [0] - form_x [0], root_y [0] - form_y [0], width, height, redrawAll, formHandle); } if (scrolledHandle != 0) { short [] scrolled_x = new short [1], scrolled_y = new short [1]; OS.XtTranslateCoords (scrolledHandle, (short) 0, (short) 0, scrolled_x, scrolled_y); redrawHandle (root_x [0] - scrolled_x [0], root_y [0] - scrolled_y [0], width, height, redrawAll, scrolledHandle); if (horizontalBar != null && horizontalBar.getVisible ()) { int horizontalHandle = horizontalBar.handle; short [] hscroll_x = new short [1], hscroll_y = new short [1]; OS.XtTranslateCoords (horizontalHandle, (short) 0, (short) 0, hscroll_x, hscroll_y); redrawHandle (root_x [0] - hscroll_x [0], root_y [0] - hscroll_y [0], width, height, redrawAll, horizontalHandle); } if (verticalBar != null && verticalBar.getVisible ()) { int verticalHandle = verticalBar.handle; short [] vscroll_x = new short [1], vscroll_y = new short [1]; OS.XtTranslateCoords (verticalHandle, (short) 0, (short) 0, vscroll_x, vscroll_y); redrawHandle (root_x [0] - vscroll_x [0], root_y [0] - vscroll_y [0], width, height, redrawAll, verticalHandle); } } } boolean setScrollBarVisible (ScrollBar bar, boolean visible) { if (scrolledHandle == 0) return false; int barHandle = bar.handle; boolean managed = OS.XtIsManaged (barHandle); if (managed == visible) return false; /* * Feature in Motif. Hiding or showing a scroll bar * can cause the widget to automatically resize in * the OS. This behavior is unwanted. The fix is * to force the widget to resize to original size. */ int [] argList = {OS.XmNwidth, 0, OS.XmNheight, 0, OS.XmNborderWidth, 0}; OS.XtGetValues (scrolledHandle, argList, argList.length / 2); int [] argList1 = {OS.XmNwidth, 0, OS.XmNheight, 0}; OS.XtGetValues (handle, argList1, argList1.length / 2); /* Hide or show the scroll bar */ if (visible) { OS.XtManageChild (barHandle); } else { OS.XtUnmanageChild (barHandle); } if ((state & CANVAS) != 0) { if (formHandle != 0) { boolean showBorder = (style & SWT.BORDER) != 0; int margin = showBorder || visible ? 3 : 0; if ((bar.style & SWT.V_SCROLL) != 0) { int [] argList2 = new int [] {OS.XmNmarginWidth, margin}; OS.XtSetValues (formHandle, argList2, argList2.length/2); } if ((bar.style & SWT.H_SCROLL) != 0) { int [] argList2 = new int [] {OS.XmNmarginHeight, margin}; OS.XtSetValues (formHandle, argList2, argList2.length/2); } } } /* * Feature in Motif. When XtSetValues() is used to restore the width and * height of the widget, the new width and height are sometimes ignored. * The fix is to use XtResizeWidget(). */ OS.XtResizeWidget (scrolledHandle, argList [1], argList [3], argList [5]); bar.sendEvent (visible ? SWT.Show : SWT.Hide); int [] argList3 = {OS.XmNwidth, 0, OS.XmNheight, 0}; OS.XtGetValues (handle, argList3, argList3.length / 2); if (argList1 [1] != argList3 [1] || argList1 [3] != argList3 [3]) { sendEvent (SWT.Resize); return true; } return false; } int topHandle () { if (scrolledHandle != 0) return scrolledHandle; if (formHandle != 0) return formHandle; return handle; } }