blob: 5fe8a803190acb00fa71ca168e3524e8d320bac5 [file] [log] [blame]
package org.eclipse.swt.widgets;
/*
* Copyright (c) 2000, 2002 IBM Corp. All rights reserved.
* This file is made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*/
import org.eclipse.swt.internal.carbon.OS;
import org.eclipse.swt.internal.carbon.Rect;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
public abstract class Scrollable extends Control {
int scrolledHandle;
int hScrollBar, vScrollBar;
ScrollBar horizontalBar, verticalBar;
Scrollable () {
/* Do nothing */
}
public Scrollable (Composite parent, int style) {
super (parent, style);
}
public Rectangle computeTrim (int x, int y, int width, int height) {
checkWidget();
int [] outMetric = new int [1];
OS.GetThemeMetric (OS.kThemeMetricScrollBarWidth, outMetric);
if (horizontalBar != null) height += outMetric [0];
if (verticalBar != null) width += outMetric [0];
Rect inset = inset ();
x -= inset.left;
y -= inset.top;
width += inset.left + inset.right;
height += inset.top + inset.bottom;
return new Rectangle (x, y, width, height);
}
ScrollBar createScrollBar (int type) {
return new ScrollBar (this, type);
}
ScrollBar createStandardBar (int style) {
short [] count = new short [1];
OS.CountSubControls (handle, count);
if (count [0] == 0) return null;
int [] outControl = new int [1];
int index = (style & SWT.HORIZONTAL) != 0 ? 1 : 2;
int status = OS.GetIndexedSubControl (handle, (short)index, outControl);
if (status != OS.noErr) return null;
ScrollBar bar = new ScrollBar ();
bar.parent = this;
bar.style = style;
bar.handle = outControl [0];
bar.register ();
bar.hookEvents ();
return bar;
}
void createWidget () {
super.createWidget ();
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 (scrolledHandle != 0) WidgetTable.remove (scrolledHandle);
}
public Rectangle getClientArea () {
checkWidget();
Rect rect = new Rect ();
OS.GetControlBounds (handle, rect);
return new Rectangle (0, 0, rect.right - rect.left, rect.bottom - rect.top);
}
public ScrollBar getHorizontalBar () {
checkWidget();
return horizontalBar;
}
public ScrollBar getVerticalBar () {
checkWidget();
return verticalBar;
}
boolean hasBorder () {
return (style & SWT.BORDER) != 0;
}
void hookEvents () {
super.hookEvents ();
if ((state & CANVAS) != 0 && scrolledHandle != 0) {
Display display = getDisplay ();
int controlProc = display.controlProc;
int [] mask = new int [] {
OS.kEventClassControl, OS.kEventControlDraw,
};
int controlTarget = OS.GetControlEventTarget (scrolledHandle);
OS.InstallEventHandler (controlTarget, controlProc, mask.length / 2, mask, scrolledHandle, null);
}
}
boolean hooksKeys () {
return hooks (SWT.KeyDown) || hooks (SWT.KeyUp) || hooks (SWT.Traverse);
}
Rect inset () {
if ((state & CANVAS) != 0) {
Rect rect = new Rect ();
int [] outMetric = new int [1];
if ((style & SWT.NO_FOCUS) == 0 && hooksKeys ()) {
OS.GetThemeMetric (OS.kThemeMetricFocusRectOutset, outMetric);
rect.left += outMetric [0];
rect.top += outMetric [0];
rect.right += outMetric [0];
rect.bottom += outMetric [0];
}
if (hasBorder ()) {
OS.GetThemeMetric (OS.kThemeMetricEditTextFrameOutset, outMetric);
rect.left += outMetric [0];
rect.top += outMetric [0];
rect.right += outMetric [0];
rect.bottom += outMetric [0];
}
return rect;
}
return EMPTY_RECT;
}
boolean isTrimHandle (int trimHandle) {
if (horizontalBar != null && horizontalBar.handle == trimHandle) return true;
if (verticalBar != null && verticalBar.handle == trimHandle) return true;
return trimHandle == scrolledHandle;
}
int kEventMouseWheelMoved (int nextHandler, int theEvent, int userData) {
int result = super.kEventMouseWheelMoved (nextHandler, theEvent, userData);
if (result == OS.noErr) return result;
if ((state & CANVAS) != 0) {
short [] wheelAxis = new short [1];
OS.GetEventParameter (theEvent, OS.kEventParamMouseWheelAxis, OS.typeMouseWheelAxis, null, 2, null, wheelAxis);
ScrollBar bar = wheelAxis [0] == OS.kEventMouseWheelAxisX ? horizontalBar : verticalBar;
if (bar != null) {
int [] wheelDelta = new int [1];
OS.GetEventParameter (theEvent, OS.kEventParamMouseWheelDelta, OS.typeSInt32, null, 4, null, wheelDelta);
bar.setSelection (Math.max (0, bar.getSelection () - bar.getIncrement () * wheelDelta [0]));
Event event = new Event ();
System.out.println (wheelDelta [0]);
event.detail = wheelDelta [0] > 0 ? SWT.PAGE_UP : SWT.PAGE_DOWN;
bar.sendEvent (SWT.Selection, event);
Display display = getDisplay ();
display.update ();
}
/*
* Feature in the Macintosh. For some reason, when eventNotHandledErr
* is returned from kEventMouseWheelMoved the event is sent twiced to
* the same control with the same mouse wheel data. The fix is to return
* noErr to stop further event processing.
*/
return OS.noErr;
}
int vPosition = verticalBar == null ? 0 : verticalBar.getSelection ();
int hPosition = horizontalBar == null ? 0 : horizontalBar.getSelection ();
result = OS.CallNextEventHandler (nextHandler, theEvent);
if (verticalBar != null) {
int position = verticalBar.getSelection ();
if (position != vPosition) {
Event event = new Event ();
event.detail = position < vPosition ? SWT.PAGE_UP : SWT.PAGE_DOWN;
verticalBar.sendEvent (SWT.Selection, event);
}
}
if (horizontalBar != null) {
int position = horizontalBar.getSelection ();
if (position != hPosition) {
Event event = new Event ();
event.detail = position < vPosition ? SWT.PAGE_UP : SWT.PAGE_DOWN;
horizontalBar.sendEvent (SWT.Selection, event);
}
}
return result;
}
void layoutControl () {
if (scrolledHandle != 0) {
int vWidth = 0, hHeight = 0;
int [] outMetric = new int [1];
OS.GetThemeMetric (OS.kThemeMetricScrollBarWidth, outMetric);
boolean isVisibleHBar = horizontalBar != null && horizontalBar.getVisible ();
boolean isVisibleVBar = verticalBar != null && verticalBar.getVisible ();
if (isVisibleHBar) hHeight = outMetric [0];
if (isVisibleVBar) vWidth = outMetric [0];
Rect rect = new Rect ();
OS.GetControlBounds (scrolledHandle, rect);
Rect inset = inset ();
int width = Math.max (0, rect.right - rect.left - vWidth - inset.left - inset.right);
int height = Math.max (0, rect.bottom - rect.top - hHeight - inset.top - inset.bottom);
if (isVisibleHBar) {
setBounds (horizontalBar.handle, inset.left, inset.top + height, width, hHeight, true, true, false);
}
if (isVisibleVBar) {
setBounds (verticalBar.handle, inset.left + width, inset.top, vWidth, height, true, true, false);
}
setBounds (handle, inset.left, inset.top, width, height, true, true, false);
}
}
void register () {
super.register ();
if (scrolledHandle != 0) WidgetTable.put (scrolledHandle, this);
}
void releaseHandle () {
super.releaseHandle ();
scrolledHandle = 0;
}
void releaseWidget () {
if (horizontalBar != null) horizontalBar.releaseResources ();
if (verticalBar != null) verticalBar.releaseResources ();
horizontalBar = verticalBar = null;
super.releaseWidget ();
}
int setBounds (int control, int x, int y, int width, int height, boolean move, boolean resize, boolean events) {
int result = super.setBounds(control, x, y, width, height, move, resize, false);
if ((result & MOVED) != 0) {
if (events) sendEvent (SWT.Move);
}
if ((result & RESIZED) != 0) {
if (control == scrolledHandle) layoutControl ();
if (events) sendEvent (SWT.Resize);
}
return result;
}
int topHandle () {
if (scrolledHandle != 0) return scrolledHandle;
return handle;
}
}