1 #include <l4/scout-gfx/scrollbar>
2 #include <l4/scout-gfx/factory>
6 #define SLIDER_RGBA _binary_slider_rgba_start
7 #define UPARROW_RGBA _binary_uparrow_rgba_start
8 #define DNARROW_RGBA _binary_downarrow_rgba_start
9 #define LFARROW_RGBA _binary_leftarrow_rgba_start
10 #define RIARROW_RGBA _binary_rightarrow_rgba_start
12 extern unsigned char SLIDER_RGBA[];
13 extern unsigned char UPARROW_RGBA[];
14 extern unsigned char DNARROW_RGBA[];
15 extern unsigned char LFARROW_RGBA[];
16 extern unsigned char RIARROW_RGBA[];
21 * Event handler interface
24 Scrollbar::Arrow_event_handler::handle(Event const &ev)
26 /* start movement with zero speed */
27 if ((ev.type == Event::PRESS) && (ev.key_cnt == 1))
29 /* press icon (slight vertical shift, darker shadow) */
30 _icon->rgba(_rgba, Area(32, 32), 1, 3);
33 _curr_speed = _direction*256;
34 _dst_speed = _direction*Max_speed;
36 _view_pos = _sb->view_pos() << 8;
40 if ((ev.type == Event::RELEASE) && (ev.key_cnt == 0))
43 _icon->rgba(_rgba, Area(32, 32));
55 Scrollbar::Arrow_event_handler::on_tick()
61 if (_curr_speed < _dst_speed)
62 _curr_speed = min(_curr_speed + _accel, _dst_speed);
65 if (_curr_speed > _dst_speed)
66 _curr_speed = max(_curr_speed - _accel, _dst_speed);
68 /* soft stopping on boundaries */
69 while ((_curr_speed < 0) && (_view_pos > 0)
70 && (_curr_speed*_curr_speed > _view_pos*_accel*4))
71 _curr_speed = min(0, _curr_speed + _accel*4);
74 while ((_curr_speed > 0)
75 && ((max_pos = (_sb->real_size() - _sb->view_size())*256 - _view_pos) > 0)
76 && (_curr_speed*_curr_speed > max_pos*_accel*4))
77 _curr_speed = max(0, _curr_speed - _accel*4);
79 /* move view position with current speed */
80 _view_pos = max(0, _view_pos + _curr_speed);
82 /* set new view position */
83 int old_view_pos = _sb->view_pos();
84 _sb->view(_sb->real_size(), _sb->view_size(), _view_pos>>8);
85 if (old_view_pos != _sb->view_pos())
86 _sb->notify_listener();
88 /* keep ticking as long as we are on speed */
89 return (_curr_speed != 0);
94 * Event handler interface
97 Scrollbar::Slider_event_handler::handle(Event const &ev)
100 int p = _sb->orientation() == Vertical ? ev.m.y() : ev.m.x();
101 /* start movement with zero speed */
102 if ((ev.type == Event::PRESS) && (ev.key_cnt == 1))
104 /* press icon (slight vertical shift, darker shadow) */
105 _icon->rgba(_rgba, Area(32,32), 1, 3);
110 _op = _sb->slider_pos();
113 if ((ev.type == Event::RELEASE) && (ev.key_cnt == 0))
116 _icon->rgba(_rgba, Area(32, 32));
120 if (ev.key_cnt && (p != _cm))
123 _sb->slider_pos(_op + _cm - _om);
124 _sb->notify_listener();
130 /*************************
131 ** Scrollbar interface **
132 *************************/
134 Scrollbar::Scrollbar(Factory *f, Orientation o)
135 : _uparrow(f->create_icon(o == Vertical ? UPARROW_RGBA : LFARROW_RGBA, Area(32, 32))),
136 _dnarrow(f->create_icon(o == Vertical ? DNARROW_RGBA : RIARROW_RGBA, Area(32, 32))),
137 _slider(f->create_icon(SLIDER_RGBA, Area(32, 32))),
139 _uph(this, _uparrow, -1, o == Vertical ? UPARROW_RGBA : LFARROW_RGBA),
140 _dnh(this, _dnarrow, 1, o == Vertical ? DNARROW_RGBA : RIARROW_RGBA),
141 _slh(this, _slider, SLIDER_RGBA)
144 /* init scrollbar elements */
153 /* define event handlers for scrollbar elements */
154 _uparrow->event_handler(&_uph);
155 _dnarrow->event_handler(&_dnh);
156 _slider->event_handler(&_slh);
159 _size = Area(Sb_elem_w, Sb_elem_h*3);
161 _size = Area(Sb_elem_w * 3, Sb_elem_h);
171 Scrollbar::refresh_slider_geometry()
173 if (_orientation == Vertical)
174 _slider->set_geometry(Rect(Point(0, slider_pos()), Area(Sb_elem_w, slider_size())));
176 _slider->set_geometry(Rect(Point(slider_pos(), 0), Area(slider_size(), Sb_elem_h)));
180 Scrollbar::slider_pos(int pos)
184 if (_orientation == Vertical)
187 slider_bg_h = _size.h() - Sb_elem_h*2;
192 slider_bg_h = _size.w() - Sb_elem_w*2;
195 _view_pos = ((pos - n)*_real_size)/slider_bg_h;
196 _view_pos = std::max(0, std::min(_view_pos, _real_size - _view_size));
198 refresh_slider_geometry();
204 /***********************
205 ** Element interface **
206 ***********************/
209 Scrollbar::min_size() const
211 Area us = _uparrow->preferred_size();
212 Area ss = _slider->preferred_size();
213 Area ds = _dnarrow->preferred_size();
214 int a = Sb_elem_w * (_orientation == Horizontal ? 4 : 1);
215 int b = Sb_elem_h * (_orientation == Vertical ? 4 : 1);
220 Scrollbar::preferred_size() const
221 { return Scrollbar::min_size(); }
224 Scrollbar::max_size() const
226 if (_orientation == Vertical)
227 return Area(preferred_size().w(), Area::Max_h);
229 return Area(Area::Max_w, preferred_size().h());
233 Scrollbar::set_geometry(Rect const &r)
236 s = s.min(max_size()).max(min_size());
240 if (_orientation == Vertical)
241 _dnarrow->set_geometry(Rect(Point(0, s.h() - Sb_elem_h), _dnarrow->size()));
243 _dnarrow->set_geometry(Rect(Point(s.w() - Sb_elem_w, 0), _dnarrow->size()));
245 refresh_slider_geometry();
249 Scrollbar::visibility(bool new_visibility)
251 if (_visibility ^ new_visibility)
253 enum { Default_alpha = 100 };
254 int alpha = new_visibility ? Default_alpha : 0;
255 int speed = new_visibility ? 3 : 2;
256 dynamic_cast<Fader*>(_uparrow)->fade_to(alpha, speed);
257 dynamic_cast<Fader*>(_dnarrow)->fade_to(alpha, speed);
258 dynamic_cast<Fader*>(_slider)->fade_to(alpha, speed);
261 _visibility = new_visibility;