1 // Copyright (C) 2005  Davis E. King (davis@dlib.net), Keita Mochizuki
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 
4 #ifndef DLIB_DRAWABLe_
5 #define DLIB_DRAWABLe_
6 
7 #include <memory>
8 
9 #include "drawable_abstract.h"
10 #include "../gui_core.h"
11 #include "../set.h"
12 #include "../binary_search_tree.h"
13 #include "../algs.h"
14 #include "../pixel.h"
15 #include "fonts.h"
16 #include "../matrix.h"
17 #include "canvas_drawing.h"
18 
19 namespace dlib
20 {
21 
22 // ----------------------------------------------------------------------------------------
23 // ----------------------------------------------------------------------------------------
24     // class drawable_window
25 // ----------------------------------------------------------------------------------------
26 // ----------------------------------------------------------------------------------------
27 
28     class drawable;
29     class drawable_window : public base_window
30     {
31         /*!
32             INITIAL VALUE
33                 - lastx == -1
34                 - lasty == -1
35                 - event_id == 1
36 
37             CONVENTION
38                 - bg_color == background_color()
39 
40                 - widgets == this binary search tree contains every drawable that is in
41                   this window.  It is a mapping of each drawable's z-order to a pointer
42                   to said drawable.
43                 - widget_set == a set that contains all the widgets in this window and
44                   want to receive events.
45 
46                 - mouse_move == this is a set of drawables that are in this window and
47                   want to receive the mouse movement events.
48                 - mouse_wheel == this is a set of drawables that are in this window and
49                   want to receive the mouse wheel events.
50                 - mouse_click == this is a set of drawables that are in this window and
51                   want to receive the mouse click events.
52                 - window_resized == this is a set of drawables that are in this window and
53                   want to receive the window_resized event.
54                 - keyboard == this is a set of drawables that are in this window and
55                   want to receive keyboard events.
56                 - focus == this is a set of drawables that are in this window and
57                   want to receive focus events.
58                 - window_moved == this is a set of drawables that are in this window and
59                   want to receive window move events.
60 
61                 - lastx == the x coordinate that we last saw the mouse at or -1 if the
62                   mouse is outside this window.
63                 - lasty == the y coordinate that we last saw the mouse at or -1 if the
64                   mouse is outside this window.
65 
66                 - event_id == a number we use to tag events so we don't end up sending
67                   an event to a drawable more than once.  This could happen if one of the
68                   event handlers does something to reset the enumerator while we are
69                   dispatching events (e.g. creating a new widget).
70         !*/
71     public:
72 
73         drawable_window(
74             bool resizable = true,
75             bool undecorated = false
76         ) :
base_window(resizable,undecorated)77             base_window(resizable,undecorated),
78             bg_color(rgb_pixel(212,208,200)),
79             lastx(-1),
80             lasty(-1),
81             event_id(1)
82         {}
83 
84         void set_background_color (
85             unsigned long red,
86             unsigned long green,
87             unsigned long blue
88         );
89 
90         rgb_pixel background_color (
91         ) const;
92 
93         virtual inline ~drawable_window()=0;
94 
95     private:
96 
97         void paint (
98             const canvas& c
99         );
100 
101     protected:
102 
103         void on_window_resized(
104         );
105 
106         void on_window_moved(
107         );
108 
109         void on_mouse_down (
110             unsigned long btn,
111             unsigned long state,
112             long x,
113             long y,
114             bool is_double_click
115         );
116 
117         void on_mouse_up (
118             unsigned long btn,
119             unsigned long state,
120             long x,
121             long y
122         );
123 
124         void on_mouse_move (
125             unsigned long state,
126             long x,
127             long y
128         );
129 
130         void on_mouse_leave (
131         );
132 
133         void on_mouse_enter (
134         );
135 
136         void on_wheel_up (
137             unsigned long state
138         );
139 
140         void on_wheel_down (
141             unsigned long state
142         );
143 
144         void on_focus_gained (
145         );
146 
147         void on_focus_lost (
148         );
149 
150         void on_keydown (
151             unsigned long key,
152             bool is_printable,
153             unsigned long state
154         );
155 
156         void on_string_put (
157             const std::wstring &str
158         );
159 
160         void on_user_event (
161             void* p,
162             int i
163         );
164 
165     private:
166 
167         friend class drawable;
168 
169 
170         rgb_pixel bg_color;
171 
172         typedef set<drawable*>::kernel_1a_c set_of_drawables;
173 
174         binary_search_tree<long,set_of_drawables>::kernel_1a_c widgets;
175 
176         set_of_drawables widget_set;
177         set_of_drawables mouse_move;
178         set_of_drawables mouse_wheel;
179         set_of_drawables mouse_click;
180         set_of_drawables window_resized;
181         set_of_drawables keyboard;
182         set_of_drawables focus;
183         set_of_drawables window_moved;
184         set_of_drawables string_put;
185 
186         long lastx, lasty;
187         unsigned long event_id;
188 
189 
190         // restricted functions
191         drawable_window(drawable_window&);        // copy constructor
192         drawable_window& operator=(drawable_window&);    // assignment operator
193 
194 
195     };
196 
~drawable_window()197     drawable_window::~drawable_window(){ close_window();}
198 
199 // ----------------------------------------------------------------------------------------
200 // ----------------------------------------------------------------------------------------
201     // class drawable
202 // ----------------------------------------------------------------------------------------
203 // ----------------------------------------------------------------------------------------
204 
205     enum
206     {
207         MOUSE_MOVE = 1,
208         MOUSE_CLICK = 2,
209         MOUSE_WHEEL = 4,
210         WINDOW_RESIZED = 8,
211         KEYBOARD_EVENTS = 16,
212         FOCUS_EVENTS = 32,
213         WINDOW_MOVED = 64,
214         STRING_PUT = 128
215     };
216 
217     class drawable
218     {
219 
220         /*!
221             INITIAL VALUE
222                 - enabled_events == false
223                 - event_id == 0
224 
225             CONVENTION
226                 - events == a bitset specifying what events this drawable is to receive.
227 
228                 - z_order_value == z_order()
229 
230                 - if (this drawable has been added to the parent window's sets and
231                   binary search tree) then
232                     - enabled_events == true
233                 - else
234                     - enabled_events == false
235 
236                 - event_id == the id of the last event we got from our parent window
237         !*/
238 
239     public:
240 
241         friend class drawable_window;
242 
243         drawable (
244             drawable_window& w,
245             unsigned long events_ = 0
246         ) :
247             m(w.wm),
248             parent(w),
249             hidden(false),
250             enabled(true),
251             lastx(w.lastx),
252             lasty(w.lasty),
253             mfont(default_font::get_font()),
254             z_order_value(0),
255             events(events_),
256             enabled_events(false),
257             event_id(0)
258         {}
259 
260         virtual ~drawable (
261         );
262 
z_order()263         long z_order (
264         ) const
265         {
266             m.lock();
267             long temp = z_order_value;
268             m.unlock();
269             return temp;
270         }
271 
272         virtual void set_z_order (
273             long order
274         );
275 
get_rect()276         const rectangle get_rect (
277         ) const
278         {
279             auto_mutex M(m);
280             return rect;
281         }
282 
bottom()283         long bottom (
284         ) const
285         {
286             auto_mutex M(m);
287             return rect.bottom();
288         }
289 
top()290         long top (
291         ) const
292         {
293             auto_mutex M(m);
294             return rect.top();
295         }
296 
left()297         long left (
298         ) const
299         {
300             auto_mutex M(m);
301             return rect.left();
302         }
303 
right()304         long right (
305         ) const
306         {
307             auto_mutex M(m);
308             return rect.right();
309         }
310 
width()311         long width (
312         ) const
313         {
314             auto_mutex M(m);
315             return rect.width();
316         }
317 
height()318         long height (
319         ) const
320         {
321             auto_mutex M(m);
322             return rect.height();
323         }
324 
is_enabled()325         bool is_enabled (
326         ) const
327         {
328             auto_mutex M(m);
329             return enabled;
330         }
331 
enable()332         virtual void enable (
333         )
334         {
335             auto_mutex M(m);
336             enabled = true;
337             parent.invalidate_rectangle(rect);
338         }
339 
disable()340         virtual void disable (
341         )
342         {
343             auto_mutex M(m);
344             enabled = false;
345             parent.invalidate_rectangle(rect);
346         }
347 
set_main_font(const std::shared_ptr<font> & f)348         virtual void set_main_font (
349             const std::shared_ptr<font>& f
350         )
351         {
352             auto_mutex M(m);
353             mfont = f;
354             parent.invalidate_rectangle(rect);
355         }
356 
main_font()357         const std::shared_ptr<font> main_font (
358         ) const
359         {
360             auto_mutex M(m);
361             return mfont;
362         }
363 
is_hidden()364         bool is_hidden (
365         ) const
366         {
367             auto_mutex M(m);
368             return hidden;
369         }
370 
set_pos(long x,long y)371         virtual void set_pos (
372             long x,
373             long y
374         )
375         {
376             m.lock();
377             rectangle old(rect);
378 
379             const unsigned long width = rect.width();
380             const unsigned long height = rect.height();
381             rect.set_top(y);
382             rect.set_left(x);
383             rect.set_right(static_cast<long>(x+width)-1);
384             rect.set_bottom(static_cast<long>(y+height)-1);
385 
386             parent.invalidate_rectangle(rect+old);
387             m.unlock();
388         }
389 
show()390         virtual void show (
391         )
392         {
393             m.lock();
394             hidden = false;
395             parent.invalidate_rectangle(rect);
396             m.unlock();
397         }
398 
hide()399         virtual void hide (
400         )
401         {
402             m.lock();
403             hidden = true;
404             parent.invalidate_rectangle(rect);
405             m.unlock();
406         }
407 
parent_window()408         base_window& parent_window (
409         ) { return parent; }
410 
parent_window()411         const base_window& parent_window (
412         ) const { return parent; }
413 
next_free_user_event_number()414         virtual int next_free_user_event_number (
415         )const { return 0; }
416 
417     protected:
418         rectangle rect;
419         const rmutex& m;
420         drawable_window& parent;
421         bool hidden;
422         bool enabled;
423         const long& lastx;
424         const long& lasty;
425         std::shared_ptr<font> mfont;
426 
427 
428         void enable_events (
429         );
430 
events_are_enabled()431         bool events_are_enabled (
432         ) const { auto_mutex M(m); return enabled_events; }
433 
434         void disable_events (
435         );
436 
437     private:
438 
439         long z_order_value;
440         const unsigned long events;
441         bool enabled_events;
442         unsigned long event_id;
443 
444 
445         // restricted functions
446         drawable(drawable&);        // copy constructor
447         drawable& operator=(drawable&);    // assignment operator
448 
449 
450     protected:
451 
452         virtual void draw (
453             const canvas& c
454         ) const=0;
455 
on_user_event(int)456         virtual void on_user_event (
457             int
458         ){}
459 
on_window_resized()460         virtual void on_window_resized(
461         ){}
462 
on_window_moved()463         virtual void on_window_moved(
464         ){}
465 
on_mouse_down(unsigned long,unsigned long,long,long,bool)466         virtual void on_mouse_down (
467             unsigned long ,
468             unsigned long ,
469             long ,
470             long ,
471             bool
472         ){}
473 
on_mouse_up(unsigned long,unsigned long,long,long)474         virtual void on_mouse_up (
475             unsigned long ,
476             unsigned long ,
477             long ,
478             long
479         ){}
480 
on_mouse_move(unsigned long,long,long)481         virtual void on_mouse_move (
482             unsigned long ,
483             long ,
484             long
485         ){}
486 
on_mouse_leave()487         virtual void on_mouse_leave (
488         ){}
489 
on_mouse_enter()490         virtual void on_mouse_enter (
491         ){}
492 
on_wheel_up(unsigned long)493         virtual void on_wheel_up (
494             unsigned long
495         ){}
496 
on_wheel_down(unsigned long)497         virtual void on_wheel_down (
498             unsigned long
499         ){}
500 
on_focus_gained()501         virtual void on_focus_gained (
502         ){}
503 
on_focus_lost()504         virtual void on_focus_lost (
505         ){}
506 
on_keydown(unsigned long,bool,unsigned long)507         virtual void on_keydown (
508             unsigned long ,
509             bool ,
510             unsigned long
511         ){}
512 
on_string_put(const std::wstring &)513         virtual void on_string_put (
514             const std::wstring&
515         ){}
516     };
517 
518 // ----------------------------------------------------------------------------------------
519 
520 }
521 
522 #ifdef NO_MAKEFILE
523 #include "drawable.cpp"
524 #endif
525 
526 #endif // DLIB_DRAWABLe_
527 
528