]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/scout-gfx/include/basic_window
Some minor fixes.
[l4.git] / l4 / pkg / scout-gfx / include / basic_window
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
11 #pragma once
12
13 #include <l4/mag-gfx/geometry>
14
15 #include <l4/scout-gfx/widget>
16 #include <l4/scout-gfx/layout>
17 #include <l4/mag-gfx/clip_guard>
18
19 namespace Scout_gfx {
20
21 /**********************
22  ** Basic_window interface **
23  **********************/
24
25
26 class View
27 {
28 public:
29   virtual Rect geometry() const = 0;
30   virtual Rect set_geometry(Rect const &, bool redraw = false) = 0;
31   virtual void top() = 0;
32   virtual void redraw(Rect const &r) = 0;
33   virtual Mag_gfx::Pixel_info const *pixel_info() const = 0;
34   virtual ~View() {}
35
36 };
37
38 class Basic_window : public Scout_gfx::Parent_widget
39 {
40 private:
41   View *_view;
42   Area _max_sz;
43   Widget *_mfocus;
44   Widget *_kbd_focused;
45   Widget *_active;
46   Point _active_pos;
47
48 protected:
49   Area _min_sz;
50   View *view() { return _view; }
51
52 public:
53
54   Area preferred_size() const
55   { return child_layout() ? child_layout()->preferred_size() : _max_sz; }
56   Area min_size() const
57   { return child_layout() ? _min_sz.max(child_layout()->min_size()) : _min_sz; }
58   Area max_size() const { return _max_sz; }
59
60   void child_invalidate()
61   {
62     if (!child_layout())
63       return;
64
65     Area s = _size.min(child_layout()->max_size()).max(child_layout()->min_size());
66     int h = child_layout()->min_height_for_width(s.w());
67     if (h > 0)
68       s.h(std::max(s.h(), h));
69
70     child_layout()->set_geometry(Rect(Point(0, 0), s));
71     _size = s;
72   }
73
74   Orientations expanding() const { return Orientations(); }
75   bool empty() const { return false; }
76
77   void set_geometry(Rect const &r, bool force)
78   {
79     bool need_redraw = false;
80     Area s = r.area().min(max_size());
81
82     if (child_layout() && (force || s != _size))
83       {
84         _size = s;
85         child_layout()->set_geometry(Rect(s));
86         child_invalidate();
87         need_redraw = true;
88       }
89     else
90       _size = s;
91
92     //_pos = r.p1(); _size = s;
93     Rect ng = _view->set_geometry(Rect(r.p1(), _size), need_redraw);
94     _pos = ng.p1(); _size = ng.area();
95   }
96
97   void set_geometry(Rect const &r)
98   { set_geometry(r, false); }
99
100   Rect geometry() const { return Rect(_pos, _size); }
101
102   Basic_window(View *view, Area const &max_sz)
103   : _view(view), _max_sz(max_sz)
104   {
105     /* init element attributes */
106     _size = view->geometry().area();
107   }
108
109   virtual ~Basic_window() { }
110
111   /**
112    * Return current window position
113    */
114   virtual Rect view_pos() const { return _view->geometry(); }
115
116   /**
117    * Accessors
118    */
119   //Platform *pf() const { return _pf; }
120   Area max() const { return _max_sz; }
121
122   /**
123    * Bring window to front
124    */
125   virtual void top() { _view->top(); }
126
127   /**
128    * Element interface
129    *
130    * This function just collects the specified regions to be
131    * redrawn but does not perform any immediate drawing
132    * operation. The actual drawing must be initiated by
133    * calling the process_redraw function.
134    */
135   void redraw_area(Rect const &r) const
136   { _view->redraw(r + _pos); }
137
138   void draw(Mag_gfx::Canvas *c, Point const &p)
139   {
140     Mag_gfx::Clip_guard g(c, Rect(p, size()));
141     Parent_widget::draw(c, p);
142   }
143
144   Widget *handle_event(Event const &ev);
145
146   /**
147    * This method handles a left-mouse button or tab press and determines the
148    * next widget receiving the keyboard focus.
149    *
150    * \returns true if Event handling has finished,
151    *          false if Event was not handled by this method
152    */
153   bool handle_key_focus(Event const &ev);
154
155 private:
156   /**
157    * This method finds the next widget with the `is_keyb_focusable()` property
158    * in the widget-hierarchy.
159    *
160    * \param cur_focus: the current widget receiving the keyboard focus
161    * \pre `cur_focus` must be non-Null
162    */
163   Widget *find_next_focus(Widget *cur_focus);
164   void _assign_mfocus(Widget *e, int force = 0);
165 };
166
167
168 /********************
169  ** Event handlers **
170  ********************/
171
172 class Drag_event_handler : public Scout_gfx::Event_handler
173 {
174 protected:
175   Point _cm;  /* original mouse position      */
176   Point _om;  /* current mouse positon        */
177
178   virtual void start_drag() = 0;
179   virtual void do_drag() = 0;
180
181   Point diff() const { return _cm - _om; }
182
183 public:
184   /**
185    * Event handler interface
186    */
187   bool handle(Scout_gfx::Event const &ev)
188   {
189     if (ev.key_cnt == 0)
190       return false;
191
192     /* first click starts dragging */
193     if ((ev.type == Scout_gfx::Event::PRESS) && (ev.key_cnt == 1))
194       {
195         _cm = ev.m;
196         _om = ev.m;
197         start_drag();
198       }
199
200     /* check if mouse was moved */
201     if (ev.m == _cm)
202       return true;
203
204     /* remember current mouse position */
205     _cm = ev.m;
206
207     do_drag();
208     return true;
209   }
210
211   virtual ~Drag_event_handler() {}
212 };
213
214
215 class Sizer_event_handler : public Drag_event_handler
216 {
217 protected:
218
219   Basic_window *_window;
220   Area _osz;   /* original window size */
221
222   /**
223    * Event handler interface
224    */
225   void start_drag()
226   { _osz = _window->view_pos().area(); }
227
228   void do_drag()
229   {
230     /* calculate new window size */
231     Area nsz = _osz.grow(diff());
232
233     _window->set_geometry(Rect(_window->geometry().p1(), nsz));
234   }
235
236 public:
237
238   /**
239    * Constructor
240    */
241   Sizer_event_handler(Basic_window *window)
242   {
243     _window = window;
244   }
245 };
246
247
248 class Mover_event_handler : public Drag_event_handler
249 {
250 protected:
251
252   Basic_window *_window;
253   Point _ob;   /* original launchpad position */
254
255
256   void start_drag()
257   {
258     _ob = _window->view_pos().p1();
259     _window->top();
260   }
261
262   void do_drag()
263   {
264     Point nb = _ob + diff();
265
266     _window->set_geometry(Rect(nb, _window->geometry().area()));
267   }
268
269 public:
270
271   /**
272    * Constructor
273    */
274   Mover_event_handler(Basic_window *window)
275   {
276     _window = window;
277   }
278 };
279
280 }