]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/scout-gfx/lib/scrollbar.cc
Inital import
[l4.git] / l4 / pkg / scout-gfx / lib / scrollbar.cc
1 #include <l4/scout-gfx/scrollbar>
2 #include <l4/scout-gfx/factory>
3
4 #include <algorithm>
5
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
11
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[];
17
18 namespace Scout_gfx {
19
20 /**
21  * Event handler interface
22  */
23 void
24 Scrollbar::Arrow_event_handler::handle(Event const &ev)
25 {
26   /* start movement with zero speed */
27   if ((ev.type == Event::PRESS) && (ev.key_cnt == 1))
28     {
29       /* press icon (slight vertical shift, darker shadow) */
30       _icon->rgba(_rgba, Area(32, 32), 1, 3);
31       _icon->refresh();
32
33       _curr_speed = _direction*256;
34       _dst_speed  = _direction*Max_speed;
35       _accel      = 16;
36       _view_pos   = _sb->view_pos() << 8;
37       schedule(10);
38     }
39
40   if ((ev.type == Event::RELEASE) && (ev.key_cnt == 0))
41     {
42       /* release icon */
43       _icon->rgba(_rgba, Area(32, 32));
44       _icon->refresh();
45
46       _accel     = 64;
47       _dst_speed = 0;
48     }
49 }
50
51 /**
52  * Tick interface
53  */
54 int
55 Scrollbar::Arrow_event_handler::on_tick()
56 {
57   using std::min;
58   using std::max;
59
60   /* accelerate */
61   if (_curr_speed < _dst_speed)
62     _curr_speed = min(_curr_speed + _accel, _dst_speed);
63
64   /* decelerate */
65   if (_curr_speed > _dst_speed)
66     _curr_speed = max(_curr_speed - _accel, _dst_speed);
67
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);
72
73   int max_pos;
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);
78
79   /* move view position with current speed */
80   _view_pos = max(0, _view_pos + _curr_speed);
81
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();
87
88   /* keep ticking as long as we are on speed */
89   return (_curr_speed != 0);
90 }
91
92
93 /**
94  * Event handler interface
95  */
96 void
97 Scrollbar::Slider_event_handler::handle(Event const &ev)
98 {
99
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))
103     {
104       /* press icon (slight vertical shift, darker shadow) */
105       _icon->rgba(_rgba, Area(32,32), 1, 3);
106       _icon->refresh();
107
108       _om = p;
109       _cm = p;
110       _op = _sb->slider_pos();
111     }
112
113   if ((ev.type == Event::RELEASE) && (ev.key_cnt == 0))
114     {
115       /* release icon */
116       _icon->rgba(_rgba, Area(32, 32));
117       _icon->refresh();
118     }
119
120   if (ev.key_cnt && (p != _cm))
121     {
122       _cm = p;
123       _sb->slider_pos(_op + _cm - _om);
124       _sb->notify_listener();
125     }
126 }
127
128
129
130 /*************************
131  ** Scrollbar interface **
132  *************************/
133
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))),
138   _orientation(o),
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)
142
143 {
144   /* init scrollbar elements */
145   _uparrow->alpha(0);
146   _dnarrow->alpha(0);
147   _slider->alpha(0);
148
149   append(_uparrow);
150   append(_dnarrow);
151   append(_slider);
152
153   /* define event handlers for scrollbar elements */
154   _uparrow->event_handler(&_uph);
155   _dnarrow->event_handler(&_dnh);
156   _slider->event_handler(&_slh);
157
158   if (o == Vertical)
159     _size = Area(Sb_elem_w, Sb_elem_h*3);
160   else
161     _size = Area(Sb_elem_w * 3, Sb_elem_h);
162
163   _real_size  = 100;
164   _view_size  = 100;
165   _view_pos   = 0;
166   _listener   = 0;
167   _visibility = 0;
168 }
169
170 void
171 Scrollbar::refresh_slider_geometry()
172 {
173   if (_orientation == Vertical)
174     _slider->set_geometry(Rect(Point(0, slider_pos()), Area(Sb_elem_w, slider_size())));
175   else
176     _slider->set_geometry(Rect(Point(slider_pos(), 0), Area(slider_size(), Sb_elem_h)));
177 }
178
179 void
180 Scrollbar::slider_pos(int pos)
181 {
182   int slider_bg_h;
183   int n;
184   if (_orientation == Vertical)
185     {
186       n = Sb_elem_h;
187       slider_bg_h = _size.h() - Sb_elem_h*2;
188     }
189   else
190     {
191       n = Sb_elem_w;
192       slider_bg_h = _size.w() - Sb_elem_w*2;
193     }
194
195   _view_pos = ((pos - n)*_real_size)/slider_bg_h;
196   _view_pos = std::max(0, std::min(_view_pos,  _real_size - _view_size));
197
198   refresh_slider_geometry();
199
200 }
201
202
203
204 /***********************
205  ** Element interface **
206  ***********************/
207
208 Area
209 Scrollbar::min_size() const
210 {
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);
216   return Area(a, b);
217 }
218
219 Area
220 Scrollbar::preferred_size() const
221 { return Scrollbar::min_size(); }
222
223 Area
224 Scrollbar::max_size() const
225 {
226   if (_orientation == Vertical)
227     return Area(preferred_size().w(), Area::Max_h);
228   else
229     return Area(Area::Max_w, preferred_size().h());
230 }
231
232 void
233 Scrollbar::set_geometry(Rect const &r)
234 {
235   Area s = r.area();
236   s = s.min(max_size()).max(min_size());
237   _pos = r.p1();
238   _size = s;
239
240   if (_orientation == Vertical)
241     _dnarrow->set_geometry(Rect(Point(0, s.h() - Sb_elem_h), _dnarrow->size()));
242   else
243     _dnarrow->set_geometry(Rect(Point(s.w() - Sb_elem_w, 0), _dnarrow->size()));
244
245   refresh_slider_geometry();
246 }
247
248 void
249 Scrollbar::visibility(bool new_visibility)
250 {
251   if (_visibility ^ new_visibility)
252     {
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);
259     }
260
261   _visibility = new_visibility;
262 }
263
264
265 }