Mercurial > projects > dwt-addons
view 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 source
/******************************************************************************* * 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) { } } }