]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/scout/lib/src/panel.h
e16d43d7e48571b04f4ec0c097b4ca2659bc9852
[l4.git] / l4 / pkg / scout / lib / src / panel.h
1 #pragma once
2
3 #include "browser_if.h"
4 #include "refracted_icon.h"
5
6 #include <l4/scout-gfx/box_layout>
7 #include <l4/scout-gfx/stack_layout>
8
9
10 class Factory;
11
12
13 #define IOR_MAP       _binary_ior_map_start
14 #define HOME_RGBA     _binary_home_rgba_start
15 #define COVER_RGBA    _binary_cover_rgba_start
16 #define INDEX_RGBA    _binary_index_rgba_start
17 #define ABOUT_RGBA    _binary_about_rgba_start
18 #define FORWARD_RGBA  _binary_forward_rgba_start
19 #define BACKWARD_RGBA _binary_backward_rgba_start
20
21 extern short         IOR_MAP[];
22 extern unsigned char HOME_RGBA[];
23 extern unsigned char COVER_RGBA[];
24 extern unsigned char INDEX_RGBA[];
25 extern unsigned char ABOUT_RGBA[];
26 extern unsigned char FORWARD_RGBA[];
27 extern unsigned char BACKWARD_RGBA[];
28
29 /* icon graphics data */
30 static unsigned char *glow_icon_gfx[] = {
31     HOME_RGBA,
32     BACKWARD_RGBA,
33     FORWARD_RGBA,
34     INDEX_RGBA,
35     ABOUT_RGBA,
36 };
37
38 /* color definitions for glowing effect of the icons */
39 static Scout_gfx::Color glow_icon_col[] = {
40     Scout_gfx::Color(210, 210,   0),
41     Scout_gfx::Color(  0,   0, 160),
42     Scout_gfx::Color(  0,   0, 160),
43     Scout_gfx::Color(  0, 160,   0),
44     Scout_gfx::Color(160,   0,   0),
45 };
46
47 /**
48  * Transform rgba source image to image with native pixel type
49  *
50  * If we specify an empty buffer as alpha channel (all values zero), we simply
51  * assign the source image data to the destination buffer. If there are valid
52  * values in the destination alpha channel, we paint the source image on top
53  * of the already present image data. This enables us to combine multiple
54  * rgba buffers (layers) into one destination buffer.
55  */
56 template <typename PTx>
57 static void extract_rgba(const unsigned char *_src, int w, int h,
58     typename PTx::Pixel *dst_pixel, unsigned char *dst_alpha)
59 {
60   using namespace Mag_gfx;
61   typedef typename PTx::Pixel PT;
62   typedef typename PTx::Color Color;
63
64   Rgba32::Pixel const *src = reinterpret_cast<Rgba32::Pixel const*>(_src);
65
66   for (int i = 0; i < w*h; ++i, ++src)
67     {
68       Rgba32::Color const s = *src;
69       if (dst_alpha[i])
70         {
71           dst_pixel[i] = PTx::mix(dst_pixel[i], color_conv<Color>(s), s.a());
72           dst_alpha[i] = std::max((int)dst_alpha[i], s.a());
73         }
74       else
75         {
76           dst_pixel[i] = color_conv<Color>(s);
77           dst_alpha[i] = s.a();
78         }
79     }
80 }
81
82
83 template< typename PT >
84 class Panel : public Scout_gfx::Parent_widget
85 {
86   enum
87   {
88     ICON_HOME     = 0,
89     ICON_BACKWARD = 1,
90     ICON_FORWARD  = 2,
91     ICON_INDEX    = 3,
92     ICON_ABOUT    = 4
93   };
94
95   /**
96    * Constants
97    */
98   enum
99   {
100     _NUM_ICONS = 5,     /* number of icons          */
101     _IW        = 64,    /* browser icon width       */
102     _IH        = 64,    /* browser icon height      */
103     _PANEL_W   = 320,   /* panel tile width         */
104     _PANEL_H   = _IH,   /* panel tile height        */
105     _SB_XPAD   = 5,     /* hor. pad of scrollbar    */
106     _SB_YPAD   = 10,    /* vert. pad of scrollbar   */
107     _SCRATCH   = 7      /* scratching factor        */
108   };
109 protected:
110   typedef typename PT::Pixel Pixel;
111   Area preferred_size() const
112   {
113     if (child_layout())
114       return child_layout()->preferred_size();
115
116     return Area(0, 0);
117   }
118
119   Area min_size() const
120   {
121     if (child_layout())
122       return child_layout()->min_size();
123
124     return Area(0, 0);
125   }
126
127   Area max_size() const
128   {
129     if (child_layout())
130       return child_layout()->max_size();
131
132     return Area(Area::Max_w, Area::Max_h);
133   }
134
135   Mag_gfx::Orientations expanding() const { return Mag_gfx::Horizontal; }
136   bool empty() const { return false; }
137
138   void set_geometry(Rect const &r)
139   {
140     if (child_layout())
141       child_layout()->set_geometry(Rect(r.area()));
142
143     _pos = r.p1();
144     _size = min_size().max(r.area()).min(max_size());
145   }
146
147   Rect geometry() const { return Rect(_pos, _size); }
148
149   /**
150    * Widgets
151    */
152   Pixel                      _icon_fg        [_NUM_ICONS][_IH][_IW];
153   unsigned char              _icon_fg_alpha  [_NUM_ICONS][_IH][_IW];
154   Refracted_icon<PT, short>  _icon           [_NUM_ICONS];
155   Pixel                      _icon_backbuf   [_IH*2][_IW*2];
156   Pixel                      _panel_fg       [_PANEL_H][_PANEL_W];
157   unsigned char              _panel_fg_alpha [_PANEL_H][_PANEL_W];
158   short                      _panel_distmap  [_PANEL_H*2][_PANEL_W*2];
159   Refracted_icon<PT, short>  _panel;
160   Pixel                      _panel_backbuf  [_PANEL_H*2][_PANEL_W*2];
161   Scout_gfx::Icon           *_glow_icon[_NUM_ICONS];
162
163   class Ev_proxy : public Scout_gfx::Event_handler
164   {
165   private:
166     Widget *b;
167
168   public:
169     Ev_proxy(Widget *b) : b(b) {}
170     /**
171      * Event handler interface
172      */
173     void handle(Scout_gfx::Event const &ev)
174     { b->handle_event(ev); }
175   };
176
177   Ev_proxy _ev_proxy;
178
179   void handler(Widget *e, Browser_if *b, bool (Browser_if::*f)());
180
181 public:
182   Panel(Scout_gfx::Factory *f, Browser_if *);
183
184 };
185
186
187 /********************
188  ** Event handlers **
189  ********************/
190
191 class Iconbar_event_handler : public Scout_gfx::Event_handler
192 {
193 private:
194
195   Scout_gfx::Fader *_fader;
196   Browser_if *_b;
197   bool (Browser_if::*_f)();
198
199 public:
200
201   /**
202    * Constructor
203    */
204   Iconbar_event_handler(Scout_gfx::Fader *fader, Browser_if *b,
205                         bool (Browser_if::*f)())
206   : _fader(fader), _b(b), _f(f) {}
207
208   /**
209    * Event handler interface
210    */
211   void handle(Scout_gfx::Event const &ev)
212   {
213     /* start movement with zero speed */
214     if ((ev.type != Scout_gfx::Event::PRESS) || (ev.key_cnt != 1))
215       return;
216
217     /* no flashing by default */
218     int flash = (_b->*_f)();
219
220     /* flash clicked icon */
221     if (0 && flash)
222       {
223
224         /* flash fader to the max */
225         _fader->step(4);
226         _fader->curr(190);
227       }
228   }
229 };
230
231 template< typename PT >
232 void
233 Panel<PT>::handler(Widget *e, Browser_if *b, bool (Browser_if::*f)())
234 {
235   e->event_handler(new Iconbar_event_handler(dynamic_cast<Scout_gfx::Fader*>(e), b, f));
236 }
237
238 template< typename PT >
239 Panel<PT>::Panel(Scout_gfx::Factory *f, Browser_if *b)
240 : _ev_proxy(this)
241 {
242   using namespace Mag_gfx;
243   using namespace Scout_gfx;
244
245
246   _size = Area(_NUM_ICONS*_IW, _IH);
247
248   /* init icons */
249   memset(_icon_fg,       0, sizeof(_icon_fg));
250   memset(_icon_fg_alpha, 0, sizeof(_icon_fg_alpha));
251   for (int i = 0; i < _NUM_ICONS; i++)
252     {
253       /* convert rgba raw image to PT pixel format and alpha channel */
254       extract_rgba<PT>(COVER_RGBA, _IW, _IH,
255           _icon_fg[i][0], _icon_fg_alpha[i][0]);
256
257       /* assign back buffer, foreground and distmap to icon */
258       _icon[i].backbuf(_icon_backbuf[0], 1);
259       _icon[i].distmap(IOR_MAP, _IW*2, _IH*2);
260       _icon[i]._min_size = Area(_IW, _IH);
261       _icon[i].foreground(_icon_fg[i][0], _icon_fg_alpha[i][0]);
262
263       /* apply foreground graphics to icon */
264       extract_rgba<PT>(glow_icon_gfx[i], _IW, _IH,
265           _icon_fg[i][0], _icon_fg_alpha[i][0]);
266
267       _icon[i].event_handler(&_ev_proxy);
268
269       /* init glow icon */
270       Scout_gfx::Icon *fadeicon = f->create_icon();
271
272       _glow_icon[i] = fadeicon;
273       fadeicon->glow(glow_icon_gfx[i], Area(_IW, _IH), glow_icon_col[i]);
274       fadeicon->default_alpha(0);
275       fadeicon->focus_alpha(100);
276       fadeicon->alpha(0);
277     }
278
279   handler(_glow_icon[ICON_HOME], b, &Browser_if::go_home);
280   handler(_glow_icon[ICON_FORWARD], b, &Browser_if::go_forward);
281   handler(_glow_icon[ICON_BACKWARD], b, &Browser_if::go_backward);
282   handler(_glow_icon[ICON_INDEX], b, &Browser_if::go_toc);
283   handler(_glow_icon[ICON_ABOUT], b, &Browser_if::go_about);
284
285   /*
286    * All icons share the same distmap. Therefore we need to scratch
287    * only one distmap to affect all icons.
288    */
289   _icon[0].scratch(_SCRATCH);
290
291   /* create panel tile texture */
292   /*
293    * NOTE: The panel height must be the same as the icon height.
294    */
295   for (int j = 0; j < _PANEL_H; j++)
296     for (int i = 0; i < _PANEL_W; i++) {
297         _panel_fg       [j][i] = _icon_fg       [ICON_INDEX][j][i&0x1];
298         _panel_fg_alpha [j][i] = _icon_fg_alpha [ICON_INDEX][j][i&0x1] + random()%3;
299     }
300
301   /* init panel background */
302   _panel.backbuf(&_panel_backbuf[0][0]);
303   _panel.distmap(_panel_distmap[0], _PANEL_W*2, _PANEL_H*2);
304   _panel.foreground(_panel_fg[0], _panel_fg_alpha[0]);
305   _panel.scratch(_SCRATCH);
306   _panel.event_handler(&_ev_proxy);
307   _panel._min_size = Area(_IW, _IH);
308
309   Scout_gfx::Layout *l = Scout_gfx::Box_layout::create_horz();
310   set_child_layout(l);
311   for (int i = 0; i <= ICON_INDEX; i++) {
312       Scout_gfx::Layout *sl = Scout_gfx::Stack_layout::create();
313       sl->add_item(&_icon[i]);
314       sl->add_item(_glow_icon[i]);
315       l->add_item(sl);
316       append(&_icon[i]);
317       append(_glow_icon[i]);
318   }
319   append(&_panel);
320   l->add_item(&_panel);
321   Scout_gfx::Layout *sl = Scout_gfx::Stack_layout::create();
322   sl->add_item(&_icon[ICON_ABOUT]);
323   sl->add_item(_glow_icon[ICON_ABOUT]);
324   l->add_item(sl);
325   append(&_icon[ICON_ABOUT]);
326   append(_glow_icon[ICON_ABOUT]);
327 }
328
329