]> 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;      /* element has mouse focus             */
38     int selected    : 1;      /* element has selected state          */
39     int takes_focus : 1;      /* element highlights mouse focus      */
40     int findable    : 1;      /* regard element in find function     */
41   } _flags;
42
43 public:
44   Widget *next;
45
46   Widget()
47   : _pos(0, 0), _size(1, 0), _parent(0), _evh(0), next(0)
48   {
49     _flags.mfocus = 0;
50     _flags.selected = 0;
51     _flags.findable = 1;
52   }
53
54   virtual ~Widget();
55
56   Area size() const { return _size; }
57   Point pos() const { return _pos; }
58   Rect geometry() const { return Rect(_pos, _size); }
59   void set_geometry(Rect const &g)
60   {
61     _pos = g.p1();
62     _size = g.area();
63   }
64
65   inline Point map_to_parent(Point const &po, Widget *p = 0) const;
66
67   Point map_from_parent(Point const &po, Widget *p = 0) const
68   { return po - map_to_parent(Point(0, 0), p); }
69
70
71   void findable(int flag) { _flags.findable = flag; }
72   bool findable() { return _flags.findable; }
73
74   virtual void draw(Canvas *c, Point const &p) = 0;
75   virtual Widget *find(Point const &p);
76   //virtual Widget *find_child(Point const &p);
77   virtual void fill_cache(Mag_gfx::Pixel_info const *) {}
78   virtual void flush_cache(Mag_gfx::Pixel_info const *) {}
79
80   void parent(Parent_widget *parent) { _parent = parent; }
81   Parent_widget *parent() const { return _parent; }
82
83   /**
84    * Define event handler object
85    */
86   void event_handler(Event_handler *evh) { _evh = evh; }
87
88   /**
89    * Check if element is completely clipped and draw it otherwise
90    */
91   void try_draw(Canvas *c, Point const &p)
92   {
93 #if 0
94     /* check if element is completely outside the clipping area */
95     if (!(c->clip() & Rect(p + _pos, _size)).valid())
96       return;
97 #endif
98     /* call actual drawing function */
99     draw(c, p);
100   }
101
102   /**
103    * Update area of an element on screen
104    *
105    * We propagate the redraw request through the element hierarchy to
106    * the parent. The root parent should overwrite this function with
107    * a function that performs the actual redraw.
108    */
109   virtual void redraw_area(Rect const &r) const;
110
111   /**
112    * Trigger the refresh of an element on screen
113    */
114   void refresh() const
115   { redraw_area(Rect(_size)); }
116
117   virtual void mfocus(int flag)
118   {
119     if ((_flags.mfocus == flag) || !_flags.takes_focus)
120       return;
121
122     _flags.mfocus = flag;
123   }
124
125   /**
126    * Handle user input or timer event
127    */
128   virtual Widget *handle_event(Event const &ev)
129   {
130     if (_evh && _evh->handle(ev))
131       return this;
132     return 0;
133   }
134 };
135
136 class Parent_widget : public Widget
137 {
138 protected:
139   Widget *_first;
140   Widget *_last;
141
142 private:
143   Layout *_child_layout;
144
145 public:
146
147   Parent_widget() : Widget(), _first(0), _last(0), _child_layout(0) {}
148
149   Layout *child_layout() const { return _child_layout; }
150   /**
151    * Adopt a child element
152    */
153   virtual void append(Widget *e);
154
155   /**
156    * Release child element from parent element
157    */
158   virtual void remove(Widget *e);
159
160   /**
161    * Dispose references to the specified element
162    *
163    * The element is not necessarily an immediate child but some element
164    * of the element-subtree.  This function gets propagated to the root
165    * parent (e.g., user state manager), which can reset the mouse focus
166    * of the focused element vanishes.
167    */
168   virtual void forget(Widget *e);
169
170   void set_child_layout(Layout *l)
171   {
172     _child_layout = l;
173     if (l)
174       l->set_parent_layout_item(this);
175   }
176
177   Area preferred_size() const
178   {
179     return child_layout() ? child_layout()->preferred_size() : Area(0, 0);
180   }
181
182   Area min_size() const
183   {
184     return child_layout() ? child_layout()->min_size() : Area(0, 0);
185   }
186
187   Area max_size() const
188   {
189     return child_layout() ? child_layout()->max_size() : Area(Area::Max_w, Area::Max_h);
190   }
191
192   Orientations expanding() const
193   {
194     return child_layout() ? child_layout()->expanding() : 0;
195   }
196
197   bool empty() const
198   {
199     return child_layout() ? child_layout()->empty() : true;
200   }
201
202   void set_geometry(Rect const &r)
203   {
204     if (child_layout())
205       child_layout()->set_geometry(Rect(r.area()));
206
207     _pos = r.p1();
208     _size = min_size().max(r.area()).min(max_size());
209   }
210
211   Rect geometry() const { return Rect(_pos, _size); }
212
213   void child_invalidate()
214   { invalidate(); }
215
216   bool has_height_for_width() const
217   { return child_layout() ? child_layout()->has_height_for_width() : false; }
218
219   int height_for_width(int w) const
220   { return child_layout() ? child_layout()->height_for_width(w) : -1; }
221
222   int min_height_for_width(int w) const
223   { return child_layout() ? child_layout()->min_height_for_width(w) : -1; }
224
225
226   void draw(Canvas *c, Point const &p);
227   Widget *find(Point const &p);
228   virtual Widget *find_child(Point const &p);
229 };
230
231 inline
232 Point
233 Widget::map_to_parent(Point const &po, Widget *p) const
234 {
235   if (p == _parent || !_parent)
236     return po + _pos;
237
238   return _parent->map_to_parent(po + _pos, p);
239 }
240
241 }