]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/scout-gfx/include/basic_window
update
[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
42   View *_view;
43   Area _max_sz;
44   Widget *_mfocus;
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 private:
147   void _assign_mfocus(Widget *e, int force = 0);
148 };
149
150
151 /********************
152  ** Event handlers **
153  ********************/
154
155 class Drag_event_handler : public Scout_gfx::Event_handler
156 {
157 protected:
158   Point _cm;  /* original mouse position      */
159   Point _om;  /* current mouse positon        */
160
161   virtual void start_drag() = 0;
162   virtual void do_drag() = 0;
163
164   Point diff() const { return _cm - _om; }
165
166 public:
167   /**
168    * Event handler interface
169    */
170   bool handle(Scout_gfx::Event const &ev)
171   {
172     if (ev.key_cnt == 0)
173       return false;
174
175     /* first click starts dragging */
176     if ((ev.type == Scout_gfx::Event::PRESS) && (ev.key_cnt == 1))
177       {
178         _cm = ev.m;
179         _om = ev.m;
180         start_drag();
181       }
182
183     /* check if mouse was moved */
184     if (ev.m == _cm)
185       return true;
186
187     /* remember current mouse position */
188     _cm = ev.m;
189
190     do_drag();
191     return true;
192   }
193
194   virtual ~Drag_event_handler() {}
195 };
196
197
198 class Sizer_event_handler : public Drag_event_handler
199 {
200 protected:
201
202   Basic_window *_window;
203   Area _osz;   /* original window size */
204
205   /**
206    * Event handler interface
207    */
208   void start_drag()
209   { _osz = _window->view_pos().area(); }
210
211   void do_drag()
212   {
213     /* calculate new window size */
214     Area nsz = _osz.grow(diff());
215
216     _window->set_geometry(Rect(_window->geometry().p1(), nsz));
217   }
218
219 public:
220
221   /**
222    * Constructor
223    */
224   Sizer_event_handler(Basic_window *window)
225   {
226     _window = window;
227   }
228 };
229
230
231 class Mover_event_handler : public Drag_event_handler
232 {
233 protected:
234
235   Basic_window *_window;
236   Point _ob;   /* original launchpad position */
237
238
239   void start_drag()
240   {
241     _ob = _window->view_pos().p1();
242     _window->top();
243   }
244
245   void do_drag()
246   {
247     Point nb = _ob + diff();
248
249     _window->set_geometry(Rect(nb, _window->geometry().area()));
250   }
251
252 public:
253
254   /**
255    * Constructor
256    */
257   Mover_event_handler(Basic_window *window)
258   {
259     _window = window;
260   }
261 };
262
263 }