// Copyright (C) 2008 Davis E. King (davis@dlib.net), and Nils Labugt // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_WIDGETs_STYLE_ #define DLIB_WIDGETs_STYLE_ #include "../algs.h" #include "style_abstract.h" #include "../gui_core.h" #include "canvas_drawing.h" #include <string> #include <sstream> #include "../unicode.h" #include "../array2d.h" #include "../pixel.h" #include "fonts.h" namespace dlib { // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // button styles // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class button_style { public: button_style() { } virtual ~button_style() {} virtual bool redraw_on_mouse_over ( ) const { return false; } virtual rectangle get_invalidation_rect ( const rectangle& rect ) const { return rect; } virtual rectangle get_min_size ( const ustring& name, const font& mfont ) const = 0; virtual void draw_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed ) const = 0; }; // ---------------------------------------------------------------------------------------- class button_style_default : public button_style { public: button_style_default () : padding(4), name_width(0) {} virtual void draw_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed ) const; virtual rectangle get_min_size ( const ustring& name, const font& mfont ) const; private: // this is the minimum amount of padding that can separate the name from the // edge of the button const unsigned long padding; // this is the width of the name string mutable unsigned long name_width; }; // ---------------------------------------------------------------------------------------- class button_style_toolbar1 : public button_style { public: button_style_toolbar1 () : padding(4), name_width(0) {} virtual void draw_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed ) const; virtual rectangle get_invalidation_rect ( const rectangle& rect ) const { rectangle temp(rect); temp.left() -= 2; temp.top() -= 2; temp.right() += 2; temp.bottom() += 2; return temp; } virtual bool redraw_on_mouse_over ( ) const { return true; } virtual rectangle get_min_size ( const ustring& name, const font& mfont ) const; private: // this is the minimum amount of padding that can separate the name from the // edge of the button const unsigned long padding; // this is the width of the name string mutable unsigned long name_width; }; // ---------------------------------------------------------------------------------------- class button_style_toolbar_icon1 : public button_style { public: template <typename image_type> button_style_toolbar_icon1 (const image_type& img_, unsigned long pad = 6) : padding(pad) { assign_image(img_mouseover,img_); make_images(); } button_style_toolbar_icon1( const button_style_toolbar_icon1& item): button_style(item), padding(item.padding) { assign_image(img_mouseover, item.img_mouseover); assign_image(img_normal, item.img_normal); assign_image(img_disabled, item.img_disabled); } virtual void draw_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed ) const; virtual bool redraw_on_mouse_over ( ) const { return true; } virtual rectangle get_min_size ( const ustring& name, const font& mfont ) const; private: void make_images ( ) { // make the disabled image grayscale and make both non-mouseover images have weaker alpha channels img_disabled.set_size(img_mouseover.nr(), img_mouseover.nc()); img_normal.set_size(img_mouseover.nr(), img_mouseover.nc()); for (long r = 0; r < img_mouseover.nr(); ++r) { for (long c = 0; c < img_mouseover.nc(); ++c) { rgb_alpha_pixel p = img_mouseover[r][c]; long avg = p.red; avg += p.green; avg += p.blue; avg /= 3; if (p.alpha > 40) p.alpha -= 40; else p.alpha = 0; img_normal[r][c] = p; if (p.alpha > 80) p.alpha -= 80; else p.alpha = 0; p.red = avg; p.green = avg; p.blue = avg; img_disabled[r][c] = p; } } } array2d<rgb_alpha_pixel> img_mouseover; array2d<rgb_alpha_pixel> img_normal; array2d<rgb_alpha_pixel> img_disabled; // this is the minimum amount of padding that can separate the name from the // edge of the button const unsigned long padding; }; // ---------------------------------------------------------------------------------------- class button_style_arrow : public button_style { public: enum arrow_direction { UP, DOWN, LEFT, RIGHT }; button_style_arrow ( arrow_direction dir_ ) : dir(dir_) {} virtual void draw_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed ) const; virtual rectangle get_min_size ( const ustring& , const font& ) const { return rectangle(); } private: arrow_direction dir; }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // toggle button styles // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class toggle_button_style { public: toggle_button_style() { } virtual ~toggle_button_style() {} virtual bool redraw_on_mouse_over ( ) const { return false; } virtual rectangle get_min_size ( const ustring& name, const font& mfont ) const = 0; virtual void draw_toggle_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed, const bool is_checked ) const = 0; }; // ---------------------------------------------------------------------------------------- class toggle_button_style_default : public toggle_button_style { public: toggle_button_style_default () : padding(4), name_width(0) {} virtual void draw_toggle_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed, const bool is_checked ) const; virtual rectangle get_min_size ( const ustring& name, const font& mfont ) const; private: // this is the minimum amount of padding that can separate the name from the // edge of the button const unsigned long padding; // this is the width of the name string mutable unsigned long name_width; }; // ---------------------------------------------------------------------------------------- class toggle_button_style_check_box : public toggle_button_style { public: virtual void draw_toggle_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed, const bool is_checked ) const; virtual rectangle get_min_size ( const ustring& name, const font& mfont ) const; }; // ---------------------------------------------------------------------------------------- class toggle_button_style_radio_button : public toggle_button_style { public: virtual void draw_toggle_button ( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed, const bool is_checked ) const; virtual rectangle get_min_size ( const ustring& name, const font& mfont ) const; }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // scroll_bar styles // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class scroll_bar_style { public: virtual ~scroll_bar_style() {} virtual bool redraw_on_mouse_over_slider ( ) const { return false; } virtual long get_width ( ) const = 0; virtual long get_slider_length ( long total_length, long max_pos ) const = 0; virtual long get_button_length ( long total_length, long max_pos ) const = 0; virtual void draw_scroll_bar_background ( const canvas& c, const rectangle& rect, const bool enabled, const long lastx, const long lasty, const bool is_depressed ) const = 0; virtual void draw_scroll_bar_slider ( const canvas& c, const rectangle& rect, const bool enabled, const long lastx, const long lasty, const bool is_being_dragged ) const = 0; }; // ---------------------------------------------------------------------------------------- class scroll_bar_style_default : public scroll_bar_style { public: button_style_arrow get_up_button_style ( ) const { return button_style_arrow(button_style_arrow::UP); } button_style_arrow get_down_button_style ( ) const { return button_style_arrow(button_style_arrow::DOWN); } button_style_arrow get_left_button_style ( ) const { return button_style_arrow(button_style_arrow::LEFT); } button_style_arrow get_right_button_style ( ) const { return button_style_arrow(button_style_arrow::RIGHT); } virtual long get_width ( ) const { return 16; } virtual long get_slider_length ( long total_length, long max_pos ) const; virtual long get_button_length ( long total_length, long max_pos ) const; virtual void draw_scroll_bar_background ( const canvas& c, const rectangle& rect, const bool enabled, const long lastx, const long lasty, const bool is_depressed ) const; virtual void draw_scroll_bar_slider ( const canvas& c, const rectangle& rect, const bool enabled, const long lastx, const long lasty, const bool is_being_dragged ) const; }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // scrollable_region styles // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class scrollable_region_style { public: virtual ~scrollable_region_style() {} virtual long get_border_size ( ) const = 0; virtual void draw_scrollable_region_border ( const canvas& c, const rectangle& rect, const bool enabled ) const = 0; }; // ---------------------------------------------------------------------------------------- class scrollable_region_style_default : public scrollable_region_style { public: scroll_bar_style_default get_horizontal_scroll_bar_style ( ) const { return scroll_bar_style_default(); } scroll_bar_style_default get_vertical_scroll_bar_style ( ) const { return scroll_bar_style_default(); } virtual long get_border_size ( ) const { return 2; } virtual void draw_scrollable_region_border ( const canvas& c, const rectangle& rect, const bool ) const { draw_sunken_rectangle(c,rect); } }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // list_box styles // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class list_box_style { public: virtual ~list_box_style() {} virtual void draw_list_box_background ( const canvas& c, const rectangle& display_rect, const bool enabled ) const = 0; virtual void draw_list_box_item ( const canvas& c, const rectangle& rect, const rectangle& display_rect, const bool enabled, const font& mfont, const std::string& text, const bool is_selected ) const = 0; virtual void draw_list_box_item ( const canvas& c, const rectangle& rect, const rectangle& display_rect, const bool enabled, const font& mfont, const std::wstring& text, const bool is_selected ) const = 0; virtual void draw_list_box_item ( const canvas& c, const rectangle& rect, const rectangle& display_rect, const bool enabled, const font& mfont, const ustring& text, const bool is_selected ) const = 0; }; // ---------------------------------------------------------------------------------------- class list_box_style_default : public list_box_style { public: scrollable_region_style_default get_scrollable_region_style ( ) const { return scrollable_region_style_default(); } virtual void draw_list_box_item ( const canvas& c, const rectangle& rect, const rectangle& display_rect, const bool enabled, const font& mfont, const std::string& text, const bool is_selected ) const { draw_list_box_item_template(c,rect,display_rect, enabled, mfont, text, is_selected); } virtual void draw_list_box_item ( const canvas& c, const rectangle& rect, const rectangle& display_rect, const bool enabled, const font& mfont, const std::wstring& text, const bool is_selected ) const { draw_list_box_item_template(c,rect,display_rect, enabled, mfont, text, is_selected); } virtual void draw_list_box_item ( const canvas& c, const rectangle& rect, const rectangle& display_rect, const bool enabled, const font& mfont, const ustring& text, const bool is_selected ) const { draw_list_box_item_template(c,rect,display_rect, enabled, mfont, text, is_selected); } template <typename string_type> void draw_list_box_item_template ( const canvas& c, const rectangle& rect, const rectangle& display_rect, const bool enabled, const font& mfont, const string_type& text, const bool is_selected ) const { if (is_selected) { if (enabled) fill_rect_with_vertical_gradient(c,rect,rgb_pixel(110,160,255), rgb_pixel(100,130,250),display_rect); else fill_rect_with_vertical_gradient(c,rect,rgb_pixel(140,190,255), rgb_pixel(130,160,250),display_rect); } if (enabled) mfont.draw_string(c,rect,text,rgb_pixel(0,0,0),0,std::string::npos,display_rect); else mfont.draw_string(c,rect,text,rgb_pixel(128,128,128),0,std::string::npos,display_rect); } virtual void draw_list_box_background ( const canvas& c, const rectangle& display_rect, const bool enabled ) const { if (enabled) { // first fill our area with white fill_rect(c, display_rect,rgb_pixel(255,255,255)); } else { // first fill our area with gray fill_rect(c, display_rect,rgb_pixel(212,208,200)); } } }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // text_box styles // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class text_box_style { public: text_box_style() { } virtual ~text_box_style() {} virtual unsigned long get_padding ( const font& mfont ) const = 0; virtual void draw_text_box ( const canvas& c, const rectangle& display_rect, const rectangle& text_rect, const bool enabled, const font& mfont, const ustring& text, const rectangle& cursor_rect, const rgb_pixel& text_color, const rgb_pixel& bg_color, const bool has_focus, const bool cursor_visible, const long highlight_start, const long highlight_end ) const = 0; }; // ---------------------------------------------------------------------------------------- class text_box_style_default : public text_box_style { public: text_box_style_default() { } scrollable_region_style_default get_scrollable_region_style ( ) const { return scrollable_region_style_default(); } virtual ~text_box_style_default() {} virtual unsigned long get_padding ( const font& ) const { return 1; } virtual void draw_text_box ( const canvas& c, const rectangle& display_rect, const rectangle& text_rect, const bool enabled, const font& mfont, const ustring& text, const rectangle& cursor_rect, const rgb_pixel& text_color, const rgb_pixel& bg_color, const bool has_focus, const bool cursor_visible, const long highlight_start, const long highlight_end ) const; }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // text_field styles // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class text_field_style { public: text_field_style() { } virtual ~text_field_style() {} virtual unsigned long get_padding ( const font& mfont ) const = 0; virtual void draw_text_field ( const canvas& c, const rectangle& rect, const rectangle& text_rect, const bool enabled, const font& mfont, const ustring& text, const unsigned long cursor_x, const unsigned long text_pos, const rgb_pixel& text_color, const rgb_pixel& bg_color, const bool has_focus, const bool cursor_visible, const long highlight_start, const long highlight_end ) const = 0; }; // ---------------------------------------------------------------------------------------- class text_field_style_default : public text_field_style { public: text_field_style_default() { } virtual ~text_field_style_default() {} virtual unsigned long get_padding ( const font& mfont ) const; virtual void draw_text_field ( const canvas& c, const rectangle& rect, const rectangle& text_rect, const bool enabled, const font& mfont, const ustring& text, const unsigned long cursor_x, const unsigned long text_pos, const rgb_pixel& text_color, const rgb_pixel& bg_color, const bool has_focus, const bool cursor_visible, const long highlight_start, const long highlight_end ) const; }; // ---------------------------------------------------------------------------------------- } #ifdef NO_MAKEFILE #include "style.cpp" #endif #endif // DLIB_WIDGETs_STYLE_