gui/widgets/scrollbar.hpp

Go to the documentation of this file.
00001 /* $Id: scrollbar.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2008 - 2012 by Mark de Wever <koraq@xs4all.nl>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #ifndef GUI_WIDGETS_SCROLLBAR_HPP_INCLUDED
00017 #define GUI_WIDGETS_SCROLLBAR_HPP_INCLUDED
00018 
00019 #include "gui/auxiliary/notifier.hpp"
00020 #include "gui/widgets/control.hpp"
00021 
00022 #include <boost/function.hpp>
00023 
00024 namespace gui2 {
00025 
00026 /**
00027  * Base class for a scroll bar.
00028  *
00029  * class will be subclassed for the horizontal and vertical scroll bar.
00030  * It might be subclassed for a slider class.
00031  *
00032  * To make this class generic we talk a lot about offset and length and use
00033  * pure virtual functions. The classes implementing us can use the heights or
00034  * widths, whichever is applicable.
00035  *
00036  * The NOTIFY_MODIFIED event is send when the position of scrollbar is changed.
00037  *
00038  * Common signal handlers:
00039  * - connect_signal_notify_modified
00040  */
00041 class tscrollbar_ : public tcontrol
00042 {
00043     /** @todo Abstract the code so this friend is no longer needed. */
00044     friend class tslider;
00045 public:
00046 
00047     tscrollbar_();
00048 
00049     /**
00050      * scroll 'step size'.
00051      *
00052      * When scrolling we always scroll a 'fixed' amount, these are the
00053      * parameters for these amounts.
00054      */
00055     enum tscroll {
00056         BEGIN,               /**< Go to begin position. */
00057         ITEM_BACKWARDS,      /**< Go one item towards the begin. */
00058         HALF_JUMP_BACKWARDS, /**< Go half the visible items towards the begin. */
00059         JUMP_BACKWARDS,      /**< Go the visibile items towards the begin. */
00060         END,                 /**< Go to the end position. */
00061         ITEM_FORWARD,        /**< Go one item towards the end. */
00062         HALF_JUMP_FORWARD,   /**< Go half the visible items towards the end. */
00063         JUMP_FORWARD };      /**< Go the visible items towards the end. */
00064 
00065     /**
00066      * Sets the item position.
00067      *
00068      * We scroll a predefined step.
00069      *
00070      * @param scroll              'step size' to scroll.
00071      */
00072     void scroll(const tscroll scroll);
00073 
00074     /** Is the positioner at the beginning of the scrollbar? */
00075     bool at_begin() const { return item_position_ == 0; }
00076 
00077     /**
00078      * Is the positioner at the and of the scrollbar?
00079      *
00080      * Note both begin and end might be true at the same time.
00081      */
00082     bool at_end() const
00083         { return item_position_ + visible_items_ >= item_count_; }
00084 
00085     /** Are all items visible? */
00086     bool all_items_visible() const { return visible_items_ >= item_count_; }
00087 
00088     /***** ***** ***** ***** layout functions ***** ***** ***** *****/
00089 
00090     /** Inherited from tcontrol. */
00091     void place(const tpoint& origin, const tpoint& size);
00092 
00093     /***** ***** ***** ***** Inherited ***** ***** ***** *****/
00094 
00095     /** Inherited from tcontrol. */
00096     void set_active(const bool active)
00097         { if(get_active() != active) set_state(active ? ENABLED : DISABLED); };
00098 
00099     /** Inherited from tcontrol. */
00100     bool get_active() const { return state_ != DISABLED; }
00101 
00102     /** Inherited from tcontrol. */
00103     unsigned get_state() const { return state_; }
00104 
00105     /***** ***** ***** setters / getters for members ***** ****** *****/
00106 
00107     void set_item_count(const unsigned item_count)
00108         { item_count_ = item_count; recalculate(); }
00109     unsigned get_item_count() const { return item_count_; }
00110 
00111     /**
00112      * Note the position isn't guaranteed to be the wanted position
00113      * the step size is honoured. The value will be rouded down.
00114      */
00115     void set_item_position(const unsigned item_position);
00116     unsigned get_item_position() const { return item_position_; }
00117 
00118     unsigned get_visible_items() const { return visible_items_; }
00119     void set_visible_items(const unsigned visible_items)
00120         { visible_items_ = visible_items; recalculate(); }
00121 
00122     unsigned get_step_size() const { return step_size_; }
00123     void set_step_size(const unsigned step_size)
00124         { step_size_ = step_size; recalculate(); }
00125 
00126 protected:
00127     unsigned get_positioner_offset() const { return positioner_offset_; }
00128 
00129     unsigned get_positioner_length() const { return positioner_length_; }
00130 
00131     /** After a recalculation the canvasses also need to be updated. */
00132     virtual void update_canvas();
00133 
00134     /**
00135      * Callback for subclasses to get notified about positioner movement.
00136      *
00137      * @todo This is a kind of hack due to the fact there's no simple
00138      * callback slot mechanism. See whether we can implement a generic way to
00139      * attach callback which would remove quite some extra code.
00140      */
00141     virtual void child_callback_positioner_moved() {}
00142 private:
00143 
00144     /**
00145      * Possible states of the widget.
00146      *
00147      * Note the order of the states must be the same as defined in settings.hpp.
00148      */
00149     enum tstate { ENABLED, DISABLED, PRESSED, FOCUSSED, COUNT };
00150 
00151     void set_state(const tstate state);
00152     /**
00153      * Current state of the widget.
00154      *
00155      * The state of the widget determines what to render and how the widget
00156      * reacts to certain 'events'.
00157      */
00158     tstate state_;
00159 
00160     /** The number of items the scrollbar 'holds'. */
00161     unsigned item_count_;
00162 
00163     /** The item the positioner is at, starts at 0. */
00164     unsigned item_position_;
00165 
00166     /**
00167      * The number of items which can be shown at the same time.
00168      *
00169      * As long as all items are visible we don't need to scroll.
00170      */
00171     unsigned visible_items_;
00172 
00173     /**
00174      * Number of items moved when scrolling.
00175      *
00176      * The step size is the minimum number of items we scroll through when we
00177      * move. Normally this value is 1, we can move per item. But for example
00178      * sliders want for example to move per 5 items.
00179      */
00180     unsigned step_size_;
00181 
00182     /**
00183      * Number of pixels per step.
00184      *
00185      * The number of pixels the positioner needs to move to go to the next step.
00186      * Note if there is too little space it can happen 1 pixel does more than 1
00187      * step.
00188      */
00189     float pixels_per_step_;
00190 
00191     /**
00192      * The position the mouse was at the last movement.
00193      *
00194      * This is used during dragging the positioner.
00195      */
00196     tpoint mouse_;
00197 
00198     /**
00199      * The start offset of the positioner.
00200      *
00201      * This takes the offset before in consideration.
00202      */
00203     unsigned positioner_offset_;
00204 
00205     /** The current length of the positioner. */
00206     unsigned positioner_length_;
00207 
00208     /***** ***** ***** ***** Pure virtual functions ***** ***** ***** *****/
00209 
00210     /** Get the length of the scrollbar. */
00211     virtual unsigned get_length() const = 0;
00212 
00213     /** The minimum length of the positioner. */
00214     virtual unsigned minimum_positioner_length() const = 0;
00215 
00216     /** The maximum length of the positioner. */
00217     virtual unsigned maximum_positioner_length() const = 0;
00218 
00219     /**
00220      * The number of pixels we can't use since they're used for borders.
00221      *
00222      * These are the pixels before the widget (left side if horizontal,
00223      * top side if vertical).
00224      */
00225     virtual unsigned offset_before() const = 0;
00226 
00227     /**
00228      * The number of pixels we can't use since they're used for borders.
00229      *
00230      * These are the pixels after the widget (right side if horizontal,
00231      * bottom side if vertical).
00232      */
00233     virtual unsigned offset_after() const = 0;
00234 
00235     /**
00236      * Is the coordinate on the positioner?
00237      *
00238      * @param coordinate          Coordinate to test whether it's on the
00239      *                            positioner.
00240      *
00241      * @returns                   Whether the location on the positioner is.
00242      */
00243     virtual bool on_positioner(const tpoint& coordinate) const = 0;
00244 
00245     /**
00246      * Is the coordinate on the bar?
00247      *
00248      * @param coordinate          Coordinate to test whether it's on the
00249      *                            bar.
00250      *
00251      * @returns                   Whether the location on the bar is.
00252      * @retval -1                 Coordinate is on the bar before positioner.
00253      * @retval 0                  Coordinate is not on the bar.
00254      * @retval 1                  Coordinate is on the bar after the positioner.
00255      */
00256     virtual int on_bar(const tpoint& coordinate) const = 0;
00257 
00258     /**
00259      * Gets the relevant difference in between the two positions.
00260      *
00261      * This function is used to determine how much the positioner needs to  be
00262      * moved.
00263      */
00264     virtual int get_length_difference(
00265         const tpoint& original, const tpoint& current) const = 0;
00266 
00267     /***** ***** ***** ***** Private functions ***** ***** ***** *****/
00268 
00269     /**
00270      * Updates the scrollbar.
00271      *
00272      * Needs to be called when someting changes eg number of items
00273      * or available size. It can only be called once we have a size
00274      * otherwise we can't calulate a thing.
00275      */
00276     void recalculate();
00277 
00278     /**
00279      * Updates the positioner.
00280      *
00281      * This is a helper for recalculate().
00282      */
00283     void recalculate_positioner();
00284 
00285     /**
00286      * Moves the positioner.
00287      *
00288      * @param distance           The distance moved, negative to begin, positive
00289      *                           to end.
00290     */
00291     void move_positioner(const int distance);
00292 
00293     /** Inherited from tcontrol. */
00294     void load_config_extra();
00295 
00296     /***** ***** ***** signal handlers ***** ****** *****/
00297 
00298     void signal_handler_mouse_enter(
00299             const event::tevent event, bool& handled, bool& halt);
00300 
00301     void signal_handler_mouse_motion(
00302               const event::tevent event
00303             , bool& handled
00304             , bool& halt
00305             , const tpoint& coordinate);
00306 
00307     void signal_handler_mouse_leave(const event::tevent event, bool& handled);
00308 
00309     void signal_handler_left_button_down(
00310             const event::tevent event, bool& handled);
00311 
00312     void signal_handler_left_button_up(
00313             const event::tevent event, bool& handled);
00314 
00315 };
00316 
00317 } // namespace gui2
00318 
00319 #endif
00320 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:59 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs