Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
scroller.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2003 Mike Byron
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 #include "vegastrike.h"
23 #include "scroller.h"
24 #include "newbutton.h"
25 #include "slider.h"
26 
27 //This object contains several controls as a group. These child controls
28 //should always be in the same places in the list of child controls.
29 static const int DOWN_BUTTON_INDEX = 0;
30 static const int UP_BUTTON_INDEX = 1;
31 static const int SLIDER_INDEX = 2;
32 static const int CHILD_CONTROL_COUNT = 3;
33 
34 //The Scroller class is a Control that offers scroll positioning.
35 //It has a drag "thumb", and scroll buttons.
36 //This implementation keeps track of the scroll position internally,
37 //and uses an integer scroll position.
38 //The only "event" it communicates to the outside world is a change
39 //of scroll position.
40 
41 //Set the position of this scroller.
43 {
44  int newScrollPosition = pos;
45  if (pos > m_maxValue)
46  newScrollPosition = m_maxValue;
47  else if (pos < m_minValue)
48  newScrollPosition = m_minValue;
49  if (m_scrollPosition != newScrollPosition) {
50  m_scrollPosition = newScrollPosition;
51 
52  Slider *slider = static_cast< Slider* > ( childAt( SLIDER_INDEX ) );
53  slider->setPosition( m_scrollPosition );
54 
55  sendCommand( "Scroller::PositionChanged", this );
56  }
57 }
58 
59 //Parameters for the scrolling range: Max value, visible values, optional min value.
60 void Scroller::setRangeValues( int max, int visible, int min )
61 {
62  const int newMax = guiMax( min, max-visible+1 );
63  if (newMax != m_maxValue || min != m_minValue || visible != m_visible) {
64  m_maxValue = newMax;
65  m_minValue = min;
66  m_visible = visible;
67  m_needLayout = true;
68 
69  Slider *slider = static_cast< Slider* > ( childAt( SLIDER_INDEX ) );
70  slider->setMaxMin( newMax, min );
71  const float thumbLength = (max > min) ? (float) visible/(max-min+1) : -1.;
72  //Note that impossible thumb lengths turn off the thumb.
73  slider->setThumbLength( thumbLength );
74  slider->setPageSize( guiMax( 1, visible-1 ) );
75  }
76 }
77 
78 //The outside boundaries of the control.
79 void Scroller::setRect( const Rect &r )
80 {
81  if (m_rect != r)
82  m_needLayout = true;
84 }
85 
86 //Background color of control.
88 {
89  assert( childCount() == CHILD_CONTROL_COUNT );
92  if ( isClear( m_thumbColor ) ) {
93  //If we don't have an explicit thumb color, calculate it.
94  Slider *slider = static_cast< Slider* > ( childAt( SLIDER_INDEX ) );
95  slider->setThumbColorBasedOnColor( c );
96  }
98 }
99 
100 //The color of the thumb.
101 void Scroller::setThumbColor( const GFXColor &c, const GFXColor &outline )
102 {
103  assert( childCount() == CHILD_CONTROL_COUNT );
104  Slider *slider = static_cast< Slider* > ( childAt( SLIDER_INDEX ) );
105  slider->setThumbColor( c, outline );
106 }
107 
108 //The color of the thumb.
110 {
111  assert( childCount() == CHILD_CONTROL_COUNT );
114 }
115 
116 //This is used as the color of the arrows on the scroller buttons.
118 {
119  assert( childCount() == CHILD_CONTROL_COUNT );
122 
124 }
125 
126 //Derived button class that can draw the arrow correctly.
127 class ScrollerButton : public NewButton
128 {
129 public:
130 //Draw the button.
131  virtual void draw( void );
132 //Which way the arrow points.
134  {
139  };
140 //Set the direction the arrow points.
141  void setArrowType( ButtonArrow arrow )
142  {
143  m_arrowType = arrow;
144  }
145 //CONSTRUCTION
147  virtual ~ScrollerButton( void ) {}
148 //VARIABLES
149 protected:
150  ButtonArrow m_arrowType; //Direction the arrow points.
151 };
152 
153 //Draw the scroller button.
155 {
156  //Draw the other stuff first, so our stuff goes on top.
157  assert( label().empty() ); //We are assuming it won't paint text on itself.
158  NewButton::draw();
159  static const float ARROW_POINT = .012; //From center to point of arrow.
160  static const float ARROW_WIDTH = .01; //From center to side points.
161  static const float ARROW_BACK = .01; //From center back to "bottom" of arrow.
163  vector< Point > coords( 3 ); //3-element vector.
164  switch (m_arrowType)
165  {
166  case LEFT_ARROW:
167  coords[0] = Point( center.x+ARROW_POINT, center.y );
168  coords[1] = Point( center.x-ARROW_BACK, center.y+ARROW_WIDTH );
169  coords[2] = Point( center.x-ARROW_BACK, center.y-ARROW_WIDTH );
170  break;
171  case RIGHT_ARROW:
172  coords[0] = Point( center.x-ARROW_POINT, center.y );
173  coords[1] = Point( center.x+ARROW_BACK, center.y+ARROW_WIDTH );
174  coords[2] = Point( center.x+ARROW_BACK, center.y-ARROW_WIDTH );
175  break;
176  case UP_ARROW:
177  coords[0] = Point( center.x, center.y+ARROW_POINT );
178  coords[1] = Point( center.x+ARROW_WIDTH, center.y-ARROW_BACK );
179  coords[2] = Point( center.x-ARROW_WIDTH, center.y-ARROW_BACK );
180  break;
181  case DOWN_ARROW:
182  coords[0] = Point( center.x, center.y-ARROW_POINT );
183  coords[1] = Point( center.x+ARROW_WIDTH, center.y+ARROW_BACK );
184  coords[2] = Point( center.x-ARROW_WIDTH, center.y+ARROW_BACK );
185  break;
186  }
187  drawFilledPolygon( coords, textColor() );
188 }
189 
190 //Calculate the rects for the child controls.
192 {
193  assert( childCount() == CHILD_CONTROL_COUNT );
194 
195  //Make the buttons slightly smaller than the scroller.
196  static const Size BUTTON_INSET = Size( .005, .005 );
197 
198  //Get pointers to the buttons.
199  ScrollerButton *downButton = static_cast< ScrollerButton* > ( childAt( DOWN_BUTTON_INDEX ) );
200  ScrollerButton *upButton = static_cast< ScrollerButton* > ( childAt( UP_BUTTON_INDEX ) );
201  //Make the buttons square, and at the bottom/right of the scroller.
202  if (m_rect.size.height >= m_rect.size.width) {
203  //This is a vertical scroller.
204  Rect rect = m_rect;
205  rect.size.height = rect.size.width;
206  downButton->setRect( rect.copyAndInset( BUTTON_INSET ) );
207  downButton->setCommand( "LineDown" );
209 
210  rect.origin.y += rect.size.height;
211  upButton->setRect( rect.copyAndInset( BUTTON_INSET ) );
212  upButton->setCommand( "LineUp" );
214 
215  Rect thumbRect = m_rect;
216  thumbRect.origin.y = rect.top();
217  thumbRect.size.height -= thumbRect.origin.y-m_rect.origin.y;
218  childAt( SLIDER_INDEX )->setRect( thumbRect );
219  } else {
220  //This is a horizontal scroller.
221  //Need to flip the button commands -- "line up" does lower values.
222  Rect rect = m_rect;
223  rect.size.width = rect.size.height;
224  downButton->setRect( rect.copyAndInset( BUTTON_INSET ) );
225  downButton->setCommand( "LineUp" );
227 
228  rect.origin.x += rect.size.width;
229  upButton->setRect( rect.copyAndInset( BUTTON_INSET ) );
230  upButton->setCommand( "LineDown" );
232 
233  Rect thumbRect = m_rect;
234  thumbRect.origin.x = rect.right();
235  thumbRect.size.width -= thumbRect.origin.x-m_rect.origin.x;
236  childAt( SLIDER_INDEX )->setRect( thumbRect );
237  }
238 }
239 
240 //Create the child controls.
242 {
243  //"Scroll Down" button.
244  NewButton *down = new ScrollerButton;
245  down->setCommand( "LineDown" );
246  down->setColor( color() );
247  down->setTextColor( textColor() ); //Arrow color.
248  down->setCommandTarget( this );
249  addChild( down );
250 
251  //"Scroll Up" button.
252  NewButton *up = new ScrollerButton;
253  up->setCommand( "LineUp" );
254  up->setColor( color() );
255  up->setTextColor( textColor() ); //Arrow color.
256  up->setCommandTarget( this );
257  addChild( up );
258 
259  //Slider control.
260  Slider *slider = new Slider;
261  slider->setColor( GUI_CLEAR );
262  slider->setThumbColorBasedOnColor( color() );
263  slider->setCommandTarget( this );
264  addChild( slider );
265 }
266 
267 //Draw the control.
268 void Scroller::draw( void )
269 {
270  drawBackground();
271  if (m_needLayout)
272  calcLayout();
274 }
275 
276 //Process a command event.
277 bool Scroller::processCommand( const EventCommandId &command, Control *control )
278 {
279  if (command == "LineUp") {
281  return true;
282  } else if (command == "LineDown") {
284  return true;
285  } else if (command == "Slider::PositionChanged") {
286  Slider *slider = static_cast< Slider* > ( childAt( SLIDER_INDEX ) );
287  setScrollPosition( slider->position() );
288  return true;
289  }
290  return GroupControl::processCommand( command, control );
291 }
292 
293 //CONSTRUCTION
295  m_minValue( 0 )
296  , m_maxValue( 10 )
297  , m_visible( 1 )
298  , m_scrollPosition( m_minValue )
299  , m_thumbColor( GUI_CLEAR )
300  , m_thumbOutlineColor( GUI_CLEAR )
301  , m_needLayout( true )
302 {
303  createControls();
304 }
305