KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gui_slider.h
Go to the documentation of this file.
1 /* $Id: gui_slider.h 18034 2014-11-03 05:56:44Z ksimek $ */
2 /* {{{=========================================================================== *
3  |
4  | Copyright (c) 1994-2012 by Kobus Barnard (author)
5  |
6  | Personal and educational use of this code is granted, provided that this
7  | header is kept intact, and that the authorship is not misrepresented, that
8  | its use is acknowledged in publications, and relevant papers are cited.
9  |
10  | For other use contact the author (kobus AT cs DOT arizona DOT edu).
11  |
12  | Please note that the code in this file has not necessarily been adequately
13  | tested. Naturally, there is no guarantee of performance, support, or fitness
14  | for any particular task. Nonetheless, I am interested in hearing about
15  | problems that you encounter.
16  |
17  | Author: Kyle Simek
18  * =========================================================================== }}}*/
19 
20 // vim: tabstop=4 shiftwidth=4 foldmethod=marker
21 //
22 #ifndef KJB_CPP_GUI_SLIDER_H
23 #define KJB_CPP_GUI_SLIDER_H
24 
25 #ifdef KJB_HAVE_OPENGL
26 
27 #include <gr_cpp/gr_opengl.h>
28 #include <gui_cpp/gui_overlay.h>
30 #include <boost/function.hpp>
31 
32 namespace kjb
33 {
34 namespace gui
35 {
36 
41 template <class Real>
42 class Slider : public kjb::gui::Interactive_overlay
43 {
44 typedef kjb::gui::Interactive_overlay Base;
45 public:
46  Slider() :
47  Base(),
48  min_(0),
49  max_(1),
50  value_(0),
51  callback_(),
52  live_updating_(false),
53  grabbed_(false)
54  {
55  if(value_ < min_ || value_ > max_)
56  KJB_THROW_2(kjb::Illegal_argument, "initial value is out of bounds");
57  }
58 
59  Slider(int x, int y,
60  int width,
61  Real min, Real max,
62  Real value) :
63  Base(x,y, width, std::max(INDICATOR_HEIGHT, BAR_HEIGHT)),
64  min_(min),
65  max_(max),
66  value_(value),
67  callback_(),
68  live_updating_(false),
69  grabbed_(false)
70  {}
71 
72  void set_changed_callback(const boost::function1<void, Real>& callback, bool live_updating = false)
73  {
74  callback_ = callback;
75  live_updating_ = live_updating;
76  }
77 
78  virtual void render() const
79  {
80  // TODO: save and restore state
81  glPushAttrib(GL_ENABLE_BIT);
82  glPushAttrib(GL_CURRENT_BIT);
83  glDisable(GL_LIGHTING);
84  int bar_center = bar_center_();
85  int bar_left = x();
86  int bar_right = x() + width();
87  int bar_bottom = bar_center - BAR_HEIGHT/2;
88  int bar_top = bar_center + BAR_HEIGHT/2;
89 
90  static const kjb::Vector3 bar_color(248.0/255.0);
91  static const kjb::Vector3 outline_color(221.0/255.0);
92 // static const kjb::Vector3 outline_color(0);
93  kjb::opengl::glColor(bar_color);
94 
95  glBegin(GL_QUADS);
96 
97  for(size_t i = 0; i < 2; ++i)
98  {
99  glVertex2i(bar_left, bar_bottom);
100  glVertex2i(bar_right, bar_bottom);
101  glVertex2i(bar_right, bar_top);
102  glVertex2i(bar_left, bar_top);
103 
104  glEnd();
105  if(i == 0)
106  {
107  kjb::opengl::glColor(outline_color);
108  glBegin(GL_LINE_LOOP);
109  }
110 
111  }
112 
113  // current indicator
114  if(has_valid_state_())
115  {
116  int current_x = position_from_value_(value_);
117  int indicator_left = current_x - INDICATOR_HEIGHT / 2;
118  int indicator_right = current_x + INDICATOR_HEIGHT / 2;
119  int indicator_bottom = bar_center - INDICATOR_HEIGHT / 2;
120  int indicator_top = bar_center + INDICATOR_HEIGHT / 2;
121  kjb::opengl::glColor(bar_color);
122  glBegin(GL_QUADS);
123  for(size_t i = 0; i < 2; ++i)
124  {
125  glVertex2i(indicator_left, indicator_bottom);
126  glVertex2i(indicator_right, indicator_bottom);
127  glVertex2i(indicator_right, indicator_top);
128  glVertex2i(indicator_left, indicator_top);
129 
130  glEnd();
131  if(i == 0)
132  {
133  kjb::opengl::glColor(outline_color);
134  glBegin(GL_LINE_LOOP);
135  }
136  }
137 
138  }
139  glPopAttrib();
140  glPopAttrib();
141  }
142 
143  virtual bool mouse_event(int button, int state, int u, int v)
144  {
145  kjb::Vector2 pos(u, v);
146 
147  if(!has_valid_state_()) return false;
148 
149  if(button != GLUT_LEFT_BUTTON) return false;
150  if(u < x() || u > x() + width() || v < y() || v > y() + height()) return false;
151 
152  if(state == GLUT_DOWN)
153  {
154  grabbed_ = true;
155 // kjb::Vector2 slider_pos(position_from_value_(value_), bar_center_());
157 // // if down: (1) on slider? (2) on timeline?
158 // if((slider_pos - pos).magnitude() <= height() / 2.0)
159 // {
160 // grabbed_ = true;
161 // return true;
162 // }
163 // else if(fabs(y - slider_pos[1]) < height() / 2.0)
164 // {
165 // grabbed_ = true;
166 // set_value(value_from_position_(x));
167 //
168 // // trigger "value changed" callback
169 // if(callback_)
170 // callback_(get_value());
171 // return true;
172 // }
173  redisplay();
174  return true;
175  }
176  else if(state == GLUT_UP)
177  {
178  if(grabbed_)
179  {
180  grabbed_ = false;
181  set_value(value_from_position_(u));
182 
183  // trigger "value changed" callback
184  if(callback_)
185  callback_(get_value());
186  redisplay();
187  }
188  }
189  return false;
190  }
191 
192  virtual bool mouse_double_event(int , int , int , int )
193  {
194  return false;
195  }
196 
197  virtual bool motion_event(int x, int y)
198  {
199  if(!grabbed_) return false;
200 
201  if(!has_valid_state_()) return false;
202 
203  set_value(value_from_position_(x));
204 
205  // trigger callback if "live updates" are enabled
206  if(callback_ && live_updating_)
207  callback_(get_value());
208 
209  return true;
210  }
211 
212  virtual bool passive_motion_event(int , int )
213  {
214  return false;
215  }
216 
217  virtual bool keyboard_event(unsigned int , int , int )
218  {
219  // todo: consider moving on keys
220  return false;
221  }
222 
223  virtual bool special_event(int , int , int )
224  {
225  // todo: consider moving on keys
226  return false;
227  }
228 
229  void set_value(const Real& v)
230  {
231  value_ = v;
232  redisplay();
233  }
234 
235  void set_min(const Real& min)
236  {
237  min_ = min;
238  redisplay();
239  }
240 
241  void set_max(const Real& max)
242  {
243  max_ = max;
244  redisplay();
245  }
246 
247  const Real& get_value() const
248  {
249  return value_;
250  }
251 
252  void redisplay() const
253  {
254 #ifdef KJB_HAVE_GLUT
255  glutPostRedisplay();
256 #endif
257  }
258 
259 private:
260  Real value_from_position_(int pos) const
261  {
262  assert(has_valid_state_());
263 
264  double delta = pos - x();
265  delta /= width();
266  if(delta < 0.0) return min_;
267  if(delta > 1.0) return max_;
268  return delta * (max_ - min_) + min_;
269  }
270 
271  int position_from_value_(const Real& v) const
272  {
273  assert(has_valid_state_());
274  double delta = v - min_;
275  delta /= (max_ - min_);
276  if(delta < 0 || delta > 1.0)
277  KJB_THROW_3(kjb::Illegal_argument, "value must be between %f and %f", (min_)(max_));
278  return x() + delta * width();
279  }
280 
281  inline int bar_center_() const
282  {
283  return y() + height() / 2.0;
284  }
285 
286  bool has_valid_state_() const
287  {
288  if(fabs(max_ - min_) < DBL_EPSILON) return false;
289  return true;
290 
291  }
292 
293 private:
294  Real min_;
295  Real max_;
296  Real value_;
297 
298  boost::function1<void, Real> callback_;
299  bool live_updating_;
300  bool grabbed_;
301 
302  static const int INDICATOR_HEIGHT;
303  static const int BAR_HEIGHT;
304 };
305 
306 template <class T>
307 const int Slider<T>::INDICATOR_HEIGHT = 15;
308 template <class T>
309 const int Slider<T>::BAR_HEIGHT = 10;
310 
311 } // namespace gui
312 } // namespace kjb
313 
314 #endif /* HAVE_OPENGL */
315 #endif
316 
Int_matrix::Value_type max(const Int_matrix &mat)
Return the maximum value in this matrix.
Definition: l_int_matrix.h:1397
height
Definition: APPgetLargeConnectedEdges.m:33
x
Definition: APPgetLargeConnectedEdges.m:100
void render(const Cuboid &c)
Definition: psi_weighted_box.cpp:56
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
#define KJB_THROW_3(ex, fmt, params)
Definition: l_exception.h:56
Int_matrix::Value_type min(const Int_matrix &mat)
Return the minimum value in this matrix.
Definition: l_int_matrix.h:1385
void glColor(const Vector &color)
glColor for a kjb::Vector.
Definition: gr_opengl.cpp:196
Object thrown when an argument to a function is not acceptable.
Definition: l_exception.h:377
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48