Mercurial > projects > dwt-addons
diff dwtx/draw2d/ScrollBar.d @ 98:95307ad235d9
Added Draw2d code, still work in progress
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 03 Aug 2008 00:52:14 +0200 |
parents | |
children | 2d6540440fe6 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/draw2d/ScrollBar.d Sun Aug 03 00:52:14 2008 +0200 @@ -0,0 +1,667 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.draw2d.ScrollBar; + +import dwt.dwthelper.utils; + +import dwtx.dwtxhelper.Bean; + +import dwt.graphics.Color; +import dwtx.draw2d.geometry.Dimension; +import dwtx.draw2d.geometry.Point; +import dwtx.draw2d.geometry.Rectangle; +import dwtx.draw2d.geometry.Transposer; + +import dwtx.draw2d.Orientable; +import dwtx.draw2d.Figure; +import dwtx.draw2d.IFigure; +import dwtx.draw2d.RangeModel; +import dwtx.draw2d.Clickable; +import dwtx.draw2d.MouseMotionListener; +import dwtx.draw2d.MouseListener; +import dwtx.draw2d.MouseEvent; +import dwtx.draw2d.FigureUtilities; +import dwtx.draw2d.ColorConstants; +import dwtx.draw2d.Button; +import dwtx.draw2d.RangeModel; +import dwtx.draw2d.DefaultRangeModel; +import dwtx.draw2d.ArrowButton; +import dwtx.draw2d.ButtonBorder; +import dwtx.draw2d.ChangeListener; +import dwtx.draw2d.ChangeEvent; +import dwtx.draw2d.Panel; +import dwtx.draw2d.ScrollBarLayout; +import dwtx.draw2d.SchemeBorder; +import dwtx.draw2d.ActionListener; +import dwtx.draw2d.ActionEvent; + +/** + * Provides for the scrollbars used by the {@link ScrollPane}. A ScrollBar is made up of + * five essential Figures: An 'Up' arrow button, a 'Down' arrow button, a draggable + * 'Thumb', a 'Pageup' button, and a 'Pagedown' button. + */ +public class ScrollBar + : Figure + , Orientable, PropertyChangeListener +{ + +private static const int ORIENTATION_FLAG = Figure.MAX_FLAG << 1; +/** @see Figure#MAX_FLAG */ +protected static const int MAX_FLAG = ORIENTATION_FLAG; + +private static const Color COLOR_TRACK; +static this(){ + COLOR_TRACK = FigureUtilities.mixColors( + ColorConstants.white, + ColorConstants.button); +} + +private RangeModel rangeModel = null; +private IFigure thumb; +private Clickable pageUp_, pageDown_; +private Clickable buttonUp, buttonDown; +/** + * Listens to mouse events on the scrollbar to take care of scrolling. + */ +protected ThumbDragger thumbDragger; + +private bool isHorizontal_ = false; + +private int pageIncrement = 50; +private int stepIncrement = 10; + +/** + * Transposes from vertical to horizontal if needed. + */ +protected /+final+/ Transposer transposer; + +private void instanceInit(){ + thumbDragger = new ThumbDragger(); + transposer = new Transposer(); + setRangeModel(new DefaultRangeModel()); +} + +/** + * Constructs a ScrollBar. ScrollBar orientation is vertical by default. Call + * {@link #setHorizontal(bool)} with <code>true</code> to set horizontal orientation. + * + * @since 2.0 + */ +public this() { + instanceInit(); + initialize(); +} + +/** + * Creates the default 'Up' ArrowButton for the ScrollBar. + * + * @return the up button + * @since 2.0 + */ +protected Clickable createDefaultUpButton() { + Button buttonUp = new ArrowButton(); + buttonUp.setBorder(new ButtonBorder(ButtonBorder.SCHEMES.BUTTON_SCROLLBAR)); + return buttonUp; +} + +/** + * Creates the default 'Down' ArrowButton for the ScrollBar. + * + * @return the down button + * @since 2.0 + */ +protected Clickable createDefaultDownButton() { + Button buttonDown = new ArrowButton(); + buttonDown.setBorder(new ButtonBorder(ButtonBorder.SCHEMES.BUTTON_SCROLLBAR)); + return buttonDown; +} + +/** + * Creates the pagedown Figure for the Scrollbar. + * + * @return the page down figure + * @since 2.0 + */ +protected Clickable createPageDown() { + return createPageUp(); +} + +/** + * Creates the pageup Figure for the Scrollbar. + * + * @return the page up figure + * @since 2.0 + */ +protected Clickable createPageUp() { + Clickable clickable = new Clickable(); + clickable.setOpaque(true); + clickable.setBackgroundColor(COLOR_TRACK); + clickable.setRequestFocusEnabled(false); + clickable.setFocusTraversable(false); + clickable.addChangeListener( dgChangeListener( (ChangeEvent evt, Clickable clickable_){ + if (clickable_.getModel().isArmed()) + clickable_.setBackgroundColor(ColorConstants.black); + else + clickable_.setBackgroundColor(COLOR_TRACK); + }, clickable)); + return clickable; +} + +/** + * Creates the Scrollbar's "thumb", the draggable Figure that indicates the Scrollbar's + * position. + * + * @return the thumb figure + * @since 2.0 + */ +protected IFigure createDefaultThumb() { + Panel thumb = new Panel(); + thumb.setMinimumSize(new Dimension(6, 6)); + thumb.setBackgroundColor(ColorConstants.button); + + thumb.setBorder(new SchemeBorder(SchemeBorder.SCHEMES.BUTTON_CONTRAST)); + return thumb; +} + +/** + * Returns the figure used as the up button. + * @return the up button + */ +protected IFigure getButtonUp() { + // TODO: The set method takes a Clickable while the get method returns an IFigure. + // Change the get method to return Clickable (since that's what it's typed as). + return buttonUp; +} + +/** + * Returns the figure used as the down button. + * @return the down button + */ +protected IFigure getButtonDown() { + // TODO: The set method takes a Clickable while the get method returns an IFigure. + // Change the get method to return Clickable (since that's what it's typed as). + return buttonDown; +} + +/** + * Returns the extent. + * @return the extent + * @see RangeModel#getExtent() + */ +public int getExtent() { + return getRangeModel().getExtent(); +} + +/** + * Returns the minumum value. + * @return the minimum + * @see RangeModel#getMinimum() + */ +public int getMinimum() { + return getRangeModel().getMinimum(); +} + +/** + * Returns the maximum value. + * @return the maximum + * @see RangeModel#getMaximum() + */ +public int getMaximum() { + return getRangeModel().getMaximum(); +} + +/** + * Returns the figure used for page down. + * @return the page down figure + */ +protected IFigure getPageDown() { + // TODO: The set method takes a Clickable while the get method returns an IFigure. + // Change the get method to return Clickable (since that's what it's typed as). + return pageDown_; +} + +/** + * Returns the the amound the scrollbar will move when the page up or page down areas are + * pressed. + * @return the page increment + */ +public int getPageIncrement() { + return pageIncrement; +} + +/** + * Returns the figure used for page up. + * @return the page up figure + */ +protected IFigure getPageUp() { + // TODO: The set method takes a Clickable while the get method returns an IFigure. + // Change the get method to return Clickable (since that's what it's typed as). + return pageUp_; +} + +/** + * Returns the range model for this scrollbar. + * @return the range model + */ +public RangeModel getRangeModel() { + return rangeModel; +} + +/** + * Returns the amount the scrollbar will move when the up or down arrow buttons are + * pressed. + * @return the step increment + */ +public int getStepIncrement() { + return stepIncrement; +} + +/** + * Returns the figure used as the scrollbar's thumb. + * @return the thumb figure + */ +protected IFigure getThumb() { + return thumb; +} + +/** + * Returns the current scroll position of the scrollbar. + * @return the current value + * @see RangeModel#getValue() + */ +public int getValue() { + return getRangeModel().getValue(); +} + +/** + * Returns the size of the range of allowable values. + * @return the value range + */ +protected int getValueRange() { + return getMaximum() - getExtent() - getMinimum(); +} + +/** + * Initilization of the ScrollBar. Sets the Scrollbar to have a ScrollBarLayout with + * vertical orientation. Creates the Figures that make up the components of the ScrollBar. + * + * @since 2.0 + */ +protected void initialize() { + setLayoutManager(new ScrollBarLayout(transposer)); + setUpClickable(createDefaultUpButton()); + setDownClickable(createDefaultDownButton()); + setPageUp(createPageUp()); + setPageDown(createPageDown()); + setThumb(createDefaultThumb()); +} + +/** + * Returns <code>true</code> if this scrollbar is orientated horizontally, + * <code>false</code> otherwise. + * @return whether this scrollbar is horizontal + */ +public bool isHorizontal() { + return isHorizontal_; +} + +private void pageDown() { + setValue(getValue() + getPageIncrement()); +} + +private void pageUp() { + setValue(getValue() - getPageIncrement()); +} + +/** + * @see PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) + */ +public void propertyChange(PropertyChangeEvent event) { + if (null !is cast(RangeModel)event.getSource() ) { + setEnabled(getRangeModel().isEnabled()); + if (RangeModel.PROPERTY_VALUE.equals(event.getPropertyName())) { + firePropertyChange("value", event.getOldValue(), //$NON-NLS-1$ + event.getNewValue()); + revalidate(); + } + if (RangeModel.PROPERTY_MINIMUM.equals(event.getPropertyName())) { + firePropertyChange("value", event.getOldValue(), //$NON-NLS-1$ + event.getNewValue()); + revalidate(); + } + if (RangeModel.PROPERTY_MAXIMUM.equals(event.getPropertyName())) { + firePropertyChange("value", event.getOldValue(), //$NON-NLS-1$ + event.getNewValue()); + revalidate(); + } + if (RangeModel.PROPERTY_EXTENT.equals(event.getPropertyName())) { + firePropertyChange("value", event.getOldValue(), //$NON-NLS-1$ + event.getNewValue()); + revalidate(); + } + } +} + +/** + * @see IFigure#revalidate() + */ +public void revalidate() { + // Override default revalidate to prevent going up the parent chain. Reason for this + // is that preferred size never changes unless orientation changes. + invalidate(); + getUpdateManager().addInvalidFigure(this); +} + +/** + * Does nothing because this doesn't make sense for a scrollbar. + * @see Orientable#setDirection(int) + */ +public void setDirection(int direction) { + //Doesn't make sense for Scrollbar. +} + +/** + * Sets the Clickable that represents the down arrow of the Scrollbar to <i>down</i>. + * + * @param down the down button + * @since 2.0 + */ +public void setDownClickable(Clickable down) { + if (buttonDown !is null) { + remove(buttonDown); + } + buttonDown = down; + if (buttonDown !is null) { + if (auto b = cast(Orientable)buttonDown ) + b.setDirection(isHorizontal() + ? Orientable.EAST + : Orientable.SOUTH); + buttonDown.setFiringMethod(Clickable.REPEAT_FIRING); + buttonDown.addActionListener(dgActionListener( (ActionEvent evt){ + stepDown(); + })); + add(buttonDown, stringcast(ScrollBarLayout.DOWN_ARROW)); + } +} + +/** + * Sets the Clickable that represents the up arrow of the Scrollbar to <i>up</i>. + * + * @param up the up button + * @since 2.0 + */ +public void setUpClickable(Clickable up) { + if (buttonUp !is null) { + remove(buttonUp); + } + buttonUp = up; + if (up !is null) { + if (auto o = cast(Orientable)up ) + o.setDirection(isHorizontal() + ? Orientable.WEST + : Orientable.NORTH); + buttonUp.setFiringMethod(Clickable.REPEAT_FIRING); + buttonUp.addActionListener(dgActionListener( (ActionEvent evt){ + stepUp(); + })); + add(buttonUp, stringcast(ScrollBarLayout.UP_ARROW)); + } +} + +/** + * @see IFigure#setEnabled(bool) + */ +public void setEnabled(bool value) { + if (isEnabled() is value) + return; + super.setEnabled(value); + setChildrenEnabled(value); + if (getThumb() !is null) { + getThumb().setVisible(value); + revalidate(); + } +} + +/** + * Sets the extent of the Scrollbar to <i>ext</i> + * + * @param ext the extent + * @since 2.0 + */ +public void setExtent(int ext) { + if (getExtent() is ext) + return; + getRangeModel().setExtent(ext); +} + +/** + * Sets the orientation of the ScrollBar. If <code>true</code>, the Scrollbar will have + * a horizontal orientation. If <code>false</code>, the scrollBar will have a vertical + * orientation. + * + * @param value <code>true</code> if the scrollbar should be horizontal + * @since 2.0 + */ +public final void setHorizontal(bool value) { + setOrientation(value ? HORIZONTAL : VERTICAL); +} + +/** + * Sets the maximum position to <i>max</i>. + * + * @param max the maximum position + * @since 2.0 + */ +public void setMaximum(int max) { + if (getMaximum() is max) + return; + getRangeModel().setMaximum(max); +} + +/** + * Sets the minimum position to <i>min</i>. + * + * @param min the minumum position + * @since 2.0 + */ +public void setMinimum(int min) { + if (getMinimum() is min) + return; + getRangeModel().setMinimum(min); +} + +/** + * @see Orientable#setOrientation(int) + */ +public void setOrientation(int value) { + if ((value is HORIZONTAL) is isHorizontal()) + return; + isHorizontal_ = value is HORIZONTAL; + transposer.setEnabled(isHorizontal_); + + setChildrenOrientation(value); + super.revalidate(); +} + +/** + * Sets the ScrollBar to scroll <i>increment</i> pixels when its pageup or pagedown + * buttons are pressed. (Note that the pageup and pagedown buttons are <b>NOT</b> the + * arrow buttons, they are the figures between the arrow buttons and the ScrollBar's + * thumb figure). + * + * @param increment the new page increment + * @since 2.0 + */ +public void setPageIncrement(int increment) { + pageIncrement = increment; +} + +/** + * Sets the pagedown button to the passed Clickable. The pagedown button is the figure + * between the down arrow button and the ScrollBar's thumb figure. + * + * @param down the page down figure + * @since 2.0 + */ +public void setPageDown(Clickable down) { + if (pageDown_ !is null) + remove(pageDown_); + pageDown_ = down; + if (pageDown_ !is null) { + pageDown_.setFiringMethod(Clickable.REPEAT_FIRING); + pageDown_.addActionListener(dgActionListener( (ActionEvent evt){ + pageDown(); + })); + add(down,stringcast( ScrollBarLayout.PAGE_DOWN)); + } +} + +/** + * Sets the pageup button to the passed Clickable. The pageup button is the rectangular + * figure between the down arrow button and the ScrollBar's thumb figure. + * + * @param up the page up figure + * @since 2.0 + */ +public void setPageUp(Clickable up) { + if (pageUp_ !is null) + remove(pageUp_); + pageUp_ = up; + if (pageUp_ !is null) { + pageUp_.setFiringMethod(Clickable.REPEAT_FIRING); + pageUp_.addActionListener(dgActionListener((ActionEvent evt){ + pageUp(); + })); + add(pageUp_, stringcast(ScrollBarLayout.PAGE_UP)); + } +} + +/** + * Sets the ScrollBar's RangeModel to the passed value. + * + * @param rangeModel the new range model + * @since 2.0 + */ +public void setRangeModel(RangeModel rangeModel) { + if (this.rangeModel !is null) + this.rangeModel.removePropertyChangeListener(this); + this.rangeModel = rangeModel; + rangeModel.addPropertyChangeListener(this); +} + +/** + * Sets the ScrollBar's step increment to the passed value. The step increment indicates + * how many pixels the ScrollBar will scroll when its up or down arrow button is pressed. + * + * @param increment the new step increment + * @since 2.0 + */ +public void setStepIncrement(int increment) { + stepIncrement = increment; +} + +/** + * Sets the ScrollBar's thumb to the passed Figure. The thumb is the draggable component + * of the ScrollBar that indicates the ScrollBar's position. + * + * @param figure the thumb figure + * @since 2.0 + */ +public void setThumb(IFigure figure) { + if (thumb !is null) { + thumb.removeMouseListener(thumbDragger); + thumb.removeMouseMotionListener(thumbDragger); + remove(thumb); + } + thumb = figure; + if (thumb !is null) { + thumb.addMouseListener(thumbDragger); + thumb.addMouseMotionListener(thumbDragger); + add(thumb, stringcast(ScrollBarLayout.THUMB)); + } +} + +/** + * Sets the value of the Scrollbar to <i>v</i> + * + * @param v the new value + * @since 2.0 + */ +public void setValue(int v) { + getRangeModel().setValue(v); +} + +/** + * Causes the ScrollBar to scroll down (or right) by the value of its step increment. + * + * @since 2.0 + */ +protected void stepDown() { + setValue(getValue() + getStepIncrement()); +} + +/** + * Causes the ScrollBar to scroll up (or left) by the value of its step increment. + * + * @since 2.0 + */ +protected void stepUp() { + setValue(getValue() - getStepIncrement()); +} + +class ThumbDragger + : MouseMotionListener.Stub + , MouseListener +{ + protected Point start; + protected int dragRange; + protected int revertValue; + protected bool armed; + public this() { } + + public void mousePressed(MouseEvent me) { + armed = true; + start = me.getLocation(); + Rectangle area = new Rectangle(transposer.t(getClientArea())); + Dimension thumbSize = transposer.t(getThumb().getSize()); + if (getButtonUp() !is null) + area.height -= transposer.t(getButtonUp().getSize()).height; + if (getButtonDown() !is null) + area.height -= transposer.t(getButtonDown().getSize()).height; + Dimension sizeDifference = new Dimension(area.width, + area.height - thumbSize.height); + dragRange = sizeDifference.height; + revertValue = getValue(); + me.consume(); + } + + public void mouseDragged(MouseEvent me) { + if (!armed) + return; + Dimension difference = transposer.t(me.getLocation().getDifference(start)); + int change = getValueRange() * difference.height / dragRange; + setValue(revertValue + change); + me.consume(); + } + + public void mouseReleased(MouseEvent me) { + if (!armed) + return; + armed = false; + me.consume(); + } + + public void mouseDoubleClicked(MouseEvent me) { } +} + +}