// Copyright (C) 2005 Davis E. King (davis@dlib.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_DRAWABLe_ #define DLIB_DRAWABLe_ #include <memory> #include "drawable_abstract.h" #include "../gui_core.h" #include "../set.h" #include "../binary_search_tree.h" #include "../algs.h" #include "../pixel.h" #include "fonts.h" #include "../matrix.h" #include "canvas_drawing.h" namespace dlib { // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // class drawable_window // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class drawable; class drawable_window : public base_window { /*! INITIAL VALUE - lastx == -1 - lasty == -1 - event_id == 1 CONVENTION - bg_color == background_color() - widgets == this binary search tree contains every drawable that is in this window. It is a mapping of each drawable's z-order to a pointer to said drawable. - widget_set == a set that contains all the widgets in this window and want to receive events. - mouse_move == this is a set of drawables that are in this window and want to receive the mouse movement events. - mouse_wheel == this is a set of drawables that are in this window and want to receive the mouse wheel events. - mouse_click == this is a set of drawables that are in this window and want to receive the mouse click events. - window_resized == this is a set of drawables that are in this window and want to receive the window_resized event. - keyboard == this is a set of drawables that are in this window and want to receive keyboard events. - focus == this is a set of drawables that are in this window and want to receive focus events. - window_moved == this is a set of drawables that are in this window and want to receive window move events. - lastx == the x coordinate that we last saw the mouse at or -1 if the mouse is outside this window. - lasty == the y coordinate that we last saw the mouse at or -1 if the mouse is outside this window. - event_id == a number we use to tag events so we don't end up sending an event to a drawable more than once. This could happen if one of the event handlers does something to reset the enumerator while we are dispatching events (e.g. creating a new widget). !*/ public: drawable_window( bool resizable = true, bool undecorated = false ) : base_window(resizable,undecorated), bg_color(rgb_pixel(212,208,200)), lastx(-1), lasty(-1), event_id(1) {} void set_background_color ( unsigned long red, unsigned long green, unsigned long blue ); rgb_pixel background_color ( ) const; virtual inline ~drawable_window()=0; private: void paint ( const canvas& c ); protected: void on_window_resized( ); void on_window_moved( ); void on_mouse_down ( unsigned long btn, unsigned long state, long x, long y, bool is_double_click ); void on_mouse_up ( unsigned long btn, unsigned long state, long x, long y ); void on_mouse_move ( unsigned long state, long x, long y ); void on_mouse_leave ( ); void on_mouse_enter ( ); void on_wheel_up ( unsigned long state ); void on_wheel_down ( unsigned long state ); void on_focus_gained ( ); void on_focus_lost ( ); void on_keydown ( unsigned long key, bool is_printable, unsigned long state ); void on_string_put ( const std::wstring &str ); void on_user_event ( void* p, int i ); private: friend class drawable; rgb_pixel bg_color; typedef set<drawable*>::kernel_1a_c set_of_drawables; binary_search_tree<long,set_of_drawables>::kernel_1a_c widgets; set_of_drawables widget_set; set_of_drawables mouse_move; set_of_drawables mouse_wheel; set_of_drawables mouse_click; set_of_drawables window_resized; set_of_drawables keyboard; set_of_drawables focus; set_of_drawables window_moved; set_of_drawables string_put; long lastx, lasty; unsigned long event_id; // restricted functions drawable_window(drawable_window&); // copy constructor drawable_window& operator=(drawable_window&); // assignment operator }; drawable_window::~drawable_window(){ close_window();} // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // class drawable // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- enum { MOUSE_MOVE = 1, MOUSE_CLICK = 2, MOUSE_WHEEL = 4, WINDOW_RESIZED = 8, KEYBOARD_EVENTS = 16, FOCUS_EVENTS = 32, WINDOW_MOVED = 64, STRING_PUT = 128 }; class drawable { /*! INITIAL VALUE - enabled_events == false - event_id == 0 CONVENTION - events == a bitset specifying what events this drawable is to receive. - z_order_value == z_order() - if (this drawable has been added to the parent window's sets and binary search tree) then - enabled_events == true - else - enabled_events == false - event_id == the id of the last event we got from our parent window !*/ public: friend class drawable_window; drawable ( drawable_window& w, unsigned long events_ = 0 ) : m(w.wm), parent(w), hidden(false), enabled(true), lastx(w.lastx), lasty(w.lasty), mfont(default_font::get_font()), z_order_value(0), events(events_), enabled_events(false), event_id(0) {} virtual ~drawable ( ); long z_order ( ) const { m.lock(); long temp = z_order_value; m.unlock(); return temp; } virtual void set_z_order ( long order ); const rectangle get_rect ( ) const { auto_mutex M(m); return rect; } long bottom ( ) const { auto_mutex M(m); return rect.bottom(); } long top ( ) const { auto_mutex M(m); return rect.top(); } long left ( ) const { auto_mutex M(m); return rect.left(); } long right ( ) const { auto_mutex M(m); return rect.right(); } long width ( ) const { auto_mutex M(m); return rect.width(); } long height ( ) const { auto_mutex M(m); return rect.height(); } bool is_enabled ( ) const { auto_mutex M(m); return enabled; } virtual void enable ( ) { auto_mutex M(m); enabled = true; parent.invalidate_rectangle(rect); } virtual void disable ( ) { auto_mutex M(m); enabled = false; parent.invalidate_rectangle(rect); } virtual void set_main_font ( const std::shared_ptr<font>& f ) { auto_mutex M(m); mfont = f; parent.invalidate_rectangle(rect); } const std::shared_ptr<font> main_font ( ) const { auto_mutex M(m); return mfont; } bool is_hidden ( ) const { auto_mutex M(m); return hidden; } virtual void set_pos ( long x, long y ) { m.lock(); rectangle old(rect); const unsigned long width = rect.width(); const unsigned long height = rect.height(); rect.set_top(y); rect.set_left(x); rect.set_right(static_cast<long>(x+width)-1); rect.set_bottom(static_cast<long>(y+height)-1); parent.invalidate_rectangle(rect+old); m.unlock(); } virtual void show ( ) { m.lock(); hidden = false; parent.invalidate_rectangle(rect); m.unlock(); } virtual void hide ( ) { m.lock(); hidden = true; parent.invalidate_rectangle(rect); m.unlock(); } base_window& parent_window ( ) { return parent; } const base_window& parent_window ( ) const { return parent; } virtual int next_free_user_event_number ( )const { return 0; } protected: rectangle rect; const rmutex& m; drawable_window& parent; bool hidden; bool enabled; const long& lastx; const long& lasty; std::shared_ptr<font> mfont; void enable_events ( ); bool events_are_enabled ( ) const { auto_mutex M(m); return enabled_events; } void disable_events ( ); private: long z_order_value; const unsigned long events; bool enabled_events; unsigned long event_id; // restricted functions drawable(drawable&); // copy constructor drawable& operator=(drawable&); // assignment operator protected: virtual void draw ( const canvas& c ) const=0; virtual void on_user_event ( int ){} virtual void on_window_resized( ){} virtual void on_window_moved( ){} virtual void on_mouse_down ( unsigned long , unsigned long , long , long , bool ){} virtual void on_mouse_up ( unsigned long , unsigned long , long , long ){} virtual void on_mouse_move ( unsigned long , long , long ){} virtual void on_mouse_leave ( ){} virtual void on_mouse_enter ( ){} virtual void on_wheel_up ( unsigned long ){} virtual void on_wheel_down ( unsigned long ){} virtual void on_focus_gained ( ){} virtual void on_focus_lost ( ){} virtual void on_keydown ( unsigned long , bool , unsigned long ){} virtual void on_string_put ( const std::wstring& ){} }; // ---------------------------------------------------------------------------------------- } #ifdef NO_MAKEFILE #include "drawable.cpp" #endif #endif // DLIB_DRAWABLe_