]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/scout-gfx/include/widget
update
[l4.git] / l4 / pkg / scout-gfx / include / widget
1 // vi:ft=cpp
2 /*
3  * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #pragma once
11
12 #include <l4/scout-gfx/event>
13 #include <l4/scout-gfx/layout_item>
14 #include <l4/scout-gfx/layout>
15
16 #include <l4/mag-gfx/gfx_colors>
17
18 namespace Mag_gfx {
19 class Canvas;
20 }
21
22 namespace Scout_gfx {
23
24 using Mag_gfx::Canvas;
25
26 class Parent_widget;
27
28 class Widget : public Layout_item
29 {
30 protected:
31   Point _pos;
32   Area  _size;
33   Parent_widget *_parent;
34   Event_handler *_evh;
35   struct
36   {
37     int mfocus      : 1; ///< Widget has mouse focus
38     int selected    : 1; ///< Widget is currently selected
39     int takes_focus : 1; ///< Widget highlights mouse focus
40     int findable    : 1; ///< Regard element in find function
41     int visible     : 1; ///< Widget is visible
42   } _flags;
43
44 public:
45   Widget *next;
46
47   Widget()
48   : _pos(0, 0), _size(1, 0), _parent(0), _evh(0), next(0)
49   {
50     _flags.mfocus = 0;
51     _flags.selected = 0;
52     _flags.findable = 1;
53     _flags.visible = 1;
54   }
55
56   virtual ~Widget();
57
58   Area size() const { return _size; }
59   Point pos() const { return _pos; }
60   Rect geometry() const { return Rect(_pos, _size); }
61   void set_geometry(Rect const &g)
62   {
63     _pos = g.p1();
64     _size = g.area();
65   }
66
67   inline Point map_to_parent(Point const &po, Widget *p = 0) const;
68
69   Point map_from_parent(Point const &po, Widget *p = 0) const
70   { return po - map_to_parent(Point(0, 0), p); }
71
72
73   void findable(int flag) { _flags.findable = flag; }
74   bool findable() const { return _flags.findable; }
75
76   void visible(bool flag) { _flags.visible = flag; }
77   bool visible() const { return _flags.visible; }
78
79   virtual void draw(Canvas *c, Point const &p) = 0;
80   virtual Widget *find(Point const &p);
81   //virtual Widget *find_child(Point const &p);
82   virtual void fill_cache(Mag_gfx::Pixel_info const *) {}
83   virtual void flush_cache(Mag_gfx::Pixel_info const *) {}
84
85   void parent(Parent_widget *parent) { _parent = parent; }
86   Parent_widget *parent() const { return _parent; }
87
88   /**
89    * Define event handler object
90    */
91   void event_handler(Event_handler *evh) { _evh = evh; }
92
93   /**
94    * Check if element is completely clipped and draw it otherwise
95    */
96   void try_draw(Canvas *c, Point const &p)
97   {
98     if (!visible())
99       return;
100 #if 0
101     /* check if element is completely outside the clipping area */
102     if (!(c->clip() & Rect(p + _pos, _size)).valid())
103       return;
104 #endif
105     /* call actual drawing function */
106     draw(c, p);
107   }
108
109   /**
110    * Update area of an element on screen
111    *
112    * We propagate the redraw request through the element hierarchy to
113    * the parent. The root parent should overwrite this function with
114    * a function that performs the actual redraw.
115    */
116   virtual void redraw_area(Rect const &r) const;
117
118   /**
119    * Trigger the refresh of an element on screen
120    */
121   void refresh() const
122   { redraw_area(Rect(_size)); }
123
124   virtual void mfocus(int flag)
125   {
126     if ((_flags.mfocus == flag) || !_flags.takes_focus)
127       return;
128
129     _flags.mfocus = flag;
130   }
131
132   /**
133    * Handle user input or timer event
134    */
135   virtual Widget *handle_event(Event const &ev)
136   {
137     if (_evh && _evh->handle(ev))
138       return this;
139     return 0;
140   }
141 };
142
143 class Parent_widget : public Widget
144 {
145 protected:
146   Widget *_first;
147   Widget *_last;
148
149 private:
150   Layout *_child_layout;
151
152 public:
153
154   Parent_widget() : Widget(), _first(0), _last(0), _child_layout(0) {}
155
156   Layout *child_layout() const { return _child_layout; }
157   /**
158    * Adopt a child element
159    */
160   virtual void append(Widget *e);
161
162   /**
163    * Release child element from parent element
164    */
165   virtual void remove(Widget *e);
166
167   /**
168    * Dispose references to the specified element
169    *
170    * The element is not necessarily an immediate child but some element
171    * of the element-subtree.  This function gets propagated to the root
172    * parent (e.g., user state manager), which can reset the mouse focus
173    * of the focused element vanishes.
174    */
175   virtual void forget(Widget *e);
176
177   void set_child_layout(Layout *l)
178   {
179     _child_layout = l;
180     if (l)
181       l->set_parent_layout_item(this);
182   }
183
184   Area preferred_size() const
185   {
186     return child_layout() ? child_layout()->preferred_size() : Area(0, 0);
187   }
188
189   Area min_size() const
190   {
191     return child_layout() ? child_layout()->min_size() : Area(0, 0);
192   }
193
194   Area max_size() const
195   {
196     return child_layout() ? child_layout()->max_size() : Area(Area::Max_w, Area::Max_h);
197   }
198
199   Orientations expanding() const
200   {
201     return child_layout() ? child_layout()->expanding() : 0;
202   }
203
204   bool empty() const
205   {
206     return child_layout() ? child_layout()->empty() : true;
207   }
208
209   void set_geometry(Rect const &r)
210   {
211     if (child_layout())
212       child_layout()->set_geometry(Rect(r.area()));
213
214     _pos = r.p1();
215     _size = min_size().max(r.area()).min(max_size());
216   }
217
218   Rect geometry() const { return Rect(_pos, _size); }
219
220   void child_invalidate()
221   { invalidate(); }
222
223   bool has_height_for_width() const
224   { return child_layout() ? child_layout()->has_height_for_width() : false; }
225
226   int height_for_width(int w) const
227   { return child_layout() ? child_layout()->height_for_width(w) : -1; }
228
229   int min_height_for_width(int w) const
230   { return child_layout() ? child_layout()->min_height_for_width(w) : -1; }
231
232
233   void draw(Canvas *c, Point const &p);
234   Widget *find(Point const &p);
235   virtual Widget *find_child(Point const &p);
236 };
237
238 inline
239 Point
240 Widget::map_to_parent(Point const &po, Widget *p) const
241 {
242   if (p == _parent || !_parent)
243     return po + _pos;
244
245   return _parent->map_to_parent(po + _pos, p);
246 }
247
248 }