diff options
Diffstat (limited to 'ml/dlib/dlib/gui_widgets')
19 files changed, 0 insertions, 31500 deletions
diff --git a/ml/dlib/dlib/gui_widgets/base_widgets.cpp b/ml/dlib/dlib/gui_widgets/base_widgets.cpp deleted file mode 100644 index 2f2eb8e9c..000000000 --- a/ml/dlib/dlib/gui_widgets/base_widgets.cpp +++ /dev/null @@ -1,3343 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_BASE_WIDGETs_CPP_ -#define DLIB_BASE_WIDGETs_CPP_ - -#include <iostream> -#include <memory> - -#include "base_widgets.h" -#include "../assert.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // button object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void button:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - rectangle min_rect = style->get_min_size(name_,*mfont); - // only change the size if it isn't going to be too small to fit the name - if (height >= min_rect.height() && - width >= min_rect.width()) - { - rectangle old(rect); - rect = resize_rect(rect,width,height); - parent.invalidate_rectangle(style->get_invalidation_rect(rect+old)); - btn_tooltip.set_size(width,height); - } - } - -// ---------------------------------------------------------------------------------------- - - void button:: - show ( - ) - { - button_action::show(); - btn_tooltip.show(); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - hide ( - ) - { - button_action::hide(); - btn_tooltip.hide(); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - enable ( - ) - { - button_action::enable(); - btn_tooltip.enable(); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - disable ( - ) - { - button_action::disable(); - btn_tooltip.disable(); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - set_tooltip_text ( - const std::string& text - ) - { - btn_tooltip.set_text(text); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - set_tooltip_text ( - const std::wstring& text - ) - { - btn_tooltip.set_text(text); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - set_tooltip_text ( - const ustring& text - ) - { - btn_tooltip.set_text(text); - } - -// ---------------------------------------------------------------------------------------- - - const std::string button:: - tooltip_text ( - ) const - { - return btn_tooltip.text(); - } - - const std::wstring button:: - tooltip_wtext ( - ) const - { - return btn_tooltip.wtext(); - } - - const dlib::ustring button:: - tooltip_utext ( - ) const - { - return btn_tooltip.utext(); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - set_name(name_); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - set_pos ( - long x, - long y - ) - { - auto_mutex M(m); - button_action::set_pos(x,y); - btn_tooltip.set_pos(x,y); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - set_name ( - const std::string& name - ) - { - set_name(convert_mbstring_to_wstring(name)); - } - - void button:: - set_name ( - const std::wstring& name - ) - { - set_name(convert_wstring_to_utf32(name)); - } - - void button:: - set_name ( - const ustring& name - ) - { - auto_mutex M(m); - name_ = name; - // do this to get rid of any reference counting that may be present in - // the std::string implementation. - name_[0] = name_[0]; - - rectangle old(rect); - rect = move_rect(style->get_min_size(name,*mfont),rect.left(),rect.top()); - btn_tooltip.set_size(rect.width(),rect.height()); - - parent.invalidate_rectangle(style->get_invalidation_rect(rect+old)); - } - -// ---------------------------------------------------------------------------------------- - - const std::string button:: - name ( - ) const - { - auto_mutex M(m); - std::string temp = convert_wstring_to_mbstring(wname()); - // do this to get rid of any reference counting that may be present in - // the std::string implementation. - char c = temp[0]; - temp[0] = c; - return temp; - } - - const std::wstring button:: - wname ( - ) const - { - auto_mutex M(m); - std::wstring temp = convert_utf32_to_wstring(uname()); - // do this to get rid of any reference counting that may be present in - // the std::wstring implementation. - wchar_t w = temp[0]; - temp[0] = w; - return temp; - } - - const dlib::ustring button:: - uname ( - ) const - { - auto_mutex M(m); - dlib::ustring temp = name_; - // do this to get rid of any reference counting that may be present in - // the dlib::ustring implementation. - temp[0] = name_[0]; - return temp; - } - -// ---------------------------------------------------------------------------------------- - - void button:: - on_button_up ( - bool mouse_over - ) - { - if (mouse_over) - { - // this is a valid button click - if (event_handler.is_set()) - event_handler(); - if (event_handler_self.is_set()) - event_handler_self(*this); - } - if (button_up_handler.is_set()) - button_up_handler(mouse_over); - if (button_up_handler_self.is_set()) - button_up_handler_self(mouse_over,*this); - } - -// ---------------------------------------------------------------------------------------- - - void button:: - on_button_down ( - ) - { - if (button_down_handler.is_set()) - button_down_handler(); - if (button_down_handler_self.is_set()) - button_down_handler_self(*this); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // draggable object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - draggable::~draggable() {} - -// ---------------------------------------------------------------------------------------- - - void draggable:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - if (drag && (state & base_window::LEFT) && enabled && !hidden) - { - // the user is trying to drag this object. we should calculate the new - // x and y positions for the upper left corner of this object's rectangle - - long new_x = x - this->x; - long new_y = y - this->y; - - // make sure these points are inside the draggable area. - if (new_x < area.left()) - new_x = area.left(); - if (new_x + static_cast<long>(rect.width()) - 1 > area.right()) - new_x = area.right() - rect.width() + 1; - - if (new_y + static_cast<long>(rect.height()) - 1 > area.bottom()) - new_y = area.bottom() - rect.height() + 1; - if (new_y < area.top()) - new_y = area.top(); - - // now make the new rectangle for this object - rectangle new_rect( - new_x, - new_y, - new_x + rect.width() - 1, - new_y + rect.height() - 1 - ); - - // only do anything if this is a new rectangle and it is inside area - if (new_rect != rect && area.intersect(new_rect) == new_rect) - { - parent.invalidate_rectangle(new_rect + rect); - rect = new_rect; - - // call the on_drag() event handler - on_drag(); - } - } - else - { - drag = false; - on_drag_stop(); - } - } - -// ---------------------------------------------------------------------------------------- - - void draggable:: - on_mouse_up ( - unsigned long , - unsigned long state, - long , - long - ) - { - if (drag && (state & base_window::LEFT) == 0) - { - drag = false; - on_drag_stop(); - } - } - -// ---------------------------------------------------------------------------------------- - - void draggable:: - on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ) - { - if (enabled && !hidden && rect.contains(x,y) && btn == base_window::LEFT) - { - drag = true; - this->x = x - rect.left(); - this->y = y - rect.top(); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // mouse_over_event object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - mouse_over_event::~mouse_over_event() {} - -// ---------------------------------------------------------------------------------------- - - void mouse_over_event:: - on_mouse_leave ( - ) - { - if (is_mouse_over_) - { - is_mouse_over_ = false; - on_mouse_not_over(); - } - } - -// ---------------------------------------------------------------------------------------- - - void mouse_over_event:: - on_mouse_move ( - unsigned long , - long x, - long y - ) - { - if (rect.contains(x,y) == false) - { - if (is_mouse_over_) - { - is_mouse_over_ = false; - on_mouse_not_over(); - } - } - else if (is_mouse_over_ == false) - { - is_mouse_over_ = true; - if (enabled && !hidden) - on_mouse_over(); - } - } - -// ---------------------------------------------------------------------------------------- - - bool mouse_over_event:: - is_mouse_over ( - ) const - { - // check if the mouse is still really over this button - if (is_mouse_over_ && rect.contains(lastx,lasty) == false) - { - // trigger a user event to call on_mouse_not_over() and repaint this object. - // we must do this in another event because someone might call is_mouse_over() - // from draw() and you don't want this function to end up calling - // parent.invalidate_rectangle(). It would lead to draw() being called over - // and over. - parent.trigger_user_event((void*)this,drawable::next_free_user_event_number()); - return false; - } - - return is_mouse_over_; - } - -// ---------------------------------------------------------------------------------------- - - void mouse_over_event:: - on_user_event ( - int num - ) - { - if (is_mouse_over_ && num == drawable::next_free_user_event_number()) - { - is_mouse_over_ = false; - on_mouse_not_over(); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // button_action object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - button_action::~button_action() {} - -// ---------------------------------------------------------------------------------------- - - void button_action:: - on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ) - { - if (enabled && !hidden && btn == base_window::LEFT && rect.contains(x,y)) - { - is_depressed_ = true; - seen_click = true; - parent.invalidate_rectangle(rect); - on_button_down(); - } - } - -// ---------------------------------------------------------------------------------------- - - void button_action:: - on_mouse_not_over ( - ) - { - if (is_depressed_) - { - is_depressed_ = false; - parent.invalidate_rectangle(rect); - on_button_up(false); - } - } - -// ---------------------------------------------------------------------------------------- - - void button_action:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - // forward event to the parent class so it can do it's thing as well as us - mouse_over_event::on_mouse_move(state,x,y); - - if (enabled == false || hidden == true) - return; - - - if ((state & base_window::LEFT) == 0) - { - seen_click = false; - if (is_depressed_) - { - is_depressed_ = false; - parent.invalidate_rectangle(rect); - on_button_up(false); - } - - // the left button isn't down so we don't care about anything else - return; - } - - if (rect.contains(x,y) == false) - { - if (is_depressed_) - { - is_depressed_ = false; - parent.invalidate_rectangle(rect); - on_button_up(false); - } - } - else if (is_depressed_ == false && seen_click) - { - is_depressed_ = true; - parent.invalidate_rectangle(rect); - on_button_down(); - } - } - -// ---------------------------------------------------------------------------------------- - - void button_action:: - on_mouse_up ( - unsigned long btn, - unsigned long, - long x, - long y - ) - { - if (enabled && !hidden && btn == base_window::LEFT) - { - if (is_depressed_) - { - is_depressed_ = false; - parent.invalidate_rectangle(rect); - - if (rect.contains(x,y)) - { - on_button_up(true); - } - else - { - on_button_up(false); - } - } - else if (seen_click && rect.contains(x,y)) - { - // this case here covers the unlikly event that you click on a button, - // move the mouse off the button and then move it back very quickly and - // release the mouse button. It is possible that this mouse up event - // will occurr before any mouse move event so you might not have set - // that the button is depressed yet. - - // So we should say that this triggers an on_button_down() event and - // then an on_button_up(true) event. - - parent.invalidate_rectangle(rect); - - on_button_down(); - on_button_up(true); - } - - seen_click = false; - } - } - -// ---------------------------------------------------------------------------------------- - - bool button_action:: - is_depressed ( - ) const - { - // check if the mouse is still really over this button - if (enabled && !hidden && is_depressed_ && rect.contains(lastx,lasty) == false) - { - // trigger a user event to call on_button_up() and repaint this object. - // we must do this in another event because someone might call is_depressed() - // from draw() and you don't want this function to end up calling - // parent.invalidate_rectangle(). It would lead to draw() being called over - // and over. - parent.trigger_user_event((void*)this,mouse_over_event::next_free_user_event_number()); - return false; - } - - return is_depressed_; - } - -// ---------------------------------------------------------------------------------------- - - void button_action:: - on_user_event ( - int num - ) - { - // forward event to the parent class so it can do it's thing as well as us - mouse_over_event::on_user_event(num); - - if (is_depressed_ && num == mouse_over_event::next_free_user_event_number()) - { - is_depressed_ = false; - parent.invalidate_rectangle(rect); - on_button_up(false); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // scroll_bar object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - scroll_bar:: - scroll_bar( - drawable_window& w, - bar_orientation orientation - ) : - drawable(w), - b1(w), - b2(w), - slider(w,*this,&scroll_bar::on_slider_drag), - ori(orientation), - top_filler(w,*this,&scroll_bar::top_filler_down,&scroll_bar::top_filler_up), - bottom_filler(w,*this,&scroll_bar::bottom_filler_down,&scroll_bar::bottom_filler_up), - pos(0), - max_pos(0), - js(10), - b1_timer(*this,&scroll_bar::b1_down_t), - b2_timer(*this,&scroll_bar::b2_down_t), - top_filler_timer(*this,&scroll_bar::top_filler_down_t), - bottom_filler_timer(*this,&scroll_bar::bottom_filler_down_t) - { - set_style(scroll_bar_style_default()); - - // don't show the slider when there is no place it can move. - slider.hide(); - - set_length(100); - - b1.set_button_down_handler(*this,&scroll_bar::b1_down); - b2.set_button_down_handler(*this,&scroll_bar::b2_down); - - b1.set_button_up_handler(*this,&scroll_bar::b1_up); - b2.set_button_up_handler(*this,&scroll_bar::b2_up); - b1.disable(); - b2.disable(); - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - scroll_bar:: - ~scroll_bar( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - // wait for all the timers to be stopped - b1_timer.stop_and_wait(); - b2_timer.stop_and_wait(); - top_filler_timer.stop_and_wait(); - bottom_filler_timer.stop_and_wait(); - } - -// ---------------------------------------------------------------------------------------- - - scroll_bar::bar_orientation scroll_bar:: - orientation ( - ) const - { - auto_mutex M(m); - return ori; - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - set_length ( - unsigned long length - ) - { - auto_mutex M(m); - // make the min length be at least 1 - if (length == 0) - { - length = 1; - } - - - parent.invalidate_rectangle(rect); - - if (ori == HORIZONTAL) - { - rect.set_right(rect.left() + length - 1); - rect.set_bottom(rect.top() + style->get_width() - 1); - - const long btn_size = style->get_button_length(rect.width(), max_pos); - - b1.set_size(btn_size,style->get_width()); - b2.set_size(btn_size,style->get_width()); - - slider.set_size(get_slider_size(),style->get_width()); - } - else - { - rect.set_right(rect.left() + style->get_width() - 1); - rect.set_bottom(rect.top() + length - 1); - - const long btn_size = style->get_button_length(rect.height(), max_pos); - - b1.set_size(style->get_width(),btn_size); - b2.set_size(style->get_width(),btn_size); - - slider.set_size(style->get_width(),get_slider_size()); - } - - // call this to put everything is in the right spot. - set_pos (rect.left(),rect.top()); - - if ((b2.get_rect().top() - b1.get_rect().bottom() - 1 <= 8 && ori == VERTICAL) || - (b2.get_rect().left() - b1.get_rect().right() - 1 <= 8 && ori == HORIZONTAL) || - max_pos == 0) - { - hide_slider(); - } - else if (enabled && !hidden) - { - show_slider(); - } - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - set_pos ( - long x, - long y - ) - { - auto_mutex M(m); - drawable::set_pos(x,y); - - b1.set_pos(rect.left(),rect.top()); - if (ori == HORIZONTAL) - { - // make the b2 button appear at the end of the scroll_bar - b2.set_pos(rect.right()-b2.get_rect().width() + 1,rect.top()); - - if (max_pos != 0) - { - double range = b2.get_rect().left() - b1.get_rect().right() - slider.get_rect().width() - 1; - double slider_pos = pos; - slider_pos /= max_pos; - slider_pos *= range; - slider.set_pos( - static_cast<long>(slider_pos)+rect.left() + b1.get_rect().width(), - rect.top() - ); - - // move the draggable area for the slider to the new location - rectangle area = rect; - area.set_left(area.left() + style->get_width()); - area.set_right(area.right() - style->get_width()); - slider.set_draggable_area(area); - - } - - - } - else - { - // make the b2 button appear at the end of the scroll_bar - b2.set_pos(rect.left(), rect.bottom() - b2.get_rect().height() + 1); - - if (max_pos != 0) - { - double range = b2.get_rect().top() - b1.get_rect().bottom() - slider.get_rect().height() - 1; - double slider_pos = pos; - slider_pos /= max_pos; - slider_pos *= range; - slider.set_pos( - rect.left(), - static_cast<long>(slider_pos) + rect.top() + b1.get_rect().height() - ); - - // move the draggable area for the slider to the new location - rectangle area = rect; - area.set_top(area.top() + style->get_width()); - area.set_bottom(area.bottom() - style->get_width()); - slider.set_draggable_area(area); - } - } - - adjust_fillers(); - } - -// ---------------------------------------------------------------------------------------- - - unsigned long scroll_bar:: - get_slider_size ( - ) const - { - if (ori == HORIZONTAL) - return style->get_slider_length(rect.width(),max_pos); - else - return style->get_slider_length(rect.height(),max_pos); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - adjust_fillers ( - ) - { - rectangle top(rect), bottom(rect); - - if (ori == HORIZONTAL) - { - if (slider.is_hidden()) - { - top.set_left(b1.get_rect().right()+1); - top.set_right(b2.get_rect().left()-1); - bottom.set_left(1); - bottom.set_right(-1); - } - else - { - top.set_left(b1.get_rect().right()+1); - top.set_right(slider.get_rect().left()-1); - bottom.set_left(slider.get_rect().right()+1); - bottom.set_right(b2.get_rect().left()-1); - } - } - else - { - if (slider.is_hidden()) - { - top.set_top(b1.get_rect().bottom()+1); - top.set_bottom(b2.get_rect().top()-1); - bottom.set_top(1); - bottom.set_bottom(-1); - } - else - { - top.set_top(b1.get_rect().bottom()+1); - top.set_bottom(slider.get_rect().top()-1); - bottom.set_top(slider.get_rect().bottom()+1); - bottom.set_bottom(b2.get_rect().top()-1); - } - } - - top_filler.rect = top; - bottom_filler.rect = bottom; - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - hide_slider ( - ) - { - rectangle top(rect), bottom(rect); - slider.hide(); - top_filler.disable(); - bottom_filler.disable(); - bottom_filler.hide(); - if (ori == HORIZONTAL) - { - top.set_left(b1.get_rect().right()+1); - top.set_right(b2.get_rect().left()-1); - } - else - { - top.set_top(b1.get_rect().bottom()+1); - top.set_bottom(b2.get_rect().top()-1); - } - top_filler.rect = top; - bottom_filler.rect = bottom; - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - show_slider ( - ) - { - if ((b2.get_rect().top() - b1.get_rect().bottom() - 1 <= 8 && ori == VERTICAL) || - (b2.get_rect().left() - b1.get_rect().right() - 1 <= 8 && ori == HORIZONTAL) || - max_pos == 0) - return; - - rectangle top(rect), bottom(rect); - slider.show(); - top_filler.enable(); - bottom_filler.enable(); - bottom_filler.show(); - if (ori == HORIZONTAL) - { - top.set_left(b1.get_rect().right()+1); - top.set_right(slider.get_rect().left()-1); - bottom.set_left(slider.get_rect().right()+1); - bottom.set_right(b2.get_rect().left()-1); - } - else - { - top.set_top(b1.get_rect().bottom()+1); - top.set_bottom(slider.get_rect().top()-1); - bottom.set_top(slider.get_rect().bottom()+1); - bottom.set_bottom(b2.get_rect().top()-1); - } - top_filler.rect = top; - bottom_filler.rect = bottom; - } - -// ---------------------------------------------------------------------------------------- - - long scroll_bar:: - max_slider_pos ( - ) const - { - auto_mutex M(m); - return max_pos; - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - set_max_slider_pos ( - long mpos - ) - { - auto_mutex M(m); - max_pos = mpos; - if (pos > mpos) - pos = mpos; - - if (ori == HORIZONTAL) - set_length(rect.width()); - else - set_length(rect.height()); - - if (mpos != 0 && enabled) - { - b1.enable(); - b2.enable(); - } - else - { - b1.disable(); - b2.disable(); - } - - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - set_slider_pos ( - long pos - ) - { - auto_mutex M(m); - if (pos < 0) - pos = 0; - if (pos > max_pos) - pos = max_pos; - - this->pos = pos; - - // move the slider object to its new position - set_pos(rect.left(),rect.top()); - } - -// ---------------------------------------------------------------------------------------- - - long scroll_bar:: - slider_pos ( - ) const - { - auto_mutex M(m); - return pos; - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - on_slider_drag ( - ) - { - if (ori == HORIZONTAL) - { - double slider_pos = slider.get_rect().left() - b1.get_rect().right() - 1; - double range = b2.get_rect().left() - b1.get_rect().right() - slider.get_rect().width() - 1; - slider_pos /= range; - slider_pos *= max_pos; - pos = static_cast<unsigned long>(slider_pos); - } - else - { - double slider_pos = slider.get_rect().top() - b1.get_rect().bottom() - 1; - double range = b2.get_rect().top() - b1.get_rect().bottom() - slider.get_rect().height() - 1; - slider_pos /= range; - slider_pos *= max_pos; - pos = static_cast<unsigned long>(slider_pos); - } - - adjust_fillers(); - - if (scroll_handler.is_set()) - scroll_handler(); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - draw ( - const canvas& - ) const - { - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - b1_down ( - ) - { - if (pos != 0) - { - set_slider_pos(pos-1); - if (scroll_handler.is_set()) - scroll_handler(); - - if (b1_timer.delay_time() == 1000) - b1_timer.set_delay_time(500); - else - b1_timer.set_delay_time(50); - b1_timer.start(); - } - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - b1_up ( - bool - ) - { - b1_timer.stop(); - b1_timer.set_delay_time(1000); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - b2_down ( - ) - { - if (pos != max_pos) - { - set_slider_pos(pos+1); - if (scroll_handler.is_set()) - scroll_handler(); - - if (b2_timer.delay_time() == 1000) - b2_timer.set_delay_time(500); - else - b2_timer.set_delay_time(50); - b2_timer.start(); - } - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - b2_up ( - bool - ) - { - b2_timer.stop(); - b2_timer.set_delay_time(1000); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - top_filler_down ( - ) - { - // ignore this if the mouse is now outside this object. This could happen - // since the timers are also calling this function. - if (top_filler.rect.contains(lastx,lasty) == false) - { - top_filler_up(false); - return; - } - - if (pos != 0) - { - if (pos < js) - { - // if there is less than jump_size() space left then jump the remaining - // amount. - delayed_set_slider_pos(0); - } - else - { - delayed_set_slider_pos(pos-js); - } - - if (top_filler_timer.delay_time() == 1000) - top_filler_timer.set_delay_time(500); - else - top_filler_timer.set_delay_time(50); - top_filler_timer.start(); - } - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - top_filler_up ( - bool - ) - { - top_filler_timer.stop(); - top_filler_timer.set_delay_time(1000); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - bottom_filler_down ( - ) - { - // ignore this if the mouse is now outside this object. This could happen - // since the timers are also calling this function. - if (bottom_filler.rect.contains(lastx,lasty) == false) - { - bottom_filler_up(false); - return; - } - - if (pos != max_pos) - { - if (max_pos - pos < js) - { - // if there is less than jump_size() space left then jump the remaining - // amount. - delayed_set_slider_pos(max_pos); - } - else - { - delayed_set_slider_pos(pos+js); - } - - if (bottom_filler_timer.delay_time() == 1000) - bottom_filler_timer.set_delay_time(500); - else - bottom_filler_timer.set_delay_time(50); - bottom_filler_timer.start(); - } - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - bottom_filler_up ( - bool - ) - { - bottom_filler_timer.stop(); - bottom_filler_timer.set_delay_time(1000); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - set_jump_size ( - long js_ - ) - { - auto_mutex M(m); - if (js_ < 1) - js = 1; - else - js = js_; - } - -// ---------------------------------------------------------------------------------------- - - long scroll_bar:: - jump_size ( - ) const - { - auto_mutex M(m); - return js; - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - on_user_event ( - int i - ) - { - switch (i) - { - case 0: - b1_down(); - break; - case 1: - b2_down(); - break; - case 2: - top_filler_down(); - break; - case 3: - bottom_filler_down(); - break; - case 4: - // if the position we are supposed to switch the slider too isn't - // already set - if (delayed_pos != pos) - { - set_slider_pos(delayed_pos); - if (scroll_handler.is_set()) - scroll_handler(); - } - break; - default: - break; - } - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - delayed_set_slider_pos ( - unsigned long dpos - ) - { - delayed_pos = dpos; - parent.trigger_user_event(this,4); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - b1_down_t ( - ) - { - parent.trigger_user_event(this,0); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - b2_down_t ( - ) - { - parent.trigger_user_event(this,1); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - top_filler_down_t ( - ) - { - parent.trigger_user_event(this,2); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar:: - bottom_filler_down_t ( - ) - { - parent.trigger_user_event(this,3); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// widget_group object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void widget_group:: - empty ( - ) - { - auto_mutex M(m); - widgets.clear(); - wg_widgets.clear(); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - add ( - drawable& widget, - unsigned long x, - unsigned long y - ) - { - auto_mutex M(m); - drawable* w = &widget; - relpos rp; - rp.x = x; - rp.y = y; - if (widgets.is_in_domain(w)) - { - widgets[w].x = x; - widgets[w].y = y; - } - else - { - widgets.add(w,rp); - } - if (is_hidden()) - widget.hide(); - else - widget.show(); - - if (is_enabled()) - widget.enable(); - else - widget.disable(); - - widget.set_z_order(z_order()); - widget.set_pos(x+rect.left(),y+rect.top()); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - add ( - widget_group& widget, - unsigned long x, - unsigned long y - ) - { - auto_mutex M(m); - drawable& w = widget; - add(w, x, y); - - widget_group* wg = &widget; - wg_widgets.add(wg); - } - -// ---------------------------------------------------------------------------------------- - - bool widget_group:: - is_member ( - const drawable& widget - ) const - { - auto_mutex M(m); - drawable* w = const_cast<drawable*>(&widget); - return widgets.is_in_domain(w); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - remove ( - const drawable& widget - ) - { - auto_mutex M(m); - drawable* w = const_cast<drawable*>(&widget); - if (widgets.is_in_domain(w)) - { - widgets.destroy(w); - - // check if we also have an entry in the wg_widgets set and if - // so then remove that too - widget_group* wg = reinterpret_cast<widget_group*>(w); - if (wg_widgets.is_member(wg)) - { - wg_widgets.destroy(wg); - } - } - } - -// ---------------------------------------------------------------------------------------- - - size_t widget_group:: - size ( - ) const - { - auto_mutex M(m); - return widgets.size(); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - set_pos ( - long x, - long y - ) - { - auto_mutex M(m); - widgets.reset(); - while (widgets.move_next()) - { - const unsigned long rx = widgets.element().value().x; - const unsigned long ry = widgets.element().value().y; - widgets.element().key()->set_pos(x+rx,y+ry); - } - drawable::set_pos(x,y); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - set_z_order ( - long order - ) - { - auto_mutex M(m); - widgets.reset(); - while (widgets.move_next()) - widgets.element().key()->set_z_order(order); - drawable::set_z_order(order); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - show ( - ) - { - auto_mutex M(m); - widgets.reset(); - while (widgets.move_next()) - widgets.element().key()->show(); - drawable::show(); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - hide ( - ) - { - auto_mutex M(m); - widgets.reset(); - while (widgets.move_next()) - widgets.element().key()->hide(); - drawable::hide(); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - enable ( - ) - { - auto_mutex M(m); - widgets.reset(); - while (widgets.move_next()) - widgets.element().key()->enable(); - drawable::enable(); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - disable () - { - auto_mutex M(m); - widgets.reset(); - while (widgets.move_next()) - widgets.element().key()->disable(); - drawable::disable(); - } - -// ---------------------------------------------------------------------------------------- - - void widget_group:: - fit_to_contents ( - ) - { - auto_mutex M(m); - - // call fit_to_contents on all the widget_groups we contain - wg_widgets.reset(); - while (wg_widgets.move_next()) - wg_widgets.element()->fit_to_contents(); - - // now accumulate a rectangle that contains everything in this widget_group - rectangle r; - widgets.reset(); - while (widgets.move_next()) - r = r + widgets.element().key()->get_rect(); - - if (r.is_empty()) - { - // make sure it is still empty after we set it at the correct position - r.set_right(rect.left()-1); - r.set_bottom(rect.top()-1); - } - - r.set_left(rect.left()); - r.set_top(rect.top()); - rect = r; - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// class popup_menu -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - popup_menu:: - popup_menu ( - ) : - base_window(false,true), - pad(2), - item_pad(3), - cur_rect(pad,pad,pad-1,pad-1), - left_width(0), - middle_width(0), - selected_item(0), - submenu_open(false) - { - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - enable_menu_item ( - unsigned long idx - ) - { - DLIB_ASSERT ( idx < size() , - "\tvoid popup_menu::enable_menu_item()" - << "\n\tidx: " << idx - << "\n\tsize(): " << size() - ); - auto_mutex M(wm); - item_enabled[idx] = true; - invalidate_rectangle(cur_rect); - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - disable_menu_item ( - unsigned long idx - ) - { - DLIB_ASSERT ( idx < size() , - "\tvoid popup_menu::enable_menu_item()" - << "\n\tidx: " << idx - << "\n\tsize(): " << size() - ); - auto_mutex M(wm); - item_enabled[idx] = false; - invalidate_rectangle(cur_rect); - } - -// ---------------------------------------------------------------------------------------- - - size_t popup_menu:: - size ( - ) const - { - auto_mutex M(wm); - return items.size(); - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - clear ( - ) - { - auto_mutex M(wm); - hide(); - cur_rect = rectangle(pad,pad,pad-1,pad-1); - win_rect = rectangle(); - left_width = 0; - middle_width = 0; - items.clear(); - item_enabled.clear(); - left_rects.clear(); - middle_rects.clear(); - right_rects.clear(); - line_rects.clear(); - submenus.clear(); - selected_item = 0; - submenu_open = false; - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - show ( - ) - { - auto_mutex M(wm); - selected_item = submenus.size(); - base_window::show(); - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - hide ( - ) - { - auto_mutex M(wm); - // hide ourselves - close_submenu(); - selected_item = submenus.size(); - base_window::hide(); - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - select_first_item ( - ) - { - auto_mutex M(wm); - close_submenu(); - selected_item = items.size(); - for (unsigned long i = 0; i < items.size(); ++i) - { - if ((items[i]->has_click_event() || submenus[i]) && item_enabled[i]) - { - selected_item = i; - break; - } - } - invalidate_rectangle(cur_rect); - } - -// ---------------------------------------------------------------------------------------- - - bool popup_menu:: - forwarded_on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - auto_mutex M(wm); - // do nothing if this popup menu is empty - if (items.size() == 0) - return false; - - - // check if the selected item is a submenu - if (selected_item != submenus.size() && submenus[selected_item] != 0 && submenu_open) - { - // send the key to the submenu and return if that menu used the key - if (submenus[selected_item]->forwarded_on_keydown(key,is_printable,state) == true) - return true; - } - - if (key == KEY_UP) - { - for (unsigned long i = 0; i < items.size(); ++i) - { - selected_item = (selected_item + items.size() - 1)%items.size(); - // only stop looking if this one is enabled and has a click event or is a submenu - if (item_enabled[selected_item] && (items[selected_item]->has_click_event() || submenus[selected_item]) ) - break; - } - invalidate_rectangle(cur_rect); - return true; - } - else if (key == KEY_DOWN) - { - for (unsigned long i = 0; i < items.size(); ++i) - { - selected_item = (selected_item + 1)%items.size(); - // only stop looking if this one is enabled and has a click event or is a submenu - if (item_enabled[selected_item] && (items[selected_item]->has_click_event() || submenus[selected_item])) - break; - } - invalidate_rectangle(cur_rect); - return true; - } - else if (key == KEY_RIGHT && submenu_open == false && display_selected_submenu()) - { - submenus[selected_item]->select_first_item(); - return true; - } - else if (key == KEY_LEFT && selected_item != submenus.size() && - submenus[selected_item] != 0 && submenu_open) - { - close_submenu(); - return true; - } - else if (key == '\n') - { - if (selected_item != submenus.size() && (items[selected_item]->has_click_event() || submenus[selected_item])) - { - const long idx = selected_item; - // only hide this popup window if this isn't a submenu - if (submenus[idx] == 0) - { - hide(); - hide_handlers.reset(); - while (hide_handlers.move_next()) - hide_handlers.element()(); - } - else - { - display_selected_submenu(); - submenus[idx]->select_first_item(); - } - items[idx]->on_click(); - return true; - } - } - else if (is_printable) - { - // check if there is a hotkey for this key - for (unsigned long i = 0; i < items.size(); ++i) - { - if (std::tolower(key) == std::tolower(items[i]->get_hot_key()) && - (items[i]->has_click_event() || submenus[i]) && item_enabled[i] ) - { - // only hide this popup window if this isn't a submenu - if (submenus[i] == 0) - { - hide(); - hide_handlers.reset(); - while (hide_handlers.move_next()) - hide_handlers.element()(); - } - else - { - if (selected_item != items.size()) - invalidate_rectangle(line_rects[selected_item]); - - selected_item = i; - display_selected_submenu(); - invalidate_rectangle(line_rects[i]); - submenus[i]->select_first_item(); - } - items[i]->on_click(); - } - } - - // always say we use a printable key for hotkeys - return true; - } - - return false; - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - on_submenu_hide ( - ) - { - hide(); - hide_handlers.reset(); - while (hide_handlers.move_next()) - hide_handlers.element()(); - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - on_window_resized( - ) - { - invalidate_rectangle(win_rect); - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - on_mouse_up ( - unsigned long btn, - unsigned long, - long x, - long y - ) - { - if (cur_rect.contains(x,y) && btn == LEFT) - { - // figure out which item this was on - for (unsigned long i = 0; i < items.size(); ++i) - { - if (line_rects[i].contains(x,y) && item_enabled[i] && items[i]->has_click_event()) - { - // only hide this popup window if this isn't a submenu - if (submenus[i] == 0) - { - hide(); - hide_handlers.reset(); - while (hide_handlers.move_next()) - hide_handlers.element()(); - } - items[i]->on_click(); - break; - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - on_mouse_move ( - unsigned long , - long x, - long y - ) - { - if (cur_rect.contains(x,y)) - { - // check if the mouse is still in the same rect it was in last time - rectangle last_rect; - if (selected_item != submenus.size()) - { - last_rect = line_rects[selected_item]; - } - - // if the mouse isn't in the same rectangle any more - if (last_rect.contains(x,y) == false) - { - if (selected_item != submenus.size()) - { - invalidate_rectangle(last_rect); - close_submenu(); - selected_item = submenus.size(); - } - - - // figure out if we should redraw any menu items - for (unsigned long i = 0; i < items.size(); ++i) - { - if (items[i]->has_click_event() || submenus[i]) - { - if (line_rects[i].contains(x,y)) - { - selected_item = i; - break; - } - } - } - - // if we found a rectangle that contains the mouse then - // tell it to redraw itself - if (selected_item != submenus.size()) - { - display_selected_submenu(); - invalidate_rectangle(line_rects[selected_item]); - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - close_submenu ( - ) - { - if (selected_item != submenus.size() && submenus[selected_item] && submenu_open) - { - submenus[selected_item]->hide(); - submenu_open = false; - } - } - -// ---------------------------------------------------------------------------------------- - - bool popup_menu:: - display_selected_submenu ( - ) - { - // show the submenu if one exists - if (selected_item != submenus.size() && submenus[selected_item]) - { - long wx, wy; - get_pos(wx,wy); - wx += line_rects[selected_item].right(); - wy += line_rects[selected_item].top(); - submenus[selected_item]->set_pos(wx+1,wy-2); - submenus[selected_item]->show(); - submenu_open = true; - return true; - } - return false; - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - on_mouse_leave ( - ) - { - if (selected_item != submenus.size()) - { - // only unhighlight a menu item if it isn't a submenu item - if (submenus[selected_item] == 0) - { - invalidate_rectangle(line_rects[selected_item]); - selected_item = submenus.size(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu:: - paint ( - const canvas& c - ) - { - c.fill(200,200,200); - draw_rectangle(c, win_rect); - for (unsigned long i = 0; i < items.size(); ++i) - { - bool is_selected = false; - if (selected_item != submenus.size() && i == selected_item && - item_enabled[i]) - is_selected = true; - - items[i]->draw_background(c,line_rects[i], item_enabled[i], is_selected); - items[i]->draw_left(c,left_rects[i], item_enabled[i], is_selected); - items[i]->draw_middle(c,middle_rects[i], item_enabled[i], is_selected); - items[i]->draw_right(c,right_rects[i], item_enabled[i], is_selected); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// class zoomable_region -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - zoomable_region:: - zoomable_region ( - drawable_window& w, - unsigned long events - ) : - drawable(w,MOUSE_CLICK | MOUSE_WHEEL | MOUSE_MOVE | events), - min_scale(0.15), - max_scale(1.0), - zoom_increment_(0.90), - vsb(w, scroll_bar::VERTICAL), - hsb(w, scroll_bar::HORIZONTAL) - { - scale = 1; - mouse_drag_screen = false; - style.reset(new scrollable_region_style_default()); - - hsb.set_scroll_handler(*this,&zoomable_region::on_h_scroll); - vsb.set_scroll_handler(*this,&zoomable_region::on_v_scroll); - } - -// ---------------------------------------------------------------------------------------- - - zoomable_region:: - ~zoomable_region() - { - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - set_pos ( - long x, - long y - ) - { - auto_mutex M(m); - drawable::set_pos(x,y); - const long border_size = style->get_border_size(); - vsb.set_pos(rect.right()-border_size+1-vsb.width(),rect.top()+border_size); - hsb.set_pos(rect.left()+border_size,rect.bottom()-border_size+1-hsb.height()); - - display_rect_ = rectangle(rect.left()+border_size, - rect.top()+border_size, - rect.right()-border_size-vsb.width(), - rect.bottom()-border_size-hsb.height()); - - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - set_zoom_increment ( - double zi - ) - { - DLIB_ASSERT(0.0 < zi && zi < 1.0, - "\tvoid zoomable_region::set_zoom_increment(zi)" - << "\n\t the zoom increment must be between 0 and 1" - << "\n\t zi: " << zi - << "\n\t this: " << this - ); - - auto_mutex M(m); - zoom_increment_ = zi; - } - -// ---------------------------------------------------------------------------------------- - - double zoomable_region:: - zoom_increment ( - ) const - { - auto_mutex M(m); - return zoom_increment_; - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - set_max_zoom_scale ( - double ms - ) - { - DLIB_ASSERT(ms > 0, - "\tvoid zoomable_region::set_max_zoom_scale(ms)" - << "\n\t the max zoom scale must be greater than 0" - << "\n\t ms: " << ms - << "\n\t this: " << this - ); - - auto_mutex M(m); - max_scale = ms; - if (scale > ms) - { - scale = max_scale; - lr_point = gui_to_graph_space(point(display_rect_.right(),display_rect_.bottom())); - redraw_graph(); - } - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - set_min_zoom_scale ( - double ms - ) - { - DLIB_ASSERT(ms > 0, - "\tvoid zoomable_region::set_min_zoom_scale(ms)" - << "\n\t the min zoom scale must be greater than 0" - << "\n\t ms: " << ms - << "\n\t this: " << this - ); - - auto_mutex M(m); - min_scale = ms; - - if (scale < ms) - { - scale = min_scale; - } - - // just call set_size so that everything gets redrawn right - set_size(rect.width(), rect.height()); - } - -// ---------------------------------------------------------------------------------------- - - double zoomable_region:: - min_zoom_scale ( - ) const - { - auto_mutex M(m); - return min_scale; - } - -// ---------------------------------------------------------------------------------------- - - double zoomable_region:: - max_zoom_scale ( - ) const - { - auto_mutex M(m); - return max_scale; - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - rectangle old(rect); - const long border_size = style->get_border_size(); - rect = resize_rect(rect,width,height); - vsb.set_pos(rect.right()-border_size+1-vsb.width(), rect.top()+border_size); - hsb.set_pos(rect.left()+border_size, rect.bottom()-border_size+1-hsb.height()); - - display_rect_ = rectangle(rect.left()+border_size, - rect.top()+border_size, - rect.right()-border_size-vsb.width(), - rect.bottom()-border_size-hsb.height()); - vsb.set_length(display_rect_.height()); - hsb.set_length(display_rect_.width()); - parent.invalidate_rectangle(rect+old); - - const double old_scale = scale; - const vector<double,2> old_gr_orig(gr_orig); - scale = min_scale; - gr_orig = vector<double,2>(0,0); - lr_point = gui_to_graph_space(point(display_rect_.right(),display_rect_.bottom())); - scale = old_scale; - - // call adjust_origin() so that the scroll bars get their max slider positions - // setup right - const point rect_corner(display_rect_.left(), display_rect_.top()); - adjust_origin(rect_corner, old_gr_orig); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - show ( - ) - { - auto_mutex M(m); - drawable::show(); - hsb.show(); - vsb.show(); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - hide ( - ) - { - auto_mutex M(m); - drawable::hide(); - hsb.hide(); - vsb.hide(); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - enable ( - ) - { - auto_mutex M(m); - drawable::enable(); - hsb.enable(); - vsb.enable(); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - disable ( - ) - { - auto_mutex M(m); - drawable::disable(); - hsb.disable(); - vsb.disable(); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - set_z_order ( - long order - ) - { - auto_mutex M(m); - drawable::set_z_order(order); - hsb.set_z_order(order); - vsb.set_z_order(order); - } - -// ---------------------------------------------------------------------------------------- - - point zoomable_region:: - graph_to_gui_space ( - const vector<double,2>& p - ) const - { - const point rect_corner(display_rect_.left(), display_rect_.top()); - return (p - gr_orig)*scale + rect_corner; - } - -// ---------------------------------------------------------------------------------------- - - vector<double,2> zoomable_region:: - gui_to_graph_space ( - const point& p - ) const - { - const point rect_corner(display_rect_.left(), display_rect_.top()); - return (p - rect_corner)/scale + gr_orig; - } - -// ---------------------------------------------------------------------------------------- - - point zoomable_region:: - max_graph_point ( - ) const - { - return lr_point; - } - -// ---------------------------------------------------------------------------------------- - - rectangle zoomable_region:: - display_rect ( - ) const - { - return display_rect_; - } - -// ---------------------------------------------------------------------------------------- - - double zoomable_region:: - zoom_scale ( - ) const - { - return scale; - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - set_zoom_scale ( - double new_scale - ) - { - // if new_scale isn't in the right range then put it back in range before we do the - // rest of this function - if (!(min_scale <= new_scale && new_scale <= max_scale)) - { - if (new_scale > max_scale) - new_scale = max_scale; - else - new_scale = min_scale; - } - - // find the point in the center of the graph area - point center((display_rect_.left()+display_rect_.right())/2, (display_rect_.top()+display_rect_.bottom())/2); - point graph_p(gui_to_graph_space(center)); - scale = new_scale; - adjust_origin(center, graph_p); - redraw_graph(); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - center_display_at_graph_point ( - const vector<double,2>& p - ) - { - // find the point in the center of the graph area - point center((display_rect_.left()+display_rect_.right())/2, (display_rect_.top()+display_rect_.bottom())/2); - adjust_origin(center, p); - redraw_graph(); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - on_wheel_down ( - unsigned long - ) - { - // zoom out - if (enabled && !hidden && scale > min_scale && display_rect_.contains(lastx,lasty)) - { - point gui_p(lastx,lasty); - point graph_p(gui_to_graph_space(gui_p)); - const double old_scale = scale; - scale *= zoom_increment_; - if (scale < min_scale) - scale = min_scale; - redraw_graph(); - adjust_origin(gui_p, graph_p); - - if (scale != old_scale) - on_view_changed(); - } - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - on_wheel_up ( - unsigned long - ) - { - // zoom in - if (enabled && !hidden && scale < max_scale && display_rect_.contains(lastx,lasty)) - { - point gui_p(lastx,lasty); - point graph_p(gui_to_graph_space(gui_p)); - const double old_scale = scale; - scale /= zoom_increment_; - if (scale > max_scale) - scale = max_scale; - redraw_graph(); - adjust_origin(gui_p, graph_p); - - if (scale != old_scale) - on_view_changed(); - } - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - if (enabled && !hidden && mouse_drag_screen) - { - adjust_origin(point(x,y), drag_screen_point); - redraw_graph(); - on_view_changed(); - } - - // check if the mouse isn't being dragged anymore - if ((state & base_window::LEFT) == 0) - { - mouse_drag_screen = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - on_mouse_up ( - unsigned long , - unsigned long , - long , - long - ) - { - mouse_drag_screen = false; - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ) - { - if (enabled && !hidden && display_rect_.contains(x,y) && btn == base_window::LEFT) - { - mouse_drag_screen = true; - drag_screen_point = gui_to_graph_space(point(x,y)); - } - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - draw ( - const canvas& c - ) const - { - style->draw_scrollable_region_border(c, rect, enabled); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - on_h_scroll ( - ) - { - gr_orig.x() = hsb.slider_pos(); - redraw_graph(); - - on_view_changed(); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - on_v_scroll ( - ) - { - gr_orig.y() = vsb.slider_pos(); - redraw_graph(); - - on_view_changed(); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - redraw_graph ( - ) - { - parent.invalidate_rectangle(display_rect_); - } - -// ---------------------------------------------------------------------------------------- - - void zoomable_region:: - adjust_origin ( - const point& gui_p, - const vector<double,2>& graph_p - ) - { - const point rect_corner(display_rect_.left(), display_rect_.top()); - const dlib::vector<double,2> v(gui_p - rect_corner); - gr_orig = graph_p - v/scale; - - - // make sure the origin isn't outside the point (0,0) - if (gr_orig.x() < 0) - gr_orig.x() = 0; - if (gr_orig.y() < 0) - gr_orig.y() = 0; - - // make sure the lower right corner of the display_rect_ doesn't map to a point beyond lr_point - point lr_rect_corner(display_rect_.right(), display_rect_.bottom()); - point p = graph_to_gui_space(lr_point); - vector<double,2> lr_rect_corner_graph_space(gui_to_graph_space(lr_rect_corner)); - vector<double,2> delta(lr_point - lr_rect_corner_graph_space); - if (lr_rect_corner.x() > p.x()) - { - gr_orig.x() += delta.x(); - } - - if (lr_rect_corner.y() > p.y()) - { - gr_orig.y() += delta.y(); - } - - - const vector<double,2> ul_rect_corner_graph_space(gui_to_graph_space(rect_corner)); - lr_rect_corner_graph_space = gui_to_graph_space(lr_rect_corner); - // now adjust the scroll bars - - hsb.set_max_slider_pos((unsigned long)std::max(lr_point.x()-(lr_rect_corner_graph_space.x()-ul_rect_corner_graph_space.x()),0.0)); - vsb.set_max_slider_pos((unsigned long)std::max(lr_point.y()-(lr_rect_corner_graph_space.y()-ul_rect_corner_graph_space.y()),0.0)); - // adjust slider position now. - hsb.set_slider_pos(static_cast<long>(ul_rect_corner_graph_space.x())); - vsb.set_slider_pos(static_cast<long>(ul_rect_corner_graph_space.y())); - - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// class scrollable_region -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - scrollable_region:: - scrollable_region ( - drawable_window& w, - unsigned long events - ) : - drawable(w, MOUSE_WHEEL|events|MOUSE_CLICK|MOUSE_MOVE), - hsb(w,scroll_bar::HORIZONTAL), - vsb(w,scroll_bar::VERTICAL), - hscroll_bar_inc(1), - vscroll_bar_inc(1), - h_wheel_scroll_bar_inc(1), - v_wheel_scroll_bar_inc(1), - mouse_drag_enabled_(false), - user_is_dragging_mouse(false) - { - style.reset(new scrollable_region_style_default()); - - hsb.set_scroll_handler(*this,&scrollable_region::on_h_scroll); - vsb.set_scroll_handler(*this,&scrollable_region::on_v_scroll); - } - -// ---------------------------------------------------------------------------------------- - - scrollable_region:: - ~scrollable_region ( - ) - { - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - show ( - ) - { - auto_mutex M(m); - drawable::show(); - if (need_h_scroll()) - hsb.show(); - if (need_v_scroll()) - vsb.show(); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - hide ( - ) - { - auto_mutex M(m); - drawable::hide(); - hsb.hide(); - vsb.hide(); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - enable ( - ) - { - auto_mutex M(m); - drawable::enable(); - hsb.enable(); - vsb.enable(); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - disable ( - ) - { - auto_mutex M(m); - drawable::disable(); - hsb.disable(); - vsb.disable(); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_z_order ( - long order - ) - { - auto_mutex M(m); - drawable::set_z_order(order); - hsb.set_z_order(order); - vsb.set_z_order(order); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - rectangle old(rect); - rect = resize_rect(rect,width,height); - vsb.set_pos(rect.right()-style->get_border_size()-vsb.width()+1, rect.top()+style->get_border_size()); - hsb.set_pos(rect.left()+style->get_border_size(), rect.bottom()-style->get_border_size()-hsb.height()+1); - - // adjust the display_rect_ - if (need_h_scroll() && need_v_scroll()) - { - // both scroll bars aren't hidden - if (!hidden) - { - vsb.show(); - hsb.show(); - } - display_rect_ = rectangle( rect.left()+style->get_border_size(), - rect.top()+style->get_border_size(), - rect.right()-style->get_border_size()-vsb.width(), - rect.bottom()-style->get_border_size()-hsb.height()); - - // figure out how many scroll bar positions there should be - unsigned long hdelta = total_rect_.width()-display_rect_.width(); - unsigned long vdelta = total_rect_.height()-display_rect_.height(); - hdelta = (hdelta+hscroll_bar_inc-1)/hscroll_bar_inc; - vdelta = (vdelta+vscroll_bar_inc-1)/vscroll_bar_inc; - - hsb.set_max_slider_pos(hdelta); - vsb.set_max_slider_pos(vdelta); - - vsb.set_jump_size((display_rect_.height()+vscroll_bar_inc-1)/vscroll_bar_inc/2+1); - hsb.set_jump_size((display_rect_.width()+hscroll_bar_inc-1)/hscroll_bar_inc/2+1); - } - else if (need_h_scroll()) - { - // only hsb is hidden - if (!hidden) - { - hsb.show(); - vsb.hide(); - } - display_rect_ = rectangle( rect.left()+style->get_border_size(), - rect.top()+style->get_border_size(), - rect.right()-style->get_border_size(), - rect.bottom()-style->get_border_size()-hsb.height()); - - // figure out how many scroll bar positions there should be - unsigned long hdelta = total_rect_.width()-display_rect_.width(); - hdelta = (hdelta+hscroll_bar_inc-1)/hscroll_bar_inc; - - hsb.set_max_slider_pos(hdelta); - vsb.set_max_slider_pos(0); - - hsb.set_jump_size((display_rect_.width()+hscroll_bar_inc-1)/hscroll_bar_inc/2+1); - } - else if (need_v_scroll()) - { - // only vsb is hidden - if (!hidden) - { - hsb.hide(); - vsb.show(); - } - display_rect_ = rectangle( rect.left()+style->get_border_size(), - rect.top()+style->get_border_size(), - rect.right()-style->get_border_size()-vsb.width(), - rect.bottom()-style->get_border_size()); - - unsigned long vdelta = total_rect_.height()-display_rect_.height(); - vdelta = (vdelta+vscroll_bar_inc-1)/vscroll_bar_inc; - - hsb.set_max_slider_pos(0); - vsb.set_max_slider_pos(vdelta); - - vsb.set_jump_size((display_rect_.height()+vscroll_bar_inc-1)/vscroll_bar_inc/2+1); - } - else - { - // both are hidden - if (!hidden) - { - hsb.hide(); - vsb.hide(); - } - display_rect_ = rectangle( rect.left()+style->get_border_size(), - rect.top()+style->get_border_size(), - rect.right()-style->get_border_size(), - rect.bottom()-style->get_border_size()); - - hsb.set_max_slider_pos(0); - vsb.set_max_slider_pos(0); - } - - vsb.set_length(display_rect_.height()); - hsb.set_length(display_rect_.width()); - - // adjust the total_rect_ position by trigging the scroll events - on_h_scroll(); - on_v_scroll(); - - parent.invalidate_rectangle(rect+old); - } - -// ---------------------------------------------------------------------------------------- - - unsigned long scrollable_region:: - horizontal_mouse_wheel_scroll_increment ( - ) const - { - auto_mutex M(m); - return h_wheel_scroll_bar_inc; - } - -// ---------------------------------------------------------------------------------------- - - unsigned long scrollable_region:: - vertical_mouse_wheel_scroll_increment ( - ) const - { - auto_mutex M(m); - return v_wheel_scroll_bar_inc; - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_horizontal_mouse_wheel_scroll_increment ( - unsigned long inc - ) - { - auto_mutex M(m); - h_wheel_scroll_bar_inc = inc; - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_vertical_mouse_wheel_scroll_increment ( - unsigned long inc - ) - { - auto_mutex M(m); - v_wheel_scroll_bar_inc = inc; - } - -// ---------------------------------------------------------------------------------------- - - unsigned long scrollable_region:: - horizontal_scroll_increment ( - ) const - { - auto_mutex M(m); - return hscroll_bar_inc; - } - -// ---------------------------------------------------------------------------------------- - - unsigned long scrollable_region:: - vertical_scroll_increment ( - ) const - { - auto_mutex M(m); - return vscroll_bar_inc; - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_horizontal_scroll_increment ( - unsigned long inc - ) - { - auto_mutex M(m); - hscroll_bar_inc = inc; - // call set_size to reset the scroll bars - set_size(rect.width(),rect.height()); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_vertical_scroll_increment ( - unsigned long inc - ) - { - auto_mutex M(m); - vscroll_bar_inc = inc; - // call set_size to reset the scroll bars - set_size(rect.width(),rect.height()); - } - -// ---------------------------------------------------------------------------------------- - - long scrollable_region:: - horizontal_scroll_pos ( - ) const - { - auto_mutex M(m); - return hsb.slider_pos(); - } - -// ---------------------------------------------------------------------------------------- - - long scrollable_region:: - vertical_scroll_pos ( - ) const - { - auto_mutex M(m); - return vsb.slider_pos(); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_horizontal_scroll_pos ( - long pos - ) - { - auto_mutex M(m); - - hsb.set_slider_pos(pos); - on_h_scroll(); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_vertical_scroll_pos ( - long pos - ) - { - auto_mutex M(m); - - vsb.set_slider_pos(pos); - on_v_scroll(); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_pos ( - long x, - long y - ) - { - auto_mutex M(m); - drawable::set_pos(x,y); - vsb.set_pos(rect.right()-style->get_border_size()-vsb.width()+1, rect.top()+style->get_border_size()); - hsb.set_pos(rect.left()+style->get_border_size(), rect.bottom()-style->get_border_size()-hsb.height()+1); - - const long delta_x = total_rect_.left() - display_rect_.left(); - const long delta_y = total_rect_.top() - display_rect_.top(); - - display_rect_ = move_rect(display_rect_, rect.left()+style->get_border_size(), rect.top()+style->get_border_size()); - - total_rect_ = move_rect(total_rect_, display_rect_.left()+delta_x, display_rect_.top()+delta_y); - } - -// ---------------------------------------------------------------------------------------- - - bool scrollable_region:: - mouse_drag_enabled ( - ) const - { - auto_mutex M(m); - return mouse_drag_enabled_; - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - enable_mouse_drag ( - ) - { - auto_mutex M(m); - mouse_drag_enabled_ = true; - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - disable_mouse_drag ( - ) - { - auto_mutex M(m); - mouse_drag_enabled_ = false; - } - -// ---------------------------------------------------------------------------------------- - - const rectangle& scrollable_region:: - display_rect ( - ) const - { - return display_rect_; - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - set_total_rect_size ( - unsigned long width, - unsigned long height - ) - { - DLIB_ASSERT((width > 0 && height > 0) || (width == 0 && height == 0), - "\tvoid scrollable_region::set_total_rect_size(width,height)" - << "\n\twidth and height must be > 0 or both == 0" - << "\n\twidth: " << width - << "\n\theight: " << height - << "\n\tthis: " << this - ); - - total_rect_ = move_rect(rectangle(width,height), - display_rect_.left()-static_cast<long>(hsb.slider_pos()), - display_rect_.top()-static_cast<long>(vsb.slider_pos())); - - // call this just to reconfigure the scroll bars - set_size(rect.width(),rect.height()); - } - -// ---------------------------------------------------------------------------------------- - - const rectangle& scrollable_region:: - total_rect ( - ) const - { - return total_rect_; - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - scroll_to_rect ( - const rectangle& r_ - ) - { - const rectangle r(total_rect_.intersect(r_)); - const rectangle old(total_rect_); - // adjust the horizontal scroll bar so that r fits as best as possible - if (r.left() < display_rect_.left()) - { - long distance = (r.left()-total_rect_.left())/hscroll_bar_inc; - hsb.set_slider_pos(distance); - } - else if (r.right() > display_rect_.right()) - { - long distance = (r.right()-total_rect_.left()-display_rect_.width()+hscroll_bar_inc)/hscroll_bar_inc; - hsb.set_slider_pos(distance); - } - - // adjust the vertical scroll bar so that r fits as best as possible - if (r.top() < display_rect_.top()) - { - long distance = (r.top()-total_rect_.top())/vscroll_bar_inc; - vsb.set_slider_pos(distance); - } - else if (r.bottom() > display_rect_.bottom()) - { - long distance = (r.bottom()-total_rect_.top()-display_rect_.height()+vscroll_bar_inc)/vscroll_bar_inc; - vsb.set_slider_pos(distance); - } - - - // adjust total_rect_ so that it matches where the scroll bars are now - total_rect_ = move_rect(total_rect_, - display_rect_.left()-hscroll_bar_inc*hsb.slider_pos(), - display_rect_.top()-vscroll_bar_inc*vsb.slider_pos()); - - // only redraw if we actually changed something - if (total_rect_ != old) - { - parent.invalidate_rectangle(display_rect_); - } - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - on_wheel_down ( - unsigned long - ) - { - if (rect.contains(lastx,lasty) && enabled && !hidden) - { - if (need_v_scroll()) - { - long pos = vsb.slider_pos(); - vsb.set_slider_pos(pos+(long)v_wheel_scroll_bar_inc); - on_v_scroll(); - } - else if (need_h_scroll()) - { - long pos = hsb.slider_pos(); - hsb.set_slider_pos(pos+(long)h_wheel_scroll_bar_inc); - on_h_scroll(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - if (enabled && !hidden && user_is_dragging_mouse && state==base_window::LEFT) - { - point current_delta = point(x,y) - point(total_rect().left(), total_rect().top()); - rectangle new_rect(translate_rect(display_rect(), drag_origin - current_delta)); - new_rect = centered_rect(new_rect, new_rect.width()-hscroll_bar_inc, new_rect.height()-vscroll_bar_inc); - scroll_to_rect(new_rect); - on_view_changed(); - } - else - { - user_is_dragging_mouse = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ) - { - if (mouse_drag_enabled_ && enabled && !hidden && display_rect().contains(x,y) && (btn==base_window::LEFT)) - { - drag_origin = point(x,y) - point(total_rect().left(), total_rect().top()); - user_is_dragging_mouse = true; - } - else - { - user_is_dragging_mouse = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - on_mouse_up ( - unsigned long , - unsigned long , - long , - long - ) - { - user_is_dragging_mouse = false; - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - on_wheel_up ( - unsigned long - ) - { - if (rect.contains(lastx,lasty) && enabled && !hidden) - { - if (need_v_scroll()) - { - long pos = vsb.slider_pos(); - vsb.set_slider_pos(pos-(long)v_wheel_scroll_bar_inc); - on_v_scroll(); - } - else if (need_h_scroll()) - { - long pos = hsb.slider_pos(); - hsb.set_slider_pos(pos-(long)h_wheel_scroll_bar_inc); - on_h_scroll(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - draw ( - const canvas& c - ) const - { - style->draw_scrollable_region_border(c, rect, enabled); - } - -// ---------------------------------------------------------------------------------------- - - bool scrollable_region:: - need_h_scroll ( - ) const - { - if (total_rect_.width() > rect.width()-style->get_border_size()*2) - { - return true; - } - else - { - // check if we would need a vertical scroll bar and if adding one would make us need - // a horizontal one - if (total_rect_.height() > rect.height()-style->get_border_size()*2 && - total_rect_.width() > rect.width()-style->get_border_size()*2-vsb.width()) - return true; - else - return false; - } - } - -// ---------------------------------------------------------------------------------------- - - bool scrollable_region:: - need_v_scroll ( - ) const - { - if (total_rect_.height() > rect.height()-style->get_border_size()*2) - { - return true; - } - else - { - // check if we would need a horizontal scroll bar and if adding one would make us need - // a vertical_scroll_pos one - if (total_rect_.width() > rect.width()-style->get_border_size()*2 && - total_rect_.height() > rect.height()-style->get_border_size()*2-hsb.height()) - return true; - else - return false; - } - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - on_h_scroll ( - ) - { - total_rect_ = move_rect(total_rect_, display_rect_.left()-hscroll_bar_inc*hsb.slider_pos(), total_rect_.top()); - parent.invalidate_rectangle(display_rect_); - if (events_are_enabled()) - on_view_changed(); - } - -// ---------------------------------------------------------------------------------------- - - void scrollable_region:: - on_v_scroll ( - ) - { - total_rect_ = move_rect(total_rect_, total_rect_.left(), display_rect_.top()-vscroll_bar_inc*vsb.slider_pos()); - parent.invalidate_rectangle(display_rect_); - if (events_are_enabled()) - on_view_changed(); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// class popup_menu_region -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - popup_menu_region:: - popup_menu_region( - drawable_window& w - ) : - drawable(w,MOUSE_CLICK | KEYBOARD_EVENTS | FOCUS_EVENTS | WINDOW_MOVED), - popup_menu_shown(false) - { - - menu_.set_on_hide_handler(*this,&popup_menu_region::on_menu_becomes_hidden); - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - popup_menu_region:: - ~popup_menu_region( - ) - { - disable_events(); - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - rect = resize_rect(rect,width,height); - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - set_rect ( - const rectangle& new_rect - ) - { - auto_mutex M(m); - rect = new_rect; - } - -// ---------------------------------------------------------------------------------------- - - popup_menu& popup_menu_region:: - menu ( - ) - { - return menu_; - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - hide ( - ) - { - auto_mutex M(m); - drawable::hide(); - menu_.hide(); - popup_menu_shown = false; - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - disable ( - ) - { - auto_mutex M(m); - drawable::disable(); - menu_.hide(); - popup_menu_shown = false; - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - if (enabled && !hidden && popup_menu_shown) - { - menu_.forwarded_on_keydown(key, is_printable, state); - } - else if (popup_menu_shown) - { - menu_.hide(); - popup_menu_shown = false; - } - - if (key == (unsigned long)base_window::KEY_ESC) - { - menu_.hide(); - popup_menu_shown = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - on_menu_becomes_hidden ( - ) - { - popup_menu_shown = false; - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - on_focus_lost ( - ) - { - if (popup_menu_shown) - { - menu_.hide(); - popup_menu_shown = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - on_focus_gained ( - ) - { - if (popup_menu_shown) - { - menu_.hide(); - popup_menu_shown = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - on_window_moved( - ) - { - if (popup_menu_shown) - { - menu_.hide(); - popup_menu_shown = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ) - { - if (enabled && !hidden && rect.contains(x,y) && btn == base_window::RIGHT) - { - long orig_x, orig_y; - parent.get_pos(orig_x, orig_y); - menu_.set_pos(orig_x+x, orig_y+y); - menu_.show(); - popup_menu_shown = true; - } - else if (popup_menu_shown) - { - menu_.hide(); - popup_menu_shown = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void popup_menu_region:: - draw ( - const canvas& - ) const - { - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_BASE_WIDGETs_CPP_ - diff --git a/ml/dlib/dlib/gui_widgets/base_widgets.h b/ml/dlib/dlib/gui_widgets/base_widgets.h deleted file mode 100644 index 7c6d25097..000000000 --- a/ml/dlib/dlib/gui_widgets/base_widgets.h +++ /dev/null @@ -1,2678 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. - -#ifndef DLIB_BASE_WIDGETs_ -#define DLIB_BASE_WIDGETs_ - -#include <cctype> -#include <memory> - -#include "base_widgets_abstract.h" -#include "drawable.h" -#include "../gui_core.h" -#include "../algs.h" -#include "../member_function_pointer.h" -#include "../timer.h" -#include "../map.h" -#include "../set.h" -#include "../array2d.h" -#include "../pixel.h" -#include "../image_transforms/assign_image.h" -#include "../array.h" -#include "style.h" -#include "../unicode.h" -#include "../any.h" - - -namespace dlib -{ - - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class draggable -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class draggable : public drawable - { - /*! - INITIAL VALUE - - drag == false - - CONVENTION - - if (the user is holding the left button down over this object) then - - drag == true - - x == the x position of the mouse relative to the upper left corner - of this object. - - y == the y position of the mouse relative to the upper left corner - of this object. - - else - - drag == false - !*/ - - public: - - draggable( - drawable_window& w, - unsigned long events = 0 - ) : - drawable(w,events | MOUSE_MOVE | MOUSE_CLICK), - drag(false) - {} - - virtual ~draggable( - ) = 0; - - rectangle draggable_area ( - ) const { auto_mutex M(m); return area; } - - void set_draggable_area ( - const rectangle& area_ - ) { auto_mutex M(m); area = area_; } - - protected: - - bool is_being_dragged ( - ) const { return drag; } - - virtual void on_drag ( - ){} - - virtual void on_drag_stop ( - ){} - - void on_mouse_move ( - unsigned long state, - long x, - long y - ); - - void on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ); - - void on_mouse_up ( - unsigned long btn, - unsigned long state, - long x, - long y - ); - - private: - - rectangle area; - bool drag; - long x, y; - - // restricted functions - draggable(draggable&); // copy constructor - draggable& operator=(draggable&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class mouse_over_event -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class mouse_over_event : public drawable - { - /*! - INITIAL VALUE - - is_mouse_over_ == false - - CONVENTION - - is_mouse_over_ == is_mouse_over() - !*/ - - public: - - mouse_over_event( - drawable_window& w, - unsigned long events = 0 - ) : - drawable(w,events | MOUSE_MOVE), - is_mouse_over_(false) - {} - - - virtual ~mouse_over_event( - ) = 0; - - int next_free_user_event_number() const - { - return drawable::next_free_user_event_number()+1; - } - - protected: - - bool is_mouse_over ( - ) const; - - virtual void on_mouse_over ( - ){} - - virtual void on_mouse_not_over ( - ){} - - void on_mouse_leave ( - ); - - void on_mouse_move ( - unsigned long state, - long x, - long y - ); - - void on_user_event ( - int num - ); - - private: - mutable bool is_mouse_over_; - - // restricted functions - mouse_over_event(mouse_over_event&); // copy constructor - mouse_over_event& operator=(mouse_over_event&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class button_action -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class button_action : public mouse_over_event - { - /*! - INITIAL VALUE - - is_depressed_ == false - - seen_click == false - - CONVENTION - - is_depressed_ == is_depressed() - - if (the user has clicked the button but hasn't yet released the - left mouse button) then - - seen_click == true - - else - - seen_click == false - !*/ - - public: - - button_action( - drawable_window& w, - unsigned long events = 0 - ) : - mouse_over_event(w,events | MOUSE_MOVE | MOUSE_CLICK), - is_depressed_(false), - seen_click(false) - {} - - - virtual ~button_action( - ) = 0; - - int next_free_user_event_number() const - { - return mouse_over_event::next_free_user_event_number()+1; - } - - protected: - - bool is_depressed ( - ) const; - - virtual void on_button_down ( - ){} - - virtual void on_button_up ( - bool - ){} - - void on_mouse_not_over ( - ); - - void on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ); - - void on_mouse_move ( - unsigned long state, - long x, - long y - ); - - void on_mouse_up ( - unsigned long btn, - unsigned long, - long x, - long y - ); - - - private: - mutable bool is_depressed_; - bool seen_click; - - void on_user_event ( - int num - ); - - // restricted functions - button_action(button_action&); // copy constructor - button_action& operator=(button_action&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class widget_group -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class widget_group : public drawable - { - /*! - INITIAL VALUE - widgets.size() == 0 - - CONVENTION - - widgets contains all the drawable objects and their relative positions - that are in *this. - - wg_widgets contains pointers to just the widgets that happen - to be widget_group objects. - !*/ - - struct relpos - { - unsigned long x; - unsigned long y; - }; - - public: - widget_group( - drawable_window& w - ) : drawable(w) { rect = rectangle(0,0,-1,-1); enable_events();} - - virtual ~widget_group( - ){ disable_events(); } - - void empty ( - ); - - void add ( - drawable& widget, - unsigned long x, - unsigned long y - ); - - void add ( - widget_group& widget, - unsigned long x, - unsigned long y - ); - - bool is_member ( - const drawable& widget - ) const; - - void remove ( - const drawable& widget - ); - - size_t size ( - ) const; - - void set_pos ( - long x, - long y - ); - - void set_z_order ( - long order - ); - - void show ( - ); - - void hide ( - ); - - void enable ( - ); - - void disable ( - ); - - void fit_to_contents ( - ); - - protected: - - // this object doesn't draw anything but also isn't abstract - void draw ( - const canvas& - ) const {} - - private: - - map<drawable*,relpos>::kernel_1a_c widgets; - set<widget_group*>::kernel_1a_c wg_widgets; - - - // restricted functions - widget_group(widget_group&); // copy constructor - widget_group& operator=(widget_group&); // assignment operator - }; - - -// ---------------------------------------------------------------------------------------- - - class image_widget : public draggable - { - /*! - INITIAL VALUE - - img.size() == 0 - - CONVENTION - - img == the image this object displays - !*/ - - public: - - image_widget( - drawable_window& w - ): draggable(w) { enable_events(); } - - ~image_widget( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - } - - template < - typename image_type - > - void set_image ( - const image_type& new_img - ) - { - auto_mutex M(m); - assign_image_scaled(img,new_img); - rectangle old(rect); - rect.set_right(rect.left()+num_columns(img)-1); - rect.set_bottom(rect.top()+num_rows(img)-1); - parent.invalidate_rectangle(rect+old); - } - - private: - - void draw ( - const canvas& c - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - draw_image(c, point(rect.left(),rect.top()), img); - } - - array2d<rgb_alpha_pixel> img; - - // restricted functions - image_widget(image_widget&); // copy constructor - image_widget& operator=(image_widget&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class tooltip -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class tooltip : public mouse_over_event - { - /*! - INITIAL VALUE - - stuff.get() == 0 - - events_are_enabled() == false - - CONVENTION - - if (events_are_enabled() == true) then - - stuff.get() != 0 - !*/ - - public: - - tooltip( - drawable_window& w - ) : - mouse_over_event(w,MOUSE_CLICK) - {} - - ~tooltip( - ){ disable_events();} - - void set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - rect = resize_rect(rect,width,height); - } - - - void set_text ( - const std::string& str - ) - { - set_text(convert_mbstring_to_wstring(str)); - } - - void set_text ( - const std::wstring& str - ) - { - set_text(convert_wstring_to_utf32(str)); - } - - void set_text ( - const ustring& str - ) - { - auto_mutex M(m); - if (!stuff) - { - stuff.reset(new data(*this)); - enable_events(); - } - - stuff->win.set_text(str); - } - - const std::string text ( - ) const - { - return convert_wstring_to_mbstring(wtext()); - } - - const std::wstring wtext ( - ) const - { - return convert_utf32_to_wstring(utext()); - } - - const dlib::ustring utext ( - ) const - { - auto_mutex M(m); - dlib::ustring temp; - if (stuff) - { - temp = stuff->win.text; - } - return temp.c_str(); - } - - void hide ( - ) - { - auto_mutex M(m); - mouse_over_event::hide(); - if (stuff) - { - stuff->tt_timer.stop(); - stuff->win.hide(); - } - } - - void disable ( - ) - { - auto_mutex M(m); - mouse_over_event::disable(); - if (stuff) - { - stuff->tt_timer.stop(); - stuff->win.hide(); - } - } - - protected: - - void on_mouse_over() - { - stuff->x = lastx; - stuff->y = lasty; - stuff->tt_timer.start(); - } - - void on_mouse_not_over () - { - stuff->tt_timer.stop(); - stuff->win.hide(); - } - - void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ) - { - mouse_over_event::on_mouse_down(btn,state,x,y,is_double_click); - stuff->tt_timer.stop(); - stuff->win.hide(); - } - - void draw ( - const canvas& - ) const{} - - private: - - class tooltip_window : public base_window - { - public: - tooltip_window (const std::shared_ptr<font>& f) : base_window(false,true), pad(3), mfont(f) - { - } - - ustring text; - rectangle rect_all; - rectangle rect_text; - const unsigned long pad; - const std::shared_ptr<font> mfont; - - void set_text ( - const std::string& str - ) - { - set_text(convert_mbstring_to_wstring(str)); - } - - void set_text ( - const std::wstring& str - ) - { - set_text(convert_wstring_to_utf32(str)); - } - - void set_text ( - const dlib::ustring& str - ) - { - text = str.c_str(); - - unsigned long width, height; - mfont->compute_size(text,width,height); - - set_size(width+pad*2, height+pad*2); - rect_all.set_left(0); - rect_all.set_top(0); - rect_all.set_right(width+pad*2-1); - rect_all.set_bottom(height+pad*2-1); - - rect_text = move_rect(rectangle(width,height),pad,pad); - } - - void paint(const canvas& c) - { - c.fill(255,255,150); - draw_rectangle(c, rect_all); - mfont->draw_string(c,rect_text,text); - } - }; - - void show_tooltip ( - ) - { - auto_mutex M(m); - long x, y; - // if the mouse has moved since we started the timer then - // keep waiting until the user stops moving it - if (lastx != stuff->x || lasty != stuff->y) - { - stuff->x = lastx; - stuff->y = lasty; - return; - } - - unsigned long display_width, display_height; - // stop the timer - stuff->tt_timer.stop(); - parent.get_pos(x,y); - x += lastx+15; - y += lasty+15; - - // make sure the tooltip isn't going to be off the screen - parent.get_display_size(display_width, display_height); - rectangle wrect(move_rect(stuff->win.rect_all,x,y)); - rectangle srect(display_width, display_height); - if (srect.contains(wrect) == false) - { - rectangle temp(srect.intersect(wrect)); - x -= wrect.width()-temp.width(); - y -= wrect.height()-temp.height(); - } - - stuff->win.set_pos(x,y); - stuff->win.show(); - } - - // put all this stuff in data so we can arrange to only - // construct it when someone is actually using the tooltip widget - // rather than just instantiating it. - struct data - { - data( - tooltip& self - ) : - x(-1), - y(-1), - win(self.mfont), - tt_timer(self,&tooltip::show_tooltip) - { - tt_timer.set_delay_time(400); - } - - long x, y; - tooltip_window win; - timer<tooltip> tt_timer; - - }; - friend struct data; - std::unique_ptr<data> stuff; - - - - // restricted functions - tooltip(tooltip&); // copy constructor - tooltip& operator=(tooltip&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class button -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class button : public button_action - { - public: - button( - drawable_window& w - ) : - button_action(w), - btn_tooltip(w) - { - style.reset(new button_style_default()); - enable_events(); - } - - ~button() { disable_events(); parent.invalidate_rectangle(style->get_invalidation_rect(rect)); } - - void set_size ( - unsigned long width, - unsigned long height - ); - - void set_name ( - const std::string& name_ - ); - - void set_name ( - const std::wstring& name_ - ); - - void set_name ( - const dlib::ustring& name_ - ); - - const std::string name ( - ) const; - - const std::wstring wname ( - ) const; - - const dlib::ustring uname ( - ) const; - - void set_tooltip_text ( - const std::string& text - ); - - void set_tooltip_text ( - const std::wstring& text - ); - - void set_tooltip_text ( - const dlib::ustring& text - ); - - void set_pos( - long x, - long y - ); - - const std::string tooltip_text ( - ) const; - - const std::wstring tooltip_wtext ( - ) const; - - const dlib::ustring tooltip_utext ( - ) const; - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - void show ( - ); - - void hide ( - ); - - void enable ( - ); - - void disable ( - ); - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ) - { - auto_mutex M(m); - style.reset(new style_type(style_)); - rect = move_rect(style->get_min_size(name_,*mfont), rect.left(), rect.top()); - parent.invalidate_rectangle(style->get_invalidation_rect(rect)); - } - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler_)() - ) - { - auto_mutex M(m); - event_handler = make_mfp(object,event_handler_); - event_handler_self.clear(); - } - - void set_click_handler ( - const any_function<void()>& event_handler_ - ) - { - auto_mutex M(m); - event_handler = event_handler_; - event_handler_self.clear(); - } - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler_)(button&) - ) - { - auto_mutex M(m); - event_handler_self = make_mfp(object,event_handler_); - event_handler.clear(); - } - - void set_sourced_click_handler ( - const any_function<void(button&)>& event_handler_ - ) - { - auto_mutex M(m); - event_handler_self = event_handler_; - event_handler.clear(); - } - - bool is_depressed ( - ) const - { - auto_mutex M(m); - return button_action::is_depressed(); - } - - template < - typename T - > - void set_button_down_handler ( - T& object, - void (T::*event_handler)() - ) - { - auto_mutex M(m); - button_down_handler = make_mfp(object,event_handler); - } - - void set_button_down_handler ( - const any_function<void()>& event_handler - ) - { - auto_mutex M(m); - button_down_handler = event_handler; - } - - template < - typename T - > - void set_button_up_handler ( - T& object, - void (T::*event_handler)(bool mouse_over) - ) - { - auto_mutex M(m); - button_up_handler = make_mfp(object,event_handler); - } - - void set_button_up_handler ( - const any_function<void(bool)>& event_handler - ) - { - auto_mutex M(m); - button_up_handler = event_handler; - } - - template < - typename T - > - void set_button_down_handler ( - T& object, - void (T::*event_handler)(button&) - ) - { - auto_mutex M(m); - button_down_handler_self = make_mfp(object,event_handler); - } - - void set_sourced_button_down_handler ( - const any_function<void(button&)>& event_handler - ) - { - auto_mutex M(m); - button_down_handler_self = event_handler; - } - - template < - typename T - > - void set_button_up_handler ( - T& object, - void (T::*event_handler)(bool mouse_over, button&) - ) - { - auto_mutex M(m); - button_up_handler_self = make_mfp(object,event_handler); - } - - void set_sourced_button_up_handler ( - const any_function<void(bool,button&)>& event_handler - ) - { - auto_mutex M(m); - button_up_handler_self = event_handler; - } - - private: - - // restricted functions - button(button&); // copy constructor - button& operator=(button&); // assignment operator - - dlib::ustring name_; - tooltip btn_tooltip; - - any_function<void()> event_handler; - any_function<void(button&)> event_handler_self; - any_function<void()> button_down_handler; - any_function<void(bool)> button_up_handler; - any_function<void(button&)> button_down_handler_self; - any_function<void(bool,button&)> button_up_handler_self; - - std::unique_ptr<button_style> style; - - protected: - - void draw ( - const canvas& c - ) const { style->draw_button(c,rect,enabled,*mfont,lastx,lasty,name_,is_depressed()); } - - void on_button_up ( - bool mouse_over - ); - - void on_button_down ( - ); - - void on_mouse_over ( - ){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(style->get_invalidation_rect(rect)); } - - void on_mouse_not_over ( - ){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(style->get_invalidation_rect(rect)); } - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class scroll_bar -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class scroll_bar : public drawable - { - /*! - INITIAL VALUE - - ori == a value given by the constructor - - style == a scroll_bar_style_default object - - pos == 0 - - max_pos == 0 - - js == 10 - - CONVENTION - - ori == orientation() - - b1 == the button that is near the 0 end of the scroll bar - - b2 == the button that is near the max_pos() end of the scroll bar - - - max_pos == max_slider_pos() - - pos == slider_pos() - - js == jump_size() - !*/ - - public: - enum bar_orientation - { - HORIZONTAL, - VERTICAL - }; - - scroll_bar( - drawable_window& w, - bar_orientation orientation_ - ); - - virtual ~scroll_bar( - ); - - bar_orientation orientation ( - ) const; - - void set_length ( - unsigned long length - ); - - long max_slider_pos ( - ) const; - - void set_max_slider_pos ( - long mpos - ); - - void set_slider_pos ( - long pos - ); - - long slider_pos ( - ) const; - - template < - typename T - > - void set_scroll_handler ( - T& object, - void (T::*eh)() - ) { auto_mutex M(m); scroll_handler = make_mfp(object,eh); } - - void set_scroll_handler ( - const any_function<void()>& eh - ) { auto_mutex M(m); scroll_handler = eh; } - - void set_pos ( - long x, - long y - ); - - void enable ( - ) - { - auto_mutex M(m); - if (!hidden) - show_slider(); - if (max_pos != 0) - { - b1.enable(); - b2.enable(); - } - drawable::enable(); - } - - void disable ( - ) - { - auto_mutex M(m); - hide_slider(); - b1.disable(); - b2.disable(); - drawable::disable(); - } - - void hide ( - ) - { - auto_mutex M(m); - hide_slider(); - top_filler.hide(); - bottom_filler.hide(); - b1.hide(); - b2.hide(); - drawable::hide(); - } - - void show ( - ) - { - auto_mutex M(m); - b1.show(); - b2.show(); - drawable::show(); - top_filler.show(); - if (enabled) - show_slider(); - } - - void set_z_order ( - long order - ) - { - auto_mutex M(m); - slider.set_z_order(order); - top_filler.set_z_order(order); - bottom_filler.set_z_order(order); - b1.set_z_order(order); - b2.set_z_order(order); - drawable::set_z_order(order); - } - - void set_jump_size ( - long js - ); - - long jump_size ( - ) const; - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ) - { - auto_mutex M(m); - style.reset(new style_type(style_)); - - if (ori == HORIZONTAL) - { - b1.set_style(style_.get_left_button_style()); - b2.set_style(style_.get_right_button_style()); - set_length(rect.width()); - } - else - { - b1.set_style(style_.get_up_button_style()); - b2.set_style(style_.get_down_button_style()); - set_length(rect.height()); - } - - } - - private: - - void hide_slider ( - ); - /*! - ensures - - hides the slider and makes any other changes needed so that the - scroll_bar still looks right. - !*/ - - void show_slider ( - ); - /*! - ensures - - shows the slider and makes any other changes needed so that the - scroll_bar still looks right. - !*/ - - - void on_slider_drag ( - ); - /*! - requires - - is called whenever the user drags the slider - !*/ - - void draw ( - const canvas& c - ) const; - - void b1_down ( - ); - - void b1_up ( - bool mouse_over - ); - - void b2_down ( - ); - - void b2_up ( - bool mouse_over - ); - - void top_filler_down ( - ); - - void top_filler_up ( - bool mouse_over - ); - - void bottom_filler_down ( - ); - - void bottom_filler_up ( - bool mouse_over - ); - - void on_user_event ( - int i - ); - - void delayed_set_slider_pos ( - unsigned long dpos - ); - - void b1_down_t ( - ); - - void b2_down_t ( - ); - - void top_filler_down_t ( - ); - - void bottom_filler_down_t ( - ); - - friend class filler; - class filler : public button_action - { - friend class scroll_bar; - public: - filler ( - drawable_window& w, - scroll_bar& object, - void (scroll_bar::*down)(), - void (scroll_bar::*up)(bool) - ): - button_action(w), - my_scroll_bar(object) - { - bup = make_mfp(object,up); - bdown = make_mfp(object,down); - - enable_events(); - } - - ~filler ( - ) - { - disable_events(); - } - - void set_size ( - unsigned long width, - unsigned long height - ) - { - rectangle old(rect); - const unsigned long x = rect.left(); - const unsigned long y = rect.top(); - rect.set_right(x+width-1); - rect.set_bottom(y+height-1); - - parent.invalidate_rectangle(rect+old); - } - - private: - - void draw ( - const canvas& c - ) const - { - my_scroll_bar.style->draw_scroll_bar_background(c,rect,enabled,lastx,lasty,is_depressed()); - } - - void on_button_down ( - ) { bdown(); } - - void on_button_up ( - bool mouse_over - ) { bup(mouse_over); } - - scroll_bar& my_scroll_bar; - any_function<void()> bdown; - any_function<void(bool)> bup; - }; - - friend class slider_class; - class slider_class : public draggable - { - friend class scroll_bar; - public: - slider_class ( - drawable_window& w, - scroll_bar& object, - void (scroll_bar::*handler)() - ) : - draggable(w, MOUSE_MOVE), - mouse_in_widget(false), - my_scroll_bar(object) - { - callback = make_mfp(object,handler); - enable_events(); - } - - ~slider_class ( - ) - { - disable_events(); - } - - void set_size ( - unsigned long width, - unsigned long height - ) - { - rectangle old(rect); - const unsigned long x = rect.left(); - const unsigned long y = rect.top(); - rect.set_right(x+width-1); - rect.set_bottom(y+height-1); - - parent.invalidate_rectangle(rect+old); - } - - private: - virtual void on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - draggable::on_mouse_move(state,x,y); - if (!hidden && my_scroll_bar.style->redraw_on_mouse_over_slider()) - { - if (rect.contains(x,y) && !mouse_in_widget) - { - mouse_in_widget = true; - parent.invalidate_rectangle(rect); - } - else if (rect.contains(x,y) == false && mouse_in_widget) - { - mouse_in_widget = false; - parent.invalidate_rectangle(rect); - } - } - } - - void on_mouse_leave ( - ) - { - if (mouse_in_widget && my_scroll_bar.style->redraw_on_mouse_over_slider()) - { - mouse_in_widget = false; - parent.invalidate_rectangle(rect); - } - } - - void on_drag_stop ( - ) - { - if (my_scroll_bar.style->redraw_on_mouse_over_slider()) - parent.invalidate_rectangle(rect); - } - - void on_drag ( - ) - { - callback(); - } - - void draw ( - const canvas& c - ) const - { - my_scroll_bar.style->draw_scroll_bar_slider(c,rect,enabled,lastx,lasty, is_being_dragged()); - } - - bool mouse_in_widget; - scroll_bar& my_scroll_bar; - any_function<void()> callback; - }; - - - void adjust_fillers ( - ); - /*! - ensures - - top_filler and bottom_filler appear in their correct positions - relative to the current positions of the slider and the b1 and - b2 buttons - !*/ - - unsigned long get_slider_size ( - ) const; - /*! - ensures - - returns the length in pixels the slider should have based on the current - state of this scroll bar - !*/ - - - button b1, b2; - slider_class slider; - bar_orientation ori; - filler top_filler, bottom_filler; - any_function<void()> scroll_handler; - - long pos; - long max_pos; - long js; - - timer<scroll_bar> b1_timer; - timer<scroll_bar> b2_timer; - timer<scroll_bar> top_filler_timer; - timer<scroll_bar> bottom_filler_timer; - long delayed_pos; - std::unique_ptr<scroll_bar_style> style; - - // restricted functions - scroll_bar(scroll_bar&); // copy constructor - scroll_bar& operator=(scroll_bar&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class popup_menu -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class menu_item - { - public: - virtual ~menu_item() {} - - virtual rectangle get_left_size ( - ) const { return rectangle(); } - virtual rectangle get_middle_size ( - ) const = 0; - virtual rectangle get_right_size ( - ) const { return rectangle(); } - - virtual unichar get_hot_key ( - ) const { return 0; } - - virtual void draw_background ( - const canvas& , - const rectangle& , - const bool , - const bool - ) const {} - - virtual void draw_left ( - const canvas& , - const rectangle& , - const bool , - const bool - ) const {} - - virtual void draw_middle ( - const canvas& , - const rectangle& , - const bool , - const bool - ) const = 0; - - virtual void draw_right ( - const canvas& , - const rectangle& , - const bool , - const bool - ) const {} - - virtual void on_click ( - ) const {} - - virtual bool has_click_event ( - ) const { return false; } - - }; - -// ---------------------------------------------------------------------------------------- - - class menu_item_submenu : public menu_item - { - void initialize ( - unichar hk - ) - { - const dlib::ustring &str = text; - if (hk != 0) - { - std::string::size_type pos = str.find_first_of(hk); - if (pos != std::string::npos) - { - // now compute the location of the underline bar - rectangle r1 = f->compute_cursor_rect( rectangle(100000,100000), str, pos); - rectangle r2 = f->compute_cursor_rect( rectangle(100000,100000), str, pos+1); - - underline_p1.x() = r1.left()+1; - underline_p2.x() = r2.left()-1; - underline_p1.y() = r1.bottom()-f->height()+f->ascender()+2; - underline_p2.y() = r2.bottom()-f->height()+f->ascender()+2; - } - } - } - public: - menu_item_submenu ( - const std::string& str, - unichar hk = 0 - ) : - text(convert_wstring_to_utf32(convert_mbstring_to_wstring(str))), - f(default_font::get_font()), - hotkey(hk) - { - initialize(hk); - } - - menu_item_submenu ( - const std::wstring& str, - unichar hk = 0 - ) : - text(convert_wstring_to_utf32(str)), - f(default_font::get_font()), - hotkey(hk) - { - initialize(hk); - } - - menu_item_submenu ( - const dlib::ustring& str, - unichar hk = 0 - ) : - text(str), - f(default_font::get_font()), - hotkey(hk) - { - initialize(hk); - } - - virtual unichar get_hot_key ( - ) const { return hotkey; } - - virtual rectangle get_middle_size ( - ) const - { - unsigned long width, height; - f->compute_size(text,width,height); - return rectangle(width+30,height); - } - - virtual rectangle get_right_size ( - ) const - { - return rectangle(15, 5); - } - - virtual void draw_background ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool is_selected - ) const - { - if (c.intersect(rect).is_empty()) - return; - - if (enabled && is_selected) - { - fill_rect_with_vertical_gradient(c, rect,rgb_alpha_pixel(0,200,0,100), rgb_alpha_pixel(0,0,0,100)); - draw_rectangle(c, rect,rgb_alpha_pixel(0,0,0,100)); - } - } - - virtual void draw_right ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool - ) const - { - if (c.intersect(rect).is_empty()) - return; - - unsigned char color = 0; - - if (enabled == false) - color = 128; - - long x, y; - x = rect.right() - 7; - y = rect.top() + rect.height()/2; - - for ( unsigned long i = 0; i < 5; ++i) - draw_line (c, point(x - i, y + i), point(x - i, y - i), color); - } - - virtual void draw_middle ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool - ) const - { - if (c.intersect(rect).is_empty()) - return; - - if (enabled) - { - f->draw_string(c,rect,text); - } - else - { - f->draw_string(c,rect,text,128); - } - - if (underline_p1 != underline_p2) - { - point base(rect.left(),rect.top()); - draw_line(c, base+underline_p1, base+underline_p2); - } - } - - private: - dlib::ustring text; - const std::shared_ptr<font> f; - any_function<void()> action; - unichar hotkey; - point underline_p1; - point underline_p2; - }; - -// ---------------------------------------------------------------------------------------- - - class menu_item_text : public menu_item - { - void initialize ( - const any_function<void()>& event_handler_, - unichar hk - ) - { - dlib::ustring &str = text; - action = event_handler_; - - if (hk != 0) - { - std::string::size_type pos = str.find_first_of(hk); - if (pos != std::string::npos) - { - // now compute the location of the underline bar - rectangle r1 = f->compute_cursor_rect( rectangle(100000,100000), str, pos); - rectangle r2 = f->compute_cursor_rect( rectangle(100000,100000), str, pos+1); - - underline_p1.x() = r1.left()+1; - underline_p2.x() = r2.left()-1; - underline_p1.y() = r1.bottom()-f->height()+f->ascender()+2; - underline_p2.y() = r2.bottom()-f->height()+f->ascender()+2; - } - } - } - - public: - template <typename T> - menu_item_text ( - const std::string& str, - T& object, - void (T::*event_handler_)(), - unichar hk = 0 - ) : - text(convert_wstring_to_utf32(convert_mbstring_to_wstring(str))), - f(default_font::get_font()), - hotkey(hk) - { - initialize(make_mfp(object, event_handler_), hk); - } - - menu_item_text ( - const std::string& str, - const any_function<void()>& event_handler_, - unichar hk = 0 - ) : - text(convert_wstring_to_utf32(convert_mbstring_to_wstring(str))), - f(default_font::get_font()), - hotkey(hk) - { - initialize(event_handler_, hk); - } - - template <typename T> - menu_item_text ( - const std::wstring& str, - T& object, - void (T::*event_handler_)(), - unichar hk = 0 - ) : - text(convert_wstring_to_utf32(str)), - f(default_font::get_font()), - hotkey(hk) - { - initialize(make_mfp(object, event_handler_), hk); - } - - menu_item_text ( - const std::wstring& str, - const any_function<void()>& event_handler_, - unichar hk = 0 - ) : - text(convert_wstring_to_utf32(str)), - f(default_font::get_font()), - hotkey(hk) - { - initialize(event_handler_, hk); - } - - template <typename T> - menu_item_text ( - const dlib::ustring& str, - T& object, - void (T::*event_handler_)(), - unichar hk = 0 - ) : - text(str), - f(default_font::get_font()), - hotkey(hk) - { - initialize(make_mfp(object, event_handler_), hk); - } - - menu_item_text ( - const dlib::ustring& str, - const any_function<void()>& event_handler_, - unichar hk = 0 - ) : - text(str), - f(default_font::get_font()), - hotkey(hk) - { - initialize(event_handler_, hk); - } - - virtual unichar get_hot_key ( - ) const { return hotkey; } - - virtual rectangle get_middle_size ( - ) const - { - unsigned long width, height; - f->compute_size(text,width,height); - return rectangle(width,height); - } - - virtual void draw_background ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool is_selected - ) const - { - if (c.intersect(rect).is_empty()) - return; - - if (enabled && is_selected) - { - fill_rect_with_vertical_gradient(c, rect,rgb_alpha_pixel(0,200,0,100), rgb_alpha_pixel(0,0,0,100)); - draw_rectangle(c, rect,rgb_alpha_pixel(0,0,0,100)); - } - } - - virtual void draw_middle ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool - ) const - { - if (c.intersect(rect).is_empty()) - return; - - unsigned char color = 0; - - if (enabled == false) - color = 128; - - f->draw_string(c,rect,text,color); - - if (underline_p1 != underline_p2) - { - point base(rect.left(),rect.top()); - draw_line(c, base+underline_p1, base+underline_p2, color); - } - } - - virtual void on_click ( - ) const - { - action(); - } - - virtual bool has_click_event ( - ) const { return true; } - - private: - dlib::ustring text; - const std::shared_ptr<font> f; - any_function<void()> action; - unichar hotkey; - point underline_p1; - point underline_p2; - }; - -// ---------------------------------------------------------------------------------------- - - class menu_item_separator : public menu_item - { - public: - virtual rectangle get_middle_size ( - ) const - { - return rectangle(10,4); - } - - virtual void draw_background ( - const canvas& c, - const rectangle& rect, - const bool , - const bool - ) const - { - if (c.intersect(rect).is_empty()) - return; - - point p1(rect.left(),rect.top()+rect.height()/2-1); - point p2(rect.right(),rect.top()+rect.height()/2-1); - - point p3(rect.left(),rect.top()+rect.height()/2); - point p4(rect.right(),rect.top()+rect.height()/2); - draw_line(c, p1,p2,128); - draw_line(c, p3,p4,255); - } - - virtual void draw_middle ( - const canvas& , - const rectangle& , - const bool , - const bool - ) const - { - } - }; - -// ---------------------------------------------------------------------------------------- - - class popup_menu : public base_window - { - /*! - INITIAL VALUE - - pad == 2 - - item_pad == 3 - - cur_rect == rectangle(pad,pad,pad-1,pad-1) - - left_width == 0 - - middle_width == 0 - - selected_item == 0 - - submenu_open == false - - items.size() == 0 - - item_enabled.size() == 0 - - left_rects.size() == 0 - - middle_rects.size() == 0 - - right_rects.size() == 0 - - line_rects.size() == 0 - - submenus.size() == 0 - - hide_handlers.size() == 0 - - CONVENTION - - pad = 2 - - item_pad = 3 - - all of the following arrays have the same size: - - items.size() - - item_enabled.size() - - left_rects.size() - - middle_rects.size() - - right_rects.size() - - line_rects.size() - - submenus.size() - - - win_rect == a rectangle that is the exact size of this window and with - its upper left corner at (0,0) - - cur_rect == the rect inside which all the menu items are drawn - - - if (a menu_item is supposed to be selected) then - - selected_item == the index in menus of the menu_item - - else - - selected_item == submenus.size() - - - if (there is a selected submenu and it is currently open) then - - submenu_open == true - - else - - submenu_open == false - - - for all valid i: - - items[i] == a pointer to the ith menu_item - - item_enabled[i] == true if the ith menu_item is enabled, false otherwise - - left_rects[i] == the left rectangle for the ith menu item - - middle_rects[i] == the middle rectangle for the ith menu item - - right_rects[i] == the right rectangle for the ith menu item - - line_rects[i] == the rectangle for the entire line on which the ith menu - item appears. - - if (submenus[i] != 0) then - - the ith menu item has a submenu and it is pointed to by submenus[i] - - - hide_handlers == an array of all the on_hide events registered for - this popup_menu - !*/ - - public: - - popup_menu ( - ); - - template < - typename menu_item_type - > - unsigned long add_menu_item ( - const menu_item_type& new_item - ) - { - auto_mutex M(wm); - bool t = true; - std::unique_ptr<menu_item> item(new menu_item_type(new_item)); - items.push_back(item); - item_enabled.push_back(t); - - // figure out how big the window should be now and what not - rectangle left = new_item.get_left_size(); - rectangle middle = new_item.get_middle_size(); - rectangle right = new_item.get_right_size(); - - bool recalc_rect_positions = false; - const rectangle all = left+middle+right; - - - // make sure left_width contains the max of all the left rectangles - if (left.width() > left_width) - { - left_width = left.width(); - recalc_rect_positions = true; - } - // make sure middle_width contains the max of all the middle rectangles - if (middle.width() > middle_width) - { - middle_width = middle.width(); - recalc_rect_positions = true; - } - - // make the current rectangle wider if necessary - if (cur_rect.width() < left_width + middle_width + right.width() + 2*item_pad) - { - cur_rect = resize_rect_width(cur_rect, left_width + middle_width + right.width() + 2*item_pad); - recalc_rect_positions = true; - } - - const long y = cur_rect.bottom()+1 + item_pad; - const long x = cur_rect.left() + item_pad; - - // make the current rectangle taller to account for this new menu item - cur_rect.set_bottom(cur_rect.bottom()+all.height() + 2*item_pad); - - // adjust all the saved rectangles since the width of the window changed - // or left_width changed - if (recalc_rect_positions) - { - long y = cur_rect.top() + item_pad; - for (unsigned long i = 0; i < left_rects.size(); ++i) - { - middle_rects[i] = move_rect(middle_rects[i], x+left_width, y); - right_rects[i] = move_rect(right_rects[i], x+cur_rect.width()-right_rects[i].width()-item_pad, y); - line_rects[i] = resize_rect_width(line_rects[i], cur_rect.width()); - - y += line_rects[i].height(); - } - } - - // save the rectangles for later use. Also position them at the - // right spots - left = move_rect(left,x,y); - middle = move_rect(middle,x+left_width,y); - right = move_rect(right,x+cur_rect.width()-right.width()-item_pad,y); - rectangle line(move_rect(rectangle(cur_rect.width(),all.height()+2*item_pad), x-item_pad, y-item_pad)); - - // make sure the left, middle, and right rectangles are centered in the - // line. - if (left.height() < all.height()) - left = translate_rect(left,0, (all.height()-left.height())/2); - if (middle.height() < all.height()) - middle = translate_rect(middle,0, (all.height()-middle.height())/2); - if (right.height() < all.height()) - right = translate_rect(right,0, (all.height()-right.height())/2); - - left_rects.push_back(left); - middle_rects.push_back(middle); - right_rects.push_back(right); - line_rects.push_back(line); - - popup_menu* junk = 0; - submenus.push_back(junk); - - win_rect.set_right(cur_rect.right()+pad); - win_rect.set_bottom(cur_rect.bottom()+pad); - set_size(win_rect.width(),win_rect.height()); - - // make it so that nothing is selected - selected_item = submenus.size(); - - return items.size()-1; - } - - template < - typename menu_item_type - > - unsigned long add_submenu ( - const menu_item_type& new_item, - popup_menu& submenu - ) - { - auto_mutex M(wm); - - submenus[add_menu_item(new_item)] = &submenu; - - submenu.set_on_hide_handler(*this,&popup_menu::on_submenu_hide); - - return items.size()-1; - } - - void enable_menu_item ( - unsigned long idx - ); - - void disable_menu_item ( - unsigned long idx - ); - - size_t size ( - ) const; - - void clear ( - ); - - void show ( - ); - - void hide ( - ); - - template <typename T> - void set_on_hide_handler ( - T& object, - void (T::*event_handler)() - ) - { - auto_mutex M(wm); - - member_function_pointer<> temp; - temp.set(object,event_handler); - - // if this handler isn't already registered then add it - bool found_handler = false; - for (unsigned long i = 0; i < hide_handlers.size(); ++i) - { - if (hide_handlers[i] == temp) - { - found_handler = true; - break; - } - } - - if (found_handler == false) - { - hide_handlers.push_back(temp); - } - } - - void select_first_item ( - ); - - bool forwarded_on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - - private: - - void on_submenu_hide ( - ); - - void on_window_resized( - ); - - void on_mouse_up ( - unsigned long btn, - unsigned long, - long x, - long y - ); - - void on_mouse_move ( - unsigned long state, - long x, - long y - ); - - void close_submenu ( - ); - - bool display_selected_submenu ( - ); - /*! - ensures - - if (submenus[selected_item] isn't null) then - - displays the selected submenu - - returns true - - else - - returns false - !*/ - - void on_mouse_leave ( - ); - - void paint ( - const canvas& c - ); - - const long pad; - const long item_pad; - rectangle cur_rect; - rectangle win_rect; - unsigned long left_width; - unsigned long middle_width; - array<std::unique_ptr<menu_item> > items; - array<bool> item_enabled; - array<rectangle> left_rects; - array<rectangle> middle_rects; - array<rectangle> right_rects; - array<rectangle> line_rects; - array<popup_menu*> submenus; - unsigned long selected_item; - bool submenu_open; - array<member_function_pointer<> > hide_handlers; - - // restricted functions - popup_menu(popup_menu&); // copy constructor - popup_menu& operator=(popup_menu&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - - class zoomable_region : public drawable - { - /*! - INITIAL VALUE - - min_scale == 0.15 - - max_scale == 1.0 - - zoom_increment_ == 0.02 - - scale == 1.0 - - mouse_drag_screen == false - - - CONVENTION - - zoom_increment() == zoom_increment_ - - min_zoom_scale() == min_scale - - max_zoom_scale() == max_scale - - zoom_scale() == scale - - if (the user is currently dragging the graph around via the mouse) then - - mouse_drag_screen == true - - else - - mouse_drag_screen == false - - - max_graph_point() == lr_point - - display_rect() == display_rect_ - - gui_to_graph_space(point(display_rect.left(),display_rect.top())) == gr_orig - !*/ - - public: - - zoomable_region ( - drawable_window& w, - unsigned long events = 0 - ); - - virtual ~zoomable_region ( - )= 0; - - virtual void set_pos ( - long x, - long y - ); - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ) - { - auto_mutex M(m); - style.reset(new style_type(style_)); - hsb.set_style(style_.get_horizontal_scroll_bar_style()); - vsb.set_style(style_.get_vertical_scroll_bar_style()); - - // do this just so that everything gets redrawn right - set_size(rect.width(), rect.height()); - } - - void set_zoom_increment ( - double zi - ); - - double zoom_increment ( - ) const; - - void set_max_zoom_scale ( - double ms - ); - - void set_min_zoom_scale ( - double ms - ); - - double min_zoom_scale ( - ) const; - - double max_zoom_scale ( - ) const; - - virtual void set_size ( - unsigned long width, - unsigned long height - ); - - void show ( - ); - - void hide ( - ); - - void enable ( - ); - - void disable ( - ); - - void set_z_order ( - long order - ); - - protected: - - virtual void on_view_changed () {} - - point graph_to_gui_space ( - const vector<double,2>& p - ) const; - - vector<double,2> gui_to_graph_space ( - const point& p - ) const; - - point max_graph_point ( - ) const; - - rectangle display_rect ( - ) const; - - double zoom_scale ( - ) const; - - void set_zoom_scale ( - double new_scale - ); - - void center_display_at_graph_point ( - const vector<double,2>& p - ); - - // ----------- event handlers --------------- - - void on_wheel_down ( - unsigned long state - ); - - void on_wheel_up ( - unsigned long state - ); - - void on_mouse_move ( - unsigned long state, - long x, - long y - ); - - void on_mouse_up ( - unsigned long btn, - unsigned long state, - long x, - long y - ); - - void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ); - - void draw ( - const canvas& c - ) const; - - private: - - void on_h_scroll ( - ); - - void on_v_scroll ( - ); - - void redraw_graph ( - ); - - void adjust_origin ( - const point& gui_p, - const vector<double,2>& graph_p - ); - /*! - ensures - - adjusts gr_orig so that we are as close to the following as possible: - - graph_to_gui_space(graph_p) == gui_p - - gui_to_graph_space(gui_p) == graph_p - !*/ - - - vector<double,2> gr_orig; // point in graph space such that it's gui space point is the upper left of display_rect_ - vector<double,2> lr_point; // point in graph space such that it is at the lower right corner of the screen at max zoom - - mutable std::ostringstream sout; - - double scale; // 0 < scale <= 1 - double min_scale; - double max_scale; - double zoom_increment_; - rectangle display_rect_; - - bool mouse_drag_screen; // true if the user is dragging the white background area - vector<double,2> drag_screen_point; // the starting point the mouse was at in graph space for the background area drag - - scroll_bar vsb; - scroll_bar hsb; - - std::unique_ptr<scrollable_region_style> style; - - // restricted functions - zoomable_region(zoomable_region&); // copy constructor - zoomable_region& operator=(zoomable_region&); // assignment operator - - }; - -// ---------------------------------------------------------------------------------------- - - class scrollable_region : public drawable - { - /*! - INITIAL VALUE - - hscroll_bar_inc == 1 - - vscroll_bar_inc == 1 - - h_wheel_scroll_bar_inc == 1 - - v_wheel_scroll_bar_inc == 1 - - mouse_drag_enabled_ == false - - user_is_dragging_mouse == false - - CONVENTION - - mouse_drag_enabled() == mouse_drag_enabled_ - - horizontal_scroll_increment() == hscroll_bar_inc - - vertical_scroll_increment() == vscroll_bar_inc - - horizontal_mouse_wheel_scroll_increment() == h_wheel_scroll_bar_inc - - vertical_mouse_wheel_scroll_increment() == v_wheel_scroll_bar_inc - - vertical_scroll_pos() == vsb.slider_pos() - - horizontal_scroll_pos() == hsb.slider_pos() - - total_rect() == total_rect_ - - display_rect() == display_rect_ - - - if (the user is currently dragging the total_rect around with a mouse drag) then - - user_is_dragging_mouse == true - - drag_origin == the point the mouse was at, with respect to total_rect, - when the dragging started - - else - - user_is_dragging_mouse == false - !*/ - - public: - - scrollable_region ( - drawable_window& w, - unsigned long events = 0 - ); - - virtual ~scrollable_region ( - ) = 0; - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ) - { - auto_mutex M(m); - style.reset(new style_type(style_)); - hsb.set_style(style_.get_horizontal_scroll_bar_style()); - vsb.set_style(style_.get_vertical_scroll_bar_style()); - - // do this just so that everything gets redrawn right - set_size(rect.width(), rect.height()); - } - - void show ( - ); - - void hide ( - ); - - void enable ( - ); - - void disable ( - ); - - void set_z_order ( - long order - ); - - virtual void set_size ( - unsigned long width, - unsigned long height - ); - - unsigned long horizontal_mouse_wheel_scroll_increment ( - ) const; - - unsigned long vertical_mouse_wheel_scroll_increment ( - ) const; - - void set_horizontal_mouse_wheel_scroll_increment ( - unsigned long inc - ); - - void set_vertical_mouse_wheel_scroll_increment ( - unsigned long inc - ); - - unsigned long horizontal_scroll_increment ( - ) const; - - unsigned long vertical_scroll_increment ( - ) const; - - void set_horizontal_scroll_increment ( - unsigned long inc - ); - - void set_vertical_scroll_increment ( - unsigned long inc - ); - - long horizontal_scroll_pos ( - ) const; - - long vertical_scroll_pos ( - ) const; - - void set_horizontal_scroll_pos ( - long pos - ); - - void set_vertical_scroll_pos ( - long pos - ); - - virtual void set_pos ( - long x, - long y - ); - - bool mouse_drag_enabled ( - ) const; - - void enable_mouse_drag ( - ); - - void disable_mouse_drag ( - ); - - protected: - - virtual void on_view_changed () {} - - const rectangle& display_rect ( - ) const; - - void set_total_rect_size ( - unsigned long width, - unsigned long height - ); - - const rectangle& total_rect ( - ) const; - - void scroll_to_rect ( - const rectangle& r_ - ); - - void on_wheel_down ( - unsigned long state - ); - - void on_mouse_move ( - unsigned long state, - long x, - long y - ); - - 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_wheel_up ( - unsigned long state - ); - - void draw ( - const canvas& c - ) const; - - private: - - bool need_h_scroll ( - ) const; - - bool need_v_scroll ( - ) const; - - void on_h_scroll ( - ); - - void on_v_scroll ( - ); - - rectangle total_rect_; - rectangle display_rect_; - scroll_bar hsb; - scroll_bar vsb; - unsigned long hscroll_bar_inc; - unsigned long vscroll_bar_inc; - unsigned long h_wheel_scroll_bar_inc; - unsigned long v_wheel_scroll_bar_inc; - bool mouse_drag_enabled_; - bool user_is_dragging_mouse; - point drag_origin; - std::unique_ptr<scrollable_region_style> style; - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class popup_menu_region -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class popup_menu_region : public drawable - { - /*! - CONVENTION - popup_menu_visible() == popup_menu_shown - !*/ - - public: - - popup_menu_region( - drawable_window& w - ); - - virtual ~popup_menu_region( - ); - - void set_size ( - unsigned long width, - unsigned long height - ); - - void set_rect ( - const rectangle& new_rect - ); - - popup_menu& menu ( - ); - - void hide ( - ); - - void disable ( - ); - - bool popup_menu_visible ( - ) const { auto_mutex M(m); return popup_menu_shown; } - - protected: - - void on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - - void on_focus_lost ( - ); - - void on_focus_gained ( - ); - - void on_window_moved( - ); - - void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ); - - void on_menu_becomes_hidden ( - ); - - void draw ( - const canvas& - ) const; - - private: - - popup_menu menu_; - bool popup_menu_shown; - - // restricted functions - popup_menu_region(popup_menu_region&); // copy constructor - popup_menu_region& operator=(popup_menu_region&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - -} - -#ifdef NO_MAKEFILE -#include "base_widgets.cpp" -#endif - -#endif // DLIB_BASE_WIDGETs_ - diff --git a/ml/dlib/dlib/gui_widgets/base_widgets_abstract.h b/ml/dlib/dlib/gui_widgets/base_widgets_abstract.h deleted file mode 100644 index 3dcee0d5a..000000000 --- a/ml/dlib/dlib/gui_widgets/base_widgets_abstract.h +++ /dev/null @@ -1,2290 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_BASE_WIDGETs_ABSTRACT_ -#ifdef DLIB_BASE_WIDGETs_ABSTRACT_ - -#include "fonts_abstract.h" -#include "drawable_abstract.h" - -#include "../gui_core.h" -#include <string> - -namespace dlib -{ - - /*! - GENERAL REMARKS - This file contains objects that are useful for creating complex drawable - widgets. - - THREAD SAFETY - All objects and functions defined in this file are thread safe. You may - call them from any thread without serializing access to them. - - EVENT HANDLERS - If you derive from any of the drawable objects and redefine any of the on_*() - event handlers then you should ensure that your version calls the same event - handler in the base object so that the base class part of your object will also - be able to process the event. - - Also note that all event handlers, including the user registered callback - functions, are executed in the event handling thread. Additionally, - the drawable::m mutex will always be locked while these event handlers - are running. Also, don't rely on get_thread_id() always returning the - same ID from inside event handlers. - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class draggable -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class draggable : public drawable - { - /*! - INITIAL VALUE - draggable_area() == an initial value for its type - - WHAT THIS OBJECT REPRESENTS - This object represents a drawable object that is draggable by the mouse. - You use it by inheriting from it and defining the draw() method and any - of the on_*() event handlers you need. - - This object is draggable by the user when is_enabled() == true and - not draggable otherwise. - !*/ - - public: - - draggable( - drawable_window& w, - unsigned long events = 0 - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - - This object will not receive any events or draw() requests until - enable_events() is called - - the events flags are passed on to the drawable object's - constructor. - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~draggable( - ) = 0; - /*! - ensures - - all resources associated with *this have been released - !*/ - - rectangle draggable_area ( - ) const; - /*! - ensures - - returns the area that this draggable can be dragged around in. - !*/ - - void set_draggable_area ( - const rectangle& area - ); - /*! - ensures - - #draggable_area() == area - !*/ - - protected: - - bool is_being_dragged ( - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - if (this widget is currently being dragged by the user) then - - returns true - - else - - returns false - !*/ - - // does nothing by default - virtual void on_drag ( - ){} - /*! - requires - - enable_events() has been called - - is_enabled() == true - - is_hidden() == false - - mutex drawable::m is locked - - is called when the user drags this object - - get_rect() == the rectangle that defines the new position - of this object. - - is_being_dragged() == true - ensures - - does not change the state of mutex drawable::m. - !*/ - - // does nothing by default - virtual void on_drag_stop ( - ){} - /*! - requires - - enable_events() has been called - - mutex drawable::m is locked - - is called when the user stops dragging this object - - is_being_dragged() == false - ensures - - does not change the state of mutex drawable::m. - !*/ - - private: - - // restricted functions - draggable(draggable&); // copy constructor - draggable& operator=(draggable&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class mouse_over_event -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class mouse_over_event : public drawable - { - /*! - INITIAL VALUE - is_mouse_over() == false - - WHAT THIS OBJECT REPRESENTS - This object represents a drawable object with the addition of two events - that will alert you when the mouse enters or leaves your drawable object. - - You use it by inheriting from it and defining the draw() method and any - of the on_*() event handlers you need. - !*/ - - public: - - mouse_over_event( - drawable_window& w, - unsigned long events = 0 - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - - #*this will not receive any events or draw() requests until - enable_events() is called - - the events flags are passed on to the drawable object's - constructor. - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~mouse_over_event( - ) = 0; - /*! - ensures - - all resources associated with *this have been released - !*/ - - protected: - - bool is_mouse_over ( - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - if (the mouse is currently over this widget) then - - returns true - - else - - returns false - !*/ - - // does nothing by default - virtual void on_mouse_over ( - ){} - /*! - requires - - enable_events() has been called - - mutex drawable::m is locked - - is_enabled() == true - - is_hidden() == false - - is called whenever this object transitions from the state where - is_mouse_over() == false to is_mouse_over() == true - ensures - - does not change the state of mutex drawable::m. - !*/ - - // does nothing by default - virtual void on_mouse_not_over ( - ){} - /*! - requires - - enable_events() has been called - - mutex drawable::m is locked - - is called whenever this object transitions from the state where - is_mouse_over() == true to is_mouse_over() == false - ensures - - does not change the state of mutex drawable::m. - !*/ - - private: - - // restricted functions - mouse_over_event(mouse_over_event&); // copy constructor - mouse_over_event& operator=(mouse_over_event&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class button_action -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class button_action : public mouse_over_event - { - /*! - INITIAL VALUE - is_depressed() == false - - WHAT THIS OBJECT REPRESENTS - This object represents the clicking action of a push button. It provides - simple callbacks that can be used to make various kinds of button - widgets. - - You use it by inheriting from it and defining the draw() method and any - of the on_*() event handlers you need. - !*/ - - public: - - button_action( - drawable_window& w, - unsigned long events = 0 - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - - #*this will not receive any events or draw() requests until - enable_events() is called - - the events flags are passed on to the drawable object's - constructor. - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~button_action( - ) = 0; - /*! - ensures - - all resources associated with *this have been released - !*/ - - protected: - - bool is_depressed ( - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - if (this button is currently in a depressed state) then - - the user has left clicked on this drawable and is still - holding the left mouse button down over it. - - returns true - - else - - returns false - !*/ - - // does nothing by default - virtual void on_button_down ( - ){} - /*! - requires - - enable_events() has been called - - mutex drawable::m is locked - - is_enabled() == true - - is_hidden() == false - - the area in parent_window() defined by get_rect() has been invalidated. - (This means you don't have to call invalidate_rectangle()) - - is called whenever this object transitions from the state where - is_depressed() == false to is_depressed() == true - ensures - - does not change the state of mutex drawable::m. - !*/ - - // does nothing by default - virtual void on_button_up ( - bool mouse_over - ){} - /*! - requires - - enable_events() has been called - - mutex drawable::m is locked - - the area in parent_window() defined by get_rect() has been invalidated. - (This means you don't have to call invalidate_rectangle()) - - is called whenever this object transitions from the state where - is_depressed() == true to is_depressed() == false - - if (the mouse was over this button when this event occurred) then - - mouse_over == true - - else - - mouse_over == false - ensures - - does not change the state of mutex drawable::m. - !*/ - - private: - - // restricted functions - button_action(button_action&); // copy constructor - button_action& operator=(button_action&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class button -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class button : public button_action - { - /*! - INITIAL VALUE - name() == "" - tooltip_text() == "" (i.e. there is no tooltip by default) - - WHAT THIS OBJECT REPRESENTS - This object represents a simple button. - - When this object is disabled it means it will not respond to user clicks. - !*/ - - public: - - button( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~button( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_size ( - unsigned long width_, - unsigned long height_ - ); - /*! - ensures - - if (width and height are big enough to contain the name of this button) then - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this button stays the - same but its width and height are modified - !*/ - - void set_name (const std::wstring& name); - void set_name (const dlib::ustring& name); - void set_name ( - const std::string& name - ); - /*! - ensures - - #name() == name - - this button has been resized such that it is big enough to contain - the new name. - throws - - std::bad_alloc - !*/ - - const std::wstring wname () const; - const dlib::string uname () const; - const std::string name ( - ) const; - /*! - ensures - - returns the name of this button - throws - - std::bad_alloc - !*/ - - void set_tooltip_text (const std::wstring& text); - void set_tooltip_text (const dlib::ustring& text); - void set_tooltip_text ( - const std::string& text - ); - /*! - ensures - - #tooltip_text() == text - - enables the tooltip for this button - !*/ - - const dlib::ustring tooltip_utext () const; - const std::wstring tooltip_wtext () const; - const std::string tooltip_text ( - ) const; - /*! - ensures - - returns the text that is displayed in the tooltip for this button - !*/ - - bool is_depressed ( - ) const; - /*! - ensures - - if (this button is currently in a depressed state) then - - the user has left clicked on this widget and is still - holding the left mouse button down over it. - - returns true - - else - - returns false - !*/ - - template < - typename style_type - > - void set_style ( - const style_type& style - ); - /*! - requires - - style_type == a type that inherits from button_style - ensures - - this button object will draw itself using the given - button style - !*/ - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the button is - clicked by the user. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_click_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when the button is clicked by - the user. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler)(button& self) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - &self == this - - the event_handler function is called on object when the button is - clicked by the user. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_sourced_click_handler ( - const any_function<void(button& self)>& event_handler - ); - /*! - ensures - - &self == this - - the event_handler function is called when the button is clicked by - the user. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_button_down_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the user causes - the button to go into its depressed state. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_button_down_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when the user causes the button - to go into its depressed state. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_button_up_handler ( - T& object, - void (T::*event_handler)(bool mouse_over) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the user causes - the button to go into its non-depressed state. - - if (the mouse is over this button when this event occurs) then - - mouse_over == true - - else - - mouse_over == false - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_button_up_handler ( - const any_function<void(bool mouse_over)>& event_handler - ); - /*! - ensures - - the event_handler function is called when the user causes the - button to go into its non-depressed state. - - if (the mouse is over this button when this event occurs) then - - mouse_over == true - - else - - mouse_over == false - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_button_down_handler ( - T& object, - void (T::*event_handler)(button& self) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - &self == this - - the event_handler function is called on object when the user causes - the button to go into its depressed state. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_sourced_button_down_handler ( - const any_function<void(button& self)>& event_handler - ); - /*! - ensures - - &self == this - - the event_handler function is called when the user causes the button - to go into its depressed state. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_button_up_handler ( - T& object, - void (T::*event_handler)(bool mouse_over, button& self) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - &self == this - - the event_handler function is called on object when the user causes - the button to go into its non-depressed state. - - if (the mouse is over this button when this event occurs) then - - mouse_over == true - - else - - mouse_over == false - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_sourced_button_up_handler ( - const any_function<void(bool mouse_over, button& self)>& event_handler - ); - /*! - ensures - - &self == this - - the event_handler function is called when the user causes the - button to go into its non-depressed state. - - if (the mouse is over this button when this event occurs) then - - mouse_over == true - - else - - mouse_over == false - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - button(button&); // copy constructor - button& operator=(button&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class scroll_bar -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class scroll_bar : public drawable - { - /*! - INITIAL VALUE - orientation() == a value given to the constructor. - max_slider_pos() == 0 - slider_pos() == 0 - jump_size() == 10 - - WHAT THIS OBJECT REPRESENTS - This object represents a scroll bar. The slider_pos() of the scroll bar - ranges from 0 to max_slider_pos(). The 0 position of the scroll_bar is - in the top or left side of the scroll_bar depending on its orientation. - - When this object is disabled it means it will not respond to user clicks. - !*/ - - public: - enum bar_orientation - { - HORIZONTAL, - VERTICAL - }; - - scroll_bar( - drawable_window& w, - bar_orientation orientation - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #orientation() == orientation - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~scroll_bar( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - bar_orientation orientation ( - ) const; - /*! - ensures - - returns the orientation of this scroll_bar - !*/ - - template < - typename style_type - > - void set_style ( - const style_type& style - ); - /*! - requires - - style_type == a type that inherits from scroll_bar_style - ensures - - this scroll_bar object will draw itself using the given - scroll bar style - !*/ - - void set_length ( - unsigned long length, - ); - /*! - ensures - - if (orientation() == HORIZONTAL) then - - #width() == max(length,1) - - else - - #height() == max(length,1) - !*/ - - long max_slider_pos ( - ) const; - /*! - ensures - - returns the maximum value that slider_pos() can take. - !*/ - - void set_max_slider_pos ( - long mpos - ); - /*! - ensures - - if (mpos < 0) then - - #max_slider_pos() == 0 - - else - - #max_slider_pos() == mpos - - if (slider_pos() > #max_slider_pos()) then - - #slider_pos() == #max_slider_pos() - - else - - #slider_pos() == slider_pos() - !*/ - - void set_slider_pos ( - unsigned long pos - ); - /*! - ensures - - if (pos < 0) then - - #slider_pos() == 0 - - else if (pos > max_slider_pos()) then - - #slider_pos() == max_slider_pos() - - else - - #slider_pos() == pos - !*/ - - long slider_pos ( - ) const; - /*! - ensures - - returns the current position of the slider box within the scroll bar. - !*/ - - long jump_size ( - ) const; - /*! - ensures - - returns the number of positions that the slider bar will jump when the - user clicks on the empty gaps above or below the slider bar. - (note that the slider will jump less than the jump size if it hits the - end of the scroll bar) - !*/ - - void set_jump_size ( - long js - ); - /*! - ensures - - if (js < 1) then - - #jump_size() == 1 - - else - - #jump_size() == js - !*/ - - - template < - typename T - > - void set_scroll_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - The event_handler function is called whenever the user causes the slider box - to move. - - This event is NOT triggered by calling set_slider_pos() - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_scroll_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - The event_handler function is called whenever the user causes the slider box - to move. - - This event is NOT triggered by calling set_slider_pos() - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - scroll_bar(scroll_bar&); // copy constructor - scroll_bar& operator=(scroll_bar&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class widget_group -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class widget_group : public drawable - { - /*! - INITIAL VALUE - size() == 0 - get_rect().is_empty() == true - left() == 0 - top() == 0 - - WHAT THIS OBJECT REPRESENTS - This object represents a grouping of drawable widgets. It doesn't draw - anything itself, rather it lets you manipulate the position, enabled - status, and visibility of a set of widgets as a group. - !*/ - - public: - widget_group( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~widget_group( - ); - /*! - ensures - - all resources associated with *this have been released. - !*/ - - void empty ( - ); - /*! - ensures - - #size() == 0 - !*/ - - void fit_to_contents ( - ); - /*! - ensures - - does not change the position of this object. - (i.e. the upper left corner of get_rect() remains at the same position) - - if (size() == 0) then - - #get_rect().is_empty() == true - - else - - recursively calls fit_to_contents() on any widget_groups inside - this object. - - #get_rect() will be the smallest rectangle that contains all the - widgets in this group and the upper left corner of get_rect(). - !*/ - - size_t size ( - ) const; - /*! - ensures - - returns the number of widgets currently in *this. - !*/ - - void add ( - drawable& widget, - unsigned long x, - unsigned long y - ); - /*! - ensures - - #is_member(widget) == true - - if (is_member(widget) == false) then - - #size() == size() + 1 - - else - - #size() == size() - - The following conditions apply to this function as well as to all of the - following functions so long as is_member(widget) == true: - enable(), disable(), hide(), show(), set_z_order(), and set_pos(). - - #widget.left() == left()+x - - #widget.width() == widget.width() - - #widget.top() == top()+y - - #widget.height() == widget.height() - - #widget.is_hidden() == is_hidden() - - #widget.is_enabled() == is_enabled() - - #widget.z_order() == z_order() - throws - - std::bad_alloc - !*/ - - bool is_member ( - const drawable& widget - ) const; - /*! - ensures - - returns true if widget is currently in this object, returns false otherwise. - !*/ - - void remove ( - const drawable& widget - ); - /*! - ensures - - #is_member(widget) == false - - if (is_member(widget) == true) then - - #size() == size() - 1 - - else - - #size() == size() - !*/ - - protected: - - // this object doesn't draw anything but also isn't abstract - void draw ( - const canvas& c - ) const {} - - private: - - // restricted functions - widget_group(widget_group&); // copy constructor - widget_group& operator=(widget_group&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class image_widget -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class image_widget : public draggable - { - /*! - INITIAL VALUE - draggable_area() == an initial value for its type. - This object isn't displaying anything. - - WHAT THIS OBJECT REPRESENTS - This object represents a draggable image. You give it an image to display - by calling set_image(). - - Also note that initially the draggable area is empty so it won't be - draggable unless you call set_draggable_area() to some non-empty region. - - The image is drawn such that: - - the pixel img[0][0] is the upper left corner of the image. - - the pixel img[img.nr()-1][0] is the lower left corner of the image. - - the pixel img[0][img.nc()-1] is the upper right corner of the image. - - the pixel img[img.nr()-1][img.nc()-1] is the lower right corner of the image. - - !*/ - - public: - - image_widget( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~image_widget( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - template < - typename image_type - > - void set_image ( - const image_type& img - ); - /*! - requires - - image_type == an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits<typename image_type::type> must be defined - ensures - - #width() == img.nc() - - #height() == img.nr() - - #*this widget is now displaying the given image img. - !*/ - - private: - - // restricted functions - image_widget(image_widget&); // copy constructor - image_widget& operator=(image_widget&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class tooltip -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class tooltip : public mouse_over_event - { - /*! - INITIAL VALUE - - text() == "" - - the tooltip is inactive until the text is changed to - a non-empty string. - - WHAT THIS OBJECT REPRESENTS - This object represents a region on a window where if the user - hovers the mouse over this region a tooltip with a message - appears. - !*/ - - public: - - tooltip( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~tooltip( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_size ( - unsigned long width_, - unsigned long height_ - ); - /*! - ensures - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this widget stays the - same but its width and height are modified - !*/ - - void set_text (const std::wstring& str); - void set_text (const dlib::ustring& str); - void set_text ( - const std::string& str - ); - /*! - ensures - - #text() == str - - activates the tooltip. i.e. after this function the tooltip - will display on the screen when the user hovers the mouse over it - !*/ - - const std::wstring wtext () const; - const dlib::ustring utext () const; - const std::string text ( - ) const; - /*! - ensures - - returns the text that is displayed inside this - tooltip - !*/ - - private: - - // restricted functions - tooltip(tooltip&); // copy constructor - tooltip& operator=(tooltip&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // popup menu stuff -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class menu_item - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an abstract class that defines the interface a - menu item in a popup_menu must implement. - - Note that a menu_item is drawn as 3 separate pieces: - --------------------------------- - | left | middle | right | - --------------------------------- - - Also note that derived classes must be copyable via - their copy constructors. - !*/ - - public: - - virtual ~menu_item() {} - - virtual void on_click ( - ) const {} - /*! - requires - - the mutex drawable::m is locked - - if (has_click_event()) then - - this function is called when the user clicks on this menu_item - !*/ - - virtual bool has_click_event ( - ) const { return false; } - /*! - ensures - - if (this menu_item wants to receive on_click events) then - - returns true - - else - - returns false - !*/ - - virtual unichar get_hot_key ( - ) const { return 0; } - /*! - ensures - - if (this menu item has a keyboard hot key) then - - returns the unicode value of the key - - else - - returns 0 - !*/ - - virtual rectangle get_left_size ( - ) const { return rectangle(); } // return empty rect by default - /*! - ensures - - returns the dimensions of the left part of the menu_item - !*/ - - virtual rectangle get_middle_size ( - ) const = 0; - /*! - ensures - - returns the dimensions of the middle part of the menu_item - !*/ - - virtual rectangle get_right_size ( - ) const { return rectangle(); } // return empty rect by default - /*! - ensures - - returns the dimensions of the right part of the menu_item - !*/ - - virtual void draw_background ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool is_selected - ) const {} - /*! - requires - - the mutex drawable::m is locked - requires - - c == the canvas to draw on - - rect == the rectangle in which we are to draw the background - - enabled == true if the menu_item is to be drawn enabled - - is_selected == true if the menu_item is to be drawn selected - ensures - - draws the background of the menu_item on the canvas c at the location - given by rect. - !*/ - - virtual void draw_left ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool is_selected - ) const {} - /*! - requires - - the mutex drawable::m is locked - requires - - c == the canvas to draw on - - rect == the rectangle in which we are to draw the background - - enabled == true if the menu_item is to be drawn enabled - - is_selected == true if the menu_item is to be drawn selected - ensures - - draws the left part of the menu_item on the canvas c at the location - given by rect. - !*/ - - virtual void draw_middle ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool is_selected - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - requires - - c == the canvas to draw on - - rect == the rectangle in which we are to draw the background - - enabled == true if the menu_item is to be drawn enabled - - is_selected == true if the menu_item is to be drawn selected - ensures - - draws the middle part of the menu_item on the canvas c at the location - given by rect. - !*/ - - virtual void draw_right ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const bool is_selected - ) const {} - /*! - requires - - the mutex drawable::m is locked - requires - - c == the canvas to draw on - - rect == the rectangle in which we are to draw the background - - enabled == true if the menu_item is to be drawn enabled - - is_selected == true if the menu_item is to be drawn selected - ensures - - draws the right part of the menu_item on the canvas c at the location - given by rect. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class menu_item_text : public menu_item - { - /*! - WHAT THIS OBJECT REPRESENTS - This object is a simple text menu item - !*/ - - public: - - template < - typename T - > - menu_item_text ( - const std::string& str, - T& object, - void (T::*on_click_handler)(), - unichar hotkey = 0 - ); - /*! - ensures - - The text of this menu item will be str - - the on_click_handler function is called on object when this menu_item - clicked by the user. - - #get_hot_key() == hotkey - !*/ - - menu_item_text ( - const std::string& str, - const any_function<void()>& on_click_handler, - unichar hotkey = 0 - ); - /*! - ensures - - The text of this menu item will be str - - the on_click_handler function is called when this menu_item - clicked by the user. - - #get_hot_key() == hotkey - !*/ - - // overloads for wide character strings - template < - typename T - > - menu_item_text ( - const std::wstring& str, - T& object, - void (T::*on_click_handler)(), - unichar hotkey = 0 - ); - - menu_item_text ( - const std::wstring& str, - const any_function<void()>& on_click_handler, - unichar hotkey = 0 - ); - - template < - typename T - > - menu_item_text ( - const dlib::ustring& str, - T& object, - void (T::*on_click_handler)(), - unichar hotkey = 0 - ); - - template < - typename T - > - menu_item_text ( - const dlib::ustring& str, - const any_function<void()>& on_click_handler, - unichar hotkey = 0 - ); - }; - -// ---------------------------------------------------------------------------------------- - - class menu_item_submenu : public menu_item - { - /*! - WHAT THIS OBJECT REPRESENTS - This object is a simple text item intended to be used with - submenus inside a popup_menu. - !*/ - - public: - - menu_item_submenu ( - const std::string& str, - unichar hotkey = 0 - ); - /*! - ensures - - The text of this menu item will be str - - #get_hot_key() == hotkey - !*/ - - //overloads for wide character strings - menu_item_submenu ( - const std::wstring& str, - unichar hotkey = 0 - ); - - menu_item_submenu ( - const dlib::ustring& str, - unichar hotkey = 0 - ); - }; - -// ---------------------------------------------------------------------------------------- - - class menu_item_separator : public menu_item - { - /*! - WHAT THIS OBJECT REPRESENTS - This object is a horizontal separator in a popup menu - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class popup_menu : public base_window - { - /*! - INITIAL VALUE - - size() == 0 - - WHAT THIS OBJECT REPRESENTS - This object represents a popup menu window capable of containing - menu_item objects. - !*/ - - public: - - popup_menu ( - ); - /*! - ensures - - #*this is properly initialized - throws - - std::bad_alloc - - dlib::thread_error - - dlib::gui_error - !*/ - - void clear ( - ); - /*! - ensures - - #*this has its initial value - throws - - std::bad_alloc - if this exception is thrown then *this is unusable - until clear() is called and succeeds - !*/ - - template < - typename menu_item_type - > - unsigned long add_menu_item ( - const menu_item_type& new_item - ); - /*! - requires - - menu_item_type == a type that inherits from menu_item - ensures - - adds new_item onto the bottom of this popup_menu. - - returns size() - (This is also the index by which this item can be - referenced by the enable_menu_item() and disable_menu_item() - functions.) - !*/ - - template < - typename menu_item_type - > - unsigned long add_submenu ( - const menu_item_type& new_item, - popup_menu& submenu - ); - /*! - requires - - menu_item_type == a type that inherits from menu_item - ensures - - adds new_item onto the bottom of this popup_menu. - - when the user puts the mouse above this menu_item the given - submenu popup_menu will be displayed. - - returns size() - (This is also the index by which this item can be - referenced by the enable_menu_item() and disable_menu_item() - functions.) - !*/ - - void enable_menu_item ( - unsigned long idx - ); - /*! - requires - - idx < size() - ensures - - the menu_item in this with the index idx has been enabled - !*/ - - void disable_menu_item ( - unsigned long idx - ); - /*! - requires - - idx < size() - ensures - - the menu_item in this with the index idx has been disabled - !*/ - - size_t size ( - ) const; - /*! - ensures - - returns the number of menu_item objects in this popup_menu - !*/ - - template <typename T> - void set_on_hide_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - ensures - - the event_handler function is called on object when this popup_menu - hides itself due to an action by the user. - - Note that you can register multiple handlers for this event. - !*/ - - void select_first_item ( - ); - /*! - ensures - - causes this popup menu to highlight the first - menu item that it contains which has a click event - and is enabled. - !*/ - - bool forwarded_on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - /*! - requires - - key, is_printable, and state are the variables from the - base_window::on_keydown() event - ensures - - forwards this keyboard event to this popup window so that it - may deal with keyboard events from other windows. - - if (this popup_menu uses the keyboard event) then - - returns true - - else - - returns false - !*/ - - private: - - // restricted functions - popup_menu(popup_menu&); // copy constructor - popup_menu& operator=(popup_menu&); // assignment operator - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class popup_menu_region -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class popup_menu_region : public drawable - { - /*! - INITIAL VALUE - - popup_menu_visible() == false - - WHAT THIS OBJECT REPRESENTS - This object represents a region on a window where if the user - right clicks the mouse over this region a popup_menu pops up. - - Note that this widget doesn't actually draw anything, it just - provides a region the user can click on to get a popup menu. - !*/ - - public: - - popup_menu_region( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~popup_menu_region( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_size ( - unsigned long width_, - unsigned long height_ - ); - /*! - ensures - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this widget stays the - same but its width and height are modified - !*/ - - void set_rect ( - const rectangle& new_rect - ); - /*! - ensures - - #get_rect() == new_rect - !*/ - - bool popup_menu_visible ( - ) const; - /*! - ensures - - if (the popup menu is currently visible on the screen) then - - returns true - - else - - returns false - !*/ - - popup_menu& menu ( - ); - /*! - ensures - - returns a reference to the popup_menu for this object. It is - the menu that is displayed when the user right clicks on - this widget - !*/ - - private: - - // restricted functions - popup_menu_region(popup_menu_region&); // copy constructor - popup_menu_region& operator=(popup_menu_region&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class zoomable_region -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class zoomable_region : public drawable - { - /* - INITIAL VALUE - - min_zoom_scale() == 0.15 - - max_zoom_scale() == 1.0 - - zoom_increment() == 0.90 - - zoom_scale() == 1.0 - - WHAT THIS OBJECT REPRESENTS - This object represents a 2D Cartesian graph that you can zoom into and - out of. It is a graphical widget that draws a rectangle with - a horizontal and vertical scroll bar that allow the user to scroll - around on a Cartesian graph that is much larger than the actual - area occupied by this object on the screen. It also allows - the user to zoom in and out. - - To use this object you inherit from it and make use of its public and - protected member functions. It provides functions for converting between - pixel locations and the points in our 2D Cartesian graph so that when the - user is scrolling/zooming the widget you can still determine where - things are to be placed on the screen and what screen pixels correspond - to in the Cartesian graph. - - Note that the Cartesian graph in this object is bounded by the point - (0,0), corresponding to the upper left corner when we are zoomed all - the way out, and max_graph_point() which corresponds to the lower right - corner when zoomed all the way out. The value of max_graph_point() is - determined automatically from the size of this object's on screen - rectangle and the value of min_zoom_scale() which determines how far - out you can zoom. - */ - - public: - - zoomable_region ( - drawable_window& w, - unsigned long events = 0 - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - - This object will not receive any events or draw() requests until - enable_events() is called - - the events flags are passed on to the drawable object's - constructor. - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~zoomable_region ( - ) = 0; - /*! - ensures - - all resources associated with *this have been released - !*/ - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ); - /*! - requires - - style_type == a type that inherits from scrollable_region_style - ensures - - this zoomable_region object will draw itself using the given - style - !*/ - - void set_zoom_increment ( - double zi - ); - /*! - requires - - 0 < zi < 1 - ensures - - #zoom_increment() == zi - !*/ - - double zoom_increment ( - ) const; - /*! - ensures - - When the user zooms in using the mouse wheel: - - #zoom_scale() == zoom_scale() / zoom_increment() - - When the user zooms out using the mouse wheel: - - #zoom_scale() == zoom_scale() * zoom_increment() - - So this function returns the number that determines how much the zoom - changes when the mouse wheel is moved. - !*/ - - void set_max_zoom_scale ( - double ms - ); - /*! - requires - - ms > 0 - ensures - - #max_zoom_scale() == ms - !*/ - - void set_min_zoom_scale ( - double ms - ); - /*! - requires - - ms > 0 - ensures - - #min_zoom_scale() == ms - !*/ - - double min_zoom_scale ( - ) const; - /*! - ensures - - returns the minimum allowed value of zoom_scale() - (i.e. this is the number that determines how far out the user is allowed to zoom) - !*/ - - double max_zoom_scale ( - ) const; - /*! - ensures - - returns the maximum allowed value of zoom_scale() - (i.e. this is the number that determines how far in the user is allowed to zoom) - !*/ - - virtual void set_size ( - unsigned long width, - unsigned long height - ); - /*! - ensures - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this button stays the - same but its width and height are modified - !*/ - - protected: - - rectangle display_rect ( - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - returns the rectangle on the screen that contains the Cartesian - graph in this widget. I.e. this is the area of this widget minus - the area taken up by the scroll bars and border decorations. - !*/ - - point graph_to_gui_space ( - const vector<double,2>& graph_point - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - returns the location of the pixel on the screen that corresponds - to the given point in Cartesian graph space - !*/ - - vector<double,2> gui_to_graph_space ( - const point& pixel_point - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - returns the point in Cartesian graph space that corresponds to the given - pixel location - !*/ - - vector<double,2> max_graph_point ( - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - returns the pixel farthest from the graph point (0,0) that is still - in the graph. I.e. returns the point in graph space that corresponds - to the lower right corner of the display_rect() when we are zoomed - all the way out. - !*/ - - double zoom_scale ( - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - returns a double Z that represents the current zoom. - - Smaller values of Z represent the user zooming out. - - Bigger values of Z represent the user zooming in. - - The default unzoomed case is when Z == 1 - - objects should be drawn such that they are zoom_scale() - times their normal size - !*/ - - void set_zoom_scale ( - double new_scale - ); - /*! - requires - - mutex drawable::m is locked - ensures - - invalidates the display_rect() so that it will be redrawn - - if (min_zoom_scale() <= new_scale && new_scale <= max_zoom_scale()) then - - #zoom_scale() == new_scale - - else if (new_scale < min_zoom_scale()) then - - #zoom_scale() == min_zoom_scale() - - else if (new_scale > max_zoom_scale()) then - - #zoom_scale() == max_zoom_scale() - !*/ - - void center_display_at_graph_point ( - const vector<double,2>& graph_point - ); - /*! - requires - - mutex drawable::m is locked - ensures - - causes the given graph point to be centered in the display - if possible - - invalidates the display_rect() so that it will be redrawn - !*/ - - virtual void on_view_changed ( - ) {} - /*! - requires - - events_are_enabled() == true - - mutex drawable::m is locked - ensures - - on_view_changed() is called whenever the user causes the view of the - zoomable_region to change. That is, this function is called when the - user scrolls or zooms around in the region. - !*/ - - // ---------------------------- event handlers ---------------------------- - // The following event handlers are used in this object. So if you - // use any of them in your derived object you should pass the events - // back to it so that they still operate unless you wish to hijack the - // event for your own reasons (e.g. to override the mouse drag this object - // performs) - - void on_wheel_down (unsigned long state); - void on_wheel_up (unsigned long state); - void on_mouse_move ( unsigned long state, long x, long y); - void on_mouse_up ( unsigned long btn, unsigned long state, long x, long y); - void on_mouse_down ( unsigned long btn, unsigned long state, long x, long y, bool is_double_click); - void draw ( const canvas& c) const; - - private: - - // restricted functions - zoomable_region(zoomable_region&); // copy constructor - zoomable_region& operator=(zoomable_region&); // assignment operator - - }; - -// ---------------------------------------------------------------------------------------- - - class scrollable_region : public drawable - { - /*! - INITIAL VALUE - - horizontal_scroll_pos() == 0 - - horizontal_scroll_increment() == 1 - - horizontal_mouse_wheel_scroll_increment() == 1 - - vertical_scroll_pos() == 0 - - vertical_scroll_increment() == 1 - - vertical_mouse_wheel_scroll_increment() == 1 - - total_rect().empty() == true - - mouse_drag_enabled() == false - - WHAT THIS OBJECT REPRESENTS - This object represents a 2D region of arbitrary size that is displayed - within a possibly smaller scrollable gui widget. That is, it is a - graphical widget that draws a rectangle with a horizontal and vertical - scroll bar that allows the user to scroll around on a region that is much - larger than the actual area occupied by this object on the screen. - - To use this object you inherit from it and make use of its public and - protected member functions. It provides a function, total_rect(), that - tells you where the 2D region is on the screen. You draw your stuff - inside total_rect() as you would normally except that you only modify - pixels that are also inside display_rect(). When the user moves the - scroll bars the position of total_rect() is updated accordingly, causing - the widget's content to scroll across the screen. - !*/ - - public: - scrollable_region ( - drawable_window& w, - unsigned long events = 0 - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - - This object will not receive any events or draw() requests until - enable_events() is called - - the events flags are passed on to the drawable object's - constructor. - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~scrollable_region ( - ) = 0; - /*! - ensures - - all resources associated with *this have been released - !*/ - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ); - /*! - requires - - style_type == a type that inherits from scrollable_region_style - ensures - - this scrollable_region object will draw itself using the given - style - !*/ - - virtual void set_size ( - unsigned long width, - unsigned long height - ); - /*! - ensures - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this widget stays the - same but its width and height are modified. - !*/ - - long horizontal_scroll_pos ( - ) const; - /*! - ensures - - returns the current position of the horizontal scroll bar. - 0 means it is at the far left while bigger values represent - scroll positions closer to the right. - !*/ - - long vertical_scroll_pos ( - ) const; - /*! - ensures - - returns the current position of the vertical scroll bar. - 0 means it is at the top and bigger values represent scroll positions - closer to the bottom. - !*/ - - void set_horizontal_scroll_pos ( - long pos - ); - /*! - ensures - - if (pos is a valid horizontal scroll position) then - - #horizontal_scroll_pos() == pos - - else - - #horizontal_scroll_pos() == the valid scroll position closest to pos - !*/ - - void set_vertical_scroll_pos ( - long pos - ); - /*! - ensures - - if (pos is a valid vertical scroll position) then - - #vertical_scroll_pos() == pos - - else - - #vertical_scroll_pos() == the valid scroll position closest to pos - !*/ - - unsigned long horizontal_mouse_wheel_scroll_increment ( - ) const; - /*! - ensures - - returns the number of positions the horizontal scroll bar - moves when the user scrolls the mouse wheel. - !*/ - - unsigned long vertical_mouse_wheel_scroll_increment ( - ) const; - /*! - ensures - - returns the number of positions the vertical scroll bar - moves when the user scrolls the mouse wheel. - !*/ - - void set_horizontal_mouse_wheel_scroll_increment ( - unsigned long inc - ); - /*! - ensures - - #horizontal_mouse_wheel_scroll_increment() == inc - !*/ - - void set_vertical_mouse_wheel_scroll_increment ( - unsigned long inc - ); - /*! - ensures - - #vertical_mouse_wheel_scroll_increment() == inc - !*/ - - - unsigned long horizontal_scroll_increment ( - ) const; - /*! - ensures - - returns the number of pixels that total_rect() is moved by when - the horizontal scroll bar moves by one position - !*/ - - unsigned long vertical_scroll_increment ( - ) const; - /*! - ensures - - returns the number of pixels that total_rect() is moved by when - the vertical scroll bar moves by one position - !*/ - - void set_horizontal_scroll_increment ( - unsigned long inc - ); - /*! - ensures - - #horizontal_scroll_increment() == inc - !*/ - - void set_vertical_scroll_increment ( - unsigned long inc - ); - /*! - ensures - - #vertical_scroll_increment() == inc - !*/ - - bool mouse_drag_enabled ( - ) const; - /*! - ensures - - if (the user can drag this contents of this widget around by - holding down the left mouse button and dragging) then - - returns true - - else - - returns false - !*/ - - void enable_mouse_drag ( - ); - /*! - ensures - - #mouse_drag_enabled() == true - !*/ - - void disable_mouse_drag ( - ); - /*! - ensures - - #mouse_drag_enabled() == false - !*/ - - protected: - - rectangle display_rect ( - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - returns the rectangle on the screen that contains the scrollable - area in this widget. I.e. this is the area of this widget minus - the area taken up by the scroll bars and border decorations. - !*/ - - void set_total_rect_size ( - unsigned long width, - unsigned long height - ); - /*! - requires - - mutex drawable::m is locked - - (width > 0 && height > 0) || (width == 0 && height == 0) - ensures - - #total_rect().width() == width - - #total_rect().height() == height - - The scroll bars as well as the position of #total_rect() - is updated so that the total rect is still in the correct - position with respect to the scroll bars. - !*/ - - const rectangle& total_rect ( - ) const; - /*! - requires - - mutex drawable::m is locked - ensures - - returns a rectangle that represents the entire scrollable - region inside this widget, even the parts that are outside - display_rect(). - !*/ - - void scroll_to_rect ( - const rectangle& r - ); - /*! - requires - - mutex drawable::m is locked - ensures - - Adjusts the scroll bars of this object so that the part of - the total_rect() rectangle that overlaps with r is displayed in - the display_rect() rectangle on the screen. - !*/ - - virtual void on_view_changed ( - ) {} - /*! - requires - - events_are_enabled() == true - - mutex drawable::m is locked - ensures - - on_view_changed() is called whenever the user causes the view of the - scrollable_region to change. That is, this function is called when the - user scrolls around in the region. - !*/ - - // ---------------------------- event handlers ---------------------------- - // The following event handlers are used in this object. So if you - // use any of them in your derived object you should pass the events - // back to it so that they still operate unless you wish to hijack the - // event for your own reasons (e.g. to override the mouse wheel action - // this object performs) - - void on_wheel_down (unsigned long state); - void on_wheel_up (unsigned long state); - void on_mouse_move (unsigned long state, long x, long y); - 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 draw (const canvas& c) const; - - private: - - // restricted functions - scrollable_region(scrollable_region&); // copy constructor - scrollable_region& operator=(scrollable_region&); // assignment operator - - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_BASE_WIDGETs_ABSTRACT_ - - diff --git a/ml/dlib/dlib/gui_widgets/canvas_drawing.cpp b/ml/dlib/dlib/gui_widgets/canvas_drawing.cpp deleted file mode 100644 index 0fecd1cd3..000000000 --- a/ml/dlib/dlib/gui_widgets/canvas_drawing.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), and Nils Labugt -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_CANVAS_DRAWINg_CPP_ -#define DLIB_CANVAS_DRAWINg_CPP_ - -#include "canvas_drawing.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - void draw_sunken_rectangle ( - const canvas& c, - const rectangle& border, - unsigned char alpha - ) - { - rectangle area = border.intersect(c); - if (area.is_empty() == false) - { - const rgb_alpha_pixel dark_gray(64,64,64,alpha); - const rgb_alpha_pixel gray(128,128,128,alpha); - const rgb_alpha_pixel white(255,255,255,alpha); - const rgb_alpha_pixel background(212,208,200,alpha); - - draw_line(c,point(border.left(),border.top()),point(border.right()-1,border.top()),gray); - - draw_line(c,point(border.left(),border.bottom()),point(border.right(),border.bottom()),white); - draw_line(c,point(border.left()+1,border.bottom()-1),point(border.right()-1,border.bottom()-1),background); - - draw_line(c,point(border.left(),border.top()+1),point(border.left(),border.bottom()-1),gray); - - draw_line(c,point(border.right(),border.top()),point(border.right(),border.bottom()-1),white); - draw_line(c,point(border.right()-1,border.top()+1),point(border.right()-1,border.bottom()-2),background); - - draw_line(c,point(border.left()+1,border.top()+1),point(border.left()+1,border.bottom()-2),dark_gray); - draw_line(c,point(border.left()+1,border.top()+1),point(border.right()-2,border.top()+1),dark_gray); - } - } - -// ---------------------------------------------------------------------------------------- - - void draw_button_down ( - const canvas& c, - const rectangle& btn, - unsigned char alpha - ) - { - rectangle area = btn.intersect(c); - if (area.is_empty() == false) - { - const rgb_alpha_pixel dark_gray(64,64,64,alpha); - const rgb_alpha_pixel gray(128,128,128,alpha); - const rgb_alpha_pixel black(0,0,0,alpha); - - draw_line(c,point(btn.left(),btn.top()),point(btn.right(),btn.top()),black); - - draw_line(c,point(btn.left()+1,btn.bottom()),point(btn.right(),btn.bottom()),dark_gray); - draw_line(c,point(btn.left()+1,btn.top()+1),point(btn.right()-1,btn.top()+1),gray); - - draw_line(c,point(btn.left(),btn.top()+1),point(btn.left(),btn.bottom()),black); - - draw_line(c,point(btn.right(),btn.top()+1),point(btn.right(),btn.bottom()-1),dark_gray); - draw_line(c,point(btn.left()+1,btn.top()+1),point(btn.left()+1,btn.bottom()-1),gray); - } - } - -// ---------------------------------------------------------------------------------------- - - void draw_button_up ( - const canvas& c, - const rectangle& btn, - unsigned char alpha - ) - { - rectangle area = btn.intersect(c); - if (area.is_empty() == false) - { - const rgb_alpha_pixel dark_gray(64,64,64,alpha); - const rgb_alpha_pixel gray(128,128,128,alpha); - const rgb_alpha_pixel white(255,255,255,alpha); - - draw_line(c,point(btn.left(),btn.top()),point(btn.right()-1,btn.top()),white); - - draw_line(c,point(btn.left(),btn.bottom()),point(btn.right(),btn.bottom()),dark_gray); - draw_line(c,point(btn.left()+1,btn.bottom()-1),point(btn.right()-1,btn.bottom()-1),gray); - - draw_line(c,point(btn.left(),btn.top()+1),point(btn.left(),btn.bottom()-1),white); - - draw_line(c,point(btn.right(),btn.top()),point(btn.right(),btn.bottom()-1),dark_gray); - draw_line(c,point(btn.right()-1,btn.top()+1),point(btn.right()-1,btn.bottom()-2),gray); - } - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_CANVAS_DRAWINg_CPP_ - diff --git a/ml/dlib/dlib/gui_widgets/canvas_drawing.h b/ml/dlib/dlib/gui_widgets/canvas_drawing.h deleted file mode 100644 index 61f688112..000000000 --- a/ml/dlib/dlib/gui_widgets/canvas_drawing.h +++ /dev/null @@ -1,964 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), and Nils Labugt -// License: Boost Software License See LICENSE.txt for the full license. - -#ifndef DLIB_GUI_CANVAS_DRAWINg_ -#define DLIB_GUI_CANVAS_DRAWINg_ - -#include "canvas_drawing_abstract.h" -#include "../gui_core.h" -#include "../algs.h" -#include "../array2d.h" -#include "../pixel.h" -#include "../image_transforms/assign_image.h" -#include "../geometry.h" -#include <cmath> - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void draw_line ( - const canvas& c, - const point& p1, - const point& p2, - const pixel_type& pixel, - const rectangle& area = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - rectangle valid_area(c.intersect(area)); - long x1 = p1.x(); - long y1 = p1.y(); - long x2 = p2.x(); - long y2 = p2.y(); - if (x1 == x2) - { - // if the x coordinate is inside the canvas's area - if (x1 <= valid_area.right() && x1 >= valid_area.left()) - { - // make sure y1 comes before y2 - if (y1 > y2) - swap(y1,y2); - - y1 = std::max(y1,valid_area.top()); - y2 = std::min(y2,valid_area.bottom()); - // this is a vertical line - for (long y = y1; y <= y2; ++y) - { - assign_pixel(c[y-c.top()][x1-c.left()], pixel); - } - } - } - else if (y1 == y2) - { - // if the y coordinate is inside the canvas's area - if (y1 <= valid_area.bottom() && y1 >= valid_area.top()) - { - // make sure x1 comes before x2 - if (x1 > x2) - swap(x1,x2); - - x1 = std::max(x1,valid_area.left()); - x2 = std::min(x2,valid_area.right()); - // this is a horizontal line - for (long x = x1; x <= x2; ++x) - { - assign_pixel(c[y1-c.top()][x-c.left()], pixel); - } - } - } - else - { - rgb_alpha_pixel alpha_pixel; - assign_pixel(alpha_pixel, pixel); - const unsigned char max_alpha = alpha_pixel.alpha; - - const long rise = (((long)y2) - ((long)y1)); - const long run = (((long)x2) - ((long)x1)); - if (std::abs(rise) < std::abs(run)) - { - const double slope = ((double)rise)/run; - - double first, last; - - if (x1 > x2) - { - first = std::max(x2,valid_area.left()); - last = std::min(x1,valid_area.right()); - } - else - { - first = std::max(x1,valid_area.left()); - last = std::min(x2,valid_area.right()); - } - - - long y; - long x; - const double x1f = x1; - const double y1f = y1; - for (double i = first; i <= last; ++i) - { - const double dy = slope*(i-x1f) + y1f; - const double dx = i; - - y = static_cast<long>(dy); - x = static_cast<long>(dx); - - - if (y >= valid_area.top() && y <= valid_area.bottom()) - { - alpha_pixel.alpha = static_cast<unsigned char>((1.0-(dy-y))*max_alpha); - assign_pixel(c[y-c.top()][x-c.left()], alpha_pixel); - } - if (y+1 >= valid_area.top() && y+1 <= valid_area.bottom()) - { - alpha_pixel.alpha = static_cast<unsigned char>((dy-y)*max_alpha); - assign_pixel(c[y+1-c.top()][x-c.left()], alpha_pixel); - } - } - } - else - { - const double slope = ((double)run)/rise; - - double first, last; - - if (y1 > y2) - { - first = std::max(y2,valid_area.top()); - last = std::min(y1,valid_area.bottom()); - } - else - { - first = std::max(y1,valid_area.top()); - last = std::min(y2,valid_area.bottom()); - } - - long x; - long y; - const double x1f = x1; - const double y1f = y1; - for (double i = first; i <= last; ++i) - { - const double dx = slope*(i-y1f) + x1f; - const double dy = i; - - y = static_cast<long>(dy); - x = static_cast<long>(dx); - - if (x >= valid_area.left() && x <= valid_area.right()) - { - alpha_pixel.alpha = static_cast<unsigned char>((1.0-(dx-x))*max_alpha); - assign_pixel(c[y-c.top()][x-c.left()], alpha_pixel); - } - if (x+1 >= valid_area.left() && x+1 <= valid_area.right()) - { - alpha_pixel.alpha = static_cast<unsigned char>((dx-x)*max_alpha); - assign_pixel(c[y-c.top()][x+1-c.left()], alpha_pixel); - } - } - } - } - - } - inline void draw_line ( - const canvas& c, - const point& p1, - const point& p2 - ){ draw_line(c,p1,p2,0); } - -// ---------------------------------------------------------------------------------------- - - void draw_sunken_rectangle ( - const canvas& c, - const rectangle& border, - unsigned char alpha = 255 - ); - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - inline void draw_pixel ( - const canvas& c, - const point& p, - const pixel_type& pixel - ) - { - if (c.contains(p)) - { - assign_pixel(c[p.y()-c.top()][p.x()-c.left()],pixel); - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void draw_checkered ( - const canvas& c, - const rectangle& a, - const pixel_type& pixel1, - const pixel_type& pixel2 - ) - { - rectangle area = a.intersect(c); - if (area.is_empty()) - return; - - for (long i = area.left(); i <= area.right(); ++i) - { - for (long j = area.top(); j <= area.bottom(); ++j) - { - canvas::pixel& p = c[j - c.top()][i - c.left()]; - if ((j&0x1) ^ (i&0x1)) - { - assign_pixel(p,pixel1); - } - else - { - assign_pixel(p,pixel2); - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - void draw_button_down ( - const canvas& c, - const rectangle& btn, - unsigned char alpha = 255 - ); - -// ---------------------------------------------------------------------------------------- - - void draw_button_up ( - const canvas& c, - const rectangle& btn, - unsigned char alpha = 255 - ); - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void draw_circle ( - const canvas& c, - const point& center_point, - double radius, - const pixel_type& pixel, - const rectangle& area = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - using std::sqrt; - rectangle valid_area(c.intersect(area)); - const long x = center_point.x(); - const long y = center_point.y(); - if (radius > 1) - { - long first_x = static_cast<long>(x - radius + 0.5); - long last_x = static_cast<long>(x + radius + 0.5); - const double rs = radius*radius; - - // ensure that we only loop over the part of the x dimension that this - // canvas contains. - if (first_x < valid_area.left()) - first_x = valid_area.left(); - if (last_x > valid_area.right()) - last_x = valid_area.right(); - - long top, bottom; - - top = static_cast<long>(sqrt(std::max(rs - (first_x-x-0.5)*(first_x-x-0.5),0.0))+0.5); - top += y; - long last = top; - - // draw the left half of the circle - long middle = std::min(x-1,last_x); - for (long i = first_x; i <= middle; ++i) - { - double a = i - x + 0.5; - // find the top of the arc - top = static_cast<long>(sqrt(std::max(rs - a*a,0.0))+0.5); - top += y; - long temp = top; - - while(top >= last) - { - bottom = y - top + y; - if (top >= valid_area.top() && top <= valid_area.bottom() ) - { - assign_pixel(c[top-c.top()][i-c.left()],pixel); - } - - if (bottom >= valid_area.top() && bottom <= valid_area.bottom() ) - { - assign_pixel(c[bottom-c.top()][i-c.left()],pixel); - } - --top; - } - - last = temp; - } - - middle = std::max(x,first_x); - top = static_cast<long>(sqrt(std::max(rs - (last_x-x+0.5)*(last_x-x+0.5),0.0))+0.5); - top += y; - last = top; - // draw the right half of the circle - for (long i = last_x; i >= middle; --i) - { - double a = i - x - 0.5; - // find the top of the arc - top = static_cast<long>(sqrt(std::max(rs - a*a,0.0))+0.5); - top += y; - long temp = top; - - while(top >= last) - { - bottom = y - top + y; - if (top >= valid_area.top() && top <= valid_area.bottom() ) - { - assign_pixel(c[top-c.top()][i-c.left()],pixel); - } - - if (bottom >= valid_area.top() && bottom <= valid_area.bottom() ) - { - assign_pixel(c[bottom-c.top()][i-c.left()],pixel); - } - --top; - } - - last = temp; - } - } - else if (radius == 1 && - x >= valid_area.left() && x <= valid_area.right() && - y >= valid_area.top() && y <= valid_area.bottom() ) - { - assign_pixel(c[y-c.top()][x-c.left()], pixel); - } - } - inline void draw_circle ( - const canvas& c, - const point& center_point, - double radius - ){ draw_circle(c, center_point, radius, 0); } - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void draw_solid_circle ( - const canvas& c, - const point& center_point, - double radius, - const pixel_type& pixel, - const rectangle& area = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - using std::sqrt; - rectangle valid_area(c.intersect(area)); - const long x = center_point.x(); - const long y = center_point.y(); - if (radius > 1) - { - long first_x = static_cast<long>(x - radius + 0.5); - long last_x = static_cast<long>(x + radius + 0.5); - const double rs = radius*radius; - - // ensure that we only loop over the part of the x dimension that this - // canvas contains. - if (first_x < valid_area.left()) - first_x = valid_area.left(); - if (last_x > valid_area.right()) - last_x = valid_area.right(); - - long top, bottom; - - top = static_cast<long>(sqrt(std::max(rs - (first_x-x-0.5)*(first_x-x-0.5),0.0))+0.5); - top += y; - long last = top; - - // draw the left half of the circle - long middle = std::min(x-1,last_x); - for (long i = first_x; i <= middle; ++i) - { - double a = i - x + 0.5; - // find the top of the arc - top = static_cast<long>(sqrt(std::max(rs - a*a,0.0))+0.5); - top += y; - long temp = top; - - while(top >= last) - { - bottom = y - top + y; - draw_line(c, point(i,top),point(i,bottom),pixel,area); - --top; - } - - last = temp; - } - - middle = std::max(x,first_x); - top = static_cast<long>(sqrt(std::max(rs - (last_x-x+0.5)*(last_x-x+0.5),0.0))+0.5); - top += y; - last = top; - // draw the right half of the circle - for (long i = last_x; i >= middle; --i) - { - double a = i - x - 0.5; - // find the top of the arc - top = static_cast<long>(sqrt(std::max(rs - a*a,0.0))+0.5); - top += y; - long temp = top; - - while(top >= last) - { - bottom = y - top + y; - draw_line(c, point(i,top),point(i,bottom),pixel,area); - --top; - } - - last = temp; - } - } - else if (radius == 1 && - x >= valid_area.left() && x <= valid_area.right() && - y >= valid_area.top() && y <= valid_area.bottom() ) - { - assign_pixel(c[y-c.top()][x-c.left()], pixel); - } - } - inline void draw_solid_circle ( - const canvas& c, - const point& center_point, - double radius - ) { draw_solid_circle(c, center_point, radius, 0); } - -// ---------------------------------------------------------------------------------------- - - namespace impl - { - - template <typename alloc> - void get_convex_polygon_shape ( - const std::vector<point>& points, - const long top, - const long bottom, - std::vector<double,alloc>& left_boundary, - std::vector<double,alloc>& right_boundary - ) - /*! - requires - - 0 <= top <= bottom - ensures - - interprets points as the coordinates defining a convex polygon. In - particular, we interpret points as a list of the vertices of the polygon - and assume they are ordered in clockwise order. - - #left_boundary.size() == bottom-top+1 - - #right_boundary.size() == bottom-top+1 - - for all top <= y <= bottom: - - #left_boundary[y-top] == the x coordinate for the left most side of - the polygon at coordinate y. - - #right_boundary[y-top] == the x coordinate for the right most side of - the polygon at coordinate y. - !*/ - { - using std::min; - using std::max; - - left_boundary.assign(bottom-top+1, std::numeric_limits<double>::infinity()); - right_boundary.assign(bottom-top+1, -std::numeric_limits<double>::infinity()); - - // trace out the points along the edge of the polynomial and record them - for (unsigned long i = 0; i < points.size(); ++i) - { - const point p1 = points[i]; - const point p2 = points[(i+1)%points.size()]; - - if (p1.y() == p2.y()) - { - if (top <= p1.y() && p1.y() <= bottom) - { - const long y = p1.y() - top; - const double xmin = min(p1.x(), p2.x()); - const double xmax = min(p1.x(), p2.x()); - left_boundary[y] = min(left_boundary[y], xmin); - right_boundary[y] = max(right_boundary[y], xmax); - } - } - else - { - // Here we trace out the line from p1 to p2 and record where it hits. - - // x = m*y + b - const double m = (p2.x() - p1.x())/(double)(p2.y()-p1.y()); - const double b = p1.x() - m*p1.y(); // because: x1 = m*y1 + b - - const long ymin = max(top,min(p1.y(), p2.y())); - const long ymax = min(bottom,max(p1.y(), p2.y())); - for (long y = ymin; y <= ymax; ++y) - { - const double x = m*y + b; - const unsigned long idx = y-top; - left_boundary[idx] = min(left_boundary[idx], x); - right_boundary[idx] = max(right_boundary[idx], x); - } - } - } - } - - // ------------------------------------------------------------------------------------ - - } - - template <typename pixel_type> - void draw_solid_convex_polygon ( - const canvas& c, - const std::vector<point>& polygon, - const pixel_type& pixel, - const rectangle& area = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - using std::max; - using std::min; - const rectangle valid_area(c.intersect(area)); - - rectangle bounding_box; - for (unsigned long i = 0; i < polygon.size(); ++i) - bounding_box += polygon[i]; - - // Don't do anything if the polygon is totally outside the area we can draw in - // right now. - if (bounding_box.intersect(valid_area).is_empty()) - return; - - rgb_alpha_pixel alpha_pixel; - assign_pixel(alpha_pixel, pixel); - const unsigned char max_alpha = alpha_pixel.alpha; - - // we will only want to loop over the part of left_boundary that is part of the - // valid_area. - long top = max(valid_area.top(),bounding_box.top()); - long bottom = min(valid_area.bottom(),bounding_box.bottom()); - - // Since we look at the adjacent rows of boundary information when doing the alpha - // blending, we want to make sure we always have some boundary information unless - // we are at the absolute edge of the polygon. - const long top_offset = (top == bounding_box.top()) ? 0 : 1; - const long bottom_offset = (bottom == bounding_box.bottom()) ? 0 : 1; - if (top != bounding_box.top()) - top -= 1; - if (bottom != bounding_box.bottom()) - bottom += 1; - - std::vector<double> left_boundary; - std::vector<double> right_boundary; - impl::get_convex_polygon_shape(polygon, top, bottom, left_boundary, right_boundary); - - - // draw the polygon row by row - for (unsigned long i = top_offset; i < left_boundary.size(); ++i) - { - long left_x = static_cast<long>(std::ceil(left_boundary[i])); - long right_x = static_cast<long>(std::floor(right_boundary[i])); - - left_x = max(left_x, valid_area.left()); - right_x = min(right_x, valid_area.right()); - - if (i < left_boundary.size()-bottom_offset) - { - // draw the main body of the polygon - for (long x = left_x; x <= right_x; ++x) - { - const long y = i+top; - assign_pixel(c[y-c.top()][x-c.left()], pixel); - } - } - - if (i == 0) - continue; - - // Now draw anti-aliased edges so they don't look all pixely. - - // Alpha blend the edges on the left side. - double delta = left_boundary[i-1] - left_boundary[i]; - if (std::abs(delta) <= 1) - { - if (std::floor(left_boundary[i]) != left_x) - { - const point p(static_cast<long>(std::floor(left_boundary[i])), i+top); - rgb_alpha_pixel temp = alpha_pixel; - temp.alpha = max_alpha-static_cast<unsigned char>((left_boundary[i]-p.x())*max_alpha); - if (valid_area.contains(p)) - assign_pixel(c[p.y()-c.top()][p.x()-c.left()],temp); - } - } - else if (delta < 0) // on the bottom side - { - for (long x = static_cast<long>(std::ceil(left_boundary[i-1])); x < left_x; ++x) - { - const point p(x, i+top); - rgb_alpha_pixel temp = alpha_pixel; - temp.alpha = static_cast<unsigned char>((x-left_boundary[i-1])/std::abs(delta)*max_alpha); - if (valid_area.contains(p)) - assign_pixel(c[p.y()-c.top()][p.x()-c.left()],temp); - } - } - else // on the top side - { - const long old_left_x = static_cast<long>(std::ceil(left_boundary[i-1])); - for (long x = left_x; x < old_left_x; ++x) - { - const point p(x, i+top-1); - rgb_alpha_pixel temp = alpha_pixel; - temp.alpha = static_cast<unsigned char>((x-left_boundary[i])/delta*max_alpha); - if (valid_area.contains(p)) - assign_pixel(c[p.y()-c.top()][p.x()-c.left()],temp); - } - } - - - // Alpha blend the edges on the right side - delta = right_boundary[i-1] - right_boundary[i]; - if (std::abs(delta) <= 1) - { - if (std::ceil(right_boundary[i]) != right_x) - { - const point p(static_cast<long>(std::ceil(right_boundary[i])), i+top); - rgb_alpha_pixel temp = alpha_pixel; - temp.alpha = max_alpha-static_cast<unsigned char>((p.x()-right_boundary[i])*max_alpha); - if (valid_area.contains(p)) - assign_pixel(c[p.y()-c.top()][p.x()-c.left()],temp); - } - } - else if (delta < 0) // on the top side - { - for (long x = static_cast<long>(std::floor(right_boundary[i-1]))+1; x <= right_x; ++x) - { - const point p(x, i+top-1); - rgb_alpha_pixel temp = alpha_pixel; - temp.alpha = static_cast<unsigned char>((right_boundary[i]-x)/std::abs(delta)*max_alpha); - if (valid_area.contains(p)) - assign_pixel(c[p.y()-c.top()][p.x()-c.left()],temp); - } - } - else // on the bottom side - { - const long old_right_x = static_cast<long>(std::floor(right_boundary[i-1])); - for (long x = right_x+1; x <= old_right_x; ++x) - { - const point p(x, i+top); - rgb_alpha_pixel temp = alpha_pixel; - temp.alpha = static_cast<unsigned char>((right_boundary[i-1]-x)/delta*max_alpha); - if (valid_area.contains(p)) - assign_pixel(c[p.y()-c.top()][p.x()-c.left()],temp); - } - } - } - } - inline void draw_solid_convex_polygon ( - const canvas& c, - const std::vector<point>& polygon - ) { draw_solid_convex_polygon(c, polygon, 0); } - -// ---------------------------------------------------------------------------------------- - - template < - typename image_type - > - void draw_image ( - const canvas& c, - const point& p, - const image_type& img, - const rectangle& area_ = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - const long x = p.x(); - const long y = p.y(); - rectangle rect(x,y,num_columns(img)+x-1,num_rows(img)+y-1); - rectangle area = c.intersect(rect).intersect(area_); - if (area.is_empty()) - return; - - for (long row = area.top(); row <= area.bottom(); ++row) - { - for (long col = area.left(); col <= area.right(); ++col) - { - assign_pixel(c[row-c.top()][col-c.left()], img[row-rect.top()][col-rect.left()]); - } - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename image_type - > - void draw_image ( - const canvas& c, - const rectangle& rect, - const image_type& img, - const rectangle& area_ = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - const rectangle area = c.intersect(rect).intersect(area_); - if (area.is_empty() || num_columns(img) * num_rows(img) == 0) - return; - - const matrix<long,1> x = matrix_cast<long>(round(linspace(0, num_columns(img)-1, rect.width()))); - const matrix<long,1> y = matrix_cast<long>(round(linspace(0, num_rows(img)-1, rect.height()))); - - for (long row = area.top(); row <= area.bottom(); ++row) - { - const long r = y(row-rect.top()); - long cc = area.left() - rect.left(); - for (long col = area.left(); col <= area.right(); ++col) - { - assign_pixel(c[row-c.top()][col-c.left()], img[r][x(cc++)]); - } - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void draw_rounded_rectangle ( - const canvas& c, - const rectangle& rect, - unsigned radius, - const pixel_type& color, - const rectangle& area_ = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - if ( rect.intersect ( c ).is_empty() ) - return; - - draw_line ( c, point(rect.left() + radius + 1, rect.bottom()), - point(rect.right() - radius - 1, rect.bottom()), color,area_ ); - - draw_line ( c, point(rect.left() + radius + 1, rect.top()), - point(rect.right() - radius - 1, rect.top()), color,area_ ); - - draw_line ( c, point(rect.left(), rect.top() + radius + 1), - point(rect.left(), rect.bottom() - radius - 1), color,area_ ); - - draw_line ( c, point(rect.right(), rect.top() + radius + 1), - point(rect.right(), rect.bottom() - radius - 1), color,area_ ); - - unsigned x = radius, y = 0, old_x = x; - - point p; - while ( x > y ) - { - p = point(rect.left() + radius - y, rect.top() + radius - x); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.right() - radius + y, rect.top() + radius - x); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.right() - radius + y, rect.bottom() - radius + x); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.left() + radius - y, rect.bottom() - radius + x); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.left() + radius - x, rect.top() + radius - y); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.right() - radius + x, rect.top() + radius - y); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.right() - radius + x, rect.bottom() - radius + y); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.left() + radius - x, rect.bottom() - radius + y); - if (area_.contains(p)) draw_pixel (c, p , color ); - y++; - old_x = x; - x = square_root ( ( radius * radius - y * y ) * 4 ) / 2; - } - - if ( x == y && old_x != x ) - { - p = point(rect.left() + radius - y, rect.top() + radius - x); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.right() - radius + y, rect.top() + radius - x); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.right() - radius + y, rect.bottom() - radius + x); - if (area_.contains(p)) draw_pixel (c, p , color ); - p = point(rect.left() + radius - y, rect.bottom() - radius + x); - if (area_.contains(p)) draw_pixel (c, p , color ); - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void fill_gradient_rounded ( - const canvas& c, - const rectangle& rect, - unsigned long radius, - const pixel_type& top_color, - const pixel_type& bottom_color, - const rectangle& area = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - - ) - { - rectangle valid_area(c.intersect(area.intersect(rect))); - if ( valid_area.is_empty() ) - return; - - - unsigned long m_prev = 0, m = radius, c_div = valid_area.height() - 1; - - const long c_top = valid_area.top(); - const long c_bottom = valid_area.bottom(); - - for ( long y = c_top; y <= c_bottom;y++ ) - { - - unsigned long c_s = y - c_top; - - unsigned long c_t = c_bottom - y; - - - if ( c_div == 0 ) - { - // only a single round, just take the average color - c_div = 2; - c_s = c_t = 1; - } - - rgb_alpha_pixel color; - vector_to_pixel(color, - ((pixel_to_vector<unsigned long>(top_color)*c_t + pixel_to_vector<unsigned long>(bottom_color)*c_s)/c_div)); - - unsigned long s = y - rect.top(); - - unsigned long t = rect.bottom() - y; - - if ( s < radius ) - { - m = radius - square_root ( ( radius * radius - ( radius - s ) * ( radius - s ) ) * 4 ) / 2; - - if ( s == m && m + 1 < m_prev ) // these are hacks to remove distracting artefacts at small radii - m++; - } - else if ( t < radius ) - { - m = radius - square_root ( ( radius * radius - ( radius - t ) * ( radius - t ) ) * 4 ) / 2; - - if ( t == m && m == m_prev ) - m++; - } - else - { - m = 0; - } - - m_prev = m; - - draw_line ( c, point(rect.left() + m, y), - point(rect.right() - m, y), color, valid_area ); - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void draw_rectangle ( - const canvas& c, - rectangle rect, - const pixel_type& pixel, - const rectangle& area = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - // top line - draw_line(c, point(rect.left(),rect.top()), - point(rect.right(),rect.top()), - pixel, area); - - // bottom line - draw_line(c, point(rect.left(),rect.bottom()), - point(rect.right(),rect.bottom()), - pixel, area); - - // left line - draw_line(c, point(rect.left(),rect.top()), - point(rect.left(),rect.bottom()), - pixel, area); - - // right line - draw_line(c, point(rect.right(),rect.top()), - point(rect.right(),rect.bottom()), - pixel, area); - } - inline void draw_rectangle ( - const canvas& c, - rectangle rect - ){ draw_rectangle(c, rect, 0); } - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void fill_rect ( - const canvas& c, - const rectangle& rect, - const pixel_type& pixel - ) - { - rectangle area = rect.intersect(c); - for (long y = area.top(); y <= area.bottom(); ++y) - { - for (long x = area.left(); x <= area.right(); ++x) - { - assign_pixel(c[y-c.top()][x-c.left()], pixel); - } - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename pixel_type> - void fill_rect_with_vertical_gradient ( - const canvas& c, - const rectangle& rect, - const pixel_type& pixel_top, - const pixel_type& pixel_bottom, - const rectangle& area_ = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) - { - rectangle area = rect.intersect(c).intersect(area_); - pixel_type pixel; - - const long s = rect.bottom()-rect.top(); - - for (long y = area.top(); y <= area.bottom(); ++y) - { - const long t = rect.bottom()-y; - const long b = y-rect.top(); - vector_to_pixel(pixel, - ((pixel_to_vector<long>(pixel_top)*t + - pixel_to_vector<long>(pixel_bottom)*b)/s)); - - for (long x = area.left(); x <= area.right(); ++x) - { - assign_pixel(c[y-c.top()][x-c.left()], pixel); - } - } - } - -// ---------------------------------------------------------------------------------------- - -} - -#ifdef NO_MAKEFILE -#include "canvas_drawing.cpp" -#endif - -#endif // DLIB_GUI_CANVAS_DRAWINg_ - diff --git a/ml/dlib/dlib/gui_widgets/canvas_drawing_abstract.h b/ml/dlib/dlib/gui_widgets/canvas_drawing_abstract.h deleted file mode 100644 index e4a298c76..000000000 --- a/ml/dlib/dlib/gui_widgets/canvas_drawing_abstract.h +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), and Nils Labugt -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_GUI_CANVAS_DRAWINg_ABSTRACT_ -#ifdef DLIB_GUI_CANVAS_DRAWINg_ABSTRACT_ - -#include "../gui_core.h" -#include "../pixel.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void draw_line ( - const canvas& c, - const point& p1, - const point& p2, - const pixel_type& pixel = rgb_pixel(0,0,0), - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - draws the part of the line from p1 to p1 that overlaps with - the canvas and area onto the canvas. - - Uses the given pixel color. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void draw_rectangle ( - const canvas& c, - rectangle rect, - const pixel_type& pixel = rgb_pixel(0,0,0), - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - Draws the part of the rectangle that overlaps with - the canvas and area onto the canvas. - - Uses the given pixel color. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void draw_circle ( - const canvas& c, - const point& center_point, - double radius, - const pixel_type& pixel = rgb_pixel(0,0,0), - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - draws the part of the circle centered at center_point with the given radius - that overlaps with the canvas and area onto the canvas. - - Uses the given pixel color. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void draw_pixel ( - const canvas& c, - const point& p, - const pixel_type& pixel - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - if (c.contains(p)) then - - sets the pixel in c that represents the point p to the - given pixel color. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void draw_solid_circle ( - const canvas& c, - const point& center_point, - double radius, - const pixel_type& pixel = rgb_pixel(0,0,0), - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - draws the part of the solid circle centered at center_point with the given - radius that overlaps with the canvas and area onto the canvas. - ("solid" means that the interior is also filled in with the given - pixel color) - - Uses the given pixel color. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void draw_solid_convex_polygon ( - const canvas& c, - const std::vector<point>& polygon, - const pixel_type& pixel = rgb_pixel(0,0,0), - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - Interprets the given std::vector polygon object as defining a convex polygon - shape. In particular, the polygon is given by taking the points and drawing - lines between them. That is, imagine drawing a line connecting polygon[i] - and polygon[(i+1)%polygon.size()], for all valid i, and then filling in the - interior of the polygon. That is what this function does. - - When drawing the polygon, only the part of the polygon which overlaps both - the given canvas and area rectangle is drawn. - - Uses the given pixel color to draw the polygon. - !*/ - -// ---------------------------------------------------------------------------------------- - - void draw_button_down ( - const canvas& c, - const rectangle& btn, - unsigned char alpha = 255 - ); - /*! - requires - - 0 <= alpha <= 255 - ensures - - draws the border of a button onto canvas c: - - the border will be that of a button that is depressed - - only the part of the border that overlaps with the canvas object - will be drawn. - - the border will be for the button whose area is defined by the - rectangle btn. - - performs alpha blending such that the button is drawn with full opacity - when alpha is 255 and fully transparent when alpha is 0. - !*/ - -// ---------------------------------------------------------------------------------------- - - void draw_sunken_rectangle ( - const canvas& c, - const rectangle& border, - unsigned char alpha = 255 - ); - /*! - requires - - 0 <= alpha <= 255 - ensures - - draws a sunken rectangle around the given border. - (This is the type of border used for text_fields and - check_boxes and the like). - - performs alpha blending such that the rectangle is drawn with full opacity - when alpha is 255 and fully transparent when alpha is 0. - !*/ - -// ---------------------------------------------------------------------------------------- - - void draw_button_up ( - const canvas& c, - const rectangle& btn, - unsigned char alpha = 255 - ); - /*! - requires - - 0 <= alpha <= 255 - ensures - - draws the border of a button onto canvas c: - - the border will be that of a button that is NOT depressed - - only the part of the border that overlaps with the canvas object - will be drawn. - - the border will be for the button whose area is defined by the - rectangle btn. - - performs alpha blending such that the button is drawn with full opacity - when alpha is 255 and fully transparent when alpha is 0. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void draw_checkered ( - const canvas& c, - const rectangle& area, - const pixel_type& pixel1, - const pixel_type& pixel2 - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - fills the area on the given canvas defined by the rectangle area with a checkers - board pattern where every other pixel gets assigned either pixel1 or pixel2. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename image_type - > - void draw_image ( - const canvas& c - const point& p, - const image_type& image, - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - image_type == an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits<typename image_type::type> is defined - ensures - - draws the given image object onto the canvas such that the upper left corner of the - image will appear at the point p in the canvas's window. (note that the - upper left corner of the image is assumed to be the pixel image[0][0] and the - lower right corner of the image is assumed to be image[image.nr()-1][image.nc()-1]) - - only draws the part of the image that overlaps with the area rectangle - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename image_type - > - void draw_image ( - const canvas& c, - const rectangle& rect, - const image_type& img, - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - image_type == an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits<typename image_type::type> is defined - ensures - - draws the given image object onto the canvas such that the upper left corner - of the image will appear at the point rect.tl_corner() in the canvas's window - and the lower right corner of the image will appear at rect.br_corner() in - the canvas's window. (note that the upper left corner of the image is - assumed to be the pixel image[0][0] and the lower right corner of the image - is assumed to be image[image.nr()-1][image.nc()-1]) - - only draws the part of the image that overlaps with the area rectangle - - Uses nearest neighbor interpolation when the given rect isn't the same size - as the input image. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void fill_rect ( - const canvas& c, - const rectangle& rect, - const pixel_type& pixel - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - fills the area defined by rect in the given canvas with the given pixel color. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void fill_rect_with_vertical_gradient ( - const canvas& c, - const rectangle& rect, - const pixel_type& pixel_top, - const pixel_type& pixel_bottom, - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - fills the rectangle defined by rect in the given canvas with the given colors. - The top of the area will have the pixel_top color and will slowly fade - towards the pixel_bottom color towards the bottom of rect. - - only draws the part of the image that overlaps with the area rectangle - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void fill_gradient_rounded ( - const canvas& c, - const rectangle& rect, - unsigned long radius, - const pixel_type& top_color, - const pixel_type& bottom_color, - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - Fills the region defined by rect in the given canvas with the given colors. - The top of the region will have the top_color color and will slowly fade - towards the bottom_color color towards the bottom of rect. - - The drawn rectangle will have rounded corners and with the amount of - - rounding given by the radius argument. - - only the part of this object that overlaps with area and the canvas - will be drawn on the canvas - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename pixel_type - > - void draw_rounded_rectangle ( - const canvas& c, - const rectangle& rect, - unsigned radius, - const pixel_type& color, - const rectangle& area = rectangle(-infinity,-infinity,infinity,infinity) - ); - /*! - requires - - pixel_traits<pixel_type> is defined - ensures - - Draws the part of the rectangle that overlaps with - the canvas onto the canvas. - - The drawn rectangle will have rounded corners and with the amount of - rounding given by the radius argument. - - Uses the given pixel color. - - only draws the part of the image that overlaps with the area rectangle - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_GUI_CANVAS_DRAWINg_ABSTRACT_ - diff --git a/ml/dlib/dlib/gui_widgets/drawable.cpp b/ml/dlib/dlib/gui_widgets/drawable.cpp deleted file mode 100644 index 8cf114950..000000000 --- a/ml/dlib/dlib/gui_widgets/drawable.cpp +++ /dev/null @@ -1,544 +0,0 @@ -// 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_CPP_ -#define DLIB_DRAWABLe_CPP_ - -#include "drawable.h" - -#include <algorithm> -#include <iostream> - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ----------- drawable_window object ------------------------------------------------------------ -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - rgb_pixel drawable_window:: - background_color ( - ) const - { - auto_mutex M(wm); - return bg_color; - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - set_background_color ( - unsigned long red_, - unsigned long green_, - unsigned long blue_ - ) - { - wm.lock(); - bg_color.red = red_; - bg_color.green = green_; - bg_color.blue = blue_; - wm.unlock(); - // now repaint the window - unsigned long width,height; - get_size(width,height); - rectangle rect(0,0,width-1,height-1); - invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - paint ( - const canvas& c - ) - { - ++event_id; - c.fill(bg_color.red,bg_color.green,bg_color.blue); - - widgets.reset(); - while (widgets.move_next()) - { - widgets.element().value().reset(); - while (widgets.element().value().move_next()) - { - // only dispatch a draw() call if this widget isn't hidden - if (widgets.element().value().element()->hidden == false && - widgets.element().value().element()->event_id != event_id) - { - widgets.element().value().element()->event_id = event_id; - widgets.element().value().element()->draw(c); - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_user_event ( - void* p, - int i - ) - { - drawable* d = static_cast<drawable*>(p); - if (widget_set.is_member(d)) - { - d->on_user_event(i); - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_window_moved( - ) - { - ++event_id; - window_moved.reset(); - while (window_moved.move_next()) - { - if (window_moved.element()->event_id != event_id) - { - window_moved.element()->event_id = event_id; - window_moved.element()->on_window_moved(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_window_resized( - ) - { - ++event_id; - window_resized.reset(); - while (window_resized.move_next()) - { - if (window_resized.element()->event_id != event_id) - { - window_resized.element()->event_id = event_id; - window_resized.element()->on_window_resized(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - ++event_id; - keyboard.reset(); - while (keyboard.move_next()) - { - if (keyboard.element()->event_id != event_id) - { - keyboard.element()->event_id = event_id; - keyboard.element()->on_keydown(key,is_printable,state); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_focus_gained ( - ) - { - ++event_id; - focus.reset(); - while (focus.move_next()) - { - if (focus.element()->event_id != event_id) - { - focus.element()->event_id = event_id; - focus.element()->on_focus_gained(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_focus_lost ( - ) - { - ++event_id; - focus.reset(); - while (focus.move_next()) - { - if (focus.element()->event_id != event_id) - { - focus.element()->event_id = event_id; - focus.element()->on_focus_lost(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ) - { - lastx = x; - lasty = y; - - ++event_id; - mouse_click.reset(); - while (mouse_click.move_next()) - { - if (mouse_click.element()->event_id != event_id) - { - mouse_click.element()->event_id = event_id; - mouse_click.element()->on_mouse_down(btn,state,x,y,is_double_click); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_mouse_up ( - unsigned long btn, - unsigned long state, - long x, - long y - ) - { - lastx = x; - lasty = y; - - ++event_id; - mouse_click.reset(); - while (mouse_click.move_next()) - { - if (mouse_click.element()->event_id != event_id) - { - mouse_click.element()->event_id = event_id; - mouse_click.element()->on_mouse_up(btn,state,x,y); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - lastx = x; - lasty = y; - - ++event_id; - mouse_move.reset(); - while (mouse_move.move_next()) - { - if (mouse_move.element()->event_id != event_id) - { - mouse_move.element()->event_id = event_id; - mouse_move.element()->on_mouse_move(state,x,y); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_mouse_leave ( - ) - { - lastx = -1; - lasty = -1; - - ++event_id; - mouse_move.reset(); - while (mouse_move.move_next()) - { - if (mouse_move.element()->event_id != event_id) - { - mouse_move.element()->event_id = event_id; - mouse_move.element()->on_mouse_leave(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_mouse_enter ( - ) - { - ++event_id; - mouse_move.reset(); - while (mouse_move.move_next()) - { - if (mouse_move.element()->event_id != event_id) - { - mouse_move.element()->event_id = event_id; - mouse_move.element()->on_mouse_enter(); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_wheel_up ( - unsigned long state - ) - { - ++event_id; - mouse_wheel.reset(); - while (mouse_wheel.move_next()) - { - if (mouse_wheel.element()->event_id != event_id) - { - mouse_wheel.element()->event_id = event_id; - mouse_wheel.element()->on_wheel_up(state); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_wheel_down ( - unsigned long state - ) - { - ++event_id; - mouse_wheel.reset(); - while (mouse_wheel.move_next()) - { - if (mouse_wheel.element()->event_id != event_id) - { - mouse_wheel.element()->event_id = event_id; - mouse_wheel.element()->on_wheel_down(state); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable_window:: - on_string_put ( - const std::wstring &str - ) - { - ++event_id; - string_put.reset(); - while (string_put.move_next()) - { - if (string_put.element()->event_id != event_id) - { - string_put.element()->event_id = event_id; - string_put.element()->on_string_put(str); - } - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ----------- drawable object ---------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void drawable:: - enable_events ( - ) - { - auto_mutex M(m); - if (enabled_events == false) - { - enabled_events = true; - drawable* temp = this; - long zo = z_order_value; - - drawable_window::set_of_drawables* sod = parent.widgets[zo]; - if (sod == 0) - { - // this drawable is the first widget at this z order so we need - // to make its containing set - drawable_window::set_of_drawables s; - s.add(temp); - parent.widgets.add(zo,s); - } - else - { - sod->add(temp); - } - - temp = this; - parent.widget_set.add(temp); - - if (events & MOUSE_MOVE) - { - temp = this; - parent.mouse_move.add(temp); - } - if (events & MOUSE_CLICK) - { - temp = this; - parent.mouse_click.add(temp); - } - if (events & MOUSE_WHEEL) - { - temp = this; - parent.mouse_wheel.add(temp); - } - if (events & WINDOW_RESIZED) - { - temp = this; - parent.window_resized.add(temp); - } - if (events & KEYBOARD_EVENTS) - { - temp = this; - parent.keyboard.add(temp); - } - if (events & FOCUS_EVENTS) - { - temp = this; - parent.focus.add(temp); - } - if (events & WINDOW_MOVED) - { - temp = this; - parent.window_moved.add(temp); - } - if (events & STRING_PUT) - { - temp = this; - parent.string_put.add(temp); - } - parent.invalidate_rectangle(rect); - } - } - -// ---------------------------------------------------------------------------------------- - - void drawable:: - set_z_order ( - long order - ) - { - auto_mutex M(m); - if (order != z_order_value && enabled_events) - { - // first remove this drawable from widgets - drawable_window::set_of_drawables* sod = parent.widgets[z_order_value]; - drawable* junk; - sod->remove(this,junk); - - // if there are no more drawables at this z order then destroy the - // set for this order - if (sod->size() == 0) - parent.widgets.destroy(z_order_value); - - // now add this drawable to its new z order - sod = parent.widgets[order]; - if (sod == 0) - { - // this drawable is the first widget at this z order so we need - // to make its containing set - drawable_window::set_of_drawables s, x; - s.add(junk); - long temp_order = order; - parent.widgets.add(temp_order,s); - } - else - { - sod->add(junk); - } - parent.invalidate_rectangle(rect); - - } - z_order_value = order; - } - -// ---------------------------------------------------------------------------------------- - - void drawable:: - disable_events ( - ) - { - auto_mutex M(m); - if (enabled_events) - { - enabled_events = false; - // first remove this drawable from widgets - drawable_window::set_of_drawables* sod = parent.widgets[z_order_value]; - drawable* junk; - sod->remove(this,junk); - - // if there are no more drawables at this z order then destroy the - // set for this order - if (sod->size() == 0) - parent.widgets.destroy(z_order_value); - - parent.widget_set.remove(this,junk); - - // now unregister this drawable from all the events it has registered for. - if (events & MOUSE_MOVE) - parent.mouse_move.remove(this,junk); - if (events & MOUSE_CLICK) - parent.mouse_click.remove(this,junk); - if (events & MOUSE_WHEEL) - parent.mouse_wheel.remove(this,junk); - if (events & WINDOW_RESIZED) - parent.window_resized.remove(this,junk); - if (events & KEYBOARD_EVENTS) - parent.keyboard.remove(this,junk); - if (events & FOCUS_EVENTS) - parent.focus.remove(this,junk); - if (events & WINDOW_MOVED) - parent.window_moved.remove(this,junk); - if (events & STRING_PUT) - parent.string_put.remove(this,junk); - } - } - -// ---------------------------------------------------------------------------------------- - - drawable:: - ~drawable ( - ) - { - try - { - DLIB_ASSERT(events_are_enabled() == false, - "\tdrawable::~drawable()" - << "\n\tYou must disable events for drawable objects in their destructor by calling disable_events()." - << "\n\tthis: " << this - ); - } - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - assert(false); - abort(); - } - disable_events(); - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_DRAWABLe_CPP_ - diff --git a/ml/dlib/dlib/gui_widgets/drawable.h b/ml/dlib/dlib/gui_widgets/drawable.h deleted file mode 100644 index a270b53c8..000000000 --- a/ml/dlib/dlib/gui_widgets/drawable.h +++ /dev/null @@ -1,527 +0,0 @@ -// 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_ - diff --git a/ml/dlib/dlib/gui_widgets/drawable_abstract.h b/ml/dlib/dlib/gui_widgets/drawable_abstract.h deleted file mode 100644 index 8f741d8bb..000000000 --- a/ml/dlib/dlib/gui_widgets/drawable_abstract.h +++ /dev/null @@ -1,717 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. - -#undef DLIB_DRAWABLe_ABSTRACT_ -#ifdef DLIB_DRAWABLe_ABSTRACT_ - -#include "../gui_core.h" -#include "fonts_abstract.h" -#include "canvas_drawing_abstract.h" - -namespace dlib -{ - - /*! - GENERAL REMARKS - This file defines the drawable interface class and the drawable_window which - is just a window that is capable of displaying drawable objects (i.e. objects - that implement the drawable interface). - - The drawable interface is a simple framework for creating more complex - graphical widgets. It provides a default set of functionality and a - set of events which a gui widget may use. - - THREAD SAFETY - All objects and functions defined in this file are thread safe. You may - call them from any thread without serializing access to them. - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class drawable_window -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class drawable_window : public base_window - { - /*! - WHAT THIS OBJECT REPRESENTS - This object represents a window on the desktop that is capable of - containing drawable objects. - - INITIAL STATE - The initial state of the drawable_window is to be hidden. This means - you need to call show() to make it appear. - - EVENTS - The drawable_window object uses all the events provided by base_window - except for the on_window_close() event. This means that if you - define handlers for these events yourself you will have to call - the drawable_window's version of them so that the drawable_window - can continue to process and forward these events to its drawable - objects. - !*/ - public: - - drawable_window ( - bool resizable = true, - bool undecorated = false - ); - /*! - requires - - if (undecorated == true) then - - resizable == false - ensures - - #*this has been properly initialized - - #background_color() == rgb_pixel(212,208,200) - - if (resizable == true) then - - this window will be resizable by the user - - else - - this window will not be resizable by the user - - if (undecorated == true) then - - this window will not have any graphical elements outside - of its drawable area or appear in the system task bar. - (e.g. a popup menu) - throws - - std::bad_alloc - - dlib::thread_error - - dlib::gui_error - This exception is thrown if there is an error while - creating this window. - !*/ - - virtual ~drawable_window( - )=0; - /*! - ensures - - if (this window has not already been closed) then - - closes the window - - does NOT trigger the on_window_close() event - - all resources associated with *this have been released - !*/ - - void set_background_color ( - unsigned long red, - unsigned long green, - unsigned long blue - ); - /*! - ensures - - #background_color().red == red - - #background_color().green == green - - #background_color().blue == blue - !*/ - - rgb_pixel background_color ( - ) const; - /*! - ensures - - returns the background color this window paints its canvas - with before it passes it onto its drawable widgets - !*/ - - private: - // restricted functions - drawable_window(drawable_window&); // copy constructor - drawable_window& operator=(drawable_window&); // assignment operator - - friend class drawable; - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // 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 - top() == 0 - left() == 0 - right() == -1 - bottom() == -1 - get_rect().is_empty() == true - is_hidden() == false - is_enabled() == true - z_order() == 0 - main_font() == default_font::get_font() - - WHAT THIS OBJECT REPRESENTS - This is an interface that all drawable widgets implement. It - provides a standard method (draw()) to draw a widget onto a canvas - and many other convenient functions for drawable objects. - - EVENT FORWARDING - All the events that come to a drawable object are forwarded from its - parent window. Additionally, there is no filtering. This means that - if a drawable registers to receive a certain kind of event then whenever - its parent window receives that event the drawable object will get a - forwarded copy of it as well even if the event occurred outside the - drawable's rectangle. - - The only events that have anything in the way of filtering are the - draw() and on_user_event() events. draw() is only called on a drawable - object when that object is not hidden. on_user_event() is only called - for drawables that the on_user_event()'s first argument specifically - references. All other events are not filtered at all though. - - Z ORDER - Z order defines the order in which drawable objects are drawn. The - lower numbered drawables are drawn first and then the higher numbered - ones. So a drawable with a z order of 0 is drawn before one with a - z order of 1 and so on. - !*/ - - public: - - friend class drawable_window; - - drawable ( - drawable_window& w, - unsigned long events = 0 - ) : - m(w.wm), - parent(w), - hidden(false), - enabled(true) - {} - /*! - ensures - - #*this is properly initialized - - #parent_window() == w - - #*this will not receive any events or draw() requests until - enable_events() is called - - once events_are_enabled() == true this drawable will receive - the on_user_event() event. (i.e. you always get this event, you don't - have to enable it by setting something in the events bitset). - - if (events & MOUSE_MOVE) then - - once events_are_enabled() == true this drawable will receive - the following events related to mouse movement: on_mouse_move, - on_mouse_leave, and on_mouse_enter. - - if (events & MOUSE_CLICK) then - - once events_are_enabled() == true this drawable will receive - the following events related to mouse clicks: on_mouse_down and - on_mouse_up. - - if (events & MOUSE_WHEEL) then - - once events_are_enabled() == true this drawable will receive - the following events related to mouse wheel scrolling: - on_wheel_up and on_wheel_down. - - if (events & WINDOW_RESIZED) then - - once events_are_enabled() == true this drawable will receive - the following event related to its parent window resizing: - on_window_resized. - - if (events & KEYBOARD_EVENTS) then - - once events_are_enabled() == true this drawable will receive - the following keyboard event: on_keydown. - - if (events & FOCUS_EVENTS) then - - once events_are_enabled() == true this drawable will receive - the following focus events: on_focus_gained and on_focus_lost. - - if (events & WINDOW_MOVED) then - - once events_are_enabled() == true this drawable will receive - the following event related to its parent window moving: - on_window_moved. - - if (events & STRING_PUT) then - - once events_are_enabled() == true this drawable will receive - the following event related to wide character string input: - on_string_put. - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~drawable ( - ); - /*! - requires - - events_are_enabled() == false - ensures - - any resources associated with *this have been released - - *this has been removed from its containing window parent_window() and - its parent window will no longer try to dispatch events to it. - Note that this does not trigger a redraw of the parent window. If you - want to do that you must do it yourself. - !*/ - - long z_order ( - ) const; - /*! - ensures - - returns the z order for this drawable. - !*/ - - virtual void set_z_order ( - long order - ); - /*! - ensures - - #z_order() == order - - if (events_are_enabled() == true) then - - parent_window() is updated to reflect the new state of #*this - throws - - std::bad_alloc - !*/ - - const rectangle get_rect ( - ) const; - /*! - ensures - - returns the rectangle that defines the area and position of this - drawable inside its containing window parent_window(). - !*/ - - long bottom ( - ) const; - /*! - ensures - - returns get_rect().bottom() - !*/ - - long top ( - ) const; - /*! - ensures - - returns get_rect().top() - !*/ - - long left ( - ) const; - /*! - ensures - - returns get_rect().left() - !*/ - - long right ( - ) const; - /*! - ensures - - returns get_rect().right() - !*/ - - unsigned long width ( - ) const; - /*! - ensures - - returns get_rect().width() - !*/ - - unsigned long height ( - ) const; - /*! - ensures - - returns get_rect().height() - !*/ - - virtual void set_pos ( - long x, - long y - ); - /*! - ensures - - #top() == y - - #left() == x - - #width() == width() - - #height() == height() - - if (events_are_enabled() == true) then - - parent_window() is updated to reflect the new state of #*this - - i.e. This just sets the upper left corner of this drawable to the - location (x,y) - !*/ - - bool is_enabled ( - ) const; - /*! - ensures - - returns true if this object is enabled and false otherwise. - (it is up to derived classes to define exactly what it means to be - "enabled") - !*/ - - virtual void enable ( - ); - /*! - ensures - - #is_enabled() == true - - if (events_are_enabled() == true) then - - parent_window() is updated to reflect the new state of #*this - !*/ - - virtual void disable ( - ); - /*! - ensures - - #is_enabled() == false - - if (events_are_enabled() == true) then - - parent_window() is updated to reflect the new state of #*this - !*/ - - virtual void set_main_font ( - const shared_ptr_thread_safe<font>& f - ); - /*! - ensures - - #main_font() == f - - if (events_are_enabled() == true) then - - parent_window() is updated to reflect the new state of #*this - !*/ - - const shared_ptr_thread_safe<font> main_font ( - ) const; - /*! - ensures - - returns the current main font being used by this widget - !*/ - - bool is_hidden ( - ) const; - /*! - ensures - - returns true if this object is NOT currently displayed on parent_window() - and false otherwise. - !*/ - - virtual void show ( - ); - /*! - ensures - - #is_hidden() == false - - if (events_are_enabled() == true) then - - parent_window() is updated to reflect the new state of #*this - !*/ - - virtual void hide ( - ); - /*! - ensures - - #is_hidden() == true - - if (events_are_enabled() == true) then - - parent_window() is updated to reflect the new state of #*this - !*/ - - drawable_window& parent_window ( - ); - /*! - ensures - - returns a reference to the drawable_window that this drawable is - being drawn on and receiving events from. - !*/ - - const drawable_window& parent_window ( - ) const; - /*! - ensures - - returns a const reference to the drawable_window that this drawable - is being drawn on and receiving events from. - !*/ - - virtual int next_free_user_event_number ( - )const { return 0; } - /*! - ensures - - returns the smallest number, i, that is the next user event number you - can use in calls to parent.trigger_user_event((void*)this,i). - - This function exists because of the following scenario. Suppose - you make a class called derived1 that inherits from drawable and - in derived1 you use a user event to do something. Then suppose - you inherit from derived1 to make derived2. Now in derived2 you - may want to use a user event to do something as well. How are you - to know which user event numbers are in use already? This function - solves that problem. You would define derived1::next_free_user_event_number() - so that it returned a number bigger than any user event numbers used by - derived1 or its ancestors. Then derived2 could just call - derived1::next_free_user_event_number() to find out what numbers it could use. - !*/ - - protected: - /*!A drawable_protected_variables - - These protected members are provided because they are needed to - implement drawable widgets. - !*/ - - // This is the rectangle that is returned by get_rect() - rectangle rect; - - // This is the mutex used to serialize access to this class. - const rmutex& m; - - // This is the parent window of this drawable - drawable_window& parent; - - // This is the bool returned by is_hidden() - bool hidden; - - // This is the bool returned by is_enabled() - bool enabled; - - // This is the font pointer returned by main_font() - shared_ptr_thread_safe<font> mfont; - - // This is the x coordinate that we last saw the mouse at or -1 if the mouse - // is outside the parent window. - const long& lastx; - - // This is the y coordinate that we last saw the mouse at or -1 if the mouse - // is outside the parent window. - const long& lasty; - - - void enable_events ( - ); - /*! - ensures - - #events_are_enabled() == true - !*/ - - void disable_events ( - ); - /*! - ensures - - #events_are_enabled() == false - !*/ - - bool events_are_enabled ( - ) const; - /*! - ensures - - returns true if this object is receiving events and draw() - requests from its parent window. - - returns false otherwise - !*/ - - // ---------------- EVENT HANDLERS ------------------ - - virtual void on_user_event ( - int i - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - is called whenever the parent window receives an on_user_event(p,i) event - where p == this. (i.e. this is just a redirect of on_user_event for - cases where the first argument of on_user_event is equal to the - this pointer). - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_window_resized( - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_window_resized() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_window_moved( - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_window_moved() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_mouse_down() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_mouse_up ( - unsigned long btn, - unsigned long state, - long x, - long y - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_mouse_up() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_mouse_move ( - unsigned long state, - long x, - long y - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - x == lastx - - y == lasty - - this is just the base_window::on_mouse_move() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_mouse_leave ( - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_mouse_leave() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_mouse_enter ( - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_mouse_enter() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_wheel_up ( - unsigned long state - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_wheel_up() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_wheel_down ( - unsigned long state - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_wheel_down() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_focus_gained ( - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_focus_gained() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_focus_lost ( - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_focus_lost() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_keydown() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void on_string_put ( - const std::wstring &str - ){} - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - this is just the base_window::on_put_string() event forwarded to - this object. See the gui_core specs for the details about this event. - ensures - - does not change the state of mutex m. - !*/ - - virtual void draw ( - const canvas& c - ) const=0; - /*! - requires - - events_are_enabled() == true - - mutex m is locked - - is_hidden() == false - - is called by parent_window() when it needs to repaint itself. - - c == the canvas object for the area of parent_window() that needs - to be repainted. - ensures - - does not change the state of mutex m. - - draws the area of *this that intersects with the canvas onto - the canvas object c. - !*/ - - private: - - // restricted functions - drawable(drawable&); // copy constructor - drawable& operator=(drawable&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_DRAWABLe_ABSTRACT_ - diff --git a/ml/dlib/dlib/gui_widgets/fonts.cpp b/ml/dlib/dlib/gui_widgets/fonts.cpp deleted file mode 100644 index dfbf9f720..000000000 --- a/ml/dlib/dlib/gui_widgets/fonts.cpp +++ /dev/null @@ -1,673 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), and Nils Labugt, Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_FONTs_CPP_ -#define DLIB_FONTs_CPP_ - -#include "fonts.h" - -#include <fstream> -#include <memory> -#include <sstream> - -#include "../serialize.h" -#include "../base64.h" -#include "../compress_stream.h" -#include "../tokenizer.h" -#include "nativefont.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - const std::string get_decoded_string_with_default_font_data() - { - dlib::base64::kernel_1a base64_coder; - dlib::compress_stream::kernel_1ea compressor; - std::ostringstream sout; - std::istringstream sin; - - /* - SOURCE BDF FILE (helvR12.bdf) COMMENTS - COMMENT $XConsortium: helvR12.bdf,v 1.15 95/01/26 18:02:58 gildea Exp $ - COMMENT $Id: helvR12.bdf,v 1.26 2004-11-28 20:08:46+00 mgk25 Rel $ - COMMENT - COMMENT + - COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. - COMMENT Copyright 1988, 1994 Digital Equipment Corporation. - COMMENT - COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be - COMMENT registered in certain jurisdictions. - COMMENT Permission to use these trademarks is hereby granted only in - COMMENT association with the images described in this file. - COMMENT - COMMENT Permission to use, copy, modify, distribute and sell this software - COMMENT and its documentation for any purpose and without fee is hereby - COMMENT granted, provided that the above copyright notices appear in all - COMMENT copies and that both those copyright notices and this permission - COMMENT notice appear in supporting documentation, and that the names of - COMMENT Adobe Systems and Digital Equipment Corporation not be used in - COMMENT advertising or publicity pertaining to distribution of the software - COMMENT without specific, written prior permission. Adobe Systems and - COMMENT Digital Equipment Corporation make no representations about the - COMMENT suitability of this software for any purpose. It is provided "as - COMMENT is" without express or implied warranty. - COMMENT - - */ - - // The base64 encoded data we want to decode and return. - sout << "AXF+zOQzCgGitrKiOCGEL4hlIv1ZenWJyjMQ4rJ6f/oPMeHqsZn+8XnpehwFQTz3dtUGlZRAUoOa"; - sout << "uVo8UiplcFxuK69A+94rpMCMAyEeeOwZ/tRzkX4eKuU3L4xtsJDknMiYUNKaMrYimb1QJ0E+SRqQ"; - sout << "wATrMTecYNZvJJm02WibiwE4cJ5scvkHNl4KJT5QfdwRdGopTyUVdZvRvtbTLLjsJP0fQEQLqemf"; - sout << "qPE4kDD79ehrBIwLO1Y6TzxtrrIoQR57zlwTUyLenqRtSN3VLtjWYd82cehRIlTLtuxBg2s+zZVq"; - sout << "jNlNnYTSM+Swy06qnQgg+Dt0lhtlB9shR1OAlcfCtTW6HKoBk/FGeDmjTGW4bNCGv7RjgM6TlLDg"; - sout << "ZYSSA6ZCCAKBgE++U32gLHCCiVkPTkkp9P6ioR+e3SSKRNm9p5MHf+ZQ3LJkW8KFJ/K9gKT1yvyv"; - sout << "F99pAvOOq16tHRFvzBs+xZj/mUpH0lGIS7kLWr9oP2KuccVrz25aJn3kDruwTYoD+CYlOqtPO0Mv"; - sout << "dEI0LUR0Ykp1M2rWo76fJ/fpzHjV7737hjkNPJ13nO72RMDr4R5V3uG7Dw7Ng+vGX3WgJZ4wh1JX"; - sout << "pl2VMqC5JXccctzvnQvnuvBvRm7THgwQUgMKKT3WK6afUUVlJy8DHKuU4k1ibfVMxAmrwKdTUX2w"; - sout << "cje3A05Qji3aop65qEdwgI5O17HIVoRQOG/na+XRMowOfUvI4H8Z4+JGACfRrQctgYDAM9eJzm8i"; - sout << "PibyutmJfZBGg0a3oC75S5R9lTxEjPocnEyJRYNnmVnVAmKKbTbTsznuaD+D1XhPdr2t3A4bRTsp"; - sout << "toKKtlFnd9YGwLWwONDwLnoQ/IXwyF7txrRHNSVToh772U0Aih/yn5vnmcMF750eiMzRAgXu5sbR"; - sout << "VXEOVCiLgVevN5umkvjZt1eGTSSzDMrIvnv4nyOfaFsD+I76wQfgLqd71rheozGtjNc0AOTx4Ggc"; - sout << "eUSFHTDAVfTExBzckurtyuIAqF986a0JLHCtsDpBa2wWNuiQYOH3/LX1zkdU2hdamhBW774bpEwr"; - sout << "dguMxxOeDGOBgIlM5gxXGYXSf5IN3fUAEPfOPRxB7T+tpjFnWd7cg+JMabci3zhJ9ANaYT7HGeTX"; - sout << "bulKnGHjYrR1BxdK3YeliogQRU4ytmxlyL5zlNFU/759mA8XSfIPMEZn9Vxkb00q1htF7REiDcr3"; - sout << "kW1rtPAc7VQNEhT54vK/YF6rMvjO7kBZ/vLYo7E8e8hDKEnY8ucrC3KGmeo31Gei74BBcEbvJBd3"; - sout << "/YAaIKgXWwU2wSUw9wLq2RwGwyguvKBx0J/gn27tjcVAHorRBwxzPpk8r+YPyN+SifSzEL7LEy1G"; - sout << "lPHxmXTrcqnH9qraeAqXJUJvU8SJJpf/tmsAE+XSKD/kpVBnT5qXsJ1SRFS7MtfPjE1j/NYbaQBI"; - sout << "bOrh81zaYCEJR0IKHWCIsu/MC3zKXfkxFgQ9XpYAuWjSSK64YpgkxSMe8VG8yYvigOw2ODg/z4FU"; - sout << "+HpnEKF/M/mKfLKK1i/8BV7xcYVHrhEww1QznoFklJs/pEg3Kd5PE1lRii6hvTn6McVAkw+YbH9q"; - sout << "/sg4gFIAvai64hMcZ1oIZYppj3ZN6KMdyhK5s4++ZS/YOV2nNhW73ovivyi2Tjg7lxjJJtsYrLKb"; - sout << "zIN1slOICKYwBq42TFBcFXaZ6rf0Czd09tL+q6A1Ztgr3BNuhCenjhWN5ji0LccGYZo6bLTggRG/"; - sout << "Uz6K3CBBU/byLs79c5qCohrr7rlpDSdbuR+aJgNiWoU6T0i2Tvua6h51LcWEHy5P2n146/Ae2di4"; - sout << "eh20WQvclrsgm1oFTGD0Oe85GKOTA7vvwKmLBc1wwA0foTuxzVgj0TMTFBiYLTLG4ujUyBYy1N6e"; - sout << "H8EKi8H+ZAlqezrjABO3BQr33ewdZL5IeJ4w7gdGUDA6+P+7cODcBW50X9++6YTnKctuEw6aXBpy"; - sout << "GgcMfPE61G8YKBbFGFic3TVvGCLvre1iURv+F+hU4/ee6ILuPnpYnSXX2iCIK/kmkBse8805d4Qe"; - sout << "DG/8rBW9ojvAgc0jX7CatPEMHGkcz+KIZoKMI7XXK4PJpGQUdq6EdIhJC4koXEynjwwXMeC+jJqH"; - sout << "agwrlDNssq/8AA=="; - - - - // Put the data into the istream sin - sin.str(sout.str()); - sout.str(""); - - // Decode the base64 text into its compressed binary form - base64_coder.decode(sin,sout); - sin.clear(); - sin.str(sout.str()); - sout.str(""); - - // Decompress the data into its original form - compressor.decompress(sin,sout); - - // Return the decoded and decompressed data - return sout.str(); - } - - - default_font:: - default_font ( - ) - { - using namespace std; - l = new letter[256]; - - try - { - istringstream sin(get_decoded_string_with_default_font_data()); - - for (int i = 0; i < 256; ++i) - { - deserialize(l[i],sin); - } - - } - catch (...) - { - delete [] l; - throw; - } - } - -// ---------------------------------------------------------------------------------------- - - void serialize ( - const letter& item, - std::ostream& out - ) - { - try - { - serialize(item.w,out); - serialize(item.count,out); - - for (unsigned long i = 0; i < item.count; ++i) - { - serialize(item.points[i].x,out); - serialize(item.points[i].y,out); - } - } - catch (serialization_error e) - { - throw serialization_error(e.info + "\n while serializing object of type letter"); - } - } - - void deserialize ( - letter& item, - std::istream& in - ) - { - try - { - if (item.points) - delete [] item.points; - - deserialize(item.w,in); - deserialize(item.count,in); - - if (item.count > 0) - item.points = new letter::point[item.count]; - else - item.points = 0; - - for (unsigned long i = 0; i < item.count; ++i) - { - deserialize(item.points[i].x,in); - deserialize(item.points[i].y,in); - } - } - catch (serialization_error e) - { - item.w = 0; - item.count = 0; - item.points = 0; - throw serialization_error(e.info + "\n while deserializing object of type letter"); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace bdf_font_helpers - { - class bdf_parser - { - public: - bdf_parser( std::istream& in ) : in_( in ) - { - std::string str_tmp; - int int_tmp; - - str_tmp = "STARTFONT"; int_tmp = STARTFONT; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "FONTBOUNDINGBOX";int_tmp = FONTBOUNDINGBOX; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "DWIDTH"; int_tmp = DWIDTH; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "CHARS"; int_tmp = CHARS; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "STARTCHAR"; int_tmp = STARTCHAR; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "ENCODING"; int_tmp = ENCODING; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "BBX"; int_tmp = BBX; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "BITMAP"; int_tmp = BITMAP; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "ENDCHAR"; int_tmp = ENDCHAR; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "ENDFONT"; int_tmp = ENDFONT; keyword_map.add( str_tmp, int_tmp ); - str_tmp = "DEFAULT_CHAR"; int_tmp = DEFAULT_CHAR; keyword_map.add( str_tmp, int_tmp ); - - tokzr.set_identifier_token( tokzr.uppercase_letters(), tokzr.uppercase_letters() + "_" ); - tokzr.set_stream( in ); - - } - - enum bdf_enums - { - NO_KEYWORD = 0, - STARTFONT = 1, - FONTBOUNDINGBOX = 2, - DWIDTH = 4, - DEFAULT_CHAR = 8, - CHARS = 16, - STARTCHAR = 32, - ENCODING = 64, - BBX = 128, - BITMAP = 256, - ENDCHAR = 512, - ENDFONT = 1024 - - }; - struct header_info - { - int FBBx, FBBy, Xoff, Yoff; - int dwx0, dwy0; - bool has_global_dw; - long default_char; - }; - struct char_info - { - int dwx0, dwy0; - int BBw, BBh, BBxoff0x, BByoff0y; - array2d<char> bitmap; - bool has_dw; - }; - bool parse_header( header_info& info ) - { - if ( required_keyword( STARTFONT ) == false ) - return false; // parse_error: required keyword missing - info.has_global_dw = false; - int find = FONTBOUNDINGBOX | DWIDTH | DEFAULT_CHAR; - int stop = CHARS | STARTCHAR | ENCODING | BBX | BITMAP | ENDCHAR | ENDFONT; - int res; - while ( 1 ) - { - res = find_keywords( find | stop ); - if ( res & FONTBOUNDINGBOX ) - { - in_ >> info.FBBx >> info.FBBy >> info.Xoff >> info.Yoff; - if ( in_.fail() ) - return false; // parse_error - find &= ~FONTBOUNDINGBOX; - continue; - } - if ( res & DWIDTH ) - { - in_ >> info.dwx0 >> info.dwy0; - if ( in_.fail() ) - return false; // parse_error - find &= ~DWIDTH; - info.has_global_dw = true; - continue; - } - if ( res & DEFAULT_CHAR ) - { - in_ >> info.default_char; - if ( in_.fail() ) - return false; // parse_error - find &= ~DEFAULT_CHAR; - continue; - } - if ( res & NO_KEYWORD ) - return false; // parse_error: unexpected EOF - break; - } - if ( res != CHARS || ( find & FONTBOUNDINGBOX ) ) - return false; // parse_error: required keyword missing or unexpeced keyword - return true; - } - int parse_glyph( char_info& info, unichar& enc ) - { - info.has_dw = false; - int e; - int res; - while ( 1 ) - { - res = find_keywords( ENCODING ); - if ( res != ENCODING ) - return 0; // no more glyphs - in_ >> e; - if ( in_.fail() ) - return -1; // parse_error - if ( e >= static_cast<int>(enc) ) - break; - } - int find = BBX | DWIDTH; - int stop = STARTCHAR | ENCODING | BITMAP | ENDCHAR | ENDFONT; - while ( 1 ) - { - res = find_keywords( find | stop ); - if ( res & BBX ) - { - in_ >> info.BBw >> info.BBh >> info.BBxoff0x >> info.BByoff0y; - if ( in_.fail() ) - return -1; // parse_error - find &= ~BBX; - continue; - } - if ( res & DWIDTH ) - { - in_ >> info.dwx0 >> info.dwy0; - if ( in_.fail() ) - return -1; // parse_error - find &= ~DWIDTH; - info.has_dw = true; - continue; - } - if ( res & NO_KEYWORD ) - return -1; // parse_error: unexpected EOF - break; - } - if ( res != BITMAP || ( find != NO_KEYWORD ) ) - return -1; // parse_error: required keyword missing or unexpeced keyword - unsigned h = info.BBh; - unsigned w = ( info.BBw + 7 ) / 8 * 2; - info.bitmap.set_size( h, w ); - for ( unsigned r = 0;r < h;r++ ) - { - trim(); - std::string str = ""; - extract_hex(str); - if(str.size() < w) - return -1; // parse_error - for ( unsigned c = 0;c < w;c++ ) - info.bitmap[r][c] = str[c]; - } - if ( in_.fail() ) - return -1; // parse_error - if ( required_keyword( ENDCHAR ) == false ) - return -1; // parse_error: required keyword missing - enc = e; - return 1; - } - private: - map<std::string, int>::kernel_1a_c keyword_map; - tokenizer::kernel_1a_c tokzr; - std::istream& in_; - void extract_hex(std::string& str) - { - int type; - std::string token; - while ( 1 ) - { - type = tokzr.peek_type(); - if ( type == tokenizer::kernel_1a_c::IDENTIFIER || type == tokenizer::kernel_1a_c::NUMBER ) - { - tokzr.get_token( type, token ); - str += token; - continue; - } - break; - } - } - void trim() - { - int type; - std::string token; - while ( 1 ) - { - type = tokzr.peek_type(); - if ( type == tokenizer::kernel_1a_c::WHITE_SPACE || type == tokenizer::kernel_1a_c::END_OF_LINE ) - { - tokzr.get_token( type, token ); - continue; - } - break; - } - } - bool required_keyword( int kw ) - { - int type; - std::string token; - while ( 1 ) - { - tokzr.get_token( type, token ); - if ( type == tokenizer::kernel_1a_c::WHITE_SPACE || type == tokenizer::kernel_1a_c::END_OF_LINE ) - continue; - if ( type != tokenizer::kernel_1a_c::IDENTIFIER || keyword_map.is_in_domain( token ) == false || ( keyword_map[token] & kw ) == 0 ) - return false; - break; - } - return true; - } - int find_keywords( int find ) - { - int type; - std::string token; - while ( 1 ) - { - tokzr.get_token( type, token ); - if ( type == tokenizer::kernel_1a_c::END_OF_FILE ) - return NO_KEYWORD; - if ( type == tokenizer::kernel_1a_c::IDENTIFIER && keyword_map.is_in_domain( token ) == true ) - { - int kw = keyword_map[token]; - if ( kw & find ) - return kw; - } - } - return true; - } - - }; - - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// bdf_font functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - bdf_font::bdf_font( - long default_char_ - ) : - default_char(0), - is_initialized( false ), - right_overflow_( 0 ), - has_global_width( false ), - specified_default_char( default_char_ ) - { - // make sure gl contains at least one letter - gl.resize(1); - } - -// ---------------------------------------------------------------------------------------- - - void bdf_font::adjust_metrics( - ) - { - if ( is_initialized == false ) - return; - // set starting values for fbb - if ( gl[default_char].num_of_points() > 0 ) - { - letter& g = gl[default_char]; - fbb.set_top( g[0].y ); - fbb.set_bottom( g[0].y ); - fbb.set_left( g[0].x ); - fbb.set_right( g[0].x ); - } - else - { - // ok, the default char was a space - // let's just choose some safe arbitrary values then... - fbb.set_top( 10000 ); - fbb.set_bottom( -10000 ); - fbb.set_left( 10000 ); - fbb.set_right( -10000 ); - } - right_overflow_ = 0; - for ( unichar n = 0; n < gl.size(); n++ ) - { - letter& g = gl[n]; - unsigned short nr_pts = g.num_of_points(); - for ( unsigned short k = 0;k < nr_pts;k++ ) - { - fbb.set_top( std::min( fbb.top(), (long)g[k].y ) ); - fbb.set_left( std::min( fbb.left(), (long)g[k].x ) ); - fbb.set_bottom( std::max( fbb.bottom(), (long)g[k].y ) ); - fbb.set_right( std::max( fbb.right(), (long)g[k].x ) ); - right_overflow_ = std::max( right_overflow_, (unsigned long)(g[k].x - g.width()) ); // superfluous? - } - } - } - -// ---------------------------------------------------------------------------------------- - - long bdf_font:: - read_bdf_file( - std::istream& in, - unichar max_enc, - unichar min_enc - ) - { - using namespace bdf_font_helpers; - - bdf_parser parser( in ); - bdf_parser::header_info hinfo; - bdf_parser::char_info cinfo; - - gl.resize(max_enc+1); - hinfo.default_char = - 1; - if ( is_initialized == false || static_cast<std::streamoff>(in.tellg()) == std::ios::beg ) - { - if ( parser.parse_header( hinfo ) == false ) - return 0; // parse_error: invalid or missing header - } - else - { - // not start of file, so use values from previous read. - hinfo.has_global_dw = has_global_width; - hinfo.dwx0 = global_width; - } - int res; - unichar nr_letters_added = 0; - unsigned width; - for ( unichar n = min_enc; n <= max_enc; n++ ) - { - if ( in.eof() ) - break; - long pos = in.tellg(); - res = parser.parse_glyph( cinfo, n ); - if ( res < 0 ) - return 0; // parse_error - if ( res == 0 ) - continue; - if ( n > max_enc ) - { - in.seekg( pos ); - break; - } - - if ( cinfo.has_dw == false ) - { - if ( hinfo.has_global_dw == false ) - return 0; // neither width info for the glyph, nor for the font as a whole (monospace). - width = hinfo.dwx0; - } - else - width = cinfo.dwx0; - - - if ( bitmap_to_letter( cinfo.bitmap, n, width, cinfo.BBxoff0x, cinfo.BByoff0y ) == false ) - return 0; - nr_letters_added++; - - if ( is_initialized == false ) - { - // Bonding rectangle for the font. - fbb.set_top( -( hinfo.Yoff + hinfo.FBBy - 1 ) ); - fbb.set_bottom( -hinfo.Yoff ); - fbb.set_left( hinfo.Xoff ); - fbb.set_right( hinfo.Xoff + hinfo.FBBx - 1 ); - // We need to compute this after all the glyphs are loaded. - right_overflow_ = 0; - // set this to something valid now, just in case. - default_char = n; - // Save any global width in case we later read from the same file. - has_global_width = hinfo.has_global_dw; - if ( has_global_width ) - global_width = hinfo.dwx0; - // dont override value specified in the constructor with value specified in the file - if ( specified_default_char < 0 && hinfo.default_char >= 0 ) - specified_default_char = hinfo.default_char; - - is_initialized = true; - } - } - if ( is_initialized == false ) - return 0; // Not a single glyph was found within the specified range. - - if ( specified_default_char >= 0 ) - default_char = specified_default_char; - // no default char specified, try find something sane. - else - default_char = 0; - - return nr_letters_added; - } - -// ---------------------------------------------------------------------------------------- - - bool bdf_font:: - bitmap_to_letter( - array2d<char>& bitmap, - unichar enc, - unsigned long width, - int x_offset, - int y_offset - ) - { - unsigned nr_points = 0; - bitmap.reset(); - while ( bitmap.move_next() ) - { - unsigned char ch = bitmap.element(); - if ( ch > '9' ) - ch -= 'A' - '9' - 1; - ch -= '0'; - if ( ch > 0xF ) - return false; // parse error: invalid hex digit - bitmap.element() = ch; - if ( ch & 8 ) - nr_points++; - if ( ch & 4 ) - nr_points++; - if ( ch & 2 ) - nr_points++; - if ( ch & 1 ) - nr_points++; - } - - letter( width, nr_points ).swap(gl[enc]); - - unsigned index = 0; - for ( int r = 0;r < bitmap.nr();r++ ) - { - for ( int c = 0;c < bitmap.nc();c++ ) - { - int x = x_offset + c * 4; - int y = -( y_offset + bitmap.nr() - r - 1 ); - char ch = bitmap[r][c]; - letter& glyph = gl[enc]; - if ( ch & 8 ) - { - glyph[index] = letter::point( x, y ); - right_overflow_ = std::max( right_overflow_, x - width ); - index++; - } - if ( ch & 4 ) - { - glyph[index] = letter::point( x + 1, y ); - right_overflow_ = std::max( right_overflow_, x + 1 - width ); - index++; - } - if ( ch & 2 ) - { - glyph[index] = letter::point( x + 2, y ); - right_overflow_ = std::max( right_overflow_, x + 2 - width ); - index++; - } - if ( ch & 1 ) - { - glyph[index] = letter::point( x + 3, y ); - right_overflow_ = std::max( right_overflow_, x + 3 - width ); - index++; - } - } - } - return true; - } - -// ---------------------------------------------------------------------------------------- - - const std::shared_ptr<font> get_native_font ( - ) - { - return nativefont::native_font::get_font(); - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_FONTs_CPP_ - diff --git a/ml/dlib/dlib/gui_widgets/fonts.h b/ml/dlib/dlib/gui_widgets/fonts.h deleted file mode 100644 index 5d3181aaa..000000000 --- a/ml/dlib/dlib/gui_widgets/fonts.h +++ /dev/null @@ -1,628 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), and Nils Labugt, Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. - -#ifndef DLIB_FONTs_ -#define DLIB_FONTs_ - -#include <memory> -#include <string> - -#include "fonts_abstract.h" -#include "../gui_core.h" -#include "../algs.h" -#include "../serialize.h" -#include "../unicode.h" -#include "../array.h" -#include "../array2d.h" -#include "../threads.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - class letter - { - /*! - INITIAL VALUE - - defined by constructor - - CONVENTION - - if (points != 0) then - - points == an array of count point structs - - w == width() - - count == num_of_points() - !*/ - public: - struct point - { - point (){} - - point ( - signed char x_, - signed char y_ - ) : - x(x_), - y(y_) - {} - - signed char x; - signed char y; - }; - - letter ( - ) : - points(0), - w(0), - count(0) - {} - - letter ( - unsigned short width_, - unsigned short point_count - ) : - points(new point[point_count]), - w(width_), - count(point_count) - {} - - ~letter( - ) - { - if (points) - delete [] points; - } - - unsigned short width ( - ) const { return w; } - - unsigned short num_of_points ( - ) const { return count;} - - point& operator[] ( - unsigned short i - ) - { - DLIB_ASSERT (i < num_of_points(), - "\tvoid letter::operator[]()" - << "\n\ti: " << i - << "\n\tnum_of_points(): " << num_of_points() ); - return points[i]; - } - - const point& operator[] ( - unsigned short i - ) const - { - DLIB_ASSERT (i < num_of_points(), - "\tvoid letter::operator[]()" - << "\n\ti: " << i - << "\n\tnum_of_points(): " << num_of_points() ); - return points[i]; - } - - friend void serialize ( - const letter& item, - std::ostream& out - ); - - friend void deserialize ( - letter& item, - std::istream& in - ); - - void swap ( - letter& item - ) - { - exchange(points, item.points); - exchange(w, item.w); - exchange(count, item.count); - } - - private: - // restricted functions - letter(letter&); // copy constructor - letter& operator=(letter&); // assignment operator - - point* points; - unsigned short w; - unsigned short count; - }; - - inline void swap ( - letter& a, - letter& b - ) { a.swap(b); } - -// ---------------------------------------------------------------------------------------- - - class font - { - public: - virtual ~font() {} - - virtual bool has_character ( - unichar ch - )const=0; - bool has_character(char ch) const { return this->has_character(zero_extend_cast<unichar>(ch)); } - bool has_character(wchar_t ch) const { return this->has_character(zero_extend_cast<unichar>(ch)); } - - const letter& operator[] (char ch) const { return (*this)[zero_extend_cast<unichar>(ch)]; }; - const letter& operator[] (wchar_t ch)const { return (*this)[zero_extend_cast<unichar>(ch)]; }; - - virtual const letter& operator[] ( - unichar ch - )const=0; - - virtual unsigned long height ( - ) const = 0; - - virtual unsigned long ascender ( - ) const = 0; - - virtual unsigned long left_overflow ( - ) const = 0; - - virtual unsigned long right_overflow ( - ) const = 0; - - // ------------------------------------------------------------------------------------ - - template <typename T, typename traits, typename alloc> - void compute_size ( - const std::basic_string<T,traits,alloc>& str, - unsigned long& width, - unsigned long& height, - typename std::basic_string<T,traits,alloc>::size_type first = 0, - typename std::basic_string<T,traits,alloc>::size_type last = (std::basic_string<T,traits,alloc>::npos) - ) const - { - typedef std::basic_string<T,traits,alloc> string; - DLIB_ASSERT ( (last == string::npos) || (first <= last && last < str.size()) , - "\tvoid font::compute_size()" - << "\n\tlast == string::npos: " << ((last == string::npos)?"true":"false") - << "\n\tfirst: " << (unsigned long)first - << "\n\tlast: " << (unsigned long)last - << "\n\tstr.size(): " << (unsigned long)str.size() ); - - unsigned long line_width = 0; - unsigned long newlines = 0; - width = 0; - height = 0; - - if (str.size()) - { - if (last == string::npos) - last = str.size()-1; - const font& f = *this; - - for (typename string::size_type i = first; i <= last; ++i) - { - // ignore '\r' characters - if (str[i] == '\r') - continue; - - if (str[i] == '\n') - { - ++newlines; - width = std::max(width,line_width); - line_width = 0; - } - else - { - if (is_combining_char(str[i]) == false) - line_width += f[str[i]].width(); - } - } - width = std::max(width,line_width); - - height = (newlines+1)*f.height(); - width += f.left_overflow() + f.right_overflow(); - } - } - - // ------------------------------------------------------------------------------------ - - template <typename T, typename traits, typename alloc, typename pixel_type> - void draw_string ( - const canvas& c, - const rectangle& rect, - const std::basic_string<T,traits,alloc>& str, - const pixel_type& color, - typename std::basic_string<T,traits,alloc>::size_type first = 0, - typename std::basic_string<T,traits,alloc>::size_type last = (std::basic_string<T,traits,alloc>::npos), - const rectangle area_ = rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max()) - ) const - { - typedef std::basic_string<T,traits,alloc> string; - DLIB_ASSERT ( (last == string::npos) || (first <= last && last < str.size()) , - "\tvoid font::draw_string()" - << "\n\tlast == string::npos: " << ((last == string::npos)?"true":"false") - << "\n\tfirst: " << (unsigned long)first - << "\n\tlast: " << (unsigned long)last - << "\n\tstr.size(): " << (unsigned long)str.size() ); - - rectangle area = rect.intersect(c).intersect(area_); - if (area.is_empty() || str.size() == 0) - return; - - if (last == string::npos) - last = str.size()-1; - - const font& f = *this; - - long y_offset = rect.top() + f.ascender() - 1; - - long pos = rect.left()+f.left_overflow(); - for (typename string::size_type i = first; i <= last; ++i) - { - // ignore the '\r' character - if (str[i] == '\r') - continue; - - // A combining character should be applied to the previous character, and we - // therefore make one step back. If a combining comes right after a newline, - // then there must be some kind of error in the string, and we don't combine. - if(is_combining_char(str[i]) && - pos > rect.left() + static_cast<long>(f.left_overflow())) - { - pos -= f[str[i]].width(); - } - - if (str[i] == '\n') - { - y_offset += f.height(); - pos = rect.left()+f.left_overflow(); - continue; - } - - // only look at letters in the intersection area - if (area.bottom() + static_cast<long>(f.height()) < y_offset) - { - // the string is now below our rectangle so we are done - break; - } - else if (area.left() > pos - static_cast<long>(f.left_overflow()) && - pos + static_cast<long>(f[str[i]].width() + f.right_overflow()) < area.left() ) - { - pos += f[str[i]].width(); - continue; - } - else if (area.right() + static_cast<long>(f.right_overflow()) < pos) - { - // keep looking because there might be a '\n' in the string that - // will wrap us around and put us back into our rectangle. - continue; - } - - // at this point in the loop we know that f[str[i]] overlaps - // horizontally with the intersection rectangle area. - - const letter& l = f[str[i]]; - for (unsigned short i = 0; i < l.num_of_points(); ++i) - { - const long x = l[i].x + pos; - const long y = l[i].y + y_offset; - // draw each pixel of the letter if it is inside the intersection - // rectangle - if (area.contains(x,y)) - { - assign_pixel(c[y-c.top()][x-c.left()], color); - } - } - - pos += l.width(); - } - } - template <typename T, typename traits, typename alloc> - void draw_string ( - const canvas& c, - const rectangle& rect, - const std::basic_string<T,traits,alloc>& str - ) const - { - draw_string(c,rect, str, 0, 0, (std::basic_string<T,traits,alloc>::npos), - rectangle(std::numeric_limits<long>::min(), std::numeric_limits<long>::min(), - std::numeric_limits<long>::max(), std::numeric_limits<long>::max())); - } - - // ------------------------------------------------------------------------------------ - - template <typename T, typename traits, typename alloc> - const rectangle compute_cursor_rect ( - const rectangle& rect, - const std::basic_string<T,traits,alloc>& str, - unsigned long index, - typename std::basic_string<T,traits,alloc>::size_type first = 0, - typename std::basic_string<T,traits,alloc>::size_type last = (std::basic_string<T,traits,alloc>::npos) - ) const - { - typedef std::basic_string<T,traits,alloc> string; - DLIB_ASSERT ( (last == string::npos) || (first <= last && last < str.size()) , - "\trectangle font::compute_cursor_rect()" - << "\n\tlast == string::npos: " << ((last == string::npos)?"true":"false") - << "\n\tfirst: " << (unsigned long)first - << "\n\tlast: " << (unsigned long)last - << "\n\tindex: " << index - << "\n\tstr.size(): " << (unsigned long)str.size() ); - - const font& f = *this; - - if (last == string::npos) - last = str.size()-1; - - long x = f.left_overflow(); - long y = 0; - int count = 0; - - if (str.size() != 0) - { - for (typename string::size_type i = first; i <= last && i < index; ++i) - { - ++count; - if (str[i] == '\n') - { - x = f.left_overflow(); - y += f.height(); - count = 0; - } - else if (is_combining_char(str[i]) == false && - str[i] != '\r') - { - x += f[str[i]].width(); - } - } - } - - x += rect.left(); - y += rect.top(); - - // if the cursor is at the start of a line then back it up one pixel - if (count == 0) - --x; - - return rectangle(x,y,x,y+f.height()-1); - } - - // ------------------------------------------------------------------------------------ - - template <typename T, typename traits, typename alloc> - unsigned long compute_cursor_pos ( - const rectangle& rect, - const std::basic_string<T,traits,alloc>& str, - long x, - long y, - typename std::basic_string<T,traits,alloc>::size_type first = 0, - typename std::basic_string<T,traits,alloc>::size_type last = (std::basic_string<T,traits,alloc>::npos) - ) const - { - typedef std::basic_string<T,traits,alloc> string; - DLIB_ASSERT ( (last == string::npos) || (first <= last && last < str.size()) , - "\tunsigned long font::compute_cursor_pos()" - << "\n\tlast == string::npos: " << ((last == string::npos)?"true":"false") - << "\n\tfirst: " << (unsigned long)first - << "\n\tlast: " << (unsigned long)last - << "\n\tx: " << x - << "\n\ty: " << y - << "\n\tstr.size(): " << (unsigned long)str.size() ); - const font& f = *this; - - - if (str.size() == 0) - return 0; - else if (first >= str.size()) - return static_cast<unsigned long>(str.size()); - - y -= rect.top(); - x -= rect.left(); - if (y < 0) - y = 0; - if (x < 0) - x = 0; - - if (last == string::npos) - last = str.size()-1; - - - // first figure out what line we are on - typename string::size_type pos = first; - long line = 0; - while (static_cast<unsigned long>(y) >= f.height()) - { - ++line; - y -= f.height(); - } - - // find the start of the given line - for (typename string::size_type i = first; i <= last && line != 0; ++i) - { - if (str[i] == '\n') - { - --line; - pos = i + 1; - } - } - - - // now str[pos] == the first character of the start of the line - // that contains the cursor. - const typename string::size_type start_of_line = pos; - - - long cur_x = f.left_overflow(); - // set the current cursor position to where the mouse clicked - while (pos <= last) - { - if (x <= cur_x || str[pos] == '\n') - break; - - if (is_combining_char(str[pos]) == false && - str[pos] != '\r') - { - cur_x += f[str[pos]].width(); - } - ++pos; - } - - if (x <= cur_x) - { - if (pos != start_of_line) - { - // we might actually be closer to the previous character - // so check for that and if so then jump us back one. - const long width = f[str[pos-1]].width(); - if (x < cur_x - width/2) - --pos; - } - } - return static_cast<unsigned long>(pos); - } - - }; - -// ---------------------------------------------------------------------------------------- - - const std::shared_ptr<font> get_native_font (); - -// ---------------------------------------------------------------------------------------- - - class default_font : public font - { - letter* l; - - - default_font( - ); - default_font(default_font&); // copy constructor - default_font& operator=(default_font&); // assignment operator - - - - public: - static const std::shared_ptr<font>& get_font ( - ) - { - static mutex m; - static std::shared_ptr<font> f; - auto_mutex M(m); - if (f.get() == 0) - f.reset(new default_font); - - return f; - } - - ~default_font( - ) - { - delete [] l; - } - - unsigned long height ( - ) const { return 16; } - - unsigned long ascender ( - ) const { return 12; } - - unsigned long left_overflow ( - ) const { return 1; } - - unsigned long right_overflow ( - ) const { return 2; } - - bool has_character ( - unichar ch - )const - { - if (ch < 256 && (l[ch].width() != 0 || l[ch].num_of_points() != 0)) - return true; - else - return false; - } - - const letter& operator[] ( - unichar ch - ) const - { - if(ch < 256) - return l[ch]; - return l[0]; // just return one of the empty characters in this case - } - }; - - -// ---------------------------------------------------------------------------------------- - - class bdf_font : public font - { - - public: - bdf_font( long default_char_ = -1 ); - - long read_bdf_file( std::istream& in, unichar max_enc, unichar min_enc = 0 ); - unsigned long height() const - { - return fbb.height(); - } - unsigned long ascender() const - { - return std::max( 0L, 1 - fbb.top() ); - } - unsigned long left_overflow() const - { - return std::max( 0L, -fbb.left() ); - } - unsigned long right_overflow() const - { - return right_overflow_; - } - const letter& operator[] ( unichar uch ) const - { - if ( !has_character(uch) ) - { - return gl[default_char]; - } - return gl[uch]; - } - - bool has_character ( - unichar ch - )const - { - if (ch < gl.size() && (gl[ch].width() != 0 || gl[ch].num_of_points() != 0)) - return true; - else - return false; - } - - void adjust_metrics(); - private: - - bool bitmap_to_letter( array2d<char>& bitmap, unichar enc, unsigned long width, int x_offset, int y_offset ); - - array<letter> gl; - unichar default_char; // if (is_intialized == true), then this MUST be an actual glyph - bool is_initialized; - rectangle fbb; - unsigned long right_overflow_; - - unsigned global_width; - bool has_global_width; - long specified_default_char; - - bdf_font( bdf_font& ); // copy constructor - bdf_font& operator=( bdf_font& ); // assignment operator - - }; - -// ---------------------------------------------------------------------------------------- - -} - -#ifdef NO_MAKEFILE -#include "fonts.cpp" -#endif - -#endif // DLIB_FONTs_ - diff --git a/ml/dlib/dlib/gui_widgets/fonts_abstract.h b/ml/dlib/dlib/gui_widgets/fonts_abstract.h deleted file mode 100644 index df194bccd..000000000 --- a/ml/dlib/dlib/gui_widgets/fonts_abstract.h +++ /dev/null @@ -1,492 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), Nils Labugt, Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_FONTs_ABSTRACT_ -#ifdef DLIB_FONTs_ABSTRACT_ - -#include "../gui_core.h" -#include <string> -#include "../serialize.h" -#include "../unicode.h" -#include <iostream> - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - class letter - { - /*! - WHAT THIS OBJECT REPRESENTS - This object represents a letter in a font. It tells you the nominal - width of the letter and which pixels form the letter. - - THREAD SAFETY - const versions of this object are thread safe but if you are going to - be modifying it then you must serialize access to it. - !*/ - public: - struct point - { - /*! - WHAT THIS OBJECT REPRESENTS - This object represents one of the pixels of a letter. - - The origin (i.e. (0,0)) of the coordinate plane is at the left - side of the letter's baseline. Also note that y is negative when - above the baseline and positive below (it is zero on the baseline - itself). - - The x value is positive going to the right and negative to the left. - The meaning of a negative x value is that any points with a negative - x value will overlap with the preceding letter. - !*/ - - point ( - ); - /*! - ensures - - This constructor does nothing. The value of x and y - are undefined after its execution. - !*/ - - point ( - signed char x_, - signed char y_ - ); - /*! - ensures - - #x == x_ - - #y == y_ - !*/ - - - signed char x; - signed char y; - }; - - // --------------------------------- - - letter ( - ); - /*! - ensures - - #width() == 0 - - #num_of_points() == 0 - !*/ - - letter ( - unsigned short width_, - unsigned short point_count - ); - /*! - ensures - - #width() == width_ - - #num_of_points() == point_count - !*/ - - ~letter( - ); - /*! - ensures - - any resources used by *this have been freed - !*/ - - const unsigned short width ( - ) const; - /*! - ensures - - returns the width reserved for this letter in pixels. This is the - number of pixels that are reserved for this letter between adjoining - letters. It isn't necessarily the width of the actual letter itself. - (for example, you can make a letter with a width less than how wide it - actually is so that it overlaps with its neighbor letters.) - !*/ - - const unsigned short num_of_points ( - ) const; - /*! - ensures - - returns the number of pixels that make up this letter. - !*/ - - point& operator[] ( - unsigned short i - ); - /*! - requires - - i < num_of_points() - ensures - - returns a non-const reference to the ith point in this letter. - !*/ - - const point& operator[] ( - unsigned short i - ) const; - /*! - requires - - i < num_of_points() - ensures - - returns a const reference to the ith point in this letter. - !*/ - - void swap ( - letter& item - ); - /*! - ensures - - swaps *this with item - !*/ - - private: - - // restricted functions - letter(letter&); // copy constructor - letter& operator=(letter&); // assignment operator - }; - - inline void swap ( - letter& a, - letter& b - ) { a.swap(b); } - /*! - provides a global swap - !*/ - -// ---------------------------------------------------------------------------------------- - - void serialize ( - const letter& item, - std::ostream& out - ); - /*! - provides serialization support for letter objects - !*/ - - void deserialize ( - letter& item, - std::istream& in - ); - /*! - provides deserialization support for letter objects - !*/ - -// ---------------------------------------------------------------------------------------- - - class font - { - /*! - WHAT THIS OBJECT REPRESENTS - This object defines an interface for a font type. It provides metrics - for the font and functions to help you draw strings on a canvas object. - - THREAD SAFETY - All the functions in this class are thread safe. - !*/ - - public: - - virtual bool has_character ( - unichar ch - )const=0; - /*! - ensures - - if (this font has a glyph for the given character) then - - returns true - - else - - returns false - !*/ - bool has_character(char ch) const { return this->has_character(zero_extend_cast<unichar>(ch)); } - bool has_character(wchar_t ch) const { return this->has_character(zero_extend_cast<unichar>(ch)); } - /* Cast char and wchar_t to unichar correctly when char or wchar_t is a signed type */ - - virtual const letter& operator[] ( - unichar ch - )const=0; - /*! - ensures - - if (has_character(ch) == true) then - - returns a letter object that tells you how to draw this character. - - else - - returns some default glyph for characters that aren't in this font. - !*/ - const letter& operator[] (char ch) const { return (*this)[zero_extend_cast<unichar>(ch)]; }; - const letter& operator[] (wchar_t ch) const { return (*this)[zero_extend_cast<unichar>(ch)]; }; - /* Cast char and wchar_t to unichar correctly when char or wchar_t is a signed type */ - - virtual const unsigned long height ( - ) const = 0; - /*! - ensures - - returns the height in pixels of the tallest letter in the font - !*/ - - virtual const unsigned long ascender ( - ) const = 0; - /*! - ensures - - returns the height() minus the number of pixels below the baseline used - by the letter that hangs the lowest below the baseline. - !*/ - - virtual const unsigned long left_overflow ( - ) const = 0; - /*! - ensures - - returns how far outside and to the left of its width a letter - from this font may set pixels. (i.e. how many extra pixels to its - left may a font use) - !*/ - - virtual const unsigned long right_overflow ( - ) const = 0; - /*! - ensures - - returns how far outside and to the right of its width a letter - from this font may set pixels. (i.e. how many extra pixels to its - right may a font use) - !*/ - - template <typename T, typename traits, typename alloc> - void compute_size ( - const std::basic_string<T,traits,alloc>& str, - unsigned long& width, - unsigned long& height, - typename std::basic_string<T,traits,alloc>::size_type first = 0, - typename std::basic_string<T,traits,alloc>::size_type last = std::basic_string<T,traits,alloc>::npos - ) const; - /*! - requires - - if (last != std::basic_string<T,traits,alloc>::npos) then - - first <= last - - last < str.size() - ensures - - all characters in str with an index < first are ignored by this - function. - - if (last != std::basic_string<T,traits,alloc>::npos) then - - all characters in str with an index > last are ignored by - this function. - - if (str.size() == 0) then - - #width == 0 - - #height == 0 - - else - - #width == sum of the widths of the characters in the widest - line in str + left_overflow() + right_overflow(). - - #height == (count(str.begin(),str.end(),'\n')+1)*height() - !*/ - - template <typename T, typename traits, typename alloc, typename pixel_type> - void draw_string ( - const canvas& c, - const rectangle& rect, - const std::basic_string<T,traits,alloc>& str, - const pixel_type& color = rgb_pixel(0,0,0), - typename std::basic_string<T,traits,alloc>::size_type first = 0, - typename std::basic_string<T,traits,alloc>::size_type last = std::basic_string<T,traits,alloc>::npos, - const rectangle area = rectangle(-infinity,-infinity,infinity,infinity) - ) const; - /*! - requires - - if (last != std::basic_string<T,traits,alloc>::npos) then - - first <= last - - last < str.size() - ensures - - all characters in str with an index < first are ignored by this - function. - - if (last != std::basic_string<T,traits,alloc>::npos) then - - all characters in str with an index > last are ignored by - this function. - - if (str.size() == 0) then - - does nothing - - else - - draws str on the given canvas at the position defined by rect. - Also uses the given pixel colors for the font color. - - If the string is too big to fit in rect then the right and - bottom sides of it will be clipped to make it fit. - - only the part of the string that is contained inside the area - rectangle will be drawn - !*/ - - template <typename T, typename traits, typename alloc> - const rectangle compute_cursor_rect ( - const rectangle& rect, - const std::basic_string<T,traits,alloc>& str, - unsigned long index, - typename std::basic_string<T,traits,alloc>::size_type first = 0, - typename std::basic_string<T,traits,alloc>::size_type last = std::basic_string<T,traits,alloc>::npos - ) const; - /*! - requires - - if (last != std::basic_string<T,traits,alloc>::npos) then - - first <= last - - last < str.size() - ensures - - the returned rectangle has a width of 1 and a - height of this->height(). - - computes the location of the cursor that would sit just before - the character str[index] if str were drawn on the screen by - draw_string(rect,str,...,first,last). The cursor location is - returned in the form of a rectangle. - - if (index < first) then - - the returned cursor will be just before the character str[first]. - - if (last != std::basic_string<T,traits,alloc>::npos && index > last) then - - the returned cursor will be just after the character str[last] - - if (str.size() == 0) then - - the returned cursor will be just at the start of the rectangle where - str would be drawn if it wasn't empty. - - if (index > str.size()-1) then - - the returned cursor will be just after the character str[str.size()-1] - !*/ - - template <typename T, typename traits, typename alloc> - const unsigned long compute_cursor_pos ( - const rectangle& rect, - const std::basic_string<T,traits,alloc>& str, - long x, - long y, - typename std::basic_string<T,traits,alloc>::size_type first = 0, - typename std::basic_string<T,traits,alloc>::size_type last = std::basic_string<T,traits,alloc>::npos - ) const; - /*! - requires - - if (last != std::basic_string<T,traits,alloc>::npos) then - - first <= last - - last < str.size() - ensures - - returns a number idx that has the following properties: - - if (first < str.size()) then - - first <= idx - - else - - idx == str.size() - - if (last != std::basic_string<T,traits,alloc>::npos) then - - idx <= last + 1 - - compute_cursor_rect(rect,str,idx,first,last) == the cursor - position that is closest to the pixel (x,y) - !*/ - - - private: - - // restricted functions - font(font&); // copy constructor - font& operator=(font&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - - class default_font : public font - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an implementation of the Helvetica 12 point font. - - THREAD SAFETY - It is safe to call get_font() and access the returned font from any - thread and no synchronization is needed as long as it is called - after the main() function has been entered. - !*/ - - public: - static const shared_ptr_thread_safe<font> get_font( - ); - /*! - ensures - - returns an instance of this font. - throws - - std::bad_alloc - This exception is thrown if there is a problem gathering the needed - memory for the font object. - !*/ - - private: - - // restricted functions - default_font(); // normal constructor - default_font(default_font&); // copy constructor - default_font& operator=(default_font&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - - class bdf_font : public font - { - - /*! - WHAT THIS OBJECT REPRESENTS - This is a font object that is capable of loading of loading BDF (Glyph - Bitmap Distribution Format) font files. - - THREAD SAFETY - If you only access this object via the functions in the parent class font - then this object is thread safe. But if you need to call any of the - functions introduced in this derived class then you need to serialize - access to this object while you call these functions. - !*/ - - public: - - bdf_font( - long default_char = -1 - ); - /*! - ensures - - for all x: - - #has_character(x) == false - (i.e. this font starts out empty. You have to call read_bdf_file() - to load it with data) - - if (default_char == -1) then - - the letter returned by (*this)[ch] for values of - ch where has_character(ch) == false will be the - default glyph defined in the bdf file. - - else - - the letter returned by (*this)[ch] for values of - ch where has_character(ch) == false will be the - letter (*this)[default_char]. - !*/ - - long read_bdf_file( - std::istream& in, - unichar max_enc, - unichar min_enc = 0 - ); - /*! - ensures - - attempts to read the font data from the given input stream into - *this. The input stream is expected to contain a valid BDF file. - - reads in characters with encodings in the range min_enc to max_enc - into this font. All characters in the font file outside this range - are ignored. - - returns the number of characters loaded into this font from the - given input stream. - !*/ - - void adjust_metrics(); - /*! - ensures - - Computes metrics based on actual glyphs loaded, instead of using - the values in the bdf file header. (May be useful if loading glyphs - from more than one file or a small part of a file.) - !*/ - - private: - - bdf_font( bdf_font& ); // copy constructor - bdf_font& operator=( bdf_font& ); // assignment operator - - }; - -// ---------------------------------------------------------------------------------------- - - const shared_ptr_thread_safe<font> get_native_font( - ); - /*! - ensures - - returns a font object that uses the local font - !*/ - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_FONTs_ABSTRACT_ - diff --git a/ml/dlib/dlib/gui_widgets/nativefont.h b/ml/dlib/dlib/gui_widgets/nativefont.h deleted file mode 100644 index 2de0edfaa..000000000 --- a/ml/dlib/dlib/gui_widgets/nativefont.h +++ /dev/null @@ -1,612 +0,0 @@ -// Copyright (C) 2006 Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_IGG_FONT_RENDERER_H_ -#define DLIB_IGG_FONT_RENDERER_H_ -#include "../platform.h" - - -#include "../gui_widgets.h" -#include "../unicode.h" -#include "../uintn.h" - -#include <map> -#include <memory> - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <locale.h> - -#if defined(WIN32) -#include <windows.h> -#include <mbstring.h> -#elif defined(POSIX) -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xlocale.h> -#endif - -namespace nativefont -{ -// ---------------------------------------------------------------------------------------- - - namespace font_renderer - { - typedef dlib::uint8 byte; - - -#ifdef WIN32 - template <typename T> struct input2native_trait{ - }; - template <> struct input2native_trait<char>{ - typedef char type_t; - }; - template <> struct input2native_trait<wchar_t>{ - typedef wchar_t type_t; - }; - template <> struct input2native_trait<dlib::unichar>{ - typedef wchar_t type_t; - }; -#endif - // T : N : sizeof_source_type - template <int N> struct size2inner_trait{ - }; - template <> struct size2inner_trait<1>{ - typedef char type_t; - }; - template <> struct size2inner_trait<2>{ - typedef dlib::uint16 type_t; - }; - template <> struct size2inner_trait<4>{ - typedef dlib::unichar type_t; - }; - - -// ---------------------------------------------------------------------------------------- - - template <int N> struct create_helper{ }; - template <> struct create_helper<1>{ - typedef char type_t; - type_t *istr; - int len; - create_helper(char *str){ - len = (int)strlen(str); - istr = str; - } - ~create_helper(){} - }; - template <> struct create_helper<2>{ - typedef wchar_t type_t; - type_t *istr; - bool allocated; - int len; - create_helper(wchar_t *str){ - allocated = false; - len = (int)wcslen(str); - istr = str; - } - create_helper(dlib::unichar *str){ - allocated = true; - len = 0; - int unicount = 0; - dlib::unichar *p = str; - while(*p){ - if (*p > 0xffff){ - len += 2; - }else{ - len++; - } - unicount++; - p++; - } - istr = new wchar_t[len+1]; - for (int i = 0, wi = 0; i < unicount; ++i){ - dlib::unichar high, low; - if (str[i] > 0xffff){ - dlib::unichar_to_surrogate_pair(str[i], high, low); - istr[wi] = (wchar_t)high, istr[wi+1] = (wchar_t)low; - wi += 2; - }else{ - istr[wi] = (wchar_t)str[i]; - wi += 1; - } - } - istr[len] = L'\0'; - } - - ~create_helper(){ - if (allocated) delete[] istr; - } - }; - template <> struct create_helper<4>{ - typedef wchar_t type_t; - type_t *istr; - int len; - create_helper(dlib::unichar *str){ - len = (int)wcslen((wchar_t *)str); - istr = (type_t *)str; - } - ~create_helper(){} - }; - -// ---------------------------------------------------------------------------------------- - - class font_renderer{ - public: - - struct rgb_type{ - byte r, g, b; - rgb_type() : r(0), g(0), b(0){}; - rgb_type(byte r_, byte g_, byte b_) : r(r_), g(g_), b(b_){}; - }; - private: - - byte *image; - int width, height; - void destroy(){ - width = height = 0; - delete image; - image = 0; - } - struct vals_internal{ - int width, height; -#ifdef WIN32 - COLORREF rgb2RGB(rgb_type &rgb){ - return RGB(rgb.r, rgb.g, rgb.b); - } - HBITMAP hBmp, hBmpOld; - HDC hDCBmp; - BYTE *pixelint; - HFONT hFont, hFontOld; - HBRUSH hBrush; - int pix_width_prev, pix_height_prev; - bool first; - int ascender, descender; - int height_prev; - char attribute_prev; - - template <typename T> void create(T *str, int height_want, bool italic, bool bold, bool fixed, rgb_type &background, rgb_type &foreground){ - struct inner{ - inline static BOOL GetTextExtentPoint32(HDC hDC, LPCSTR str, int len, LPSIZE lpsize){ - return ::GetTextExtentPoint32A(hDC, str, len, lpsize); - } - inline static BOOL GetTextExtentPoint32(HDC hDC, LPCWSTR str, int len, LPSIZE lpsize){ - return ::GetTextExtentPoint32W(hDC, str, len, lpsize); - } - inline static BOOL TextOut(HDC hDC, int nxstart, int nystart, LPCSTR str, int cbstr){ - return ::TextOutA(hDC, nxstart, nystart, str, cbstr); - } - inline static BOOL TextOut(HDC hDC, int nxstart, int nystart, LPCWSTR str, int cbstr){ - return ::TextOutW(hDC, nxstart, nystart, str, cbstr); - } - }; - - create_helper<sizeof(typename input2native_trait<T>::type_t)> ch(str); - - if (hDCBmp == NULL){ - HWND hWnd = GetDesktopWindow(); - HDC hDC = GetDC(hWnd); - hDCBmp = CreateCompatibleDC(hDC); - ReleaseDC(hWnd, hDC); - } - SetTextColor(hDCBmp, rgb2RGB(foreground)); - SetBkColor(hDCBmp, rgb2RGB(background)); - - char attribute = (italic ? 1 : 0) | (bold ? 2 : 0) | (fixed ? 4 : 0); - if (!hFont || height_prev != height || attribute != attribute_prev){ - attribute_prev = attribute; - height_prev = height_want; - if (hFont){ - SelectObject(hDCBmp, hFontOld); - DeleteObject(hFont); - } - hFont = CreateFont(height_want, 0, 0, 0, bold ? FW_BOLD : FW_DONTCARE, italic ? TRUE : FALSE, - FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, - fixed ? (FIXED_PITCH | FF_DONTCARE) : (VARIABLE_PITCH | FF_DONTCARE), NULL); - hFontOld = (HFONT)SelectObject(hDCBmp, hFont); - } - - { - SIZE sz; - inner::GetTextExtentPoint32(hDCBmp, ch.istr, ch.len, &sz); - width = ((sz.cx + 3) / 4) * 4; - height = sz.cy; - } - - if (pix_width_prev < width || pix_height_prev < height){ - if (hBmp){ - SelectObject(hDCBmp, hBmpOld); - DeleteObject(hBmp); - } - pix_width_prev = width * 2; - pix_height_prev = height * 2; - BITMAPINFO bi; - ZeroMemory(&bi, sizeof(bi)); - bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi.bmiHeader.biBitCount = 24; - bi.bmiHeader.biPlanes = 1; - bi.bmiHeader.biWidth = pix_width_prev; - bi.bmiHeader.biHeight = -pix_height_prev; - hBmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void **)&pixelint, NULL, 0); - hBmpOld = (HBITMAP)SelectObject(hDCBmp, hBmp); - } - - { - HBRUSH hBrush = CreateSolidBrush(rgb2RGB(background)); - RECT rc; - rc.left = rc.top = 0; - rc.right = pix_width_prev; - rc.bottom = pix_height_prev; - FillRect(hDCBmp, &rc, hBrush); - } - - inner::TextOut(hDCBmp, 0, 0, ch.istr, ch.len); - TEXTMETRICW tm; - GetTextMetricsW(hDCBmp,&tm); - ascender = tm.tmAscent; - descender = tm.tmDescent; - } - - template <typename T> vals_internal(T *str, int height_want, bool italic = false, - bool bold = false, bool fixed = false, rgb_type background = rgb_type(), rgb_type foreground = rgb_type()){ - first = true; - hFont = NULL; - hDCBmp = 0; - hBmpOld = 0; - hBmp = 0; - hDCBmp = 0; - pixelint = 0; - pix_width_prev = pix_height_prev = 0; - height_prev = -1; - attribute_prev = 0; - create(str, height_want, italic, bold, fixed, background, foreground); - first = false; - } - - inline int get_ascender(){ - return ascender; - } - - inline int get_descender(){ - return descender; - } - - inline void get_pixel(int x, int y, byte &r, byte &g, byte &b){ - byte *p = pixelint + (y * pix_width_prev + x) * 3; - r = *(p+2), g = *(p+1), b = *p; - } - - void destroy(){ - SelectObject(hDCBmp, hBmpOld); - DeleteObject(hBmp); - SelectObject(hDCBmp, hFontOld); - DeleteObject(hFont); - DeleteDC(hDCBmp); - hFont = NULL; - hDCBmp = 0; - hBmpOld = 0; - hBmp = 0; - hDCBmp = 0; - pixelint = 0; - } - ~vals_internal(){ - destroy(); - } -#elif defined(POSIX) - XImage *ximg; - Display *d; - GC gc; - XFontSet fs; - Pixmap pix; - Colormap cmap; - int ascender, descender; - int pix_width_prev, pix_height_prev; - char fontset_prev[256]; - unsigned long rgb2color(rgb_type col, Display *d, Colormap &cmap){ - XColor xcol; - xcol.red = col.r * 257; - xcol.green = col.g * 257; - xcol.blue = col.b * 257; - XAllocColor(d, cmap, &xcol); - return xcol.pixel; - } - template <typename T> void create(T *str, int height_want, bool italic, bool bold, bool fixed, rgb_type background, rgb_type foreground){ - struct inner{ - inline static int XTextExtents (XFontSet fs, char *str, int len, XRectangle *ink, XRectangle *logical){ - return XmbTextExtents(fs, str, len, ink, logical); - } - inline static int XTextExtents (XFontSet fs, wchar_t *str, int len, XRectangle *ink, XRectangle *logical){ - return XwcTextExtents(fs, str, len, ink, logical); - } - inline static void XDrawString(Display *d, Window w, XFontSet fs, GC gc, int x, int y, char *str, int num_bytes){ - XmbDrawString(d, w, fs, gc, x, y, str, num_bytes); - } - inline static void XDrawString(Display *d, Window w, XFontSet fs, GC gc, int x, int y, wchar_t *str, int num_bytes){ - XwcDrawString(d, w, fs, gc, x, y, str, num_bytes); - } - }; - create_helper<sizeof(T)> ch((typename size2inner_trait<sizeof(T)>::type_t *)str); - setlocale(LC_CTYPE, ""); - if (d == NULL){ - d = XOpenDisplay(NULL); - if (d == 0) - { - d = XOpenDisplay(":0.0"); - if (d == 0) - { - throw dlib::gui_error("Unable to connect to the X display."); - } - } - - cmap = DefaultColormap(d, DefaultScreen(d)); - } - char fontset[256]; - { - char *p = fontset; - p += sprintf(fontset, "-*-*-%s-%c-normal--%d-*-*-*-%c", - bold ? "bold" : "medium", italic ? 'i' : 'r', height_want, fixed ? 'c' : 'p'); - if (fixed){ - sprintf(p, ",-*-*-%s-%c-normal--%d-*-*-*-m", - bold ? "bold" : "medium", italic ? 'i' : 'r', height_want); - } - } - bool equal_font; - if (strcmp(fontset, fontset_prev) == 0){ - equal_font = true; - }else{ - equal_font = false; - strcpy(fontset_prev, fontset); - } - - char **mlist; - int mcount; - char *def_str; - if (!equal_font){ - if (fs){ - XFreeFontSet(d, fs); - } - fs = XCreateFontSet(d, fontset, &mlist, &mcount, &def_str); - if (fs == NULL) - throw dlib::gui_error("gui_error: XCreateFontSet() failure"); - - XFontSetExtents *extent; - extent = XExtentsOfFontSet(fs); - ascender = -extent->max_logical_extent.y; - descender = extent->max_logical_extent.height - ascender; - XFreeStringList(mlist); - } - XRectangle ink, logical; - inner::XTextExtents (fs, ch.istr, ch.len, &ink, &logical); - width = logical.width; - height = height_want; - - if (pix == None || pix_width_prev < width || pix_height_prev < height){ - if (pix != None){ - XFreeGC(d, gc); - XFreePixmap(d, pix); - } - pix_width_prev = width * 2; - pix_height_prev = height * 2; - pix = XCreatePixmap(d, DefaultRootWindow(d), pix_width_prev, pix_height_prev, XDefaultDepth(d, DefaultScreen(d))); - gc = XCreateGC(d, pix, 0, NULL); - } - - unsigned long backcolor = rgb2color(background, d, cmap); - XSetForeground(d, gc, backcolor); - XSetBackground(d, gc, backcolor); - XFillRectangle(d, pix, gc, 0, 0, width, height); - XSetForeground(d, gc, rgb2color(foreground, d, cmap)); - inner::XDrawString(d, pix, fs, gc, 0, ascender, ch.istr, ch.len); - - if (ximg) XDestroyImage(ximg); - ximg = XGetImage(d, pix, 0, 0, width, height, AllPlanes, ZPixmap ); - } - - template <typename T> vals_internal(T *str, int height_want, bool italic = false, - bool bold = false, bool fixed = false, rgb_type background = rgb_type(), rgb_type foreground = rgb_type()){ - fontset_prev[0] = '\0'; - ximg = NULL; - d = NULL; - pix = None; - fs = NULL; - ascender = descender = -1; - pix_width_prev = pix_height_prev = -1; - create(str, height_want, italic, bold, fixed, background, foreground); - } - - inline int get_ascender(){ - return ascender; - } - - inline int get_descender(){ - return descender; - } - - std::map<unsigned long,rgb_type> col2rgb; - rgb_type color2rgb(unsigned long color, Display *d, Colormap &cmap){ - if (col2rgb.count(color)){ - return col2rgb[color]; - }else{ - XColor xcol; - xcol.pixel = color; - XQueryColor(d, cmap, &xcol); - rgb_type rgb_((byte)(xcol.red/257), (byte)(xcol.green/257), (byte)(xcol.blue/257)); - col2rgb[color] = rgb_; - return rgb_; - } - } - inline void get_pixel(int x, int y, byte &r, byte &g, byte &b){ - rgb_type c = color2rgb(XGetPixel(ximg,x,y), d, cmap); - r = c.r, g = c.g, b = c.b; - } - - ~vals_internal(){ - XDestroyImage(ximg); - - XFreeGC(d, gc); - XFreeFontSet(d, fs); - XFreePixmap(d, pix); - XCloseDisplay(d); - } -#endif - }; - - struct image_size_setter{ - void operator()(int&, int&){ - } - }; - - int ascender, descender; - vals_internal *vi; - public: - font_renderer() : image(0), width(0), height(0){ - ascender = descender = 0; - vi = NULL; - } - - template<typename T> font_renderer(T *str, int height_want, bool italic = false, bool bold = false, bool fixed = false, rgb_type background = rgb_type(0,0,0), rgb_type foreground = rgb_type(255,255,255)){ - render(str, height_want, italic, bold, fixed, background, foreground); - } - - template<typename T> void render(T *str, int height_want, - bool italic = false, bool bold = false, bool fixed = false, - rgb_type background = rgb_type(0,0,0), rgb_type foreground = rgb_type(255,255,255)){ - if (vi == NULL){ - vi = new vals_internal(str, height_want, italic, bold, fixed, background, foreground); - }else{ - vi->create(str, height_want, italic, bold, fixed, background, foreground); - } - width = vi->width, height = vi->height; - image = new byte[width * height * 3]; - ascender = vi->get_ascender(); - descender = vi->get_descender(); - - int h = height, w = width; - for (int j = 0, i3 = 0; j < h; ++j){ - for (int i = 0; i < w; ++i, i3 += 3){ - vi->get_pixel(i, j, image[i3], image[i3+1], image[i3+2]); - } - } - } - - ~font_renderer(){ - if (vi) delete vi; - destroy(); - } - int get_width(){ - return width; - } - int get_height(){ - return height; - } - inline int get_ascender(){ - return ascender; - } - inline int get_descender(){ - return descender; - } - - const byte *get_image(){ - return image; - } - }; - } - -// ---------------------------------------------------------------------------------------- - - class native_font : public dlib::font - { - unsigned long ascender_; - native_font(){ - setlocale(LC_CTYPE, ""); - ascender_ = 0; - get_letter((int)('x')); - } - typedef std::map<int,dlib::letter *> letters_map_type; - letters_map_type letters; - font_renderer::font_renderer fl; - public: - - virtual ~native_font() - { - // delete all the letter objects we have in our letters map - letters_map_type::iterator i; - for (i = letters.begin(); i != letters.end(); ++i) - { - delete i->second; - } - } - - virtual bool has_character ( - dlib::unichar ch - )const{ - return (*this)[ch].width() > 0; - } - - static const std::shared_ptr<font>& get_font ( - ) - { - static std::shared_ptr<font> f(new native_font); - return f; - } - - virtual const dlib::letter& operator[] (dlib::unichar ch) const{ - return (const_cast<native_font *>(this))->get_letter(ch); - } - - dlib::letter& get_letter ( - dlib::unichar ch - ){ - if (letters.count(ch)){ - dlib::letter *l = letters.find(ch)->second; - return *l; - } - - dlib::unichar c[2]; - c[0] = ch; - c[1] = 0; - - fl.render(c, height(),false,false,true); - if (ascender_ == 0){ - ascender_ = fl.get_ascender(); - } - std::vector<dlib::letter::point> v; - const font_renderer::byte *bp = fl.get_image(); - for (int j = 0; j < fl.get_height(); ++j){ - for (int i = 0; i < fl.get_width(); ++i, bp += 3){ - if (*bp){ - v.push_back(dlib::letter::point(i,j-ascender()+1)); - } - } - } - dlib::letter *l = new dlib::letter(fl.get_width(), (unsigned long)v.size()); - - letters.insert(std::make_pair(ch,l)); - for (int i = 0; i < (int)v.size(); ++i){ - (*l)[i] = v.at(i); - } - return *l; - } - - virtual unsigned long height ( - ) const { return 12; } - - virtual unsigned long ascender ( - ) const { return ascender_; } - - virtual unsigned long left_overflow ( - ) const { return 1; } - - virtual unsigned long right_overflow ( - ) const { return 2; } - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_IGG_FONT_RENDERER_H_ - diff --git a/ml/dlib/dlib/gui_widgets/style.cpp b/ml/dlib/dlib/gui_widgets/style.cpp deleted file mode 100644 index a3d22d10f..000000000 --- a/ml/dlib/dlib/gui_widgets/style.cpp +++ /dev/null @@ -1,998 +0,0 @@ -// 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_CPP_ -#define DLIB_WIDGETs_STYLE_CPP_ - -#include "style.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // button style stuff -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void button_style_default::draw_button ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const font& mfont, - const long , - const long , - const ustring& name, - const bool is_depressed - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - fill_rect(c,rect,rgb_pixel(212,208,200)); - - unsigned char red, green, blue; - if (enabled) - { - red = 0; - green = 0; - blue = 0; - } - else - { - red = 128; - green = 128; - blue = 128; - } - - // compute the name length if it hasn't already been computed - if (name_width == 0) - { - unsigned long height; - mfont.compute_size(name,name_width,height); - } - - // figure out where the name string should appear - rectangle name_rect; - const unsigned long width = name_width; - const unsigned long height = mfont.height(); - name_rect.set_left((rect.right() + rect.left() - width)/2); - name_rect.set_top((rect.bottom() + rect.top() - height)/2 + 1); - name_rect.set_right(name_rect.left()+width-1); - name_rect.set_bottom(name_rect.top()+height); - - - if (is_depressed) - { - name_rect.set_left(name_rect.left()+1); - name_rect.set_right(name_rect.right()+1); - name_rect.set_top(name_rect.top()+1); - name_rect.set_bottom(name_rect.bottom()+1); - - mfont.draw_string(c,name_rect,name,rgb_pixel(red,green,blue)); - - draw_button_down(c,rect); - } - else - { - mfont.draw_string(c,name_rect,name,rgb_pixel(red,green,blue)); - - // now draw the edge of the button - draw_button_up(c,rect); - } - } - -// ---------------------------------------------------------------------------------------- - - rectangle button_style_default:: - get_min_size ( - const ustring& name, - const font& mfont - ) const - { - - unsigned long width; - unsigned long height; - mfont.compute_size(name,width,height); - name_width = width; - - return rectangle(width+2*padding, height+2*padding); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void button_style_toolbar1::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 - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - const long radius = 4; - - unsigned char red, green, blue; - if (enabled) - { - red = 0; - green = 0; - blue = 0; - - long d = 0; - if (rect.contains(lastx,lasty)) - d = -70; - - if (is_depressed) - d = 20; - - if (d != 0) - { - rectangle temp(rect); - temp.left()--; temp.top()--; temp.right()++; temp.bottom()++; - draw_rounded_rectangle(c, temp, radius, rgb_alpha_pixel(255,255,0,120)); - temp.left()--; temp.top()--; temp.right()++; temp.bottom()++; - draw_rounded_rectangle(c, temp, radius, rgb_alpha_pixel(255,255,0,40)); - } - - fill_gradient_rounded(c,rect,radius,rgb_alpha_pixel(255, 255, 255,120-d), - rgb_alpha_pixel(255, 255, 255,0)); - draw_rounded_rectangle(c,rect,radius, rgb_alpha_pixel(30,30,30,200)); - } - else - { - red = 128; - green = 128; - blue = 128; - draw_rounded_rectangle(c,rect,radius, rgb_alpha_pixel(red,green,blue,210)); - } - - - // compute the name length if it hasn't already been computed - if (name_width == 0) - { - unsigned long height; - mfont.compute_size(name,name_width,height); - } - - // figure out where the name string should appear - rectangle name_rect; - const unsigned long width = name_width; - const unsigned long height = mfont.height(); - name_rect.set_left((rect.right() + rect.left() - width)/2); - name_rect.set_top((rect.bottom() + rect.top() - height)/2 + 1); - name_rect.set_right(name_rect.left()+width-1); - name_rect.set_bottom(name_rect.top()+height); - - - if (is_depressed) - { - name_rect.set_left(name_rect.left()+1); - name_rect.set_right(name_rect.right()+1); - name_rect.set_top(name_rect.top()+1); - name_rect.set_bottom(name_rect.bottom()+1); - - mfont.draw_string(c,name_rect,name,rgb_pixel(red,green,blue)); - - } - else - { - mfont.draw_string(c,name_rect,name,rgb_pixel(red,green,blue)); - } - } - -// ---------------------------------------------------------------------------------------- - - rectangle button_style_toolbar1:: - get_min_size ( - const ustring& name, - const font& mfont - ) const - { - - unsigned long width; - unsigned long height; - mfont.compute_size(name,width,height); - name_width = width; - - return rectangle(width+2*padding, height+2*padding); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void button_style_toolbar_icon1::draw_button ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const font& , - const long lastx, - const long lasty, - const ustring& , - const bool is_depressed - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - const long radius = padding; - - if (enabled) - { - if (rect.contains(lastx,lasty)) - { - if (is_depressed) - { - fill_gradient_rounded(c,rect,radius,rgb_alpha_pixel(100,100,200,150), - rgb_alpha_pixel(50,50,100,100)); - draw_rounded_rectangle(c,rect,radius, rgb_alpha_pixel(150,150,30,200)); - } - else - { - fill_gradient_rounded(c,rect,radius,rgb_alpha_pixel(150,150,250,130), - rgb_alpha_pixel(100,100,150,90)); - draw_rounded_rectangle(c,rect,radius, rgb_alpha_pixel(150,150,30,200)); - } - } - - if (is_depressed) - { - rectangle img_rect(translate_rect(centered_rect(rect,img_mouseover.nc(),img_mouseover.nr()),1,1)); - point p(img_rect.left(),img_rect.top()); - draw_image(c,p,img_mouseover); - } - else - { - rectangle img_rect(centered_rect(rect,img_normal.nc(),img_normal.nr())); - point p(img_rect.left(),img_rect.top()); - if (rect.contains(lastx,lasty)) - draw_image(c,p,img_mouseover); - else - draw_image(c,p,img_normal); - } - - } - else - { - rectangle img_rect(centered_rect(rect,img_normal.nc(),img_normal.nr())); - point p(img_rect.left(),img_rect.top()); - draw_image(c,p,img_disabled); - } - } - -// ---------------------------------------------------------------------------------------- - - rectangle button_style_toolbar_icon1:: - get_min_size ( - const ustring& , - const font& - ) const - { - return rectangle(img_normal.nc()+2*padding, img_normal.nr()+2*padding); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void button_style_arrow:: - draw_button ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const font& , - const long , - const long , - const ustring& , - const bool is_depressed - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - fill_rect(c,rect,rgb_pixel(212,208,200)); - - const long height = rect.height(); - const long width = rect.width(); - - const long smallest = (width < height) ? width : height; - - const long rows = (smallest+3)/4; - const long start = rows + rows/2-1; - long dep; - - long tip_x = 0; - long tip_y = 0; - long wy = 0; - long hy = 0; - long wx = 0; - long hx = 0; - - if (is_depressed) - { - dep = 0; - - // draw the button's border - draw_button_down(c,rect); - } - else - { - dep = -1; - - // draw the button's border - draw_button_up(c,rect); - } - - - switch (dir) - { - case UP: - tip_x = width/2 + rect.left() + dep; - tip_y = (height - start)/2 + rect.top() + dep + 1; - wy = 0; - hy = 1; - wx = 1; - hx = 0; - break; - - case DOWN: - tip_x = width/2 + rect.left() + dep; - tip_y = rect.bottom() - (height - start)/2 + dep; - wy = 0; - hy = -1; - wx = 1; - hx = 0; - break; - - case LEFT: - tip_x = rect.left() + (width - start)/2 + dep + 1; - tip_y = height/2 + rect.top() + dep; - wy = 1; - hy = 0; - wx = 0; - hx = 1; - break; - - case RIGHT: - tip_x = rect.right() - (width - start)/2 + dep; - tip_y = height/2 + rect.top() + dep; - wy = 1; - hy = 0; - wx = 0; - hx = -1; - break; - } - - - rgb_pixel color; - if (enabled) - { - color.red = 0; - color.green = 0; - color.blue = 0; - } - else - { - color.red = 128; - color.green = 128; - color.blue = 128; - } - - - - for (long i = 0; i < rows; ++i) - { - draw_line(c,point(tip_x + wx*i + hx*i, tip_y + wy*i + hy*i), - point(tip_x + wx*i*-1 + hx*i, tip_y + wy*i*-1 + hy*i), - color); - } - - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // toggle button style stuff -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void toggle_button_style_default::draw_toggle_button ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const font& mfont, - const long , - const long , - const ustring& name, - const bool is_depressed, - const bool is_checked - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - fill_rect(c,rect,rgb_pixel(212,208,200)); - - unsigned char red, green, blue; - if (enabled) - { - red = 0; - green = 0; - blue = 0; - } - else - { - red = 128; - green = 128; - blue = 128; - } - - // compute the name length if it hasn't already been computed - if (name_width == 0) - { - unsigned long height; - mfont.compute_size(name,name_width,height); - } - - // figure out where the name string should appear - rectangle name_rect; - const unsigned long width = name_width; - const unsigned long height = mfont.height(); - name_rect.set_left((rect.right() + rect.left() - width)/2); - name_rect.set_top((rect.bottom() + rect.top() - height)/2 + 1); - name_rect.set_right(name_rect.left()+width-1); - name_rect.set_bottom(name_rect.top()+height); - - long d = 0; - if (is_checked) - d = 1; - - if (is_depressed) - d = 2; - - name_rect.set_left(name_rect.left()+d); - name_rect.set_right(name_rect.right()+d); - name_rect.set_top(name_rect.top()+d); - name_rect.set_bottom(name_rect.bottom()+d); - - mfont.draw_string(c,name_rect,name,rgb_pixel(red,green,blue)); - - // now draw the edge of the button - if (is_checked || is_depressed) - draw_button_down(c,rect); - else - draw_button_up(c,rect); - } - -// ---------------------------------------------------------------------------------------- - - rectangle toggle_button_style_default:: - get_min_size ( - const ustring& name, - const font& mfont - ) const - { - - unsigned long width; - unsigned long height; - mfont.compute_size(name,width,height); - name_width = width; - - return rectangle(width+2*padding, height+2*padding); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void toggle_button_style_check_box::draw_toggle_button ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const font& mfont, - const long , - const long , - const ustring& name, - const bool is_depressed, - const bool is_checked - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - - rgb_pixel color; - if (enabled) - { - color.red = 0; - color.green = 0; - color.blue = 0; - } - else - { - color.red = 128; - color.green = 128; - color.blue = 128; - } - - - // figure out where the name string should appear - rectangle name_rect, box_rect; - unsigned long padding = 0; - if (mfont.height() < 13) - padding = (rect.height() - mfont.height())/2; - - name_rect = rect; - name_rect.set_left(rect.left() + 17-1); - name_rect.set_top(rect.top() + padding); - name_rect.set_bottom(rect.bottom() - padding); - - box_rect = rect; - box_rect.set_right(rect.left() + 12); - box_rect.set_bottom(rect.top() + 12); - - mfont.draw_string(c,name_rect,name,color); - - if (enabled && is_depressed == false) - fill_rect(c, box_rect,rgb_pixel(255,255,255)); - else - fill_rect(c, box_rect,rgb_pixel(212,208,200)); - - draw_sunken_rectangle(c, box_rect); - - - if (is_checked) - { - const long x = box_rect.left(); - const long y = box_rect.top(); - draw_line(c,point(3+x,5+y),point(6+x,8+y),color); - draw_line(c,point(3+x,6+y),point(5+x,8+y),color); - draw_line(c,point(3+x,7+y),point(5+x,9+y),color); - draw_line(c,point(6+x,6+y),point(9+x,3+y),color); - draw_line(c,point(6+x,7+y),point(9+x,4+y),color); - draw_line(c,point(6+x,8+y),point(9+x,5+y),color); - } - } - -// ---------------------------------------------------------------------------------------- - - rectangle toggle_button_style_check_box:: - get_min_size ( - const ustring& name, - const font& mfont - ) const - { - unsigned long width; - unsigned long height; - mfont.compute_size(name,width,height); - - if (height < 13) - height = 13; - - return rectangle(width + 17 -1, height -1); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void toggle_button_style_radio_button::draw_toggle_button ( - const canvas& c, - const rectangle& rect, - const bool enabled, - const font& mfont, - const long , - const long , - const ustring& name, - const bool is_depressed, - const bool is_checked - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - - rgb_pixel color; - - // figure out where the name string should appear - rectangle name_rect, box_rect; - unsigned long padding = 0; - if (mfont.height() < 13) - padding = (rect.height() - mfont.height())/2; - - name_rect = rect; - name_rect.set_left(rect.left() + 17-1); - name_rect.set_top(rect.top() + padding); - name_rect.set_bottom(rect.bottom() - padding); - - box_rect = rect; - box_rect.set_right(rect.left() + 12); - box_rect.set_bottom(rect.top() + 12); - - - const long x = box_rect.left(); - const long y = box_rect.top(); - - if (enabled && is_depressed == false) - draw_solid_circle(c,point(rect.left()+5,rect.top()+5),4.5,rgb_pixel(255,255,255)); - else - draw_solid_circle(c,point(rect.left()+5,rect.top()+5),4.5,rgb_pixel(212,208,200)); - - - color = rgb_pixel(128,128,128); - draw_line(c,point(0+x,4+y),point(0+x,7+y),color); - draw_line(c,point(1+x,2+y),point(1+x,9+y),color); - draw_line(c,point(2+x,1+y),point(9+x,1+y),color); - draw_line(c,point(4+x,0+y),point(7+x,0+y),color); - - color = rgb_pixel(255,255,255); - draw_line(c,point(4+x,11+y),point(7+x,11+y),color); - draw_line(c,point(2+x,10+y),point(9+x,10+y),color); - draw_line(c,point(10+x,2+y),point(10+x,9+y),color); - draw_line(c,point(11+x,4+y),point(11+x,7+y),color); - - color = rgb_pixel(64,64,64); - draw_line(c,point(1+x,4+y),point(1+x,7+y),color); - draw_line(c,point(4+x,1+y),point(7+x,1+y),color); - draw_pixel(c,point(2+x,3+y),color); - draw_pixel(c,point(3+x,2+y),color); - draw_pixel(c,point(2+x,2+y),color); - draw_pixel(c,point(2+x,8+y),color); - draw_pixel(c,point(8+x,2+y),color); - draw_pixel(c,point(9+x,2+y),color); - - color = rgb_pixel(212,208,200); - draw_line(c,point(4+x,10+y),point(7+x,10+y),color); - draw_line(c,point(10+x,4+y),point(10+x,7+y),color); - draw_pixel(c,point(3+x,9+y),color); - draw_pixel(c,point(9+x,3+y),color); - - if (enabled) - { - color.red = 0; - color.green = 0; - color.blue = 0; - } - else - { - color.red = 128; - color.green = 128; - color.blue = 128; - } - - mfont.draw_string(c,name_rect,name,color); - - if (is_checked) - { - draw_line(c,point(5+x,4+y),point(6+x,4+y),color); - draw_line(c,point(4+x,5+y),point(7+x,5+y),color); - draw_line(c,point(4+x,6+y),point(7+x,6+y),color); - draw_line(c,point(5+x,7+y),point(6+x,7+y),color); - } - - } - -// ---------------------------------------------------------------------------------------- - - rectangle toggle_button_style_radio_button:: - get_min_size ( - const ustring& name, - const font& mfont - ) const - { - unsigned long width; - unsigned long height; - mfont.compute_size(name,width,height); - - if (height < 13) - height = 13; - - return rectangle(width + 17 -1, height -1); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // scroll bar style stuff -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - long scroll_bar_style_default:: - get_slider_length ( - long total_length, - long max_pos - ) const - { - // if the length is too small then we have to smash up the arrow buttons - // and hide the slider. - if (total_length <= get_width()*2) - { - return 0; - } - else - { - double range = total_length - get_button_length(total_length, max_pos)*2; - - double scale_factor = 30.0/(max_pos + 30.0); - - if (scale_factor < 0.1) - scale_factor = 0.1; - - - double fraction = range/(max_pos + range)*scale_factor; - double result = fraction * range; - long res = static_cast<long>(result); - if (res < 8) - res = 8; - return res; - } - } - -// ---------------------------------------------------------------------------------------- - - long scroll_bar_style_default:: - get_button_length ( - long total_length, - long - ) const - { - // if the length is too small then we have to smash up the arrow buttons - // and hide the slider. - if (total_length <= get_width()*2) - { - return total_length/2; - } - else - { - return get_width(); - } - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar_style_default:: - draw_scroll_bar_background ( - const canvas& c, - const rectangle& rect, - const bool , - const long , - const long , - const bool is_depressed - ) const - { - if (is_depressed) - draw_checkered(c, rect,rgb_pixel(0,0,0),rgb_pixel(43,47,55)); - else - draw_checkered(c, rect,rgb_pixel(255,255,255),rgb_pixel(212,208,200)); - } - -// ---------------------------------------------------------------------------------------- - - void scroll_bar_style_default:: - draw_scroll_bar_slider ( - const canvas& c, - const rectangle& rect, - const bool , - const long , - const long , - const bool - ) const - { - fill_rect(c, rect, rgb_pixel(212,208,200)); - draw_button_up(c, rect); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // text_field styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - unsigned long text_field_style_default:: - get_padding ( - const font& mfont - ) const - { - return mfont.height()-mfont.ascender(); - } - -// ---------------------------------------------------------------------------------------- - - void text_field_style_default:: - 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 - { - rectangle area = rect.intersect(c); - - if (enabled) - { - // first fill our area with the bg_color - fill_rect(c, area,bg_color); - } - else - { - // first fill our area with gray - fill_rect(c, area,rgb_pixel(212,208,200)); - } - - - if (enabled) - mfont.draw_string(c,text_rect,text,text_color,text_pos); - else - mfont.draw_string(c,text_rect,text,rgb_pixel(128,128,128),text_pos); - - // now draw the edge of the text_field - draw_sunken_rectangle(c, rect); - - if (highlight_start <= highlight_end && enabled) - { - rectangle highlight_rect = text_rect; - unsigned long left_pad = 0, right_pad = mfont.left_overflow(); - - long i; - for (i = text_pos; i <= highlight_end; ++i) - { - if (i == highlight_start) - left_pad = right_pad; - - right_pad += mfont[text[i]].width(); - } - - highlight_rect.set_left(text_rect.left()+left_pad); - highlight_rect.set_right(text_rect.left()+right_pad); - - // highlight the highlight_rect area - highlight_rect = highlight_rect.intersect(c); - for (long row = highlight_rect.top(); row <= highlight_rect.bottom(); ++row) - { - for (long col = highlight_rect.left(); col <= highlight_rect.right(); ++col) - { - canvas::pixel& pixel = c[row-c.top()][col-c.left()]; - if (pixel.red == 255 && pixel.green == 255 && pixel.blue == 255) - { - // this is a background (and white) pixel so set it to a dark - // blueish color. - pixel.red = 10; - pixel.green = 36; - pixel.blue = 106; - } - else - { - // this should be a pixel that is part of a letter so set it to white - pixel.red = 255; - pixel.green = 255; - pixel.blue = 255; - } - } - } - } - - // now draw the cursor if we need to - if (cursor_visible && has_focus && enabled) - { - const unsigned long top = rect.top()+3; - const unsigned long bottom = rect.bottom()-3; - draw_line(c, point(rect.left()+cursor_x,top),point(rect.left()+cursor_x,bottom)); - } - - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // text_box styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void text_box_style_default:: - 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 - { - rectangle area = display_rect.intersect(c); - - if (enabled) - { - // first fill our area with the bg_color - fill_rect(c, area,bg_color); - } - else - { - // first fill our area with gray - fill_rect(c, area,rgb_pixel(212,208,200)); - } - - - if (enabled) - mfont.draw_string(c,text_rect,text,text_color, 0, ustring::npos, area); - else - mfont.draw_string(c,text_rect,text,rgb_pixel(128,128,128), 0, ustring::npos, area); - - - // now draw the highlight if there is any - if (highlight_start <= highlight_end && enabled) - { - const rectangle first_pos = mfont.compute_cursor_rect(text_rect, text, highlight_start); - const rectangle last_pos = mfont.compute_cursor_rect(text_rect, text, highlight_end+1); - - const rgb_alpha_pixel color(10, 30, 106, 90); - - // if the highlighted text is all on one line - if (first_pos.top() == last_pos.top()) - { - fill_rect(c, (first_pos + last_pos).intersect(display_rect), color); - } - else - { - const rectangle min_boundary(display_rect.left()+4, display_rect.top()+4, - display_rect.right()-4, display_rect.bottom()-4); - const rectangle boundary( display_rect.intersect(text_rect) + min_boundary); - - rectangle first_row, last_row, middle_rows; - first_row += first_pos; - first_row += point(boundary.right(), first_pos.top()); - last_row += last_pos; - last_row += point(boundary.left(), last_pos.bottom()); - - middle_rows.left() = boundary.left(); - middle_rows.right() = boundary.right(); - middle_rows.top() = first_row.bottom()+1; - middle_rows.bottom() = last_row.top()-1; - - fill_rect(c, first_row.intersect(display_rect), color); - fill_rect(c, middle_rows, color); - fill_rect(c, last_row.intersect(display_rect), color); - } - } - - // now draw the cursor if we need to - if (cursor_visible && has_focus && enabled) - { - draw_line(c, point(cursor_rect.left(), cursor_rect.top()),point(cursor_rect.left(), cursor_rect.bottom()), 0, area); - } - - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_WIDGETs_STYLE_CPP_ - diff --git a/ml/dlib/dlib/gui_widgets/style.h b/ml/dlib/dlib/gui_widgets/style.h deleted file mode 100644 index f31caee30..000000000 --- a/ml/dlib/dlib/gui_widgets/style.h +++ /dev/null @@ -1,825 +0,0 @@ -// 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_ - - diff --git a/ml/dlib/dlib/gui_widgets/style_abstract.h b/ml/dlib/dlib/gui_widgets/style_abstract.h deleted file mode 100644 index e4d3245df..000000000 --- a/ml/dlib/dlib/gui_widgets/style_abstract.h +++ /dev/null @@ -1,777 +0,0 @@ -// Copyright (C) 2008 Davis E. King (davis@dlib.net), and Nils Labugt -// License: Boost Software License See LICENSE.txt for the full license. -#undef DLIB_WIDGETs_STYLE_ABSTRACT_ -#ifdef DLIB_WIDGETs_STYLE_ABSTRACT_ - -#include "../algs.h" -#include "../gui_core.h" -#include "widgets_abstract.h" -#include "../unicode/unicode_abstract.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // button styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class button_style - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an abstract class that defines the interface a - button style object must implement. - - Note that derived classes must be copyable via - their copy constructors. - !*/ - - public: - - virtual ~button_style() {} - - virtual bool redraw_on_mouse_over ( - ) const { return false; } - /*! - ensures - - if (this style draws buttons differently when a mouse is over them) then - - returns true - - else - - returns false - !*/ - - virtual rectangle get_invalidation_rect ( - const rectangle& rect - ) const { return rect; } - /*! - requires - - the mutex drawable::m is locked - - rect == the get_rect() that defines where the button is - ensures - - returns a rectangle that should be invalidated whenever a button - needs to redraw itself. (e.g. If you wanted your button style to - draw outside the button then you could return a larger rectangle) - !*/ - - virtual rectangle get_min_size ( - const ustring& name, - const font& mfont - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - ensures - - returns a rectangle that represents the minimum size of the button - given the name and font. - !*/ - - 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; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - rect, enabled, mfont, lastx, and lasty are the variables - defined in the protected section of the drawable class. - - name == the name of the button to be drawn - - is_depressed == true if the button is to be drawn in a depressed state - ensures - - draws the button on the canvas c at the location given by rect. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class button_style_default : public button_style - { - /*! - This is the default style for button objects. It will cause - a button to appear as the simple MS Windows 2000 button style. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class button_style_toolbar1 : public button_style - { - /*! - This draws a simple toolbar style button that displays its name in the - middle of itself. When the mouse moves over it it will light up. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class button_style_toolbar_icon1 : public button_style - { - /*! - This draws a simple toolbar style button that displays an image in the - middle of itself. When the mouse moves over it it will light up. - !*/ - template <typename image_type> - button_style_toolbar_icon1 ( - const image_type& img, - unsigned long border_size = 6 - ); - /*! - requires - - image_type == an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits<typename image_type::type> is defined - ensures - - displays image img in the middle of the button - - the distance between the edge of the button and the image - will be border_size pixels - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class button_style_arrow : public button_style - { - public: - /*! - This draws a simple button with an arrow in it - !*/ - - enum arrow_direction - { - UP, - DOWN, - LEFT, - RIGHT - }; - - button_style_arrow ( - arrow_direction dir - ); - /*! - ensures - - the arrow in the button will point in the given direction - !*/ - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // toggle button styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class toggle_button_style - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an abstract class that defines the interface a - toggle button style object must implement. - - Note that derived classes must be copyable via - their copy constructors. - !*/ - - public: - - virtual ~toggle_button_style() {} - - virtual bool redraw_on_mouse_over ( - ) const { return false; } - /*! - ensures - - if (this style draws buttons differently when a mouse is over them) then - - returns true - - else - - returns false - !*/ - - virtual rectangle get_min_size ( - const ustring& name, - const font& mfont - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - ensures - - returns a rectangle that represents the minimum size of the button - given the name and font. - !*/ - - 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; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - rect, enabled, mfont, lastx, and lasty are the variables - defined in the protected section of the drawable class. - - name == the name of the button to be drawn - - is_depressed == true if the button is to be drawn in a depressed state - - is_checked == true if the toggle_button is in the checked state - ensures - - draws the button on the canvas c at the location given by rect. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class toggle_button_style_default : public toggle_button_style - { - /*! - This is the default style for toggle_button objects. It will cause - a button to appear as the simple MS Windows 2000 button style. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class toggle_button_style_check_box : public toggle_button_style - { - /*! - This draws a simple check box style toggle button that displays its - name to the right of a check box. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class toggle_button_style_radio_button : public toggle_button_style - { - /*! - This draws a simple radio button style toggle button that displays its - name to the right of a circular radio button. - !*/ - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // scroll_bar styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class scroll_bar_style - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an abstract class that defines the interface a - scroll_bar style object must implement. - - Note that derived classes must be copyable via - their copy constructors. - - There are three parts of a scroll bar, the slider, the background, - and the two buttons on its ends. The "slider" is the thing that you - drag around on the scroll bar and the "background" is the part - in between the slider and the buttons on the ends. - !*/ - - public: - - virtual ~scroll_bar_style() {} - - virtual bool redraw_on_mouse_over_slider ( - ) const { return false; } - /*! - ensures - - if (this style draws a scroll_bar's slider differently when a mouse is over it - or it is being dragged) then - - returns true - - else - - returns false - !*/ - - virtual long get_width ( - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - ensures - - returns the width in pixels of the scroll bar - !*/ - - virtual long get_slider_length ( - long total_length, - long max_pos - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - - total_length == the total length in pixels of the scroll bar - - max_pos == the value of scroll_bar::max_slider_pos() for this - scroll bar - ensures - - returns the length in pixels of the scroll bar's slider - !*/ - - virtual long get_button_length ( - long total_length, - long max_pos - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - - total_length == the total length in pixels of the scroll bar - - max_pos == the value of scroll_bar::max_slider_pos() for this - scroll bar - ensures - - returns the length in pixels of each of the scroll bar's - buttons - !*/ - - 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; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - rect, enabled, lastx, and lasty are the variables - defined in the protected section of the drawable class. - - is_depressed == true if the background area of the scroll_bar is to - be drawn in a depressed state (because the user is clicking on it) - ensures - - draws the background part of the scroll_bar on the canvas c at the - location given by rect. - !*/ - - 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; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - rect, enabled, lastx, and lasty are the variables - defined in the protected section of the drawable class - - is_being_dragged == true if the user is dragging the slider - ensures - - draws the slider part of the scroll_bar on the canvas c at the - location given by rect. - !*/ - - button_style_type get_up_button_style ( - ) const; - /*! - ensures - - returns the type of button_style to use for a button on the - top side of a vertical scroll bar. - !*/ - - button_style_type get_down_button_style ( - ) const; - /*! - ensures - - returns the type of button_style to use for a button on the - bottom side of a vertical scroll bar. - !*/ - - button_style_type get_left_button_style ( - ) const; - /*! - ensures - - returns the type of button_style to use for a button on the - left side of a horizontal scroll bar. - !*/ - - button_style_type get_right_button_style ( - ) const; - /*! - ensures - - returns the type of button_style to use for a button on the - right side of a horizontal scroll bar. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class scroll_bar_style_default : public scroll_bar_style - { - /*! - This is the default style for scroll_bar objects. It will cause - a scroll_bar to appear as the simple MS Windows 2000 scroll_bar style. - !*/ - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // scrollable_region (and zoomable_region) styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class scrollable_region_style - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an abstract class that defines the interface a - scrollable_region and zoomable_region style object must implement. - - Note that derived classes must be copyable via - their copy constructors. - !*/ - public: - - virtual ~scrollable_region_style() {} - - virtual long get_border_size ( - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - ensures - - returns the size of the border region in pixels - !*/ - - virtual void draw_scrollable_region_border ( - const canvas& c, - const rectangle& rect, - const bool enabled - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - rect and enabled are the variables defined in the protected section - of the drawable class. - ensures - - draws the border part of a scrollable_region on the canvas c at the - location given by rect. - !*/ - - scroll_bar_style_type get_horizontal_scroll_bar_style ( - ) const; - /*! - ensures - - returns the style of scroll_bar to use for the - horizontal scroll_bar in this widget. - !*/ - - scroll_bar_style_type get_vertical_scroll_bar_style ( - ) const; - /*! - ensures - - returns the style of scroll_bar to use for the - vertical scroll_bar in this widget. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class scrollable_region_style_default : public scrollable_region_style - { - public: - /*! - This is the default style for scrollable_region and zoomable_region objects. - !*/ - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // text_box styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class text_box_style - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an abstract class that defines the interface a - text_box style object must implement. - - Note that derived classes must be copyable via - their copy constructors. - !*/ - public: - - virtual ~text_field_style() {} - - scrollable_region_style_type get_scrollable_region_style ( - ) const; - /*! - ensures - - returns the style of scrollable_region to use for the - text_box. - !*/ - - virtual unsigned long get_padding ( - const font& mfont - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - ensures - - returns the number of pixels that separate the text in the text_box - from the edge of the text_box widget itself. - !*/ - - 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; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - enabled and mfont are the variables defined in the protected section - - text_rect == the rectangle in which we should draw the given text - of the drawable class. - - display_rect == the rectangle returned by scrollable_region::display_rect() - - text == the current text in the text_box - - cursor_rect == A rectangle of width 1 that represents the current - position of the cursor on the screen. - - text_color == the color of the text to be drawn - - bg_color == the background color of the text field - - has_focus == true if this text field has keyboard input focus - - cursor_visible == true if the cursor should be drawn - - if (highlight_start <= highlight_end) then - - text[highlight_start] though text[highlight_end] should be - highlighted - ensures - - draws the text_box on the canvas c at the location given by text_rect. - (Note that the scroll bars and borders are drawn by the scrollable_region - and therefore the style returned by get_scrollable_region_style() - controls how those appear) - - doesn't draw anything outside display_rect - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class text_box_style_default : public text_box_style - { - public: - /*! - This is the default style for text_box objects. - !*/ - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // list_box styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class list_box_style - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an abstract class that defines the interface a - list_box style object must implement. - - Note that derived classes must be copyable via - their copy constructors. - !*/ - public: - - virtual ~list_box_style() {} - - virtual void draw_list_box_background ( - const canvas& c, - const rectangle& display_rect, - const bool enabled - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - display_rect == the display_rect for the list_box. This is the area - in which list box items are drawn (see display_rect in the scrollable_region - widget for more info) - - enabled == true if the list box is enabled - ensures - - draws the background of a list box on the canvas c at the location given - by display_rect. - !*/ - - scrollable_region_style_type get_scrollable_region_style ( - ) const; - /*! - ensures - - returns the style of scrollable_region to use for the - list_box. - !*/ - - 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; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - rect == the rectangle that defines where on the screen this list box item is. - - display_rect == the display_rect for the list_box. This is the area - in which list box items are drawn (see display_rect in the scrollable_region - widget for more info) - - mfont == the font to use to draw the list box item - - text == the text of the list box item to be drawn - - enabled == true if the list box is enabled - - is_selected == true if the item is to be drawn in a selected state - ensures - - draws the list box item on the canvas c at the location given by rect. - !*/ - - // wide character overloads - 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: - /*! - This is the default style for list_box objects. - !*/ - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // text_field styles -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class text_field_style - { - /*! - WHAT THIS OBJECT REPRESENTS - This is an abstract class that defines the interface a - text_field style object must implement. - - Note that derived classes must be copyable via - their copy constructors. - !*/ - public: - - virtual ~text_field_style() {} - - virtual unsigned long get_padding ( - const font& mfont - ) const = 0; - /*! - requires - - the mutex drawable::m is locked - ensures - - returns the number of pixels that separate the text in the text_field - from the edge of the text_field widget itself. - !*/ - - 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; - /*! - requires - - the mutex drawable::m is locked - - c == the canvas to draw on - - rect, enabled, and mfont are the variables defined in the protected section - of the drawable class. - - text == the current text in the text_field - - text_rect == the rectangle in which we should draw the given text - - cursor_x == the x coordinate of the cursor relative to the left side - of rect. i.e. the number of pixels that separate the cursor from the - left side of the text_field. - - text_pos == the index of the first letter in text that appears in - this text field. - - text_color == the color of the text to be drawn - - bg_color == the background color of the text field - - has_focus == true if this text field has keyboard input focus - - cursor_visible == true if the cursor should be drawn - - if (highlight_start <= highlight_end) then - - text[highlight_start] though text[highlight_end] should be - highlighted - ensures - - draws the text_field on the canvas c at the location given by rect. - !*/ - - }; - -// ---------------------------------------------------------------------------------------- - - class text_field_style_default : public text_field_style - { - public: - /*! - This is the default style for text_field objects. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_WIDGETs_STYLE_ABSTRACT_ - - - diff --git a/ml/dlib/dlib/gui_widgets/widgets.cpp b/ml/dlib/dlib/gui_widgets/widgets.cpp deleted file mode 100644 index c460d946d..000000000 --- a/ml/dlib/dlib/gui_widgets/widgets.cpp +++ /dev/null @@ -1,7341 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_WIDGETs_CPP_ -#define DLIB_WIDGETs_CPP_ - -#include <algorithm> -#include <memory> - -#include "widgets.h" -#include "../string.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // toggle_button object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - rectangle min_rect = style->get_min_size(name_,*mfont); - // only change the size if it isn't going to be too small to fit the name - if (height >= min_rect.height() && - width >= min_rect.width()) - { - rectangle old(rect); - rect = resize_rect(rect,width,height); - parent.invalidate_rectangle(rect+old); - btn_tooltip.set_size(width,height); - } - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - set_checked ( - ) - { - auto_mutex M(m); - checked = true; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - set_unchecked ( - ) - { - auto_mutex M(m); - checked = false; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - bool toggle_button:: - is_checked ( - ) const - { - auto_mutex M(m); - return checked; - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - show ( - ) - { - button_action::show(); - btn_tooltip.show(); - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - hide ( - ) - { - button_action::hide(); - btn_tooltip.hide(); - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - enable ( - ) - { - button_action::enable(); - btn_tooltip.enable(); - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - disable ( - ) - { - button_action::disable(); - btn_tooltip.disable(); - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - set_tooltip_text ( - const std::string& text - ) - { - btn_tooltip.set_text(text); - } - - void toggle_button:: - set_tooltip_text ( - const std::wstring& text - ) - { - btn_tooltip.set_text(text); - } - - void toggle_button:: - set_tooltip_text ( - const dlib::ustring& text - ) - { - btn_tooltip.set_text(text); - } - -// ---------------------------------------------------------------------------------------- - - const std::string toggle_button:: - tooltip_text ( - ) const - { - return btn_tooltip.text(); - } - - const std::wstring toggle_button:: - tooltip_wtext ( - ) const - { - return btn_tooltip.wtext(); - } - - const dlib::ustring toggle_button:: - tooltip_utext ( - ) const - { - return btn_tooltip.utext(); - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - set_name(name_); - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - set_pos ( - long x, - long y - ) - { - auto_mutex M(m); - button_action::set_pos(x,y); - btn_tooltip.set_pos(x,y); - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - set_name ( - const std::string& name - ) - { - set_name(convert_mbstring_to_wstring(name)); - } - - void toggle_button:: - set_name ( - const std::wstring& name - ) - { - set_name(convert_wstring_to_utf32(name)); - } - - void toggle_button:: - set_name ( - const dlib::ustring& name - ) - { - auto_mutex M(m); - name_ = name; - // do this to get rid of any reference counting that may be present in - // the std::string implementation. - name_[0] = name_[0]; - - rectangle old(rect); - rect = move_rect(style->get_min_size(name,*mfont),rect.left(),rect.top()); - btn_tooltip.set_size(rect.width(),rect.height()); - - parent.invalidate_rectangle(rect+old); - } - -// ---------------------------------------------------------------------------------------- - - const std::string toggle_button:: - name ( - ) const - { - return convert_wstring_to_mbstring(wname()); - } - - const std::wstring toggle_button:: - wname ( - ) const - { - return convert_utf32_to_wstring(uname()); - } - - const dlib::ustring toggle_button:: - uname ( - ) const - { - auto_mutex M(m); - dlib::ustring temp = name_; - // do this to get rid of any reference counting that may be present in - // the std::string implementation. - temp[0] = name_[0]; - return temp; - } - -// ---------------------------------------------------------------------------------------- - - void toggle_button:: - on_button_up ( - bool mouse_over - ) - { - if (mouse_over) - { - checked = !checked; - // this is a valid toggle_button click - if (event_handler.is_set()) - event_handler(); - else if (event_handler_self.is_set()) - event_handler_self(*this); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // label object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void label:: - draw ( - const canvas& c - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty() || text_.size() == 0) - return; - - using namespace std; - unsigned char r = text_color_.red; - unsigned char g = text_color_.green; - unsigned char b = text_color_.blue; - if (!enabled) - { - r = 128; - g = 128; - b = 128; - } - - rectangle text_rect(rect); - - string::size_type first, last; - first = 0; - last = text_.find_first_of('\n'); - mfont->draw_string(c,text_rect,text_,rgb_pixel(r,g,b),first,last); - - while (last != string::npos) - { - first = last+1; - last = text_.find_first_of('\n',first); - text_rect.set_top(text_rect.top()+mfont->height()); - mfont->draw_string(c,text_rect,text_,rgb_pixel(r,g,b),first,last); - } - } - -// ---------------------------------------------------------------------------------------- - - void label:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - set_text(text_); - } - -// ---------------------------------------------------------------------------------------- - - - void label:: - set_text ( - const std::string& text - ) - { - set_text(convert_mbstring_to_wstring(text)); - } - - void label:: - set_text ( - const std::wstring& text - ) - { - set_text(convert_wstring_to_utf32(text)); - } - - void label:: - set_text ( - const dlib::ustring& text - ) - { - using namespace std; - auto_mutex M(m); - text_ = text; - // do this to get rid of any reference counting that may be present in - // the std::string implementation. - text_[0] = text[0]; - - rectangle old(rect); - - unsigned long width; - unsigned long height; - mfont->compute_size(text,width,height); - - rect.set_right(rect.left() + width - 1); - rect.set_bottom(rect.top() + height - 1); - - parent.invalidate_rectangle(rect+old); - } - -// ---------------------------------------------------------------------------------------- - - const std::string label:: - text ( - ) const - { - return convert_wstring_to_mbstring(wtext()); - } - - const std::wstring label:: - wtext ( - ) const - { - return convert_utf32_to_wstring(utext()); - } - - const dlib::ustring label:: - utext ( - ) const - { - auto_mutex M(m); - dlib::ustring temp = text_; - // do this to get rid of any reference counting that may be present in - // the std::string implementation. - temp[0] = text_[0]; - return temp; - } - -// ---------------------------------------------------------------------------------------- - - void label:: - set_text_color ( - const rgb_pixel color - ) - { - m.lock(); - text_color_ = color; - parent.invalidate_rectangle(rect); - m.unlock(); - } - -// ---------------------------------------------------------------------------------------- - - const rgb_pixel label:: - text_color ( - ) const - { - auto_mutex M(m); - return text_color_; - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // text_field object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - rectangle text_field:: - get_text_rect ( - ) const - { - // figure out where the text string should appear - unsigned long vertical_pad = (rect.height() - mfont->height())/2+1; - - rectangle text_rect; - text_rect.set_left(rect.left()+style->get_padding(*mfont)); - text_rect.set_top(rect.top()+vertical_pad); - text_rect.set_right(rect.right()-style->get_padding(*mfont)); - text_rect.set_bottom(text_rect.top()+mfont->height()-1); - return text_rect; - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - enable ( - ) - { - drawable::enable(); - right_click_menu.enable(); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - give_input_focus ( - ) - { - auto_mutex M(m); - has_focus = true; - cursor_visible = true; - parent.invalidate_rectangle(rect); - t.start(); - } - -// ---------------------------------------------------------------------------------------- - - bool text_field:: - has_input_focus ( - ) const - { - auto_mutex M(m); - return has_focus; - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - select_all_text ( - ) - { - auto_mutex M(m); - on_select_all(); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_cut ( - ) - { - on_copy(); - on_delete_selected(); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_copy ( - ) - { - if (highlight_start <= highlight_end) - { - put_on_clipboard(text_.substr(highlight_start, highlight_end-highlight_start+1)); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_paste ( - ) - { - ustring temp_str; - get_from_clipboard(temp_str); - - // If this is a multi line string then just take the first line. - ustring::size_type pos = temp_str.find_first_of('\n'); - if (pos != ustring::npos) - { - temp_str = temp_str.substr(0,pos); - } - - if (highlight_start <= highlight_end) - { - text_ = text_.substr(0,highlight_start) + temp_str + - text_.substr(highlight_end+1,text_.size()-highlight_end-1); - move_cursor(highlight_start+temp_str.size()); - highlight_start = 0; - highlight_end = -1; - parent.invalidate_rectangle(rect); - on_no_text_selected(); - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - else - { - text_ = text_.substr(0,cursor_pos) + temp_str + - text_.substr(cursor_pos,text_.size()-cursor_pos); - move_cursor(cursor_pos+temp_str.size()); - - // send out the text modified event - if (temp_str.size() != 0 && text_modified_handler.is_set()) - text_modified_handler(); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_select_all ( - ) - { - move_cursor(static_cast<long>(text_.size())); - highlight_start = 0; - highlight_end = static_cast<long>(text_.size()-1); - if (highlight_start <= highlight_end) - on_text_is_selected(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_delete_selected ( - ) - { - if (highlight_start <= highlight_end) - { - text_ = text_.erase(highlight_start,highlight_end-highlight_start+1); - move_cursor(highlight_start); - highlight_start = 0; - highlight_end = -1; - - on_no_text_selected(); - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - - parent.invalidate_rectangle(rect); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_text_is_selected ( - ) - { - right_click_menu.menu().enable_menu_item(0); - right_click_menu.menu().enable_menu_item(1); - right_click_menu.menu().enable_menu_item(3); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_no_text_selected ( - ) - { - right_click_menu.menu().disable_menu_item(0); - right_click_menu.menu().disable_menu_item(1); - right_click_menu.menu().disable_menu_item(3); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - show ( - ) - { - drawable::show(); - right_click_menu.show(); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - disable ( - ) - { - auto_mutex M(m); - drawable::disable(); - t.stop(); - has_focus = false; - cursor_visible = false; - right_click_menu.disable(); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - hide ( - ) - { - auto_mutex M(m); - drawable::hide(); - t.stop(); - has_focus = false; - cursor_visible = false; - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - // adjust the height of this text field so that it is appropriate for the current - // font size - rect.set_bottom(rect.top() + mfont->height()+ (style->get_padding(*mfont))*2); - set_text(text_); - right_click_menu.set_rect(get_text_rect()); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - draw ( - const canvas& c - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - style->draw_text_field(c,rect,get_text_rect(), enabled, *mfont, text_, cursor_x, text_pos, - text_color_, bg_color_, has_focus, cursor_visible, highlight_start, - highlight_end); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - set_text ( - const std::string& text - ) - { - set_text(convert_mbstring_to_wstring(text)); - } - - void text_field:: - set_text ( - const std::wstring& text - ) - { - set_text(convert_wstring_to_utf32(text)); - } - - void text_field:: - set_text ( - const dlib::ustring& text - ) - { - DLIB_ASSERT ( text.find_first_of('\n') == std::string::npos , - "\tvoid text_field::set_text()" - << "\n\ttext: " << narrow(text) ); - auto_mutex M(m); - // do this to get rid of any reference counting that may be present in - // the std::string implementation. - text_ = text.c_str(); - - move_cursor(0); - - highlight_start = 0; - highlight_end = -1; - - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - const std::string text_field:: - text ( - ) const - { - std::string temp = convert_wstring_to_mbstring(wtext()); - return temp; - } - - const std::wstring text_field:: - wtext ( - ) const - { - std::wstring temp = convert_utf32_to_wstring(utext()); - return temp; - } - - const dlib::ustring text_field:: - utext ( - ) const - { - auto_mutex M(m); - // do this to get rid of any reference counting that may be present in - // the dlib::ustring implementation. - dlib::ustring temp = text_.c_str(); - return temp; - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - set_width ( - unsigned long width - ) - { - auto_mutex M(m); - if (width < style->get_padding(*mfont)*2) - return; - - rectangle old(rect); - - rect.set_right(rect.left() + width - 1); - - right_click_menu.set_rect(get_text_rect()); - parent.invalidate_rectangle(rect+old); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - set_pos ( - long x, - long y - ) - { - drawable::set_pos(x,y); - right_click_menu.set_rect(get_text_rect()); - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - set_background_color ( - const rgb_pixel color - ) - { - auto_mutex M(m); - bg_color_ = color; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - const rgb_pixel text_field:: - background_color ( - ) const - { - auto_mutex M(m); - return bg_color_; - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - set_text_color ( - const rgb_pixel color - ) - { - auto_mutex M(m); - text_color_ = color; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - const rgb_pixel text_field:: - text_color ( - ) const - { - auto_mutex M(m); - return text_color_; - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - if (!enabled || hidden || !has_focus) - { - return; - } - - if (state & base_window::LEFT) - { - if (highlight_start <= highlight_end) - { - if (highlight_start == cursor_pos) - shift_pos = highlight_end + 1; - else - shift_pos = highlight_start; - } - - unsigned long new_pos = mfont->compute_cursor_pos(get_text_rect(),text_,x,y,text_pos); - if (static_cast<long>(new_pos) != cursor_pos) - { - move_cursor(new_pos); - parent.invalidate_rectangle(rect); - } - } - else if (shift_pos != -1) - { - shift_pos = -1; - } - - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_mouse_up ( - unsigned long btn, - unsigned long, - long , - long - ) - { - if (!enabled || hidden) - return; - - if (btn == base_window::LEFT) - shift_pos = -1; - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool double_clicked - ) - { - using namespace std; - if (!enabled || hidden || btn != (unsigned long)base_window::LEFT) - return; - - if (rect.contains(x,y)) - { - has_focus = true; - cursor_visible = true; - parent.invalidate_rectangle(rect); - t.start(); - - if (double_clicked) - { - // highlight the double clicked word - string::size_type first, last; - const ustring ustr = convert_utf8_to_utf32(std::string(" \t\n")); - first = text_.substr(0,cursor_pos).find_last_of(ustr.c_str()); - last = text_.find_first_of(ustr.c_str(),cursor_pos); - long f = static_cast<long>(first); - long l = static_cast<long>(last); - if (first == string::npos) - f = -1; - if (last == string::npos) - l = static_cast<long>(text_.size()); - - ++f; - --l; - - move_cursor(l+1); - highlight_start = f; - highlight_end = l; - on_text_is_selected(); - } - else - { - if (state & base_window::SHIFT) - { - if (highlight_start <= highlight_end) - { - if (highlight_start == cursor_pos) - shift_pos = highlight_end + 1; - else - shift_pos = highlight_start; - } - else - { - shift_pos = cursor_pos; - } - } - - bool at_end = false; - if (cursor_pos == 0 || cursor_pos == static_cast<long>(text_.size())) - at_end = true; - const long old_pos = cursor_pos; - - unsigned long new_pos = mfont->compute_cursor_pos(get_text_rect(),text_,x,y,text_pos); - if (static_cast<long>(new_pos) != cursor_pos) - { - move_cursor(new_pos); - parent.invalidate_rectangle(rect); - } - shift_pos = cursor_pos; - - if (at_end && cursor_pos == old_pos) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - - } - else if (has_focus) - { - t.stop(); - has_focus = false; - cursor_visible = false; - shift_pos = -1; - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - - if (focus_lost_handler.is_set()) - focus_lost_handler(); - parent.invalidate_rectangle(rect); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - // If the right click menu is up then we don't want to do anything with - // the keyboard ourselves. Let the popup menu use the keyboard for now. - if (right_click_menu.popup_menu_visible()) - return; - - const ustring space_str = convert_utf8_to_utf32(std::string(" \t\n")); - const bool shift = (state&base_window::KBD_MOD_SHIFT) != 0; - const bool ctrl = (state&base_window::KBD_MOD_CONTROL) != 0; - if (has_focus && enabled && !hidden) - { - if (shift && is_printable == false) - { - if (shift_pos == -1) - { - if (highlight_start <= highlight_end) - { - if (highlight_start == cursor_pos) - shift_pos = highlight_end + 1; - else - shift_pos = highlight_start; - } - else - { - shift_pos = cursor_pos; - } - } - } - else - { - shift_pos = -1; - } - - if (key == base_window::KEY_LEFT || - key == base_window::KEY_UP) - { - if (cursor_pos != 0) - { - unsigned long new_pos; - if (ctrl) - { - // find the first non-whitespace to our left - std::string::size_type pos = text_.find_last_not_of(space_str.c_str(),cursor_pos); - if (pos != std::string::npos) - { - pos = text_.find_last_of(space_str.c_str(),pos); - if (pos != std::string::npos) - new_pos = static_cast<unsigned long>(pos); - else - new_pos = 0; - } - else - { - new_pos = 0; - } - } - else - { - new_pos = cursor_pos-1; - } - - move_cursor(new_pos); - } - else if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - - } - else if (key == base_window::KEY_RIGHT || - key == base_window::KEY_DOWN) - { - if (cursor_pos != static_cast<long>(text_.size())) - { - unsigned long new_pos; - if (ctrl) - { - // find the first non-whitespace to our left - std::string::size_type pos = text_.find_first_not_of(space_str.c_str(),cursor_pos); - if (pos != std::string::npos) - { - pos = text_.find_first_of(space_str.c_str(),pos); - if (pos != std::string::npos) - new_pos = static_cast<unsigned long>(pos+1); - else - new_pos = static_cast<unsigned long>(text_.size()); - } - else - { - new_pos = static_cast<unsigned long>(text_.size()); - } - } - else - { - new_pos = cursor_pos+1; - } - - move_cursor(new_pos); - } - else if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - else if (is_printable) - { - if (ctrl) - { - if (key == 'a') - { - on_select_all(); - } - else if (key == 'c') - { - on_copy(); - } - else if (key == 'v') - { - on_paste(); - } - else if (key == 'x') - { - on_cut(); - } - } - else if (key != '\n') - { - if (highlight_start <= highlight_end) - { - text_ = text_.substr(0,highlight_start) + static_cast<unichar>(key) + - text_.substr(highlight_end+1,text_.size()-highlight_end-1); - move_cursor(highlight_start+1); - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - else - { - text_ = text_.substr(0,cursor_pos) + static_cast<unichar>(key) + - text_.substr(cursor_pos,text_.size()-cursor_pos); - move_cursor(cursor_pos+1); - } - unsigned long height; - mfont->compute_size(text_,text_width,height,text_pos); - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - else if (key == '\n') - { - if (enter_key_handler.is_set()) - enter_key_handler(); - } - } - else if (key == base_window::KEY_BACKSPACE) - { - // if something is highlighted then delete that - if (highlight_start <= highlight_end) - { - on_delete_selected(); - } - else if (cursor_pos != 0) - { - text_ = text_.erase(cursor_pos-1,1); - move_cursor(cursor_pos-1); - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - else - { - // do this just so it repaints itself right - move_cursor(cursor_pos); - } - unsigned long height; - mfont->compute_size(text_,text_width,height,text_pos); - parent.invalidate_rectangle(rect); - } - else if (key == base_window::KEY_DELETE) - { - // if something is highlighted then delete that - if (highlight_start <= highlight_end) - { - on_delete_selected(); - } - else if (cursor_pos != static_cast<long>(text_.size())) - { - text_ = text_.erase(cursor_pos,1); - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - else - { - // do this just so it repaints itself right - move_cursor(cursor_pos); - } - parent.invalidate_rectangle(rect); - - unsigned long height; - mfont->compute_size(text_,text_width,height,text_pos); - } - else if (key == base_window::KEY_HOME) - { - move_cursor(0); - if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - else if (key == base_window::KEY_END) - { - move_cursor(static_cast<unsigned long>(text_.size())); - if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - cursor_visible = true; - recent_movement = true; - - } - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - on_string_put( - const std::wstring &str - ) - { - if (has_focus && enabled && !hidden){ - ustring ustr = convert_wstring_to_utf32(str); - if (highlight_start <= highlight_end) - { - text_ = text_.substr(0,highlight_start) + ustr + - text_.substr(highlight_end+1,text_.size()-highlight_end-1); - move_cursor(highlight_start+ustr.size()); - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - else - { - text_ = text_.substr(0,cursor_pos) + ustr + - text_.substr(cursor_pos,text_.size()-cursor_pos); - move_cursor(cursor_pos+ustr.size()); - } - unsigned long height; - mfont->compute_size(text_,text_width,height,text_pos); - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_field:: - move_cursor ( - unsigned long pos - ) - { - using namespace std; - const long old_cursor_pos = cursor_pos; - - if (text_pos >= pos) - { - // the cursor should go all the way to the left side of the text - if (pos >= 6) - text_pos = pos-6; - else - text_pos = 0; - - cursor_pos = pos; - unsigned long height; - mfont->compute_size(text_,text_width,height,text_pos); - - unsigned long width; - unsigned long new_x = style->get_padding(*mfont); - if (static_cast<long>(cursor_pos)-1 >= static_cast<long>(text_pos)) - { - mfont->compute_size(text_,width,height,text_pos,cursor_pos-1); - if (cursor_pos != 0) - new_x += width - mfont->right_overflow(); - } - - cursor_x = new_x; - } - else - { - unsigned long height; - unsigned long width; - mfont->compute_size(text_,width,height,text_pos,pos-1); - - unsigned long new_x = style->get_padding(*mfont) + - width - mfont->right_overflow(); - - // move the text to the left if necessary - if (new_x + 4 > rect.width()) - { - while (new_x > rect.width() - rect.width()/5) - { - new_x -= (*mfont)[text_[text_pos]].width(); - ++text_pos; - } - } - - cursor_x = new_x; - cursor_pos = pos; - mfont->compute_size(text_,text_width,height,text_pos); - } - - parent.set_im_pos(rect.left()+cursor_x, rect.top()); - - if (old_cursor_pos != cursor_pos) - { - if (shift_pos != -1) - { - highlight_start = std::min(shift_pos,cursor_pos); - highlight_end = std::max(shift_pos,cursor_pos)-1; - } - else - { - highlight_start = 0; - highlight_end = -1; - } - - if (highlight_start > highlight_end) - on_no_text_selected(); - else - on_text_is_selected(); - - recent_movement = true; - cursor_visible = true; - parent.invalidate_rectangle(rect); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// tabbed_display object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - tabbed_display:: - tabbed_display( - drawable_window& w - ) : - drawable(w,MOUSE_CLICK), - selected_tab_(0), - left_pad(6), - right_pad(4), - top_pad(3), - bottom_pad(3) - { - rect = rectangle(0,0,40,mfont->height()+top_pad+bottom_pad); - enable_events(); - tabs.set_max_size(1); - tabs.set_size(1); - } - -// ---------------------------------------------------------------------------------------- - - tabbed_display:: - ~tabbed_display( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - set_pos ( - long x, - long y - ) - { - auto_mutex M(m); - // we have to adjust the positions of all the tab rectangles - const long xdelta = rect.left() - x; - const long ydelta = rect.top() - y; - for (unsigned long i = 0; i < tabs.size(); ++i) - { - tabs[i].rect.set_left(tabs[i].rect.left()+xdelta); - tabs[i].rect.set_right(tabs[i].rect.right()+xdelta); - - tabs[i].rect.set_top(tabs[i].rect.top()+ydelta); - tabs[i].rect.set_bottom(tabs[i].rect.bottom()+ydelta); - - - // adjust the position of the group associated with this tab if it exists - if (tabs[i].group) - tabs[i].group->set_pos(x+3, y+mfont->height()+top_pad+bottom_pad+3); - } - drawable::set_pos(x,y); - recompute_tabs(); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - fit_to_contents ( - ) - { - auto_mutex M(m); - rectangle new_rect; - point p(rect.left(),rect.top()); - new_rect += p; - - for (unsigned long i = 0; i < tabs.size(); ++i) - { - if (tabs[i].group) - { - tabs[i].group->fit_to_contents(); - new_rect += tabs[i].group->get_rect(); - } - } - - // and give the new rect an additional 4 pixels on the bottom and right sides - // so that the contents to hit the edge of the tabbed display - new_rect = resize_rect(new_rect, new_rect.width()+4, new_rect.height()+4); - - parent.invalidate_rectangle(new_rect+rect); - rect = new_rect; - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - rectangle old(rect); - const long x = rect.left(); - const long y = rect.top(); - rect.set_right(x+width-1); - rect.set_bottom(y+height-1); - - recompute_tabs(); - - parent.invalidate_rectangle(rect+old); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - set_number_of_tabs ( - unsigned long num - ) - { - auto_mutex M(m); - - DLIB_ASSERT ( num > 0 , - "\tvoid tabbed_display::set_number_of_tabs()" - << "\n\tnum: " << num ); - - tabs.set_max_size(num); - tabs.set_size(num); - - selected_tab_ = 0; - - recompute_tabs(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - unsigned long tabbed_display:: - selected_tab ( - ) const - { - auto_mutex M(m); - return selected_tab_; - } - - unsigned long tabbed_display:: - number_of_tabs ( - ) const - { - auto_mutex M(m); - return tabs.size(); - } - -// ---------------------------------------------------------------------------------------- - - const std::string tabbed_display:: - tab_name ( - unsigned long idx - ) const - { - return convert_wstring_to_mbstring(tab_wname(idx)); - } - - const std::wstring tabbed_display:: - tab_wname ( - unsigned long idx - ) const - { - return convert_utf32_to_wstring(tab_uname(idx)); - } - - const dlib::ustring& tabbed_display:: - tab_uname ( - unsigned long idx - ) const - { - auto_mutex M(m); - - DLIB_ASSERT ( idx < number_of_tabs() , - "\tvoid tabbed_display::tab_name()" - << "\n\tidx: " << idx - << "\n\tnumber_of_tabs(): " << number_of_tabs() ); - - return tabs[idx].name; - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - set_tab_name ( - unsigned long idx, - const std::string& new_name - ) - { - set_tab_name(idx, convert_mbstring_to_wstring(new_name)); - } - - void tabbed_display:: - set_tab_name ( - unsigned long idx, - const std::wstring& new_name - ) - { - set_tab_name(idx, convert_wstring_to_utf32(new_name)); - } - - void tabbed_display:: - set_tab_name ( - unsigned long idx, - const dlib::ustring& new_name - ) - { - auto_mutex M(m); - - - DLIB_ASSERT ( idx < number_of_tabs() , - "\tvoid tabbed_display::set_tab_name()" - << "\n\tidx: " << idx - << "\n\tnumber_of_tabs(): " << number_of_tabs() ); - - - tabs[idx].name = new_name; - // do this so that there isn't any reference counting going on - tabs[idx].name[0] = tabs[idx].name[0]; - unsigned long height; - mfont->compute_size(new_name,tabs[idx].width,height); - - - recompute_tabs(); - - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - on_mouse_down ( - unsigned long btn, - unsigned long, - long x, - long y, - bool - ) - { - if (rect.contains(x,y) && btn == base_window::LEFT && enabled && !hidden) - { - rectangle temp = rect; - const long offset = mfont->height() + bottom_pad + top_pad; - temp.set_bottom(rect.top()+offset); - if (temp.contains(x,y)) - { - // now we have to figure out which tab was clicked - for (unsigned long i = 0; i < tabs.size(); ++i) - { - if (selected_tab_ != i && tabs[i].rect.contains(x,y) && - tabs[selected_tab_].rect.contains(x,y) == false) - { - unsigned long old_idx = selected_tab_; - selected_tab_ = i; - recompute_tabs(); - parent.invalidate_rectangle(temp); - - // adjust the widget_group objects for these tabs if they exist - if (tabs[i].group) - tabs[i].group->show(); - if (tabs[old_idx].group) - tabs[old_idx].group->hide(); - - if (event_handler.is_set()) - event_handler(i,old_idx); - break; - } - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - set_tab_group ( - unsigned long idx, - widget_group& group - ) - { - auto_mutex M(m); - - DLIB_ASSERT ( idx < number_of_tabs() , - "\tvoid tabbed_display::set_tab_group()" - << "\n\tidx: " << idx - << "\n\tnumber_of_tabs(): " << number_of_tabs() ); - - - tabs[idx].group = &group; - group.set_pos(rect.left()+3,rect.top()+mfont->height()+top_pad+bottom_pad+2); - if (idx == selected_tab_) - group.show(); - else - group.hide(); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - disable ( - ) - { - auto_mutex M(m); - if (tabs[selected_tab_].group) - tabs[selected_tab_].group->disable(); - drawable::disable(); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - enable ( - ) - { - auto_mutex M(m); - if (tabs[selected_tab_].group) - tabs[selected_tab_].group->enable(); - drawable::enable(); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - hide ( - ) - { - auto_mutex M(m); - if (tabs[selected_tab_].group) - tabs[selected_tab_].group->hide(); - drawable::hide(); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - show ( - ) - { - auto_mutex M(m); - if (tabs[selected_tab_].group) - tabs[selected_tab_].group->show(); - drawable::show(); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - draw ( - const canvas& c - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - // draw the main border first - rectangle main_box(rect.left(),rect.top()+mfont->height()+top_pad+bottom_pad,rect.right(),rect.bottom()); - draw_button_up(c,main_box); - draw_pixel(c,point(main_box.right()-1,main_box.top()),rgb_pixel(128,128,128)); - - rgb_pixel color; - if (enabled) - { - color.red = 0; - color.green = 0; - color.blue = 0; - } - else - { - color.red = 128; - color.green = 128; - color.blue = 128; - } - - // draw the tabs - for (unsigned long i = 0; i < tabs.size(); ++i) - { - if (selected_tab_ != i) - draw_tab(tabs[i].rect,c); - - // draw the name string - rectangle temp = tabs[i].rect; - temp.set_top(temp.top()+top_pad); - temp.set_bottom(temp.bottom()+bottom_pad); - temp.set_left(temp.left()+left_pad); - temp.set_right(temp.right()+right_pad); - mfont->draw_string(c,temp,tabs[i].name,color); - } - draw_tab(tabs[selected_tab_].rect,c); - draw_line(c, - point(tabs[selected_tab_].rect.left()+1, - tabs[selected_tab_].rect.bottom()), - point(tabs[selected_tab_].rect.right()-2, - tabs[selected_tab_].rect.bottom()), - rgb_pixel(212,208,200)); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - draw_tab ( - const rectangle& tab, - const canvas& c - ) const - { - const rgb_pixel white(255,255,255); - const rgb_pixel background(212,208,200); - const rgb_pixel dark_gray(64,64,64); - const rgb_pixel gray(128,128,128); - draw_line(c,point(tab.left(),tab.top()+2),point(tab.left(),tab.bottom()),white); - draw_line(c,point(tab.left()+1,tab.top()+2),point(tab.left()+1,tab.bottom()),background); - draw_line(c,point(tab.right(),tab.top()+2),point(tab.right(),tab.bottom()),dark_gray); - draw_line(c,point(tab.right()-1,tab.top()+2),point(tab.right()-1,tab.bottom()),gray); - draw_line(c,point(tab.left()+2,tab.top()),point(tab.right()-2,tab.top()),white); - draw_pixel(c,point(tab.left()+1,tab.top()+1),white); - draw_pixel(c,point(tab.right()-1,tab.top()+1),dark_gray); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - - for (unsigned long i = 0; i < tabs.size(); ++i) - { - unsigned long height; - mfont->compute_size(tabs[i].name,tabs[i].width,height); - } - - recompute_tabs(); - set_pos(rect.left(), rect.top()); - - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void tabbed_display:: - recompute_tabs ( - ) - { - const long offset = mfont->height() + bottom_pad + top_pad; - - - // figure out the size and position of all the tabs - rectangle sel_tab_rect, other_tab; - sel_tab_rect.set_top(rect.top()); - sel_tab_rect.set_bottom(rect.top()+offset); - - other_tab.set_top(rect.top()+2); - other_tab.set_bottom(rect.top()+offset-1); - - long cur_x = rect.left(); - for (unsigned long i = 0; i < tabs.size(); ++i) - { - const unsigned long str_width = tabs[i].width; - if (selected_tab_ != i) - { - other_tab.set_left(cur_x); - cur_x += left_pad + str_width + right_pad; - other_tab.set_right(cur_x); - tabs[i].rect = other_tab; - ++cur_x; - - } - else - { - if (i != 0) - sel_tab_rect.set_left(cur_x-2); - else - sel_tab_rect.set_left(cur_x); - - cur_x += left_pad + str_width + right_pad; - - if (i != tabs.size()-1) - sel_tab_rect.set_right(cur_x+2); - else - sel_tab_rect.set_right(cur_x); - ++cur_x; - - tabs[i].rect = sel_tab_rect; - } - } - - // make sure this object is wide enough - const rectangle& last = tabs[tabs.size()-1].rect; - const rectangle& first = tabs[0].rect; - rect = last + rect + first; - - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// named_rectangle object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - named_rectangle:: - named_rectangle( - drawable_window& w - ) : - drawable(w), - name_width(0), - name_height(0) - { - make_name_fit_in_rect(); - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - named_rectangle:: - ~named_rectangle( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void named_rectangle:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - rectangle old(rect); - const long x = rect.left(); - const long y = rect.top(); - rect.set_right(x+width-1); - rect.set_bottom(y+height-1); - - make_name_fit_in_rect(); - parent.invalidate_rectangle(rect+old); - } - -// ---------------------------------------------------------------------------------------- - - void named_rectangle:: - wrap_around ( - const rectangle& r - ) - { - auto_mutex M(m); - rectangle old(rect); - const unsigned long pad = name_height/2; - - rect = rectangle(r.left()-pad, r.top()-name_height*4/3, r.right()+pad, r.bottom()+pad); - - make_name_fit_in_rect(); - parent.invalidate_rectangle(rect+old); - } - -// ---------------------------------------------------------------------------------------- - - void named_rectangle:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - mfont->compute_size(name_,name_width,name_height); - make_name_fit_in_rect(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void named_rectangle:: - make_name_fit_in_rect ( - ) - { - // make sure the named rectangle is big enough to contain the name - const unsigned long wtemp = mfont->height() + name_width; - const unsigned long htemp = mfont->height() + name_height; - if (rect.width() < wtemp) - rect.set_right(rect.left() + wtemp - 1 ); - if (rect.height() < htemp) - rect.set_bottom(rect.bottom() + htemp - 1 ); - } - -// ---------------------------------------------------------------------------------------- - - void named_rectangle:: - set_name ( - const std::string& name - ) - { - set_name(convert_mbstring_to_wstring(name)); - } - - void named_rectangle:: - set_name ( - const std::wstring& name - ) - { - set_name(convert_wstring_to_utf32(name)); - } - - void named_rectangle:: - set_name ( - const dlib::ustring& name - ) - { - auto_mutex M(m); - name_ = name.c_str(); - mfont->compute_size(name_,name_width,name_height); - - make_name_fit_in_rect(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - const std::string named_rectangle:: - name ( - ) const - { - return convert_wstring_to_mbstring(wname()); - } - - const std::wstring named_rectangle:: - wname ( - ) const - { - return convert_utf32_to_wstring(uname()); - } - - const dlib::ustring named_rectangle:: - uname ( - ) const - { - auto_mutex M(m); - return dlib::ustring(name_.c_str()); - } - -// ---------------------------------------------------------------------------------------- - - void named_rectangle:: - draw ( - const canvas& c - ) const - { - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - const unsigned long gap = mfont->height()/2; - rectangle strrect = rect; - strrect.set_left(rect.left() + gap); - - const unsigned long rtop = rect.top() + name_height/2; - - const rgb_pixel white(255,255,255); - const rgb_pixel gray(128,128,128); - - mfont->draw_string(c,strrect,name_); - draw_line(c,point(rect.left(), rtop), - point(rect.left()+gap/2, rtop), gray); - draw_line(c,point(rect.left(), rtop), - point(rect.left(), rect.bottom()-1), gray); - draw_line(c,point(rect.left(), rect.bottom()-1), - point(rect.right()-1, rect.bottom()-1), gray); - draw_line(c,point(rect.right()-1, rtop), - point(rect.right()-1, rect.bottom()-2), gray); - draw_line(c,point(strrect.left() + name_width + 2, rtop), - point(rect.right()-1, rtop), gray); - - draw_line(c,point(strrect.left() + name_width + 2, rtop+1), - point( rect.right()-2, rtop+1), white); - draw_line(c,point(rect.right(), rtop), - point(rect.right(), rect.bottom()), white); - draw_line(c,point(rect.left(), rect.bottom()), - point(rect.right(), rect.bottom()), white); - draw_line(c,point(rect.left()+1, rtop+1), - point(rect.left()+1, rect.bottom()-2), white); - draw_line(c,point(rect.left()+1, rtop+1), - point(rect.left()+gap/2, rtop+1), white); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class mouse_tracker -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - mouse_tracker:: - mouse_tracker( - drawable_window& w - ) : - draggable(w), - offset(18), - nr(w), - x_label(w), - y_label(w), - click_x(-1), - click_y(-1) - { - set_draggable_area(rectangle(0,0,500,500)); - - - x_label.set_text("x: "); - y_label.set_text("y: "); - nr.set_name("mouse position"); - - - x_label.set_pos(offset,offset); - y_label.set_pos(x_label.get_rect().left(), x_label.get_rect().bottom()+3); - - nr.wrap_around(x_label.get_rect() + y_label.get_rect()); - rect = nr.get_rect(); - - set_z_order(2000000000); - x_label.set_z_order(2000000001); - y_label.set_z_order(2000000001); - nr.set_z_order(2000000001); - - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - mouse_tracker:: - ~mouse_tracker( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - nr.set_main_font(f); - x_label.set_main_font(f); - y_label.set_main_font(f); - mfont = f; - nr.wrap_around(x_label.get_rect() + y_label.get_rect()); - rect = nr.get_rect(); - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - set_pos ( - long x, - long y - ) - { - draggable::set_pos(x,y); - nr.set_pos(x,y); - x_label.set_pos(rect.left()+offset,rect.top()+offset); - y_label.set_pos(x_label.get_rect().left(), x_label.get_rect().bottom()+3); - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - show ( - ) - { - draggable::show(); - nr.show(); - x_label.show(); - y_label.show(); - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - hide ( - ) - { - draggable::hide(); - nr.hide(); - x_label.hide(); - y_label.hide(); - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - enable ( - ) - { - draggable::enable(); - nr.enable(); - x_label.enable(); - y_label.enable(); - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - disable ( - ) - { - draggable::disable(); - nr.disable(); - x_label.disable(); - y_label.disable(); - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool double_clicked - ) - { - draggable::on_mouse_down(btn,state,x,y,double_clicked); - if ((state & base_window::SHIFT) && (btn == base_window::LEFT) && enabled && !hidden) - { - parent.invalidate_rectangle(rectangle(x,y,x,y)); - parent.invalidate_rectangle(rectangle(click_x,click_y,click_x,click_y)); - click_x = x; - click_y = y; - - y_label.set_text("y: 0"); - x_label.set_text("x: 0"); - } - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - if (!hidden && enabled) - { - parent.invalidate_rectangle(rect); - draggable::on_mouse_move(state,x,y); - - long dx = 0; - long dy = 0; - if (click_x != -1) - dx = click_x; - if (click_y != -1) - dy = click_y; - - sout.str(""); - sout << "y: " << y - dy; - y_label.set_text(sout.str()); - - sout.str(""); - sout << "x: " << x - dx; - x_label.set_text(sout.str()); - } - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - on_drag ( - ) - { - nr.set_pos(rect.left(),rect.top()); - x_label.set_pos(rect.left()+offset,rect.top()+offset); - y_label.set_pos(x_label.get_rect().left(), x_label.get_rect().bottom()+3); - - long x = 0; - long y = 0; - if (click_x != -1) - x = click_x; - if (click_y != -1) - y = click_y; - - sout.str(""); - sout << "y: " << lasty - y; - y_label.set_text(sout.str()); - - sout.str(""); - sout << "x: " << lastx - x; - x_label.set_text(sout.str()); - } - -// ---------------------------------------------------------------------------------------- - - void mouse_tracker:: - draw ( - const canvas& c - ) const - { - fill_rect(c, rect,rgb_pixel(212,208,200)); - draw_pixel(c, point(click_x,click_y),rgb_pixel(255,0,0)); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class list_box -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace list_box_helper{ - template <typename S> - list_box<S>:: - list_box( - drawable_window& w - ) : - scrollable_region(w,MOUSE_WHEEL|MOUSE_CLICK), - ms_enabled(false), - last_selected(0) - { - set_vertical_scroll_increment(mfont->height()); - set_horizontal_scroll_increment(mfont->height()); - - style.reset(new list_box_style_default()); - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - list_box<S>:: - ~list_box( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - void list_box<S>:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - // recompute the sizes of all the items - for (unsigned long i = 0; i < items.size(); ++i) - { - mfont->compute_size(items[i].name,items[i].width, items[i].height); - } - set_vertical_scroll_increment(mfont->height()); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - bool list_box<S>:: - is_selected ( - unsigned long index - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( index < size() , - "\tbool list_box::is_selected(index)" - << "\n\tindex: " << index - << "\n\tsize(): " << size() ); - - return items[index].is_selected; - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - void list_box<S>:: - select ( - unsigned long index - ) - { - auto_mutex M(m); - DLIB_ASSERT ( index < size() , - "\tvoid list_box::select(index)" - << "\n\tindex: " << index - << "\n\tsize(): " << size() ); - - last_selected = index; - items[index].is_selected = true; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - void list_box<S>:: - unselect ( - unsigned long index - ) - { - auto_mutex M(m); - DLIB_ASSERT ( index < size() , - "\tvoid list_box::unselect(index)" - << "\n\tindex: " << index - << "\n\tsize(): " << size() ); - items[index].is_selected = false; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const S& list_box<S>::operator [] ( - unsigned long index - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( index < size() , - "\tconst std::string& list_box::operator[](index)" - << "\n\tindex: " << index - << "\n\tsize(): " << size() ); - return items[index].name; - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - bool list_box<S>:: - multiple_select_enabled ( - ) const - { - auto_mutex M(m); - return ms_enabled; - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - void list_box<S>:: - enable_multiple_select ( - ) - { - auto_mutex M(m); - ms_enabled = true; - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - void list_box<S>:: - disable_multiple_select ( - ) - { - auto_mutex M(m); - ms_enabled = false; - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - bool list_box<S>:: - at_start ( - ) const - { - auto_mutex M(m); - return items.at_start(); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - void list_box<S>:: - reset ( - ) const - { - auto_mutex M(m); - items.reset(); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - bool list_box<S>:: - current_element_valid ( - ) const - { - auto_mutex M(m); - return items.current_element_valid(); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const S &list_box<S>:: - element ( - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( current_element_valid() , - "\tconst std::string& list_box::element()" - ); - return items.element().name; - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - const S &list_box<S>:: - element ( - ) - { - auto_mutex M(m); - DLIB_ASSERT ( current_element_valid() , - "\tconst std::string& list_box::element()" - ); - return items.element().name; - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - bool list_box<S>:: - move_next ( - ) const - { - auto_mutex M(m); - return items.move_next(); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - size_t list_box<S>:: - size ( - ) const - { - auto_mutex M(m); - return items.size(); - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - void list_box<S>:: - draw ( - const canvas& c - ) const - { - scrollable_region::draw(c); - - rectangle area = display_rect().intersect(c); - if (area.is_empty()) - return; - - style->draw_list_box_background(c, display_rect(), enabled); - - long y = total_rect().top(); - for (unsigned long i = 0; i < items.size(); ++i) - { - if (y+(long)items[i].height <= area.top()) - { - y += items[i].height; - continue; - } - - rectangle r(total_rect().left(), y, display_rect().right(), y+items[i].height-1); - - style->draw_list_box_item(c,r, display_rect(), enabled, *mfont, items[i].name, items[i].is_selected); - - - y += items[i].height; - - if (y > area.bottom()) - break; - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - void list_box<S>:: - on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ) - { - if (display_rect().contains(x,y) && btn == base_window::LEFT && enabled && !hidden ) - { - if ( ms_enabled == false || - ((!(state&base_window::CONTROL)) && !(state&base_window::SHIFT))) - { - items.reset(); - while (items.move_next()) - { - items.element().is_selected = false; - } - } - - y -= total_rect().top(); - long h = 0; - for (unsigned long i = 0; i < items.size(); ++i) - { - h += items[i].height; - if (h >= y) - { - if (ms_enabled) - { - if (state&base_window::CONTROL) - { - items[i].is_selected = !items[i].is_selected; - if (items[i].is_selected) - last_selected = i; - } - else if (state&base_window::SHIFT) - { - // we want to select everything between (and including) the - // current thing clicked and last_selected. - const unsigned long first = std::min(i,last_selected); - const unsigned long last = std::max(i,last_selected); - for (unsigned long j = first; j <= last; ++j) - items[j].is_selected = true; - } - else - { - items[i].is_selected = true; - last_selected = i; - if (is_double_click && event_handler.is_set()) - event_handler(i); - else if (single_click_event_handler.is_set()) - single_click_event_handler(i); - } - } - else - { - items[i].is_selected = true; - last_selected = i; - if (is_double_click && event_handler.is_set()) - event_handler(i); - else if (single_click_event_handler.is_set()) - single_click_event_handler(i); - } - - break; - } - } - - parent.invalidate_rectangle(rect); - } - } - -// ---------------------------------------------------------------------------------------- - - template <typename S> - unsigned long list_box<S>:: - get_selected ( - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( multiple_select_enabled() == false, - "\tunsigned long list_box::get_selected()" - ); - for (unsigned long i = 0; i < items.size(); ++i) - { - if (items[i].is_selected) - return i; - } - return items.size(); - } -// ---------------------------------------------------------------------------------------- - - // making instance of template - template class list_box<std::string>; - template class list_box<std::wstring>; - template class list_box<dlib::ustring>; - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // function message_box() -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace message_box_helper - { - void box_win:: - initialize ( - ) - { - msg.set_pos(20,20); - msg.set_text(message); - rectangle msg_rect = msg.get_rect(); - btn_ok.set_name("OK"); - btn_ok.set_size(60,btn_ok.height()); - if (msg_rect.width() >= 60) - btn_ok.set_pos(msg_rect.width()/2+msg_rect.left()-btn_ok.width()/2,msg_rect.bottom()+15); - else - btn_ok.set_pos(20,msg_rect.bottom()+15); - btn_ok.set_click_handler(*this,&box_win::on_click); - - rectangle size = btn_ok.get_rect() + msg_rect; - set_size(size.right()+20,size.bottom()+20); - - - show(); - set_title(title); - } - - // ------------------------------------------------------------------------------------ - - box_win:: - box_win ( - const std::string& title_, - const std::string& message_ - ) : - drawable_window(false), - title(convert_mbstring_to_wstring(title_)), - message(convert_mbstring_to_wstring(message_)), - msg(*this), - btn_ok(*this) - { - initialize(); - } - - // ------------------------------------------------------------------------------------ - - box_win:: - box_win ( - const std::wstring& title_, - const std::wstring& message_ - ) : - drawable_window(false), - title(title_), - message(message_), - msg(*this), - btn_ok(*this) - { - initialize(); - } - - // ------------------------------------------------------------------------------------ - - box_win:: - box_win ( - const dlib::ustring& title_, - const dlib::ustring& message_ - ) : - drawable_window(false), - title(convert_utf32_to_wstring(title_)), - message(convert_utf32_to_wstring(message_)), - msg(*this), - btn_ok(*this) - { - initialize(); - } - - // ------------------------------------------------------------------------------------ - - box_win:: - ~box_win ( - ) - { - close_window(); - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - deleter_thread ( - void* param - ) - { - // The point of this extra event_handler stuff is to allow the user - // to end the program from within the callback. So we want to destroy the - // window *before* we call their callback. - box_win& w = *static_cast<box_win*>(param); - w.close_window(); - any_function<void()> event_handler(w.event_handler); - delete &w; - if (event_handler.is_set()) - event_handler(); - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_click ( - ) - { - hide(); - create_new_thread(&deleter_thread,this); - } - - // ------------------------------------------------------------------------------------ - - base_window::on_close_return_code box_win:: - on_window_close ( - ) - { - // The point of this extra event_handler stuff is to allow the user - // to end the program within the callback. So we want to destroy the - // window *before* we call their callback. - any_function<void()> event_handler_copy(event_handler); - delete this; - if (event_handler_copy.is_set()) - event_handler_copy(); - return CLOSE_WINDOW; - } - - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - // ------------------------------------------------------------------------------------ - - void blocking_box_win:: - initialize ( - ) - { - msg.set_pos(20,20); - msg.set_text(message); - rectangle msg_rect = msg.get_rect(); - btn_ok.set_name("OK"); - btn_ok.set_size(60,btn_ok.height()); - if (msg_rect.width() >= 60) - btn_ok.set_pos(msg_rect.width()/2+msg_rect.left()-btn_ok.width()/2,msg_rect.bottom()+15); - else - btn_ok.set_pos(20,msg_rect.bottom()+15); - btn_ok.set_click_handler(*this,&blocking_box_win::on_click); - - rectangle size = btn_ok.get_rect() + msg_rect; - set_size(size.right()+20,size.bottom()+20); - - - set_title(title); - show(); - } - - // ------------------------------------------------------------------------------------ - - blocking_box_win:: - blocking_box_win ( - const std::string& title_, - const std::string& message_ - ) : - drawable_window(false), - title(convert_mbstring_to_wstring(title_)), - message(convert_mbstring_to_wstring(message_)), - msg(*this), - btn_ok(*this) - { - initialize(); - } - - // ------------------------------------------------------------------------------------ - - blocking_box_win:: - blocking_box_win ( - const std::wstring& title_, - const std::wstring& message_ - ) : - drawable_window(false), - title(title_), - message(message_), - msg(*this), - btn_ok(*this) - { - initialize(); - } - - // ------------------------------------------------------------------------------------ - - blocking_box_win:: - blocking_box_win ( - const dlib::ustring& title_, - const dlib::ustring& message_ - ) : - drawable_window(false), - title(convert_utf32_to_wstring(title_)), - message(convert_utf32_to_wstring(message_)), - msg(*this), - btn_ok(*this) - { - initialize(); - } - - // ------------------------------------------------------------------------------------ - - blocking_box_win:: - ~blocking_box_win ( - ) - { - close_window(); - } - - // ------------------------------------------------------------------------------------ - - void blocking_box_win:: - on_click ( - ) - { - close_window(); - } - - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // function open_file_box() -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace open_file_box_helper - { - box_win:: - box_win ( - const std::string& title, - bool has_text_field - ) : - lbl_dirs(*this), - lbl_files(*this), - lbl_file_name(*this), - lb_dirs(*this), - lb_files(*this), - btn_ok(*this), - btn_cancel(*this), - btn_root(*this), - tf_file_name(*this) - { - if (has_text_field == false) - { - tf_file_name.hide(); - lbl_file_name.hide(); - } - else - { - lbl_file_name.set_text("File: "); - } - - cur_dir = -1; - set_size(500,300); - - lbl_dirs.set_text("Directories:"); - lbl_files.set_text("Files:"); - btn_ok.set_name("Ok"); - btn_cancel.set_name("Cancel"); - btn_root.set_name("/"); - - btn_root.set_click_handler(*this,&box_win::on_root_click); - btn_cancel.set_click_handler(*this,&box_win::on_cancel_click); - btn_ok.set_click_handler(*this,&box_win::on_open_click); - lb_dirs.set_double_click_handler(*this,&box_win::on_dirs_click); - lb_files.set_click_handler(*this,&box_win::on_files_click); - lb_files.set_double_click_handler(*this,&box_win::on_files_double_click); - - - btn_root.set_pos(5,5); - - set_sizes(); - set_title(title); - - on_root_click(); - - // make it so that the file box starts out in our current working - // directory - std::string full_name(get_current_dir()); - - while (full_name.size() > 0) - { - std::string::size_type pos = full_name.find_first_of("\\/"); - std::string left(full_name.substr(0,pos)); - if (pos != std::string::npos) - full_name = full_name.substr(pos+1); - else - full_name.clear(); - - if (left.size() > 0) - enter_folder(left); - } - - - show(); - } - - // ------------------------------------------------------------------------------------ - - box_win:: - ~box_win ( - ) - { - close_window(); - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - set_sizes( - ) - { - unsigned long width, height; - get_size(width,height); - - - if (lbl_file_name.is_hidden()) - { - lbl_dirs.set_pos(0,btn_root.bottom()+5); - lb_dirs.set_pos(0,lbl_dirs.bottom()); - lb_dirs.set_size(width/2,height-lb_dirs.top()-btn_cancel.height()-10); - - lbl_files.set_pos(lb_dirs.right(),btn_root.bottom()+5); - lb_files.set_pos(lb_dirs.right(),lbl_files.bottom()); - lb_files.set_size(width-lb_files.left(),height-lb_files.top()-btn_cancel.height()-10); - - btn_ok.set_pos(width - btn_ok.width()-25,lb_files.bottom()+5); - btn_cancel.set_pos(btn_ok.left() - btn_cancel.width()-5,lb_files.bottom()+5); - } - else - { - - lbl_dirs.set_pos(0,btn_root.bottom()+5); - lb_dirs.set_pos(0,lbl_dirs.bottom()); - lb_dirs.set_size(width/2,height-lb_dirs.top()-btn_cancel.height()-10-tf_file_name.height()); - - lbl_files.set_pos(lb_dirs.right(),btn_root.bottom()+5); - lb_files.set_pos(lb_dirs.right(),lbl_files.bottom()); - lb_files.set_size(width-lb_files.left(),height-lb_files.top()-btn_cancel.height()-10-tf_file_name.height()); - - lbl_file_name.set_pos(lb_files.left(), lb_files.bottom()+8); - tf_file_name.set_pos(lbl_file_name.right(), lb_files.bottom()+5); - tf_file_name.set_width(width-tf_file_name.left()-5); - - btn_ok.set_pos(width - btn_ok.width()-25,tf_file_name.bottom()+5); - btn_cancel.set_pos(btn_ok.left() - btn_cancel.width()-5,tf_file_name.bottom()+5); - } - - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_window_resized ( - ) - { - set_sizes(); - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - deleter_thread ( - ) - { - close_window(); - delete this; - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - enter_folder ( - const std::string& folder_name - ) - { - if (btn_root.is_checked()) - btn_root.set_unchecked(); - if (cur_dir != -1) - sob[cur_dir]->set_unchecked(); - - - const std::string old_path = path; - const long old_cur_dir = cur_dir; - - std::unique_ptr<toggle_button> new_btn(new toggle_button(*this)); - new_btn->set_name(folder_name); - new_btn->set_click_handler(*this,&box_win::on_path_button_click); - - // remove any path buttons that won't be part of the path anymore - if (sob.size()) - { - while (sob.size() > (unsigned long)(cur_dir+1)) - { - std::unique_ptr<toggle_button> junk; - sob.remove(cur_dir+1,junk); - } - } - - if (sob.size()) - new_btn->set_pos(sob[sob.size()-1]->right()+5,sob[sob.size()-1]->top()); - else - new_btn->set_pos(btn_root.right()+5,btn_root.top()); - - cur_dir = sob.size(); - sob.add(sob.size(),new_btn); - - path += folder_name + directory::get_separator(); - if (set_dir(prefix + path) == false) - { - sob.remove(sob.size()-1,new_btn); - path = old_path; - cur_dir = old_cur_dir; - } - else - { - - sob[cur_dir]->set_checked(); - } - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_dirs_click ( - unsigned long idx - ) - { - enter_folder(lb_dirs[idx]); - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_files_click ( - unsigned long idx - ) - { - if (tf_file_name.is_hidden() == false) - { - tf_file_name.set_text(lb_files[idx]); - } - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_files_double_click ( - unsigned long - ) - { - on_open_click(); - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_cancel_click ( - ) - { - hide(); - create_new_thread<box_win,&box_win::deleter_thread>(*this); - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_open_click ( - ) - { - if (lb_files.get_selected() != lb_files.size() || tf_file_name.text().size() > 0) - { - if (event_handler.is_set()) - { - if (tf_file_name.is_hidden()) - event_handler(prefix + path + lb_files[lb_files.get_selected()]); - else if (tf_file_name.text().size() > 0) - event_handler(prefix + path + tf_file_name.text()); - } - hide(); - create_new_thread<box_win,&box_win::deleter_thread>(*this); - } - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_path_button_click ( - toggle_button& btn - ) - { - if (btn_root.is_checked()) - btn_root.set_unchecked(); - if (cur_dir != -1) - sob[cur_dir]->set_unchecked(); - std::string new_path; - - for (unsigned long i = 0; i < sob.size(); ++i) - { - new_path += sob[i]->name() + directory::get_separator(); - if (sob[i].get() == &btn) - { - cur_dir = i; - sob[i]->set_checked(); - break; - } - } - if (path != new_path) - { - path = new_path; - set_dir(prefix+path); - } - } - - // ------------------------------------------------------------------------------------ - - struct case_insensitive_compare - { - bool operator() ( - const std::string& a, - const std::string& b - ) const - { - std::string::size_type i, size; - size = std::min(a.size(),b.size()); - for (i = 0; i < size; ++i) - { - if (std::tolower(a[i]) < std::tolower(b[i])) - return true; - else if (std::tolower(a[i]) > std::tolower(b[i])) - return false; - } - if (a.size() < b.size()) - return true; - else - return false; - } - }; - - // ------------------------------------------------------------------------------------ - - bool box_win:: - set_dir ( - const std::string& dir - ) - { - try - { - directory d(dir); - queue<directory>::kernel_1a_c qod; - queue<file>::kernel_1a_c qof; - queue<std::string>::sort_1a_c qos; - d.get_dirs(qod); - d.get_files(qof); - - qod.reset(); - while (qod.move_next()) - { - std::string temp = qod.element().name(); - qos.enqueue(temp); - } - qos.sort(case_insensitive_compare()); - lb_dirs.load(qos); - qos.clear(); - - qof.reset(); - while (qof.move_next()) - { - std::string temp = qof.element().name(); - qos.enqueue(temp); - } - qos.sort(case_insensitive_compare()); - lb_files.load(qos); - return true; - } - catch (directory::listing_error& ) - { - return false; - } - catch (directory::dir_not_found&) - { - return false; - } - } - - // ------------------------------------------------------------------------------------ - - void box_win:: - on_root_click ( - ) - { - btn_root.set_checked(); - if (cur_dir != -1) - sob[cur_dir]->set_unchecked(); - - queue<directory>::kernel_1a_c qod, qod2; - queue<file>::kernel_1a_c qof; - queue<std::string>::sort_1a_c qos; - get_filesystem_roots(qod); - path.clear(); - cur_dir = -1; - if (qod.size() == 1) - { - qod.current().get_files(qof); - qod.current().get_dirs(qod2); - prefix = qod.current().full_name(); - - qod2.reset(); - while (qod2.move_next()) - { - std::string temp = qod2.element().name(); - qos.enqueue(temp); - } - qos.sort(case_insensitive_compare()); - lb_dirs.load(qos); - qos.clear(); - - qof.reset(); - while (qof.move_next()) - { - std::string temp = qof.element().name(); - qos.enqueue(temp); - } - qos.sort(case_insensitive_compare()); - lb_files.load(qos); - } - else - { - prefix.clear(); - qod.reset(); - while (qod.move_next()) - { - std::string temp = qod.element().full_name(); - temp = temp.substr(0,temp.size()-1); - qos.enqueue(temp); - } - qos.sort(case_insensitive_compare()); - lb_dirs.load(qos); - qos.clear(); - lb_files.load(qos); - } - } - - // ------------------------------------------------------------------------------------ - - base_window::on_close_return_code box_win:: - on_window_close ( - ) - { - delete this; - return CLOSE_WINDOW; - } - - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class menu_bar -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - menu_bar:: - menu_bar( - drawable_window& w - ) : - drawable(w, 0xFFFF), // listen for all events - open_menu(0) - { - adjust_position(); - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - menu_bar:: - ~menu_bar() - { - disable_events(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - adjust_position(); - compute_menu_geometry(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - set_number_of_menus ( - unsigned long num - ) - { - auto_mutex M(m); - menus.set_max_size(num); - menus.set_size(num); - open_menu = menus.size(); - compute_menu_geometry(); - - for (unsigned long i = 0; i < menus.size(); ++i) - { - menus[i].menu.set_on_hide_handler(*this,&menu_bar::on_popup_hide); - } - - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - unsigned long menu_bar:: - number_of_menus ( - ) const - { - auto_mutex M(m); - return menus.size(); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - set_menu_name ( - unsigned long idx, - const std::string name, - char underline_ch - ) - { - set_menu_name(idx, convert_mbstring_to_wstring(name), underline_ch); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - set_menu_name ( - unsigned long idx, - const std::wstring name, - char underline_ch - ) - { - set_menu_name(idx, convert_wstring_to_utf32(name), underline_ch); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - set_menu_name ( - unsigned long idx, - const dlib::ustring name, - char underline_ch - ) - { - DLIB_ASSERT ( idx < number_of_menus() , - "\tvoid menu_bar::set_menu_name()" - << "\n\tidx: " << idx - << "\n\tnumber_of_menus(): " << number_of_menus() - ); - auto_mutex M(m); - menus[idx].name = name.c_str(); - menus[idx].underline_pos = name.find_first_of(underline_ch); - compute_menu_geometry(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - const std::string menu_bar:: - menu_name ( - unsigned long idx - ) const - { - return convert_wstring_to_mbstring(menu_wname(idx)); - } - -// ---------------------------------------------------------------------------------------- - - const std::wstring menu_bar:: - menu_wname ( - unsigned long idx - ) const - { - return convert_utf32_to_wstring(menu_uname(idx)); - } - -// ---------------------------------------------------------------------------------------- - - const dlib::ustring menu_bar:: - menu_uname ( - unsigned long idx - ) const - { - DLIB_ASSERT ( idx < number_of_menus() , - "\tstd::string menu_bar::menu_name()" - << "\n\tidx: " << idx - << "\n\tnumber_of_menus(): " << number_of_menus() - ); - auto_mutex M(m); - return menus[idx].name.c_str(); - } - -// ---------------------------------------------------------------------------------------- - - popup_menu& menu_bar:: - menu ( - unsigned long idx - ) - { - DLIB_ASSERT ( idx < number_of_menus() , - "\tpopup_menu& menu_bar::menu()" - << "\n\tidx: " << idx - << "\n\tnumber_of_menus(): " << number_of_menus() - ); - auto_mutex M(m); - return menus[idx].menu; - } - -// ---------------------------------------------------------------------------------------- - - const popup_menu& menu_bar:: - menu ( - unsigned long idx - ) const - { - DLIB_ASSERT ( idx < number_of_menus() , - "\tconst popup_menu& menu_bar::menu()" - << "\n\tidx: " << idx - << "\n\tnumber_of_menus(): " << number_of_menus() - ); - auto_mutex M(m); - return menus[idx].menu; - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - on_window_resized ( - ) - { - adjust_position(); - hide_menu(); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - draw ( - const canvas& c - ) const - { - rectangle area(rect.intersect(c)); - if (area.is_empty()) - return; - - const unsigned char opacity = 40; - fill_rect_with_vertical_gradient(c, rect,rgb_alpha_pixel(255,255,255,opacity), - rgb_alpha_pixel(0,0,0,opacity)); - - // first draw the border between the menu and the rest of the window - draw_line(c, point(rect.left(),rect.bottom()-1), - point(rect.right(),rect.bottom()-1), 100); - draw_line(c, point(rect.left(),rect.bottom()), - point(rect.right(),rect.bottom()), 255); - - // now draw all the menu buttons - for (unsigned long i = 0; i < menus.size(); ++i) - { - mfont->draw_string(c,menus[i].rect, menus[i].name ); - if (menus[i].underline_p1 != menus[i].underline_p2) - draw_line(c, menus[i].underline_p1, menus[i].underline_p2); - - if (open_menu == i) - { - fill_rect_with_vertical_gradient(c, menus[i].bgrect,rgb_alpha_pixel(255,255,0,40), rgb_alpha_pixel(0,0,0,40)); - } - } - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - on_window_moved ( - ) - { - hide_menu(); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - on_focus_lost ( - ) - { - hide_menu(); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ) - { - - if (rect.contains(x,y) == false || btn != (unsigned long)base_window::LEFT) - { - hide_menu(); - return; - } - - unsigned long old_menu = menus.size(); - - // if a menu is currently open then save its index - if (open_menu != menus.size()) - { - old_menu = open_menu; - hide_menu(); - } - - // figure out which menu should be open if any - for (unsigned long i = 0; i < menus.size(); ++i) - { - if (menus[i].bgrect.contains(x,y)) - { - if (old_menu != i) - show_menu(i); - - break; - } - } - - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - on_mouse_move ( - unsigned long , - long x, - long y - ) - { - // if the mouse is over the menu_bar and some menu is currently open - if (rect.contains(x,y) && open_menu != menus.size()) - { - // if the mouse is still in the same rectangle then don't do anything - if (menus[open_menu].bgrect.contains(x,y) == false) - { - // figure out which menu should be instead - for (unsigned long i = 0; i < menus.size(); ++i) - { - if (menus[i].bgrect.contains(x,y)) - { - show_menu(i); - break; - } - } - - } - } - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - if (state&base_window::KBD_MOD_ALT) - { - // check if the key matches any of our underlined keys - for (unsigned long i = 0; i < menus.size(); ++i) - { - // if we have found a matching key - if (is_printable && - menus[i].underline_pos != std::string::npos && - std::tolower(menus[i].name[menus[i].underline_pos]) == std::tolower(key)) - { - show_menu(i); - menus[open_menu].menu.select_first_item(); - return; - } - } - } - - if (open_menu != menus.size()) - { - unsigned long i = open_menu; - // if the submenu doesn't use this key for something then we will - if (menus[open_menu].menu.forwarded_on_keydown(key,is_printable,state) == false) - { - if (key == base_window::KEY_LEFT) - { - i = (i+menus.size()-1)%menus.size(); - show_menu(i); - menus[open_menu].menu.select_first_item(); - } - else if (key == base_window::KEY_RIGHT) - { - i = (i+1)%menus.size(); - show_menu(i); - menus[open_menu].menu.select_first_item(); - } - else if (key == base_window::KEY_ESC) - { - hide_menu(); - } - } - } - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - show_menu ( - unsigned long i - ) - { - rectangle temp; - - // menu already open so do nothing - if (i == open_menu) - return; - - // if a menu is currently open - if (open_menu != menus.size()) - { - menus[open_menu].menu.hide(); - temp = menus[open_menu].bgrect; - } - - // display the new menu - open_menu = i; - long wx, wy; - parent.get_pos(wx,wy); - wx += menus[i].bgrect.left(); - wy += menus[i].bgrect.bottom()+1; - menus[i].menu.set_pos(wx,wy); - menus[i].menu.show(); - parent.invalidate_rectangle(menus[i].bgrect+temp); - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - hide_menu ( - ) - { - // if a menu is currently open - if (open_menu != menus.size()) - { - menus[open_menu].menu.hide(); - parent.invalidate_rectangle(menus[open_menu].bgrect); - open_menu = menus.size(); - } - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - on_popup_hide ( - ) - { - // if a menu is currently open - if (open_menu != menus.size()) - { - parent.invalidate_rectangle(menus[open_menu].bgrect); - open_menu = menus.size(); - } - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - compute_menu_geometry ( - ) - { - long x = 7; - long bg_x = 0; - for (unsigned long i = 0; i < menus.size(); ++i) - { - // compute the locations of the text rectangles - menus[i].rect.set_top(5); - menus[i].rect.set_left(x); - menus[i].rect.set_bottom(rect.bottom()-2); - - unsigned long width, height; - mfont->compute_size(menus[i].name,width,height); - menus[i].rect = resize_rect_width(menus[i].rect, width); - x = menus[i].rect.right()+10; - - menus[i].bgrect.set_top(0); - menus[i].bgrect.set_left(bg_x); - menus[i].bgrect.set_bottom(rect.bottom()-2); - menus[i].bgrect.set_right(x-5); - bg_x = menus[i].bgrect.right()+1; - - if (menus[i].underline_pos != std::string::npos) - { - // now compute the location of the underline bar - rectangle r1 = mfont->compute_cursor_rect( - menus[i].rect, - menus[i].name, - menus[i].underline_pos); - - rectangle r2 = mfont->compute_cursor_rect( - menus[i].rect, - menus[i].name, - menus[i].underline_pos+1); - - menus[i].underline_p1.x() = r1.left()+1; - menus[i].underline_p2.x() = r2.left()-1; - menus[i].underline_p1.y() = r1.bottom()-mfont->height()+mfont->ascender()+2; - menus[i].underline_p2.y() = r2.bottom()-mfont->height()+mfont->ascender()+2; - } - else - { - // there is no underline in this case - menus[i].underline_p1 = menus[i].underline_p2; - } - - } - } - -// ---------------------------------------------------------------------------------------- - - void menu_bar:: - adjust_position ( - ) - { - unsigned long width, height; - rectangle old(rect); - parent.get_size(width,height); - rect.set_left(0); - rect.set_top(0); - rect = resize_rect(rect,width,mfont->height()+10); - parent.invalidate_rectangle(old+rect); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// class text_grid -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - text_grid:: - text_grid ( - drawable_window& w - ) : - scrollable_region(w, KEYBOARD_EVENTS | MOUSE_CLICK | FOCUS_EVENTS ), - has_focus(false), - cursor_timer(*this,&text_grid::timer_action), - border_color_(128,128,128) - { - - cursor_timer.set_delay_time(500); - set_vertical_scroll_increment(10); - set_horizontal_scroll_increment(10); - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - text_grid:: - ~text_grid ( - ) - { - // Disable all further events for this drawable object. We have to do this - // because we don't want draw() events coming to this object while or after - // it has been destructed. - disable_events(); - - // wait for the timer to stop doing its thing - cursor_timer.stop_and_wait(); - // Tell the parent window to redraw its area that previously contained this - // drawable object. - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_grid_size ( - unsigned long rows, - unsigned long cols - ) - { - auto_mutex M(m); - row_height.set_max_size(rows); - row_height.set_size(rows); - - col_width.set_max_size(cols); - col_width.set_size(cols); - - grid.set_size(rows,cols); - - for (unsigned long i = 0; i < row_height.size(); ++i) - row_height[i] = (mfont->height()*3)/2; - for (unsigned long i = 0; i < col_width.size(); ++i) - col_width[i] = mfont->height()*5; - - compute_total_rect(); - compute_bg_rects(); - } - -// ---------------------------------------------------------------------------------------- - - unsigned long text_grid:: - number_of_columns ( - ) const - { - auto_mutex M(m); - return grid.nc(); - } - -// ---------------------------------------------------------------------------------------- - - unsigned long text_grid:: - number_of_rows ( - ) const - { - auto_mutex M(m); - return grid.nr(); - } - -// ---------------------------------------------------------------------------------------- - - int text_grid:: - next_free_user_event_number ( - ) const - { - return scrollable_region::next_free_user_event_number()+1; - } - -// ---------------------------------------------------------------------------------------- - - rgb_pixel text_grid:: - border_color ( - ) const - { - auto_mutex M(m); - return border_color_; - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_border_color ( - rgb_pixel color - ) - { - auto_mutex M(m); - border_color_ = color; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - const std::string text_grid:: - text ( - unsigned long row, - unsigned long col - ) const - { - return convert_wstring_to_mbstring(wtext(row, col)); - } - -// ---------------------------------------------------------------------------------------- - - const std::wstring text_grid:: - wtext ( - unsigned long row, - unsigned long col - ) const - { - return convert_utf32_to_wstring(utext(row, col)); - } - -// ---------------------------------------------------------------------------------------- - - const dlib::ustring text_grid:: - utext ( - unsigned long row, - unsigned long col - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), - "\tconst std::string text_grid::text(row,col)" - << "\n\trow: " << row - << "\n\tcol: " << col - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\tthis: " << this - ); - return grid[row][col].text.c_str(); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_text ( - unsigned long row, - unsigned long col, - const std::string& str - ) - { - set_text(row, col, convert_mbstring_to_wstring(str)); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_text ( - unsigned long row, - unsigned long col, - const std::wstring& str - ) - { - set_text(row, col, convert_wstring_to_utf32(str)); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_text ( - unsigned long row, - unsigned long col, - const dlib::ustring& str - ) - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), - "\tvoid text_grid::set_text(row,col)" - << "\n\trow: " << row - << "\n\tcol: " << col - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\tthis: " << this - ); - grid[row][col].text = str.c_str(); - parent.invalidate_rectangle(get_text_rect(row,col)); - } - -// ---------------------------------------------------------------------------------------- - - const rgb_pixel text_grid:: - text_color ( - unsigned long row, - unsigned long col - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), - "\tconst rgb_pixel text_grid::text_color(row,col)" - << "\n\trow: " << row - << "\n\tcol: " << col - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\tthis: " << this - ); - return grid[row][col].text_color; - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_text_color ( - unsigned long row, - unsigned long col, - const rgb_pixel color - ) - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), - "\tvoid text_grid::set_text_color(row,col,color)" - << "\n\trow: " << row - << "\n\tcol: " << col - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\tthis: " << this - ); - grid[row][col].text_color = color; - parent.invalidate_rectangle(get_text_rect(row,col)); - } - -// ---------------------------------------------------------------------------------------- - - const rgb_pixel text_grid:: - background_color ( - unsigned long row, - unsigned long col - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), - "\tconst rgb_pixel text_grid::background_color(row,col,color)" - << "\n\trow: " << row - << "\n\tcol: " << col - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\tthis: " << this - ); - return grid[row][col].bg_color; - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_background_color ( - unsigned long row, - unsigned long col, - const rgb_pixel color - ) - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), - "\tvoid text_grid::set_background_color(row,col,color)" - << "\n\trow: " << row - << "\n\tcol: " << col - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\tthis: " << this - ); - grid[row][col].bg_color = color; - parent.invalidate_rectangle(get_bg_rect(row,col)); - } - -// ---------------------------------------------------------------------------------------- - - bool text_grid:: - is_editable ( - unsigned long row, - unsigned long col - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), - "\tbool text_grid::is_editable(row,col)" - << "\n\trow: " << row - << "\n\tcol: " << col - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\tthis: " << this - ); - return grid[row][col].is_editable; - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_editable ( - unsigned long row, - unsigned long col, - bool editable - ) - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), - "\tvoid text_grid::set_editable(row,col,editable)" - << "\n\trow: " << row - << "\n\tcol: " << col - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\teditable: " << editable - << "\n\tthis: " << this - ); - grid[row][col].is_editable = editable; - if (has_focus && active_row == static_cast<long>(row) && active_col == static_cast<long>(col)) - { - drop_input_focus(); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_column_width ( - unsigned long col, - unsigned long width - ) - { - auto_mutex M(m); - DLIB_ASSERT ( col < number_of_columns(), - "\tvoid text_grid::set_column_width(col,width)" - << "\n\tcol: " << col - << "\n\tnumber_of_columns(): " << number_of_columns() - << "\n\twidth: " << width - << "\n\tthis: " << this - ); - col_width[col] = width; - compute_total_rect(); - compute_bg_rects(); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - set_row_height ( - unsigned long row, - unsigned long height - ) - { - auto_mutex M(m); - DLIB_ASSERT ( row < number_of_rows() , - "\tvoid text_grid::set_row_height(row,height)" - << "\n\trow: " << row - << "\n\tnumber_of_rows(): " << number_of_rows() - << "\n\theight: " << height - << "\n\tthis: " << this - ); - row_height[row] = height; - compute_total_rect(); - compute_bg_rects(); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - disable ( - ) - { - auto_mutex M(m); - scrollable_region::disable(); - drop_input_focus(); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - hide ( - ) - { - auto_mutex M(m); - scrollable_region::hide(); - drop_input_focus(); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - on_user_event ( - int num - ) - { - // ignore this user event if it isn't for us - if (num != scrollable_region::next_free_user_event_number()) - return; - - if (has_focus && !recent_cursor_move && enabled && !hidden) - { - show_cursor = !show_cursor; - parent.invalidate_rectangle(get_text_rect(active_row,active_col)); - } - recent_cursor_move = false; - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - timer_action ( - ) - { - parent.trigger_user_event(this,scrollable_region::next_free_user_event_number()); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - compute_bg_rects ( - ) - { - // loop over each element in the grid and figure out what its rectangle should be - // with respect to the total_rect() - point p1, p2; - p1.y() = total_rect().top(); - for (long row = 0; row < grid.nr(); ++row) - { - p1.x() = total_rect().left(); - p2.y() = p1.y() + row_height[row]-1; - for (long col = 0; col < grid.nc(); ++col) - { - // if this is the last box in this row make it super wide so that it always - // goes to the end of the widget - if (col+1 == grid.nc()) - p2.x() = 1000000; - else - p2.x() = p1.x() + col_width[col]-1; - - // at this point p1 is the upper left corner of this box and p2 is the - // lower right corner of the box; - rectangle bg_rect(p1); - bg_rect += p2; - - grid[row][col].bg_rect = translate_rect(bg_rect, -total_rect().left(), -total_rect().top()); - - - p1.x() += 1 + col_width[col]; - } - p1.y() += 1 + row_height[row]; - } - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - compute_total_rect ( - ) - { - if (grid.size() == 0) - { - set_total_rect_size(0,0); - } - else - { - unsigned long width = col_width.size()-1; - unsigned long height = row_height.size()-1; - - for (unsigned long i = 0; i < col_width.size(); ++i) - width += col_width[i]; - for (unsigned long i = 0; i < row_height.size(); ++i) - height += row_height[i]; - - set_total_rect_size(width,height); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - // ignore this event if we are disabled or hidden - if (!enabled || hidden) - return; - - if (has_focus) - { - if (is_printable) - { - // if the user hit the tab key then jump to the next box - if (key == '\t') - { - if (active_col+1 == grid.nc()) - { - if (active_row+1 == grid.nr()) - move_cursor(0,0,0); - else - move_cursor(active_row+1,0,0); - } - else - { - move_cursor(active_row,active_col+1,0); - } - } - if (key == '\n') - { - // ignore the enter key - } - else if (grid[active_row][active_col].is_editable) - { - // insert the key the user pressed into the string - grid[active_row][active_col].text.insert(cursor_pos,1,static_cast<char>(key)); - move_cursor(active_row,active_col,cursor_pos+1); - - if (text_modified_handler.is_set()) - text_modified_handler(active_row,active_col); - } - } - else if ((state & base_window::KBD_MOD_CONTROL)) - { - if (key == base_window::KEY_LEFT) - move_cursor(active_row,active_col-1,0); - else if (key == base_window::KEY_RIGHT) - move_cursor(active_row,active_col+1,0); - else if (key == base_window::KEY_UP) - move_cursor(active_row-1,active_col,0); - else if (key == base_window::KEY_DOWN) - move_cursor(active_row+1,active_col,0); - else if (key == base_window::KEY_END) - move_cursor(active_row,active_col,grid[active_row][active_col].text.size()); - else if (key == base_window::KEY_HOME) - move_cursor(active_row,active_col,0); - } - else - { - if (key == base_window::KEY_LEFT) - move_cursor(active_row,active_col,cursor_pos-1); - else if (key == base_window::KEY_RIGHT) - move_cursor(active_row,active_col,cursor_pos+1); - else if (key == base_window::KEY_UP) - move_cursor(active_row-1,active_col,0); - else if (key == base_window::KEY_DOWN) - move_cursor(active_row+1,active_col,0); - else if (key == base_window::KEY_END) - move_cursor(active_row,active_col,grid[active_row][active_col].text.size()); - else if (key == base_window::KEY_HOME) - move_cursor(active_row,active_col,0); - else if (key == base_window::KEY_BACKSPACE) - { - if (cursor_pos > 0 && grid[active_row][active_col].is_editable) - { - grid[active_row][active_col].text.erase( - grid[active_row][active_col].text.begin()+cursor_pos-1, - grid[active_row][active_col].text.begin()+cursor_pos); - move_cursor(active_row,active_col,cursor_pos-1); - - if (text_modified_handler.is_set()) - text_modified_handler(active_row,active_col); - } - } - else if (key == base_window::KEY_DELETE) - { - if (cursor_pos < static_cast<long>(grid[active_row][active_col].text.size()) && - grid[active_row][active_col].is_editable) - { - grid[active_row][active_col].text.erase( - grid[active_row][active_col].text.begin()+cursor_pos); - move_cursor(active_row,active_col,cursor_pos); - - if (text_modified_handler.is_set()) - text_modified_handler(active_row,active_col); - } - } - } - } // if (has_focus) - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ) - { - scrollable_region::on_mouse_down(btn, state, x, y, is_double_click); - if (display_rect().contains(x,y) && enabled && !hidden) - { - // figure out which box this click landed in - rectangle hit; - - // find which column we hit - unsigned long col = 0; - long box_x = total_rect().left(); - for (unsigned long i = 0; i < col_width.size(); ++i) - { - if (box_x <= x && (x < box_x+static_cast<long>(col_width[i]) || (i+1 == col_width.size()))) - { - col = i; - hit.set_left(box_x); - hit.set_right(box_x+col_width[i]-1); - break; - } - else - { - box_x += col_width[i]+1; - } - } - - // find which row we hit - unsigned long row = 0; - long box_y = total_rect().top(); - for (unsigned long i = 0; i < row_height.size(); ++i) - { - if (box_y <= y && y < box_y+static_cast<long>(row_height[i])) - { - row = i; - hit.set_top(box_y); - hit.set_bottom(box_y+row_height[i]-1); - break; - } - else - { - box_y += row_height[i]+1; - } - } - - // if we hit a box - if (hit.is_empty() == false) - { - move_cursor(row, - col, - mfont->compute_cursor_pos(get_text_rect(row,col), grid[row][col].text, x, y, grid[row][col].first) - ); - } - else - { - drop_input_focus(); - } - } - else - { - drop_input_focus(); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - on_mouse_up ( - unsigned long btn, - unsigned long state, - long x, - long y - ) - { - scrollable_region::on_mouse_up(btn, state, x, y); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - on_focus_lost ( - ) - { - drop_input_focus(); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - draw ( - const canvas& c - ) const - { - scrollable_region::draw(c); - rectangle area = c.intersect(display_rect()); - if (area.is_empty() == true) - return; - - if (enabled) - fill_rect(c, area, 255); - - // don't do anything if the grid is empty - if (grid.size() == 0) - return; - - // draw all the vertical lines - point p1, p2; - p1.x() = p2.x() = total_rect().left(); - p1.y() = total_rect().top(); - p2.y() = total_rect().bottom(); - for (unsigned long i = 0; i < col_width.size()-1; ++i) - { - p1.x() += col_width[i]; - p2.x() += col_width[i]; - if (enabled) - draw_line(c,p1,p2,border_color_,area); - else - draw_line(c,p1,p2,128,area); - p1.x() += 1; - p2.x() += 1; - } - - // draw all the horizontal lines - p1.y() = p2.y() = total_rect().top(); - p1.x() = display_rect().left(); - p2.x() = display_rect().right(); - for (unsigned long i = 0; i < row_height.size(); ++i) - { - p1.y() += row_height[i]; - p2.y() += row_height[i]; - if (enabled) - draw_line(c,p1,p2,border_color_,area); - else - draw_line(c,p1,p2,128,area); - p1.y() += 1; - p2.y() += 1; - } - - // draw the backgrounds and text for each box - for (long row = 0; row < grid.nr(); ++row) - { - for (long col = 0; col < grid.nc(); ++col) - { - rectangle bg_rect(get_bg_rect(row,col)); - - rectangle text_rect(get_text_rect(row,col)); - - if (enabled) - { - fill_rect(c,bg_rect.intersect(area),grid[row][col].bg_color); - - mfont->draw_string(c, - text_rect, - grid[row][col].text, - grid[row][col].text_color, - grid[row][col].first, - std::string::npos, - area); - } - else - { - mfont->draw_string(c, - text_rect, - grid[row][col].text, - 128, - grid[row][col].first, - std::string::npos, - area); - } - - // if this box has input focus then draw it with a cursor - if (has_focus && active_col == col && active_row == row && show_cursor) - { - rectangle cursor_rect = mfont->compute_cursor_rect(text_rect, - grid[row][col].text, - cursor_pos, - grid[row][col].first); - draw_rectangle(c,cursor_rect,0,area); - } - - } - } - - - } - -// ---------------------------------------------------------------------------------------- - - rectangle text_grid:: - get_text_rect ( - unsigned long row, - unsigned long col - ) const - { - rectangle bg_rect(get_bg_rect(row,col)); - long padding = (bg_rect.height() - mfont->height())/2 + (bg_rect.height() - mfont->height())%2; - if (padding < 0) - padding = 0; - bg_rect.set_left(bg_rect.left()+padding); - bg_rect.set_top(bg_rect.top()+padding); - bg_rect.set_right(bg_rect.right()-padding); - bg_rect.set_bottom(bg_rect.bottom()-padding); - return bg_rect; - } - -// ---------------------------------------------------------------------------------------- - - rectangle text_grid:: - get_bg_rect ( - unsigned long row, - unsigned long col - ) const - { - return translate_rect(grid[row][col].bg_rect, total_rect().left(), total_rect().top()); - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - drop_input_focus ( - ) - { - if (has_focus) - { - parent.invalidate_rectangle(get_text_rect(active_row,active_col)); - has_focus = false; - show_cursor = false; - cursor_timer.stop(); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_grid:: - move_cursor ( - long row, - long col, - long new_cursor_pos - ) - { - // don't do anything if the grid is empty - if (grid.size() == 0) - { - return; - } - - if (row < 0) - row = 0; - if (row >= grid.nr()) - row = grid.nr()-1; - if (col < 0) - col = 0; - if (col >= grid.nc()) - col = grid.nc()-1; - - if (new_cursor_pos < 0) - { - if (col == 0) - { - new_cursor_pos = 0; - } - else - { - --col; - new_cursor_pos = grid[row][col].text.size(); - } - } - - if (new_cursor_pos > static_cast<long>(grid[row][col].text.size())) - { - if (col+1 == grid.nc()) - { - new_cursor_pos = grid[row][col].text.size(); - } - else - { - ++col; - new_cursor_pos = 0; - } - } - - // if some other box had the input focus then redraw it - if (has_focus && (active_row != row || active_col != col )) - { - parent.invalidate_rectangle(get_text_rect(active_row,active_col)); - } - - if (has_focus == false) - { - cursor_timer.start(); - } - - has_focus = true; - recent_cursor_move = true; - show_cursor = true; - active_row = row; - active_col = col; - cursor_pos = new_cursor_pos; - - // adjust the first character to draw so that the string is displayed well - rectangle text_rect(get_text_rect(active_row,active_col)); - rectangle cursor_rect = mfont->compute_cursor_rect(text_rect, - grid[row][col].text, - cursor_pos, - grid[row][col].first); - - // if the cursor rect is too far to the left of the string - if (cursor_pos < static_cast<long>(grid[row][col].first)) - { - if (cursor_pos > 5) - { - grid[row][col].first = cursor_pos - 5; - } - else - { - grid[row][col].first = 0; - } - } - // if the cursor rect is too far to the right of the string - else if (cursor_rect.left() > text_rect.right()) - { - long distance = (cursor_rect.left() - text_rect.right()) + text_rect.width()/3; - // find the letter that is distance pixels from the start of the string - long sum = 0; - for (unsigned long i = grid[row][col].first; i < grid[row][col].text.size(); ++i) - { - sum += (*mfont)[grid[row][col].text[i]].width(); - if (sum >= distance) - { - grid[row][col].first = i; - break; - } - } - } - - scroll_to_rect(get_bg_rect(row,col)); - - // redraw our box - parent.invalidate_rectangle(text_rect); - - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // text_field object methods -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - rectangle text_box:: - get_text_rect ( - ) const - { - const unsigned long padding = style->get_padding(*mfont); - - rectangle text_rect; - text_rect.set_left(total_rect().left()+padding); - text_rect.set_top(total_rect().top()+padding); - text_rect.set_right(total_rect().right()-padding); - text_rect.set_bottom(total_rect().bottom()-padding); - return text_rect; - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - enable ( - ) - { - scrollable_region::enable(); - right_click_menu.enable(); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_cut ( - ) - { - on_copy(); - on_delete_selected(); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_copy ( - ) - { - if (highlight_start <= highlight_end) - { - put_on_clipboard(text_.substr(highlight_start, highlight_end-highlight_start+1)); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_paste ( - ) - { - ustring temp_str; - get_from_clipboard(temp_str); - - - if (highlight_start <= highlight_end) - { - text_ = text_.substr(0,highlight_start) + temp_str + - text_.substr(highlight_end+1,text_.size()-highlight_end-1); - move_cursor(highlight_start+temp_str.size()); - highlight_start = 0; - highlight_end = -1; - parent.invalidate_rectangle(rect); - on_no_text_selected(); - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - else - { - text_ = text_.substr(0,cursor_pos) + temp_str + - text_.substr(cursor_pos,text_.size()-cursor_pos); - move_cursor(cursor_pos+temp_str.size()); - - // send out the text modified event - if (temp_str.size() != 0 && text_modified_handler.is_set()) - text_modified_handler(); - } - - adjust_total_rect(); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_select_all ( - ) - { - move_cursor(static_cast<long>(text_.size())); - highlight_start = 0; - highlight_end = static_cast<long>(text_.size()-1); - if (highlight_start <= highlight_end) - on_text_is_selected(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_delete_selected ( - ) - { - if (highlight_start <= highlight_end) - { - text_ = text_.erase(highlight_start,highlight_end-highlight_start+1); - move_cursor(highlight_start); - highlight_start = 0; - highlight_end = -1; - - on_no_text_selected(); - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - - adjust_total_rect(); - - parent.invalidate_rectangle(rect); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_text_is_selected ( - ) - { - right_click_menu.menu().enable_menu_item(0); - right_click_menu.menu().enable_menu_item(1); - right_click_menu.menu().enable_menu_item(3); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_no_text_selected ( - ) - { - right_click_menu.menu().disable_menu_item(0); - right_click_menu.menu().disable_menu_item(1); - right_click_menu.menu().disable_menu_item(3); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - show ( - ) - { - scrollable_region::show(); - right_click_menu.show(); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - disable ( - ) - { - auto_mutex M(m); - scrollable_region::disable(); - t.stop(); - has_focus = false; - cursor_visible = false; - right_click_menu.disable(); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - hide ( - ) - { - auto_mutex M(m); - scrollable_region::hide(); - t.stop(); - has_focus = false; - cursor_visible = false; - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - adjust_total_rect ( - ) - { - const unsigned long padding = style->get_padding(*mfont); - unsigned long text_width; - unsigned long text_height; - - mfont->compute_size(text_, text_width, text_height); - - set_total_rect_size(text_width + padding*2, text_height + padding*2); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - set_main_font ( - const std::shared_ptr<font>& f - ) - { - auto_mutex M(m); - mfont = f; - adjust_total_rect(); - right_click_menu.set_rect(display_rect()); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - draw ( - const canvas& c - ) const - { - scrollable_region::draw(c); - rectangle area = rect.intersect(c); - if (area.is_empty()) - return; - - const point origin(total_rect().left(), total_rect().top()); - - style->draw_text_box(c,display_rect(),get_text_rect(), enabled, *mfont, text_, - translate_rect(cursor_rect, origin), - text_color_, bg_color_, has_focus, cursor_visible, highlight_start, - highlight_end); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - set_text ( - const std::string& text - ) - { - set_text(convert_mbstring_to_wstring(text)); - } - - void text_box:: - set_text ( - const std::wstring& text - ) - { - set_text(convert_wstring_to_utf32(text)); - } - - void text_box:: - set_text ( - const dlib::ustring& text - ) - { - auto_mutex M(m); - // do this to get rid of any reference counting that may be present in - // the std::string implementation. - text_ = text.c_str(); - - adjust_total_rect(); - move_cursor(0); - - highlight_start = 0; - highlight_end = -1; - } - -// ---------------------------------------------------------------------------------------- - - const std::string text_box:: - text ( - ) const - { - std::string temp = convert_wstring_to_mbstring(wtext()); - return temp; - } - - const std::wstring text_box:: - wtext ( - ) const - { - std::wstring temp = convert_utf32_to_wstring(utext()); - return temp; - } - - const dlib::ustring text_box:: - utext ( - ) const - { - auto_mutex M(m); - // do this to get rid of any reference counting that may be present in - // the dlib::ustring implementation. - dlib::ustring temp = text_.c_str(); - return temp; - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex M(m); - scrollable_region::set_size(width,height); - right_click_menu.set_rect(display_rect()); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - set_pos ( - long x, - long y - ) - { - scrollable_region::set_pos(x,y); - right_click_menu.set_rect(get_text_rect()); - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - set_background_color ( - const rgb_pixel color - ) - { - auto_mutex M(m); - bg_color_ = color; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - const rgb_pixel text_box:: - background_color ( - ) const - { - auto_mutex M(m); - return bg_color_; - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - set_text_color ( - const rgb_pixel color - ) - { - auto_mutex M(m); - text_color_ = color; - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - const rgb_pixel text_box:: - text_color ( - ) const - { - auto_mutex M(m); - return text_color_; - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - if (!enabled || hidden || !has_focus) - { - return; - } - - if (state & base_window::LEFT) - { - if (highlight_start <= highlight_end) - { - if (highlight_start == cursor_pos) - shift_pos = highlight_end + 1; - else - shift_pos = highlight_start; - } - - unsigned long new_pos = mfont->compute_cursor_pos(get_text_rect(),text_,x,y); - if (static_cast<long>(new_pos) != cursor_pos) - { - move_cursor(new_pos); - parent.invalidate_rectangle(rect); - } - } - else if (shift_pos != -1) - { - shift_pos = -1; - } - - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_mouse_up ( - unsigned long btn, - unsigned long, - long , - long - ) - { - if (!enabled || hidden) - return; - - if (btn == base_window::LEFT) - shift_pos = -1; - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool double_clicked - ) - { - using namespace std; - if (!enabled || hidden || btn != (unsigned long)base_window::LEFT) - return; - - if (display_rect().contains(x,y)) - { - has_focus = true; - cursor_visible = true; - parent.invalidate_rectangle(rect); - t.start(); - - - if (double_clicked) - { - // highlight the double clicked word - string::size_type first, last; - const ustring ustr = convert_utf8_to_utf32(std::string(" \t\n")); - first = text_.substr(0,cursor_pos).find_last_of(ustr.c_str()); - last = text_.find_first_of(ustr.c_str(),cursor_pos); - long f = static_cast<long>(first); - long l = static_cast<long>(last); - if (first == string::npos) - f = -1; - if (last == string::npos) - l = static_cast<long>(text_.size()); - - ++f; - --l; - - move_cursor(l+1); - highlight_start = f; - highlight_end = l; - on_text_is_selected(); - } - else - { - if (state & base_window::SHIFT) - { - if (highlight_start <= highlight_end) - { - if (highlight_start == cursor_pos) - shift_pos = highlight_end + 1; - else - shift_pos = highlight_start; - } - else - { - shift_pos = cursor_pos; - } - } - - bool at_end = false; - if (cursor_pos == 0 || cursor_pos == static_cast<long>(text_.size())) - at_end = true; - const long old_pos = cursor_pos; - - unsigned long new_pos = mfont->compute_cursor_pos(get_text_rect(),text_,x,y); - move_cursor(new_pos); - - shift_pos = cursor_pos; - - if (at_end && cursor_pos == old_pos) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - } - } - - } - else if (has_focus && rect.contains(x,y) == false) - { - t.stop(); - has_focus = false; - cursor_visible = false; - shift_pos = -1; - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - - if (focus_lost_handler.is_set()) - focus_lost_handler(); - parent.invalidate_rectangle(rect); - } - else - { - has_focus = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - // If the right click menu is up then we don't want to do anything with - // the keyboard ourselves. Let the popup menu use the keyboard for now. - if (right_click_menu.popup_menu_visible()) - return; - - if (has_focus && enabled && !hidden) - { - const ustring space_str = convert_utf8_to_utf32(std::string(" \t\n")); - const bool shift = (state&base_window::KBD_MOD_SHIFT) != 0; - const bool ctrl = (state&base_window::KBD_MOD_CONTROL) != 0; - - if (shift && is_printable == false) - { - if (shift_pos == -1) - { - if (highlight_start <= highlight_end) - { - if (highlight_start == cursor_pos) - shift_pos = highlight_end + 1; - else - shift_pos = highlight_start; - } - else - { - shift_pos = cursor_pos; - } - } - } - else - { - shift_pos = -1; - } - - if (key == base_window::KEY_LEFT) - { - if (cursor_pos != 0) - { - unsigned long new_pos; - if (ctrl) - { - // find the first non-whitespace to our left - std::string::size_type pos = text_.find_last_not_of(space_str.c_str(),cursor_pos); - if (pos != std::string::npos) - { - pos = text_.find_last_of(space_str.c_str(),pos); - if (pos != std::string::npos) - new_pos = static_cast<unsigned long>(pos); - else - new_pos = 0; - } - else - { - new_pos = 0; - } - } - else - { - new_pos = cursor_pos-1; - } - - move_cursor(new_pos); - } - else if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - - } - else if (key == base_window::KEY_RIGHT) - { - if (cursor_pos != static_cast<long>(text_.size())) - { - unsigned long new_pos; - if (ctrl) - { - // find the first non-whitespace to our left - std::string::size_type pos = text_.find_first_not_of(space_str.c_str(),cursor_pos); - if (pos != std::string::npos) - { - pos = text_.find_first_of(space_str.c_str(),pos); - if (pos != std::string::npos) - new_pos = static_cast<unsigned long>(pos+1); - else - new_pos = static_cast<unsigned long>(text_.size()); - } - else - { - new_pos = static_cast<unsigned long>(text_.size()); - } - } - else - { - new_pos = cursor_pos+1; - } - - move_cursor(new_pos); - } - else if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - else if (key == base_window::KEY_UP) - { - if (ctrl) - { - move_cursor(0); - } - else - { - const point origin(total_rect().left(), total_rect().top()); - // move the cursor so the position that is just a few pixels above - // the current cursor_rect - move_cursor(mfont->compute_cursor_pos( - get_text_rect(), text_, cursor_rect.left()+origin.x(), - cursor_rect.top()+origin.y()-mfont->height()/2)); - - } - - if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - else if (key == base_window::KEY_DOWN) - { - if (ctrl) - { - move_cursor(static_cast<unsigned long>(text_.size())); - } - else - { - const point origin(total_rect().left(), total_rect().top()); - // move the cursor so the position that is just a few pixels above - // the current cursor_rect - move_cursor(mfont->compute_cursor_pos( - get_text_rect(), text_, cursor_rect.left()+origin.x(), - cursor_rect.bottom()+origin.y()+mfont->height()/2)); - } - - if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - else if (is_printable) - { - if (ctrl) - { - if (key == 'a') - { - on_select_all(); - } - else if (key == 'c') - { - on_copy(); - } - else if (key == 'v') - { - on_paste(); - } - else if (key == 'x') - { - on_cut(); - } - } - else - { - if (highlight_start <= highlight_end) - { - text_ = text_.substr(0,highlight_start) + static_cast<unichar>(key) + - text_.substr(highlight_end+1,text_.size()-highlight_end-1); - - adjust_total_rect(); - move_cursor(highlight_start+1); - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - } - else - { - text_ = text_.substr(0,cursor_pos) + static_cast<unichar>(key) + - text_.substr(cursor_pos,text_.size()-cursor_pos); - adjust_total_rect(); - move_cursor(cursor_pos+1); - } - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - - } - - if (key == '\n') - { - if (enter_key_handler.is_set()) - enter_key_handler(); - } - } - else if (key == base_window::KEY_BACKSPACE) - { - // if something is highlighted then delete that - if (highlight_start <= highlight_end) - { - on_delete_selected(); - } - else if (cursor_pos != 0) - { - text_ = text_.erase(cursor_pos-1,1); - adjust_total_rect(); - move_cursor(cursor_pos-1); - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - else - { - // do this just so it repaints itself right - move_cursor(cursor_pos); - } - - } - else if (key == base_window::KEY_DELETE) - { - // if something is highlighted then delete that - if (highlight_start <= highlight_end) - { - on_delete_selected(); - } - else if (cursor_pos != static_cast<long>(text_.size())) - { - text_ = text_.erase(cursor_pos,1); - - adjust_total_rect(); - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - else - { - // do this just so it repaints itself right - move_cursor(cursor_pos); - } - - } - else if (key == base_window::KEY_HOME) - { - if (ctrl) - { - move_cursor(0); - } - else if (cursor_pos != 0) - { - // find the start of the current line - ustring::size_type pos = text_.find_last_of('\n',cursor_pos-1); - if (pos == ustring::npos) - pos = 0; - else - pos += 1; - move_cursor(static_cast<unsigned long>(pos)); - - } - - if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - else if (key == base_window::KEY_END) - { - if (ctrl) - { - move_cursor(static_cast<unsigned long>(text_.size())); - } - { - ustring::size_type pos = text_.find_first_of('\n',cursor_pos); - if (pos == ustring::npos) - pos = text_.size(); - - move_cursor(static_cast<unsigned long>(pos)); - } - - if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - parent.invalidate_rectangle(rect); - } - } - else if (key == base_window::KEY_PAGE_DOWN || key == base_window::KEY_PAGE_UP) - { - long jump_size = display_rect().height() - - std::min(mfont->height()*3, display_rect().height()/5); - - // if we are supposed to page up then just jump in the other direction - if (key == base_window::KEY_PAGE_UP) - jump_size = -jump_size; - - scroll_to_rect(translate_rect(display_rect(), point(0, jump_size ))); - } - - cursor_visible = true; - recent_movement = true; - - } - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - on_string_put( - const std::wstring &str - ) - { - if (has_focus && enabled && !hidden) - { - ustring ustr = convert_wstring_to_utf32(str); - if (highlight_start <= highlight_end) - { - text_ = text_.substr(0,highlight_start) + ustr + - text_.substr(highlight_end+1,text_.size()-highlight_end-1); - - adjust_total_rect(); - move_cursor(highlight_start+ustr.size()); - highlight_start = 0; - highlight_end = -1; - on_no_text_selected(); - } - else - { - text_ = text_.substr(0,cursor_pos) + ustr + - text_.substr(cursor_pos,text_.size()-cursor_pos); - - adjust_total_rect(); - move_cursor(cursor_pos+ustr.size()); - } - - - // send out the text modified event - if (text_modified_handler.is_set()) - text_modified_handler(); - } - } - -// ---------------------------------------------------------------------------------------- - - void text_box:: - move_cursor ( - unsigned long pos - ) - { - using namespace std; - const long old_cursor_pos = cursor_pos; - - - - // figure out where the cursor is supposed to be - cursor_rect = mfont->compute_cursor_rect(get_text_rect(), text_, pos); - const point origin(total_rect().left(), total_rect().top()); - - - cursor_pos = pos; - - - const unsigned long padding = style->get_padding(*mfont); - - // now scroll us so that we can see the current cursor - scroll_to_rect(centered_rect(cursor_rect, cursor_rect.width() + padding + 6, cursor_rect.height() + 1)); - - // adjust the cursor_rect so that it is relative to the total_rect - cursor_rect = translate_rect(cursor_rect, -origin); - - parent.set_im_pos(cursor_rect.left(), cursor_rect.top()); - - if (old_cursor_pos != cursor_pos) - { - if (shift_pos != -1) - { - highlight_start = std::min(shift_pos,cursor_pos); - highlight_end = std::max(shift_pos,cursor_pos)-1; - } - - if (highlight_start > highlight_end) - on_no_text_selected(); - else - on_text_is_selected(); - - recent_movement = true; - cursor_visible = true; - parent.invalidate_rectangle(display_rect()); - } - - if (shift_pos == -1) - { - highlight_start = 0; - highlight_end = -1; - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// perspective_display member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - perspective_display:: - perspective_display( - drawable_window& w - ) : - drawable(w,MOUSE_MOVE|MOUSE_CLICK|MOUSE_WHEEL) - { - clear_overlay(); - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - perspective_display:: - ~perspective_display( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex lock(m); - rectangle old(rect); - rect = resize_rect(rect,width,height); - tform = camera_transform(tform.get_camera_pos(), - tform.get_camera_looking_at(), - tform.get_camera_up_direction(), - tform.get_camera_field_of_view(), - std::min(rect.width(),rect.height())); - parent.invalidate_rectangle(old+rect); - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - add_overlay ( - const std::vector<overlay_line>& overlay - ) - { - auto_mutex M(m); - if (overlay.size() == 0) - return; - // push this new overlay into our overlay vector - overlay_lines.insert(overlay_lines.end(), overlay.begin(), overlay.end()); - - for (unsigned long i = 0; i < overlay.size(); ++i) - { - sum_pts += overlay[i].p1; - sum_pts += overlay[i].p2; - max_pts.x() = std::max(overlay[i].p1.x(), max_pts.x()); - max_pts.x() = std::max(overlay[i].p2.x(), max_pts.x()); - max_pts.y() = std::max(overlay[i].p1.y(), max_pts.y()); - max_pts.y() = std::max(overlay[i].p2.y(), max_pts.y()); - max_pts.z() = std::max(overlay[i].p1.z(), max_pts.z()); - max_pts.z() = std::max(overlay[i].p2.z(), max_pts.z()); - } - - tform = camera_transform(max_pts, - sum_pts/(overlay_lines.size()*2+overlay_dots.size()), - vector<double>(0,0,1), - tform.get_camera_field_of_view(), - std::min(rect.width(),rect.height())); - - - // make the parent window redraw us now that we changed the overlay - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - add_overlay ( - const std::vector<overlay_dot>& overlay - ) - { - auto_mutex M(m); - if (overlay.size() == 0) - return; - - for (unsigned long i = 0; i < overlay.size(); ++i) - { - overlay_dots.push_back(overlay[i]); - - sum_pts += overlay[i].p; - max_pts.x() = std::max(overlay[i].p.x(), max_pts.x()); - max_pts.y() = std::max(overlay[i].p.y(), max_pts.y()); - max_pts.z() = std::max(overlay[i].p.z(), max_pts.z()); - } - - tform = camera_transform(max_pts, - sum_pts/(overlay_lines.size()*2+overlay_dots.size()), - vector<double>(0,0,1), - tform.get_camera_field_of_view(), - std::min(rect.width(),rect.height())); - - - // make the parent window redraw us now that we changed the overlay - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - clear_overlay ( - ) - { - auto_mutex lock(m); - overlay_dots.clear(); - overlay_lines.clear(); - sum_pts = vector<double>(); - max_pts = vector<double>(-std::numeric_limits<double>::infinity(), - -std::numeric_limits<double>::infinity(), - -std::numeric_limits<double>::infinity()); - - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - set_dot_double_clicked_handler ( - const any_function<void(const vector<double>&)>& event_handler_ - ) - { - auto_mutex M(m); - dot_clicked_event_handler = event_handler_; - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - draw ( - const canvas& c - ) const - { - if (depth.nr() < (long)c.height() || depth.nc() < (long)c.width()) - depth.set_size(c.height(), c.width()); - assign_all_pixels(depth, std::numeric_limits<float>::infinity()); - - rectangle area = rect.intersect(c); - fill_rect(c, area, 0); - for (unsigned long i = 0; i < overlay_lines.size(); ++i) - { - draw_line(c, tform(overlay_lines[i].p1)+rect.tl_corner(), - tform(overlay_lines[i].p2)+rect.tl_corner(), - overlay_lines[i].color, - area); - } - for (unsigned long i = 0; i < overlay_dots.size(); ++i) - { - double scale, distance; - point p = tform(overlay_dots[i].p, scale, distance) + rect.tl_corner(); - if (area.contains(p) && depth[p.y()-c.top()][p.x()-c.left()] > distance) - { - depth[p.y()-c.top()][p.x()-c.left()] = distance; - assign_pixel(c[p.y()-c.top()][p.x()-c.left()], overlay_dots[i].color); - } - } - - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - on_wheel_up ( - unsigned long //state - ) - { - if (rect.contains(lastx,lasty) == false || hidden || !enabled) - return; - - const double alpha = 0.10; - const vector<double> delta = alpha*(tform.get_camera_pos() - tform.get_camera_looking_at()); - tform = camera_transform( - tform.get_camera_pos() - delta, - tform.get_camera_looking_at(), - tform.get_camera_up_direction(), - tform.get_camera_field_of_view(), - std::min(rect.width(),rect.height())); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - on_wheel_down ( - unsigned long //state - ) - { - if (rect.contains(lastx,lasty) == false || hidden || !enabled) - return; - - const double alpha = 0.10; - const vector<double> delta = alpha*(tform.get_camera_pos() - tform.get_camera_looking_at()); - tform = camera_transform( - tform.get_camera_pos() + delta, - tform.get_camera_looking_at(), - tform.get_camera_up_direction(), - tform.get_camera_field_of_view(), - std::min(rect.width(),rect.height())); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - on_mouse_down ( - unsigned long btn, - unsigned long, //state - long x, - long y, - bool is_double_click - ) - { - if (btn == base_window::LEFT || btn == base_window::RIGHT) - { - last = point(x,y); - } - if (is_double_click && btn == base_window::LEFT && enabled && !hidden && overlay_dots.size() != 0) - { - double best_dist = std::numeric_limits<double>::infinity(); - unsigned long best_idx = 0; - const dpoint pp(x,y); - for (unsigned long i = 0; i < overlay_dots.size(); ++i) - { - dpoint p = tform(overlay_dots[i].p) + rect.tl_corner(); - double dist = length_squared(p-pp); - if (dist < best_dist) - { - best_dist = dist; - best_idx = i; - } - } - if (dot_clicked_event_handler.is_set()) - dot_clicked_event_handler(overlay_dots[best_idx].p); - } - } - -// ---------------------------------------------------------------------------------------- - - void perspective_display:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - if (!enabled || hidden) - return; - - if (state == base_window::LEFT) - { - const point cur(x, y); - dpoint delta = last-cur; - last = cur; - - const vector<double> radius = tform.get_camera_pos()-tform.get_camera_looking_at(); - delta *= 2*pi*length(radius)/600.0; - vector<double> tangent_x = tform.get_camera_up_direction().cross(radius).normalize(); - vector<double> tangent_y = radius.cross(tangent_x).normalize(); - vector<double> new_pos = tform.get_camera_pos() + tangent_x*delta.x() + tangent_y*-delta.y(); - - // now make it have the correct radius relative to the looking at point. - new_pos = (new_pos-tform.get_camera_looking_at()).normalize()*length(radius) + tform.get_camera_looking_at(); - - tform = camera_transform(new_pos, - tform.get_camera_looking_at(), - tangent_y, - tform.get_camera_field_of_view(), - std::min(rect.width(),rect.height())); - parent.invalidate_rectangle(rect); - } - else if (state == (base_window::LEFT|base_window::SHIFT) || - state == base_window::RIGHT) - { - const point cur(x, y); - dpoint delta = last-cur; - last = cur; - - const vector<double> radius = tform.get_camera_pos()-tform.get_camera_looking_at(); - delta *= 2*pi*length(radius)/600.0; - vector<double> tangent_x = tform.get_camera_up_direction().cross(radius).normalize(); - vector<double> tangent_y = radius.cross(tangent_x).normalize(); - - vector<double> offset = tangent_x*delta.x() + tangent_y*-delta.y(); - - - tform = camera_transform( - tform.get_camera_pos()+offset, - tform.get_camera_looking_at()+offset, - tform.get_camera_up_direction(), - tform.get_camera_field_of_view(), - std::min(rect.width(),rect.height())); - parent.invalidate_rectangle(rect); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// image_display member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace impl - { - class image_display_functor - { - const std::string str; - const member_function_pointer<const std::string&> mfp; - public: - image_display_functor ( - const std::string& str_, - const member_function_pointer<const std::string&>& mfp_ - ) : str(str_), - mfp(mfp_) - {} - - void operator() ( - ) const { mfp(str); } - }; - } - - image_display:: - image_display( - drawable_window& w - ): - scrollable_region(w,KEYBOARD_EVENTS), - zoom_in_scale(1), - zoom_out_scale(1), - drawing_rect(true), - rect_is_selected(false), - selected_rect(0), - default_rect_color(255,0,0,255), - parts_menu(w), - part_width(100), // "parts" circles are drawn 1.0/part_width size on the screen relative to the size of the bounding rectangle. - overlay_editing_enabled(true), - highlight_timer(*this, &image_display::timer_event_unhighlight_rect), - highlighted_rect(std::numeric_limits<unsigned long>::max()), - holding_shift_key(false) - { - enable_mouse_drag(); - - highlight_timer.set_delay_time(250); - set_horizontal_scroll_increment(1); - set_vertical_scroll_increment(1); - set_horizontal_mouse_wheel_scroll_increment(30); - set_vertical_mouse_wheel_scroll_increment(30); - - parts_menu.disable(); - - - enable_events(); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - on_part_add ( - const std::string& part_name - ) - { - if (!rect_is_selected) - return; - - const point loc = last_right_click_pos; - - // Transform loc from gui window space into the space used by the overlay - // rectangles (i.e. relative to the raw image) - const point origin(total_rect().tl_corner()); - point c1 = loc - origin; - if (zoom_in_scale != 1) - { - c1 = c1/(double)zoom_in_scale; - } - else if (zoom_out_scale != 1) - { - c1 = c1*(double)zoom_out_scale; - } - - overlay_rects[selected_rect].parts[part_name] = c1; - parent.invalidate_rectangle(rect); - - if (event_handler.is_set()) - event_handler(); - } - -// ---------------------------------------------------------------------------------------- - - image_display:: - ~image_display( - ) - { - highlight_timer.stop_and_wait(); - disable_events(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - rectangle image_display:: - get_image_display_rect ( - ) const - { - if (zoom_in_scale != 1) - { - return rectangle(0,0, img.nc()*zoom_in_scale-1, img.nr()*zoom_in_scale-1); - } - else if (zoom_out_scale != 1) - { - return rectangle(0,0, img.nc()/zoom_out_scale-1, img.nr()/zoom_out_scale-1); - } - else - { - return dlib::get_rect(img); - } - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - add_overlay ( - const overlay_rect& overlay - ) - { - auto_mutex M(m); - // push this new overlay into our overlay vector - overlay_rects.push_back(overlay); - - // make the parent window redraw us now that we changed the overlay - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - add_overlay ( - const overlay_line& overlay - ) - { - auto_mutex M(m); - - // push this new overlay into our overlay vector - overlay_lines.push_back(overlay); - - // make the parent window redraw us now that we changed the overlay - parent.invalidate_rectangle(get_rect_on_screen(rectangle(overlay.p1, overlay.p2))); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - add_overlay ( - const overlay_circle& overlay - ) - { - auto_mutex M(m); - - // push this new overlay into our overlay vector - overlay_circles.push_back(overlay); - - // make the parent window redraw us now that we changed the overlay - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - add_overlay ( - const std::vector<overlay_rect>& overlay - ) - { - auto_mutex M(m); - - // push this new overlay into our overlay vector - overlay_rects.insert(overlay_rects.end(), overlay.begin(), overlay.end()); - - // make the parent window redraw us now that we changed the overlay - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - add_overlay ( - const std::vector<overlay_line>& overlay - ) - { - auto_mutex M(m); - - // push this new overlay into our overlay vector - overlay_lines.insert(overlay_lines.end(), overlay.begin(), overlay.end()); - - // make the parent window redraw us now that we changed the overlay - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - add_overlay ( - const std::vector<overlay_circle>& overlay - ) - { - auto_mutex M(m); - - // push this new overlay into our overlay vector - overlay_circles.insert(overlay_circles.end(), overlay.begin(), overlay.end()); - - // make the parent window redraw us now that we changed the overlay - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - clear_overlay ( - ) - { - auto_mutex M(m); - overlay_rects.clear(); - overlay_lines.clear(); - overlay_circles.clear(); - parent.invalidate_rectangle(rect); - } - -// ---------------------------------------------------------------------------------------- - - rectangle image_display:: - get_rect_on_screen ( - rectangle orect - ) const - { - const point origin(total_rect().tl_corner()); - orect.left() = orect.left()*zoom_in_scale/zoom_out_scale; - orect.top() = orect.top()*zoom_in_scale/zoom_out_scale; - if (zoom_in_scale != 1) - { - // make it so the box surrounds the pixels when we zoom in. - orect.right() = (orect.right()+1)*zoom_in_scale/zoom_out_scale; - orect.bottom() = (orect.bottom()+1)*zoom_in_scale/zoom_out_scale; - } - else - { - orect.right() = orect.right()*zoom_in_scale/zoom_out_scale; - orect.bottom() = orect.bottom()*zoom_in_scale/zoom_out_scale; - } - - return translate_rect(orect, origin); - } - -// ---------------------------------------------------------------------------------------- - - rectangle image_display:: - get_rect_on_screen ( - unsigned long idx - ) const - { - return get_rect_on_screen(overlay_rects[idx].rect); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - draw ( - const canvas& c - ) const - { - scrollable_region::draw(c); - - rectangle area = display_rect().intersect(c); - if (area.is_empty()) - return; - - const point origin(total_rect().tl_corner()); - - // draw the image on the screen - const double scale = zoom_out_scale/(double)zoom_in_scale; - const rectangle img_area = total_rect().intersect(area); - for (long row = img_area.top(); row <= img_area.bottom(); ++row) - { - const long rc = row-c.top(); - const long rimg = (row-origin.y())*scale; - for (long col = img_area.left(); col <= img_area.right(); ++col) - { - assign_pixel(c[rc][col-c.left()], - img[rimg][(col-origin.x())*scale]); - } - } - - // draw the mouse cross-hairs - if (holding_shift_key && total_rect().contains(lastx,lasty) ) - { - draw_line(c, point(lastx,-10000), point(lastx,100000),rgb_pixel(255,255,0), area); - draw_line(c, point(-10000,lasty), point(100000,lasty),rgb_pixel(255,255,0), area); - } - - // now draw all the overlay rectangles - for (unsigned long i = 0; i < overlay_rects.size(); ++i) - { - const rectangle orect = get_rect_on_screen(i); - rgb_alpha_pixel color = overlay_rects[i].color; - // draw crossed out boxes slightly faded - if (overlay_rects[i].crossed_out) - color.alpha = 150; - - if (rect_is_selected && selected_rect == i) - { - draw_rectangle(c, orect, invert_pixel(color), area); - } - else if (highlighted_rect < overlay_rects.size() && highlighted_rect == i) - { - // Draw the rectangle wider and with a slightly different color that tapers - // out at the edges of the line. - hsi_pixel temp; - assign_pixel(temp, 0); - assign_pixel(temp, overlay_rects[i].color); - temp.s = 255; - temp.h = temp.h + 20; - if (temp.i < 245) - temp.i += 10; - rgb_pixel p; - assign_pixel(p, temp); - rgb_alpha_pixel po, po2; - assign_pixel(po, p); - po.alpha = 160; - po2 = po; - po2.alpha = 90; - draw_rectangle(c, grow_rect(orect,2), po2, area); - draw_rectangle(c, grow_rect(orect,1), po, area); - draw_rectangle(c, orect, p, area); - draw_rectangle(c, shrink_rect(orect,1), po, area); - draw_rectangle(c, shrink_rect(orect,2), po2, area); - } - else - { - draw_rectangle(c, orect, color, area); - } - - if (overlay_rects[i].label.size() != 0) - { - // make a rectangle that is at the spot we want to draw our string - rectangle r(orect.br_corner(), c.br_corner()); - mfont->draw_string(c, r, overlay_rects[i].label, color, 0, - std::string::npos, area); - } - - - // draw circles for each "part" in this overlay rectangle. - std::map<std::string,point>::const_iterator itr; - for (itr = overlay_rects[i].parts.begin(); itr != overlay_rects[i].parts.end(); ++itr) - { - if (itr->second == OBJECT_PART_NOT_PRESENT) - continue; - - const long part_size = (long)std::max(1.0,std::round(std::sqrt(orect.area())/part_width)); - rectangle temp = centered_rect(get_rect_on_screen(centered_rect(itr->second,1,1)), part_size, part_size); - - if (rect_is_selected && selected_rect == i && - selected_part_name.size() != 0 && selected_part_name == itr->first) - { - draw_circle(c, center(temp), temp.width(), invert_pixel(color), area); - } - else - { - draw_circle(c, center(temp), temp.width(), color, area); - } - - // make a rectangle that is at the spot we want to draw our string - rectangle r((temp.br_corner() + temp.bl_corner())/2, - c.br_corner()); - mfont->draw_string(c, r, itr->first, color, 0, - std::string::npos, area); - } - - if (overlay_rects[i].crossed_out) - { - if (rect_is_selected && selected_rect == i) - { - draw_line(c, orect.tl_corner(), orect.br_corner(),invert_pixel(color), area); - draw_line(c, orect.bl_corner(), orect.tr_corner(),invert_pixel(color), area); - } - else - { - draw_line(c, orect.tl_corner(), orect.br_corner(),color, area); - draw_line(c, orect.bl_corner(), orect.tr_corner(),color, area); - } - } - } - - // now draw all the overlay lines - for (unsigned long i = 0; i < overlay_lines.size(); ++i) - { - draw_line(c, - zoom_in_scale*overlay_lines[i].p1/zoom_out_scale + origin, - zoom_in_scale*overlay_lines[i].p2/zoom_out_scale + origin, - overlay_lines[i].color, area); - } - - // now draw all the overlay circles - for (unsigned long i = 0; i < overlay_circles.size(); ++i) - { - const point center = zoom_in_scale*overlay_circles[i].center/zoom_out_scale + origin; - const int radius = zoom_in_scale*overlay_circles[i].radius/zoom_out_scale; - draw_circle(c, - center, - radius, - overlay_circles[i].color, area); - - if (overlay_circles[i].label.size() != 0) - { - const point temp = center + point(0,radius); - - // make a rectangle that is at the spot we want to draw our string - rectangle r(temp, c.br_corner()); - mfont->draw_string(c, r, overlay_circles[i].label, overlay_circles[i].color, 0, - std::string::npos, area); - } - } - - if (drawing_rect) - draw_rectangle(c, rect_to_draw, invert_pixel(default_rect_color), area); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - scrollable_region::on_keydown(key,is_printable, state); - - if (!is_printable && key==base_window::KEY_SHIFT) - { - if (!holding_shift_key) - { - holding_shift_key = true; - parent.invalidate_rectangle(rect); - } - } - else if (holding_shift_key) - { - holding_shift_key = false; - parent.invalidate_rectangle(rect); - } - - if (!is_printable && !hidden && enabled && rect_is_selected && - (key == base_window::KEY_BACKSPACE || key == base_window::KEY_DELETE)) - { - moving_overlay = false; - rect_is_selected = false; - parts_menu.disable(); - if (selected_part_name.size() == 0) - overlay_rects.erase(overlay_rects.begin() + selected_rect); - else - overlay_rects[selected_rect].parts.erase(selected_part_name); - parent.invalidate_rectangle(rect); - - if (event_handler.is_set()) - event_handler(); - } - - if (!hidden && enabled && rect_is_selected && - ((is_printable && key == 'i') || (!is_printable && key==base_window::KEY_END))) - { - overlay_rects[selected_rect].crossed_out = !overlay_rects[selected_rect].crossed_out; - parent.invalidate_rectangle(rect); - - if (event_handler.is_set()) - event_handler(); - } - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - add_labelable_part_name ( - const std::string& name - ) - { - auto_mutex lock(m); - if (part_names.insert(name).second) - { - member_function_pointer<const std::string&> mfp; - mfp.set(*this,&image_display::on_part_add); - parts_menu.menu().add_menu_item(menu_item_text("Add " + name,impl::image_display_functor(name,mfp))); - } - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - clear_labelable_part_names ( - ) - { - auto_mutex lock(m); - part_names.clear(); - parts_menu.menu().clear(); - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ) - { - scrollable_region::on_mouse_down(btn, state, x, y, is_double_click); - - if (state&base_window::SHIFT) - { - holding_shift_key = true; - } - else if (holding_shift_key) - { - holding_shift_key = false; - parent.invalidate_rectangle(rect); - } - - if (rect.contains(x,y) == false || hidden || !enabled) - return; - - if (image_clicked_handler.is_set()) - { - const point origin(total_rect().tl_corner()); - point p(x,y); - p -= origin; - if (zoom_in_scale != 1) - p = p/zoom_in_scale; - else if (zoom_out_scale != 1) - p = p*zoom_out_scale; - - if (dlib::get_rect(img).contains(p)) - image_clicked_handler(p, is_double_click, btn); - } - - if (!overlay_editing_enabled) - return; - - if (btn == base_window::RIGHT && (state&base_window::SHIFT)) - { - const bool rect_was_selected = rect_is_selected; - rect_is_selected = false; - parts_menu.disable(); - - long best_dist = std::numeric_limits<long>::max(); - long best_idx = 0; - std::string best_part; - - // check if this click landed on any of the overlay rectangles - for (unsigned long i = 0; i < overlay_rects.size(); ++i) - { - const rectangle orect = get_rect_on_screen(i); - - const long dist = distance_to_rect_edge(orect, point(x,y)); - - if (dist < best_dist) - { - best_dist = dist; - best_idx = i; - best_part.clear(); - } - - std::map<std::string,point>::const_iterator itr; - for (itr = overlay_rects[i].parts.begin(); itr != overlay_rects[i].parts.end(); ++itr) - { - if (itr->second == OBJECT_PART_NOT_PRESENT) - continue; - - const long part_size = (long)std::max(1.0,std::round(std::sqrt(orect.area())/part_width)); - rectangle temp = centered_rect(get_rect_on_screen(centered_rect(itr->second,1,1)), part_size, part_size); - point c = center(temp); - - // distance from edge of part circle - const long dist = static_cast<long>(std::abs(length(c - point(x,y)) + 0.5 - temp.width())); - if (dist < best_dist) - { - best_idx = i; - best_dist = dist; - best_part = itr->first; - } - } - } - - - if (best_dist < 13) - { - moving_overlay = true; - moving_rect = best_idx; - moving_part_name = best_part; - // If we are moving one of the sides of the rectangle rather than one of - // the parts circles then we need to figure out which side of the rectangle - // we are moving. - if (best_part.size() == 0) - { - // which side is the click closest to? - const rectangle orect = get_rect_on_screen(best_idx); - const point p = nearest_point(orect,point(x,y)); - long dist_left = std::abs(p.x()-orect.left()); - long dist_top = std::abs(p.y()-orect.top()); - long dist_right = std::abs(p.x()-orect.right()); - long dist_bottom = std::abs(p.y()-orect.bottom()); - long min_val = std::min(std::min(dist_left,dist_right),std::min(dist_top,dist_bottom)); - if (dist_left == min_val) - moving_what = MOVING_RECT_LEFT; - else if (dist_top == min_val) - moving_what = MOVING_RECT_TOP; - else if (dist_right == min_val) - moving_what = MOVING_RECT_RIGHT; - else - moving_what = MOVING_RECT_BOTTOM; - } - else - { - moving_what = MOVING_PART; - } - // Do this to make the moving stuff snap to the mouse immediately. - on_mouse_move(state|btn,x,y); - } - - if (rect_was_selected) - parent.invalidate_rectangle(rect); - - return; - } - - if (btn == base_window::RIGHT && rect_is_selected) - { - last_right_click_pos = point(x,y); - parts_menu.set_rect(rect); - return; - } - - if (btn == base_window::LEFT && (state&base_window::CONTROL) && !drawing_rect) - { - long best_dist = std::numeric_limits<long>::max(); - long best_idx = 0; - // check if this click landed on any of the overlay rectangles - for (unsigned long i = 0; i < overlay_rects.size(); ++i) - { - const rectangle orect = get_rect_on_screen(i); - const long dist = distance_to_rect_edge(orect, point(x,y)); - - if (dist < best_dist) - { - best_dist = dist; - best_idx = i; - } - } - if (best_dist < 13) - { - overlay_rects[best_idx].label = default_rect_label; - overlay_rects[best_idx].color = default_rect_color; - highlighted_rect = best_idx; - highlight_timer.stop(); - highlight_timer.start(); - if (event_handler.is_set()) - event_handler(); - parent.invalidate_rectangle(rect); - } - return; - } - - - if (!is_double_click && btn == base_window::LEFT && (state&base_window::SHIFT)) - { - drawing_rect = true; - rect_anchor = point(x,y); - - if (rect_is_selected) - { - rect_is_selected = false; - parts_menu.disable(); - parent.invalidate_rectangle(rect); - } - } - else if (drawing_rect) - { - if (rect_is_selected) - { - rect_is_selected = false; - parts_menu.disable(); - } - - drawing_rect = false; - parent.invalidate_rectangle(rect); - } - else if (is_double_click) - { - const bool rect_was_selected = rect_is_selected; - rect_is_selected = false; - parts_menu.disable(); - - long best_dist = std::numeric_limits<long>::max(); - long best_idx = 0; - std::string best_part; - - // check if this click landed on any of the overlay rectangles - for (unsigned long i = 0; i < overlay_rects.size(); ++i) - { - const rectangle orect = get_rect_on_screen(i); - - const long dist = distance_to_rect_edge(orect, point(x,y)); - - if (dist < best_dist) - { - best_dist = dist; - best_idx = i; - best_part.clear(); - } - - std::map<std::string,point>::const_iterator itr; - for (itr = overlay_rects[i].parts.begin(); itr != overlay_rects[i].parts.end(); ++itr) - { - if (itr->second == OBJECT_PART_NOT_PRESENT) - continue; - - const long part_size = (long)std::max(1.0,std::round(std::sqrt(orect.area())/part_width)); - rectangle temp = centered_rect(get_rect_on_screen(centered_rect(itr->second,1,1)), part_size, part_size); - point c = center(temp); - - // distance from edge of part circle - const long dist = static_cast<long>(std::abs(length(c - point(x,y)) + 0.5 - temp.width())); - if (dist < best_dist) - { - best_idx = i; - best_dist = dist; - best_part = itr->first; - } - } - } - - - if (best_dist < 13) - { - rect_is_selected = true; - if (part_names.size() != 0) - parts_menu.enable(); - selected_rect = best_idx; - selected_part_name = best_part; - if (orect_selected_event_handler.is_set()) - orect_selected_event_handler(overlay_rects[best_idx]); - } - - if (rect_is_selected || rect_was_selected) - parent.invalidate_rectangle(rect); - } - else if (rect_is_selected) - { - rect_is_selected = false; - parts_menu.disable(); - parent.invalidate_rectangle(rect); - } - } - -// ---------------------------------------------------------------------------------------- - - std::vector<image_display::overlay_rect> image_display:: - get_overlay_rects ( - ) const - { - auto_mutex lock(m); - return overlay_rects; - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - set_default_overlay_rect_label ( - const std::string& label - ) - { - auto_mutex lock(m); - default_rect_label = label; - } - -// ---------------------------------------------------------------------------------------- - - std::string image_display:: - get_default_overlay_rect_label ( - ) const - { - auto_mutex lock(m); - return default_rect_label; - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - set_default_overlay_rect_color ( - const rgb_alpha_pixel& color - ) - { - auto_mutex lock(m); - default_rect_color = color; - } - -// ---------------------------------------------------------------------------------------- - - rgb_alpha_pixel image_display:: - get_default_overlay_rect_color ( - ) const - { - auto_mutex lock(m); - return default_rect_color; - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - on_mouse_up ( - unsigned long btn, - unsigned long state, - long x, - long y - ) - { - scrollable_region::on_mouse_up(btn,state,x,y); - - if (state&base_window::SHIFT) - { - holding_shift_key = true; - } - else if (holding_shift_key) - { - holding_shift_key = false; - parent.invalidate_rectangle(rect); - } - - if (drawing_rect && btn == base_window::LEFT && (state&base_window::SHIFT) && - !hidden && enabled) - { - const point origin(total_rect().tl_corner()); - point c1 = point(x,y) - origin; - point c2 = rect_anchor - origin; - - if (zoom_in_scale != 1) - { - c1 = c1/(double)zoom_in_scale; - c2 = c2/(double)zoom_in_scale; - } - else if (zoom_out_scale != 1) - { - c1 = c1*(double)zoom_out_scale; - c2 = c2*(double)zoom_out_scale; - } - - rectangle new_rect(c1,c2); - if (zoom_in_scale != 1) - { - // When we are zoomed in we adjust the rectangles a little so they - // are drown surrounding the pixels inside the rect. This adjustment - // is necessary to make this code consistent with this goal. - new_rect.right() -= 1; - new_rect.bottom() -= 1; - } - - - if (new_rect.width() > 0 && new_rect.height() > 0) - { - add_overlay(overlay_rect(new_rect, default_rect_color, default_rect_label)); - - if (event_handler.is_set()) - event_handler(); - } - } - - if (drawing_rect) - { - drawing_rect = false; - parent.invalidate_rectangle(rect); - } - if (moving_overlay) - { - moving_overlay = false; - } - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - scrollable_region::on_mouse_move(state,x,y); - - if (enabled && !hidden) - { - if (holding_shift_key) - parent.invalidate_rectangle(rect); - - if (state&base_window::SHIFT) - holding_shift_key = true; - else if (holding_shift_key) - holding_shift_key = false; - } - - if (drawing_rect) - { - if ((state&base_window::LEFT) && (state&base_window::SHIFT) && !hidden && enabled) - { - rectangle new_rect(point(x,y), rect_anchor); - parent.invalidate_rectangle(new_rect + rect_to_draw); - rect_to_draw = new_rect; - } - else - { - drawing_rect = false; - parent.invalidate_rectangle(rect); - } - moving_overlay = false; - } - else if (moving_overlay) - { - if ((state&base_window::RIGHT) && (state&base_window::SHIFT) && !hidden && enabled) - { - // map point(x,y) into the image coordinate space. - point p = point(x,y) - total_rect().tl_corner(); - if (zoom_in_scale != 1) - { - if (moving_what == MOVING_PART) - p = p/(double)zoom_in_scale-dpoint(0.5,0.5); - else - p = p/(double)zoom_in_scale; - } - else if (zoom_out_scale != 1) - { - p = p*(double)zoom_out_scale; - } - - - if (moving_what == MOVING_PART) - { - if (overlay_rects[moving_rect].parts[moving_part_name] != p) - { - overlay_rects[moving_rect].parts[moving_part_name] = p; - parent.invalidate_rectangle(rect); - if (event_handler.is_set()) - event_handler(); - } - } - else - { - rectangle original = overlay_rects[moving_rect].rect; - if (moving_what == MOVING_RECT_LEFT) - overlay_rects[moving_rect].rect.left() = std::min(p.x(), overlay_rects[moving_rect].rect.right()); - else if (moving_what == MOVING_RECT_RIGHT) - overlay_rects[moving_rect].rect.right() = std::max(p.x()-1, overlay_rects[moving_rect].rect.left()); - else if (moving_what == MOVING_RECT_TOP) - overlay_rects[moving_rect].rect.top() = std::min(p.y(), overlay_rects[moving_rect].rect.bottom()); - else - overlay_rects[moving_rect].rect.bottom() = std::max(p.y()-1, overlay_rects[moving_rect].rect.top()); - - if (original != overlay_rects[moving_rect].rect) - { - parent.invalidate_rectangle(rect); - if (event_handler.is_set()) - event_handler(); - } - } - } - else - { - moving_overlay = false; - } - } - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - on_wheel_up ( - unsigned long state - ) - { - // disable mouse wheel if the user is drawing a rectangle - if (drawing_rect) - return; - - // if CONTROL is not being held down - if ((state & base_window::CONTROL) == 0) - { - scrollable_region::on_wheel_up(state); - return; - } - - if (rect.contains(lastx,lasty) == false || hidden || !enabled) - return; - - - if (zoom_in_scale < 100 && zoom_out_scale == 1) - { - const point mouse_loc(lastx, lasty); - // the pixel in img that the mouse is over - const point pix_loc = (mouse_loc - total_rect().tl_corner())/zoom_in_scale; - - zoom_in_scale = zoom_in_scale*10/9 + 1; - - set_total_rect_size(img.nc()*zoom_in_scale, img.nr()*zoom_in_scale); - - // make is to the pixel under the mouse doesn't move while we zoom - const point delta = total_rect().tl_corner() - (mouse_loc - pix_loc*zoom_in_scale); - scroll_to_rect(translate_rect(display_rect(), delta)); - } - else if (zoom_out_scale != 1) - { - const point mouse_loc(lastx, lasty); - // the pixel in img that the mouse is over - const point pix_loc = (mouse_loc - total_rect().tl_corner())*zoom_out_scale; - - zoom_out_scale = zoom_out_scale*9/10; - if (zoom_out_scale == 0) - zoom_out_scale = 1; - - set_total_rect_size(img.nc()/zoom_out_scale, img.nr()/zoom_out_scale); - - // make is to the pixel under the mouse doesn't move while we zoom - const point delta = total_rect().tl_corner() - (mouse_loc - pix_loc/zoom_out_scale); - scroll_to_rect(translate_rect(display_rect(), delta)); - } - } - -// ---------------------------------------------------------------------------------------- - - void image_display:: - on_wheel_down ( - unsigned long state - ) - { - // disable mouse wheel if the user is drawing a rectangle - if (drawing_rect) - return; - - // if CONTROL is not being held down - if ((state & base_window::CONTROL) == 0) - { - scrollable_region::on_wheel_down(state); - return; - } - - if (rect.contains(lastx,lasty) == false || hidden || !enabled) - return; - - - if (zoom_in_scale != 1) - { - const point mouse_loc(lastx, lasty); - // the pixel in img that the mouse is over - const point pix_loc = (mouse_loc - total_rect().tl_corner())/zoom_in_scale; - - zoom_in_scale = zoom_in_scale*9/10; - if (zoom_in_scale == 0) - zoom_in_scale = 1; - - set_total_rect_size(img.nc()*zoom_in_scale, img.nr()*zoom_in_scale); - - // make is to the pixel under the mouse doesn't move while we zoom - const point delta = total_rect().tl_corner() - (mouse_loc - pix_loc*zoom_in_scale); - scroll_to_rect(translate_rect(display_rect(), delta)); - } - else if (std::max(img.nr(), img.nc())/zoom_out_scale > 10) - { - const point mouse_loc(lastx, lasty); - // the pixel in img that the mouse is over - const point pix_loc = (mouse_loc - total_rect().tl_corner())*zoom_out_scale; - - zoom_out_scale = zoom_out_scale*10/9 + 1; - - set_total_rect_size(img.nc()/zoom_out_scale, img.nr()/zoom_out_scale); - - // make is to the pixel under the mouse doesn't move while we zoom - const point delta = total_rect().tl_corner() - (mouse_loc - pix_loc/zoom_out_scale); - scroll_to_rect(translate_rect(display_rect(), delta)); - } - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// image_window member functions -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - image_window:: - image_window( - ) : - gui_img(*this), - window_has_closed(false), - have_last_click(false), - mouse_btn(0), - clicked_signaler(this->wm), - tie_input_events(false) - { - - gui_img.set_image_clicked_handler(*this, &image_window::on_image_clicked); - gui_img.disable_overlay_editing(); - // show this window on the screen - show(); - } - -// ---------------------------------------------------------------------------------------- - - image_window:: - ~image_window( - ) - { - // You should always call close_window() in the destructor of window - // objects to ensure that no events will be sent to this window while - // it is being destructed. - close_window(); - } - -// ---------------------------------------------------------------------------------------- - - base_window::on_close_return_code image_window:: - on_window_close( - ) - { - window_has_closed = true; - clicked_signaler.broadcast(); - return base_window::CLOSE_WINDOW; - } - -// ---------------------------------------------------------------------------------------- - - bool image_window:: - get_next_keypress ( - unsigned long& key, - bool& is_printable, - unsigned long& state - ) - { - auto_mutex lock(wm); - while (have_last_keypress == false && !window_has_closed && - (have_last_click == false || !tie_input_events)) - { - clicked_signaler.wait(); - } - - if (window_has_closed) - return false; - - if (have_last_keypress) - { - // Mark that we are taking the key click so the next call to get_next_keypress() - // will have to wait for another click. - have_last_keypress = false; - key = next_key; - is_printable = next_is_printable; - state = next_state; - return true; - } - else - { - key = 0; - is_printable = true; - return false; - } - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ) - { - dlib::drawable_window::on_keydown(key,is_printable,state); - - have_last_keypress = true; - next_key = key; - next_is_printable = is_printable; - next_state = state; - clicked_signaler.signal(); - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - tie_events ( - ) - { - auto_mutex lock(wm); - tie_input_events = true; - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - untie_events ( - ) - { - auto_mutex lock(wm); - tie_input_events = false; - } - -// ---------------------------------------------------------------------------------------- - - bool image_window:: - events_tied ( - ) const - { - auto_mutex lock(wm); - return tie_input_events; - } - -// ---------------------------------------------------------------------------------------- - - bool image_window:: - get_next_double_click ( - point& p, - unsigned long& mouse_button - ) - { - p = point(-1,-1); - - auto_mutex lock(wm); - while (have_last_click == false && !window_has_closed && - (have_last_keypress==false || !tie_input_events)) - { - clicked_signaler.wait(); - } - - if (window_has_closed) - return false; - - if (have_last_click) - { - // Mark that we are taking the point click so the next call to - // get_next_double_click() will have to wait for another click. - have_last_click = false; - mouse_button = mouse_btn; - p = last_clicked_point; - return true; - } - else - { - return false; - } - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - on_image_clicked ( - const point& p, - bool is_double_click, - unsigned long btn - ) - { - if (is_double_click) - { - have_last_click = true; - last_clicked_point = p; - mouse_btn = btn; - clicked_signaler.signal(); - } - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - add_overlay ( - const overlay_rect& overlay - ) - { - gui_img.add_overlay(overlay); - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - add_overlay ( - const overlay_line& overlay - ) - { - gui_img.add_overlay(overlay); - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - add_overlay ( - const overlay_circle& overlay - ) - { - gui_img.add_overlay(overlay); - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - add_overlay ( - const std::vector<overlay_rect>& overlay - ) - { - gui_img.add_overlay(overlay); - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - add_overlay ( - const std::vector<overlay_line>& overlay - ) - { - gui_img.add_overlay(overlay); - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - add_overlay ( - const std::vector<overlay_circle>& overlay - ) - { - gui_img.add_overlay(overlay); - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - clear_overlay ( - ) - { - gui_img.clear_overlay(); - } - -// ---------------------------------------------------------------------------------------- - - void image_window:: - on_window_resized( - ) - { - drawable_window::on_window_resized(); - unsigned long width, height; - get_size(width,height); - gui_img.set_size(width, height); - - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_WIDGETs_CPP_ - diff --git a/ml/dlib/dlib/gui_widgets/widgets.h b/ml/dlib/dlib/gui_widgets/widgets.h deleted file mode 100644 index 305d7dc00..000000000 --- a/ml/dlib/dlib/gui_widgets/widgets.h +++ /dev/null @@ -1,4165 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. - -#ifndef DLIB_WIDGETs_ -#define DLIB_WIDGETs_ - -#include <cctype> -#include <memory> -#include <set> -#include <sstream> -#include <string> -#include <vector> - -#include "../algs.h" -#include "widgets_abstract.h" -#include "drawable.h" -#include "../gui_core.h" -#include "fonts.h" -#include "../timer.h" -#include "base_widgets.h" -#include "../member_function_pointer.h" -#include "../array.h" -#include "../array2d.h" -#include "../sequence.h" -#include "../dir_nav.h" -#include "../queue.h" -#include "style.h" -#include "../string.h" -#include "../misc_api.h" -#include "../any.h" -#include "../image_processing/full_object_detection.h" - -#ifdef _MSC_VER -// This #pragma directive is also located in the algs.h file but for whatever -// reason visual studio 9 just ignores it when it is only there. - -// this is to disable the "'this' : used in base member initializer list" -// warning you get from some of the GUI objects since all the objects -// require that their parent class be passed into their constructor. -// In this case though it is totally safe so it is ok to disable this warning. -#pragma warning(disable : 4355) -#endif - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class label -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class label : public drawable - { - public: - label( - drawable_window& w - ) : - drawable(w), - text_color_(0,0,0) - { - enable_events(); - } - - ~label() - { disable_events(); parent.invalidate_rectangle(rect); } - - void set_text ( - const std::string& text - ); - - void set_text ( - const std::wstring& text - ); - - void set_text ( - const dlib::ustring& text - ); - - const std::string text ( - ) const; - - const std::wstring wtext ( - ) const; - - const dlib::ustring utext ( - ) const; - - void set_text_color ( - const rgb_pixel color - ); - - const rgb_pixel text_color ( - ) const; - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - private: - dlib::ustring text_; - rgb_pixel text_color_; - - - // restricted functions - label(label&); // copy constructor - label& operator=(label&); // assignment operator - - protected: - - void draw ( - const canvas& c - ) const; - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class toggle_button -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class toggle_button : public button_action - { - /*! - INITIAL VALUE - - checked == false - - CONVENTION - - is_checked() == checked - !*/ - - public: - - toggle_button( - drawable_window& w - ) : - button_action(w), - btn_tooltip(w), - checked(false) - { - style.reset(new toggle_button_style_default()); - enable_events(); - } - - ~toggle_button() { disable_events(); parent.invalidate_rectangle(rect); } - - void set_name ( - const std::string& name - ); - - void set_name ( - const std::wstring& name - ); - - void set_name ( - const dlib::ustring& name - ); - - void set_size ( - unsigned long width_, - unsigned long height_ - ); - - void set_tooltip_text ( - const std::string& text - ); - - void set_tooltip_text ( - const std::wstring& text - ); - - void set_tooltip_text ( - const ustring& text - ); - - const std::string tooltip_text ( - ) const; - - const std::wstring tooltip_wtext ( - ) const; - - const dlib::ustring tooltip_utext ( - ) const; - - bool is_checked ( - ) const; - - const std::string name ( - ) const; - - const std::wstring wname ( - ) const; - - const dlib::ustring uname ( - ) const; - - void set_checked ( - ); - - void set_unchecked ( - ); - - void show ( - ); - - void hide ( - ); - - void enable ( - ); - - void disable ( - ); - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - void set_pos ( - long x, - long y - ); - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ) - { - auto_mutex M(m); - style.reset(new style_type(style_)); - rect = move_rect(style->get_min_size(name_,*mfont), rect.left(), rect.top()); - parent.invalidate_rectangle(rect); - } - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler_)() - ) - { - auto_mutex M(m); - event_handler = make_mfp(object,event_handler_); - event_handler_self.clear(); - } - - void set_click_handler ( - const any_function<void()>& event_handler_ - ) - { - auto_mutex M(m); - event_handler = event_handler_; - event_handler_self.clear(); - } - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler_)(toggle_button&) - ) - { - auto_mutex M(m); - event_handler_self = make_mfp(object,event_handler_); - event_handler.clear(); - } - - void set_sourced_click_handler ( - const any_function<void(toggle_button&)>& event_handler_ - ) - { - auto_mutex M(m); - event_handler_self = event_handler_; - event_handler.clear(); - } - - private: - - // restricted functions - toggle_button(toggle_button&); // copy constructor - toggle_button& operator=(toggle_button&); // assignment operator - - dlib::ustring name_; - tooltip btn_tooltip; - bool checked; - - any_function<void()> event_handler; - any_function<void(toggle_button&)> event_handler_self; - - std::unique_ptr<toggle_button_style> style; - - protected: - - void draw ( - const canvas& c - ) const { style->draw_toggle_button(c,rect,enabled,*mfont,lastx,lasty,name_,is_depressed(),checked); } - - void on_button_up ( - bool mouse_over - ); - - void on_mouse_over ( - ){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(rect); } - - void on_mouse_not_over ( - ){ if (style->redraw_on_mouse_over()) parent.invalidate_rectangle(rect); } - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class text_field -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class text_field : public drawable - { - /*! - INITIAL VALUE - text_color_ == rgb_pixel(0,0,0) - bg_color_ == rgb_pixel(255,255,255) - cursor_pos == 0 - text_width == 0 - text_ == "" - has_focus == false - cursor_visible == false - recent_movement == false - highlight_start == 0 - highlight_end == -1 - shift_pos == -1 - text_pos == 0 - - CONVENTION - - cursor_pos == the position of the cursor in the string text_. The - cursor appears before the letter text_[cursor_pos] - - cursor_x == the x coordinate of the cursor relative to the left side - of rect. i.e. the number of pixels that separate the cursor from the - left side of the text_field. - - has_focus == true if this text field has keyboard input focus - - cursor_visible == true if the cursor should be painted - - text_ == text() - - text_pos == the index of the first letter in text_ that appears in - this text field. - - text_width == the width of text_[text_pos] though text_[text.size()-1] - - - if (has_focus && the user has recently moved the cursor) then - - recent_movement == true - - else - - recent_movement == false - - - if (highlight_start <= highlight_end) then - - text[highlight_start] though text[highlight_end] should be - highlighted - - - if (shift_pos != -1) then - - has_focus == true - - the shift key is being held down or the left mouse button is - being held down. - - shift_pos == the position of the cursor when the shift or mouse key - was first pressed. - - - text_color() == text_color_ - - background_color() == bg_color_ - !*/ - - public: - text_field( - drawable_window& w - ) : - drawable(w,MOUSE_CLICK | KEYBOARD_EVENTS | MOUSE_MOVE | STRING_PUT), - text_color_(0,0,0), - bg_color_(255,255,255), - text_width(0), - text_pos(0), - recent_movement(false), - has_focus(false), - cursor_visible(false), - cursor_pos(0), - highlight_start(0), - highlight_end(-1), - shift_pos(-1), - t(*this,&text_field::timer_action), - right_click_menu(w) - { - style.reset(new text_field_style_default()); - rect.set_bottom(mfont->height()+ (style->get_padding(*mfont))*2); - rect.set_right((style->get_padding(*mfont))*2); - cursor_x = style->get_padding(*mfont); - - right_click_menu.menu().add_menu_item(menu_item_text("Cut",*this,&text_field::on_cut,'t')); - right_click_menu.menu().add_menu_item(menu_item_text("Copy",*this,&text_field::on_copy,'C')); - right_click_menu.menu().add_menu_item(menu_item_text("Paste",*this,&text_field::on_paste,'P')); - right_click_menu.menu().add_menu_item(menu_item_text("Delete",*this,&text_field::on_delete_selected,'D')); - right_click_menu.menu().add_menu_item(menu_item_separator()); - right_click_menu.menu().add_menu_item(menu_item_text("Select All",*this,&text_field::on_select_all,'A')); - - right_click_menu.set_rect(get_text_rect()); - enable_events(); - - t.set_delay_time(500); - } - - ~text_field ( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - t.stop_and_wait(); - } - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ) - { - auto_mutex M(m); - style.reset(new style_type(style_)); - // call this just so that this widget redraws itself with the new style - set_main_font(mfont); - } - - void set_text ( - const std::string& text_ - ); - - void set_text ( - const std::wstring& text_ - ); - - void give_input_focus ( - ); - - bool has_input_focus ( - ) const; - - void select_all_text ( - ); - - void set_text ( - const dlib::ustring& text_ - ); - - const std::string text ( - ) const; - - const std::wstring wtext ( - ) const; - - const dlib::ustring utext ( - ) const; - - void set_text_color ( - const rgb_pixel color - ); - - const rgb_pixel text_color ( - ) const; - - void set_background_color ( - const rgb_pixel color - ); - - const rgb_pixel background_color ( - ) const; - - void set_width ( - unsigned long width - ); - - void set_pos ( - long x, - long y - ); - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - int next_free_user_event_number ( - ) const - { - return drawable::next_free_user_event_number()+1; - } - - void disable ( - ); - - void enable ( - ); - - void hide ( - ); - - void show ( - ); - - template < - typename T - > - void set_text_modified_handler ( - T& object, - void (T::*event_handler)() - ) - { - auto_mutex M(m); - text_modified_handler = make_mfp(object,event_handler); - } - - template < - typename T - > - void set_enter_key_handler ( - T& object, - void (T::*event_handler)() - ) - { - auto_mutex M(m); - enter_key_handler = make_mfp(object,event_handler); - } - - void set_text_modified_handler ( - const any_function<void()>& event_handler - ) - { - auto_mutex M(m); - text_modified_handler = event_handler; - } - - void set_enter_key_handler ( - const any_function<void()>& event_handler - ) - { - auto_mutex M(m); - enter_key_handler = event_handler; - } - - template < - typename T - > - void set_focus_lost_handler ( - T& object, - void (T::*event_handler)() - ) - { - auto_mutex M(m); - focus_lost_handler = make_mfp(object,event_handler); - } - - void set_focus_lost_handler ( - const any_function<void()>& event_handler - ) - { - auto_mutex M(m); - focus_lost_handler = event_handler; - } - - private: - - void on_cut ( - ); - - void on_copy ( - ); - - void on_paste ( - ); - - void on_select_all ( - ); - - void on_delete_selected ( - ); - - void on_text_is_selected ( - ); - - void on_no_text_selected ( - ); - - void on_user_event ( - int num - ) - { - // ignore this user event if it isn't for us - if (num != drawable::next_free_user_event_number()) - return; - - if (recent_movement == false) - { - cursor_visible = !cursor_visible; - parent.invalidate_rectangle(rect); - } - else - { - if (cursor_visible == false) - { - cursor_visible = true; - parent.invalidate_rectangle(rect); - } - recent_movement = false; - } - } - - void timer_action ( - ) { parent.trigger_user_event(this,drawable::next_free_user_event_number()); } - /*! - ensures - - flips the state of cursor_visible - !*/ - - void move_cursor ( - unsigned long pos - ); - /*! - requires - - pos <= text_.size() - ensures - - moves the cursor to the position given by pos and moves the text - in the text box if necessary - - if the position changes then the parent window will be updated - !*/ - - rectangle get_text_rect ( - ) const; - /*! - ensures - - returns the rectangle that should contain the text in this widget - !*/ - - dlib::ustring text_; - rgb_pixel text_color_; - rgb_pixel bg_color_; - - unsigned long text_width; - unsigned long text_pos; - - - bool recent_movement; - bool has_focus; - bool cursor_visible; - long cursor_pos; - unsigned long cursor_x; - - // this tells you what part of the text is highlighted - long highlight_start; - long highlight_end; - long shift_pos; - any_function<void()> text_modified_handler; - any_function<void()> enter_key_handler; - any_function<void()> focus_lost_handler; - - std::unique_ptr<text_field_style> style; - - timer<text_field> t; - - popup_menu_region right_click_menu; - - // restricted functions - text_field(text_field&); // copy constructor - text_field& operator=(text_field&); // assignment operator - - - protected: - - void draw ( - const canvas& c - ) const; - - - 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_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - - void on_string_put ( - const std::wstring &str - ); - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class text_box -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class text_box : public scrollable_region - { - /*! - INITIAL VALUE - text_color_ == rgb_pixel(0,0,0) - bg_color_ == rgb_pixel(255,255,255) - cursor_pos == 0 - text_ == "" - has_focus == false - cursor_visible == false - recent_movement == false - highlight_start == 0 - highlight_end == -1 - shift_pos == -1 - - CONVENTION - - cursor_pos == the position of the cursor in the string text_. The - cursor appears before the letter text_[cursor_pos] - - cursor_rect == The rectangle that should be drawn for the cursor. - The position is relative to total_rect(). - - has_focus == true if this text field has keyboard input focus - - cursor_visible == true if the cursor should be painted - - text_ == text() - - - if (has_focus && the user has recently moved the cursor) then - - recent_movement == true - - else - - recent_movement == false - - - if (highlight_start <= highlight_end) then - - text[highlight_start] though text[highlight_end] should be - highlighted - - - if (shift_pos != -1) then - - has_focus == true - - the shift key is being held down or the left mouse button is - being held down. - - shift_pos == the position of the cursor when the shift or mouse key - was first pressed. - - - text_color() == text_color_ - - background_color() == bg_color_ - !*/ - - public: - text_box( - drawable_window& w - ) : - scrollable_region(w,MOUSE_CLICK | KEYBOARD_EVENTS | MOUSE_MOVE | STRING_PUT), - text_color_(0,0,0), - bg_color_(255,255,255), - recent_movement(false), - has_focus(false), - cursor_visible(false), - cursor_pos(0), - highlight_start(0), - highlight_end(-1), - shift_pos(-1), - t(*this,&text_box::timer_action), - right_click_menu(w) - { - style.reset(new text_box_style_default()); - - const long padding = static_cast<long>(style->get_padding(*mfont)); - cursor_rect = mfont->compute_cursor_rect(rectangle(padding,padding,1000000,1000000), text_, 0); - - adjust_total_rect(); - - set_vertical_mouse_wheel_scroll_increment(mfont->height()); - set_horizontal_mouse_wheel_scroll_increment(mfont->height()); - - right_click_menu.menu().add_menu_item(menu_item_text("Cut",*this,&text_box::on_cut,'t')); - right_click_menu.menu().add_menu_item(menu_item_text("Copy",*this,&text_box::on_copy,'C')); - right_click_menu.menu().add_menu_item(menu_item_text("Paste",*this,&text_box::on_paste,'P')); - right_click_menu.menu().add_menu_item(menu_item_text("Delete",*this,&text_box::on_delete_selected,'D')); - right_click_menu.menu().add_menu_item(menu_item_separator()); - right_click_menu.menu().add_menu_item(menu_item_text("Select All",*this,&text_box::on_select_all,'A')); - - right_click_menu.set_rect(get_text_rect()); - - set_size(100,100); - - enable_events(); - - t.set_delay_time(500); - } - - ~text_box ( - ) - { - disable_events(); - parent.invalidate_rectangle(rect); - t.stop_and_wait(); - } - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ) - { - auto_mutex M(m); - style.reset(new style_type(style_)); - - scrollable_region::set_style(style_.get_scrollable_region_style()); - // call this just so that this widget redraws itself with the new style - set_main_font(mfont); - } - - void set_text ( - const std::string& text_ - ); - - void set_text ( - const std::wstring& text_ - ); - - void set_text ( - const dlib::ustring& text_ - ); - - const std::string text ( - ) const; - - const std::wstring wtext ( - ) const; - - const dlib::ustring utext ( - ) const; - - void set_text_color ( - const rgb_pixel color - ); - - const rgb_pixel text_color ( - ) const; - - void set_background_color ( - const rgb_pixel color - ); - - const rgb_pixel background_color ( - ) const; - - void set_size ( - unsigned long width, - unsigned long height - ); - - void set_pos ( - long x, - long y - ); - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - int next_free_user_event_number ( - ) const - { - return scrollable_region::next_free_user_event_number()+1; - } - - void disable ( - ); - - void enable ( - ); - - void hide ( - ); - - void show ( - ); - - template < - typename T - > - void set_text_modified_handler ( - T& object, - void (T::*event_handler)() - ) - { - auto_mutex M(m); - text_modified_handler = make_mfp(object,event_handler); - } - - void set_text_modified_handler ( - const any_function<void()>& event_handler - ) - { - auto_mutex M(m); - text_modified_handler = event_handler; - } - - template < - typename T - > - void set_enter_key_handler ( - T& object, - void (T::*event_handler)() - ) - { - auto_mutex M(m); - enter_key_handler = make_mfp(object,event_handler); - } - - void set_enter_key_handler ( - const any_function<void()>& event_handler - ) - { - auto_mutex M(m); - enter_key_handler = event_handler; - } - - template < - typename T - > - void set_focus_lost_handler ( - T& object, - void (T::*event_handler)() - ) - { - auto_mutex M(m); - focus_lost_handler = make_mfp(object,event_handler); - } - - void set_focus_lost_handler ( - const any_function<void()>& event_handler - ) - { - auto_mutex M(m); - focus_lost_handler = event_handler; - } - - private: - - void on_cut ( - ); - - void on_copy ( - ); - - void on_paste ( - ); - - void on_select_all ( - ); - - void on_delete_selected ( - ); - - void on_text_is_selected ( - ); - - void on_no_text_selected ( - ); - - void on_user_event ( - int num - ) - { - // ignore this user event if it isn't for us - if (num != scrollable_region::next_free_user_event_number()) - return; - - if (recent_movement == false) - { - cursor_visible = !cursor_visible; - parent.invalidate_rectangle(rect); - } - else - { - if (cursor_visible == false) - { - cursor_visible = true; - parent.invalidate_rectangle(rect); - } - recent_movement = false; - } - } - - // The reason for using user actions here rather than just having the timer just call - // what it needs directly is to avoid a potential deadlock during destruction of this widget. - void timer_action ( - ) { parent.trigger_user_event(this,scrollable_region::next_free_user_event_number()); } - /*! - ensures - - flips the state of cursor_visible - !*/ - - void move_cursor ( - unsigned long pos - ); - /*! - requires - - pos <= text_.size() - ensures - - moves the cursor to the position given by pos and moves the text - in the text box if necessary - - if the position changes then the parent window will be updated - !*/ - - rectangle get_text_rect ( - ) const; - /*! - ensures - - returns the rectangle that should contain the text in this widget - !*/ - - void adjust_total_rect ( - ); - /*! - ensures - - adjusts total_rect() so that it is big enough to contain the text - currently in this object. - !*/ - - dlib::ustring text_; - rgb_pixel text_color_; - rgb_pixel bg_color_; - - - - bool recent_movement; - bool has_focus; - bool cursor_visible; - long cursor_pos; - rectangle cursor_rect; - - // this tells you what part of the text is highlighted - long highlight_start; - long highlight_end; - long shift_pos; - any_function<void()> text_modified_handler; - any_function<void()> enter_key_handler; - any_function<void()> focus_lost_handler; - - std::unique_ptr<text_box_style> style; - - timer<text_box> t; - - popup_menu_region right_click_menu; - - // restricted functions - text_box(text_box&); // copy constructor - text_box& operator=(text_box&); // assignment operator - - - protected: - - void draw ( - const canvas& c - ) const; - - - 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_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - - void on_string_put ( - const std::wstring &str - ); - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class check_box -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class check_box : public toggle_button - { - public: - check_box( - drawable_window& w - ) : toggle_button(w) - { - set_style(toggle_button_style_check_box()); - } - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class radio_button -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class radio_button : public toggle_button - { - public: - radio_button ( - drawable_window& w - ) : toggle_button(w) - { - set_style(toggle_button_style_radio_button()); - } - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class tabbed_display -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class tabbed_display : public drawable - { - /*! - INITIAL VALUE - - tabs.size() == 0 - - selected_tab_ == 0 - - CONVENTION - - number_of_tabs() == tabs.size() - - tab_name(idx) == tabs[idx] - - if (tabs.size() > 0) then - - selected_tab_ == the index of the tab that is currently selected - - - for all valid i: - - tabs[i].width == mfont->compute_size(tabs[i].name) - - tabs[i].rect == the rectangle that defines where this tab is - - if (tabs[i].group != 0) then - - tabs[i].group == a pointer to the widget_group for this tab. - - - left_pad == the amount of padding in a tab to the left of the name string. - - right_pad == the amount of padding in a tab to the right of the name string. - - top_pad == the amount of padding in a tab to the top of the name string. - - bottom_pad == the amount of padding in a tab to the bottom of the name string. - - - if (event_handler.is_set()) then - - event_handler() is what is called to process click events - on this object. - !*/ - - public: - - tabbed_display( - drawable_window& w - ); - - virtual ~tabbed_display( - ); - - void set_size ( - unsigned long width, - unsigned long height - ); - - void set_number_of_tabs ( - unsigned long num - ); - - unsigned long selected_tab ( - ) const; - - unsigned long number_of_tabs ( - ) const; - - const std::string tab_name ( - unsigned long idx - ) const; - - const std::wstring tab_wname ( - unsigned long idx - ) const; - - const dlib::ustring& tab_uname ( - unsigned long idx - ) const; - - void set_tab_name ( - unsigned long idx, - const std::string& new_name - ); - - void set_tab_name ( - unsigned long idx, - const std::wstring& new_name - ); - - void set_tab_name ( - unsigned long idx, - const dlib::ustring& new_name - ); - - void set_pos ( - long x, - long y - ); - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*eh)(unsigned long new_idx,unsigned long old_idx) - ) - { - auto_mutex M(m); - event_handler = make_mfp(object,eh); - } - - void set_click_handler ( - const any_function<void(unsigned long,unsigned long)>& eh - ) - { - auto_mutex M(m); - event_handler = eh; - } - - void set_tab_group ( - unsigned long idx, - widget_group& group - ); - - void show ( - ); - - void hide ( - ); - - void enable ( - ); - - void disable ( - ); - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - void fit_to_contents ( - ); - - protected: - void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ); - - void draw ( - const canvas& c - ) const; - - private: - void recompute_tabs ( - ); - /*! - ensures - - recomputes the rectangles for all the tabs and makes this object - wider if needed - !*/ - - void draw_tab ( - const rectangle& tab, - const canvas& c - ) const; - /*! - ensures - - draws the outline of a tab as given by the rectangle onto c - !*/ - - struct tab_data - { - tab_data() : width(0), group(0) {} - - dlib::ustring name; - unsigned long width; - rectangle rect; - widget_group* group; - }; - - unsigned long selected_tab_; - - array<tab_data> tabs; - - const long left_pad; - const long right_pad; - const long top_pad; - const long bottom_pad; - - any_function<void(unsigned long,unsigned long)> event_handler; - - // restricted functions - tabbed_display(tabbed_display&); // copy constructor - tabbed_display& operator=(tabbed_display&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class named_rectangle -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class named_rectangle : public drawable - { - /*! - INITIAL VALUE - name == "" - - CONVENTION - name_ == name() - !*/ - - public: - - named_rectangle( - drawable_window& w - ); - - virtual ~named_rectangle( - ); - - void set_size ( - unsigned long width, - unsigned long height - ); - - void set_name ( - const std::string& name - ); - - void set_name ( - const std::wstring& name - ); - - void set_name ( - const dlib::ustring& name - ); - - const std::string name ( - ) const; - - const std::wstring wname ( - ) const; - - const dlib::ustring uname ( - ) const; - - void wrap_around ( - const rectangle& rect - ); - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - protected: - - void draw ( - const canvas& c - ) const; - - private: - - void make_name_fit_in_rect ( - ); - - dlib::ustring name_; - unsigned long name_width; - unsigned long name_height; - - // restricted functions - named_rectangle(named_rectangle&); // copy constructor - named_rectangle& operator=(named_rectangle&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class mouse_tracker -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class mouse_tracker : public draggable - { - - public: - - mouse_tracker( - drawable_window& w - ); - - ~mouse_tracker( - ); - - void show ( - ); - - void hide ( - ); - - void enable ( - ); - - void disable ( - ); - - void set_pos ( - long x, - long y - ); - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - protected: - - void on_mouse_move ( - unsigned long state, - long x, - long y - ); - - void on_drag ( - ); - - void draw ( - const canvas& c - ) const; - - void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ); - - - private: - - const long offset; - named_rectangle nr; - label x_label; - label y_label; - std::ostringstream sout; - - long click_x, click_y; - - // restricted functions - mouse_tracker(mouse_tracker&); // copy constructor - mouse_tracker& operator=(mouse_tracker&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // function message_box() -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace message_box_helper - { - class box_win : public drawable_window - { - void initialize ( - ); - public: - box_win ( - const std::string& title_, - const std::string& message_ - ); - - box_win ( - const std::wstring& title_, - const std::wstring& message_ - ); - - box_win ( - const dlib::ustring& title_, - const dlib::ustring& message_ - ); - - ~box_win ( - ); - - void set_click_handler ( - const any_function<void()>& event_handler_ - ) - { - auto_mutex M(wm); - event_handler = event_handler_; - } - - private: - - static void deleter_thread ( - void* param - ); - - void on_click ( - ); - - on_close_return_code on_window_close ( - ); - - const std::wstring title; - const std::wstring message; - label msg; - button btn_ok; - - any_function<void()> event_handler; - }; - - class blocking_box_win : public drawable_window - { - void initialize ( - ); - - public: - blocking_box_win ( - const std::string& title_, - const std::string& message_ - ); - - blocking_box_win ( - const std::wstring& title_, - const std::wstring& message_ - ); - - blocking_box_win ( - const dlib::ustring& title_, - const dlib::ustring& message_ - ); - - ~blocking_box_win ( - ); - - private: - - void on_click ( - ); - - const std::wstring title; - const std::wstring message; - label msg; - button btn_ok; - }; - } - - template < - typename T - > - void message_box ( - const std::string& title, - const std::string& message, - T& object, - void (T::*event_handler)() - ) - { - using namespace message_box_helper; - box_win* win = new box_win(title,message); - win->set_click_handler(make_mfp(object,event_handler)); - } - - inline void message_box ( - const std::string& title, - const std::string& message, - const any_function<void()>& event_handler - ) - { - using namespace message_box_helper; - box_win* win = new box_win(title,message); - win->set_click_handler(event_handler); - } - - inline void message_box ( - const std::string& title, - const std::string& message - ) - { - using namespace message_box_helper; - new box_win(title,message); - } - - inline void message_box_blocking ( - const std::string& title, - const std::string& message - ) - { - using namespace message_box_helper; - blocking_box_win w(title,message); - w.wait_until_closed(); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class list_box -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace list_box_helper{ - template <typename S = std::string> - class list_box : public scrollable_region, - public enumerable<const S> - { - /*! - INITIAL VALUE - - ms_enabled == false - - items.size() == 0 - - last_selected = 0 - - CONVENTION - - size() == items.size() - - (*this)[i] == items[i].name - - is_selected(i) == items[i].is_selected - - ms_enabled == multiple_select_enabled() - - - items[i].width == the width of items[i].name as given by font::compute_size() - - items[i].height == the height of items[i].name as given by font::compute_size() - - - last_selected == the last item the user selected - !*/ - - public: - - list_box( - drawable_window& w - ); - - ~list_box( - ); - - bool is_selected ( - unsigned long index - ) const; - - void select ( - unsigned long index - ); - - void unselect ( - unsigned long index - ); - - template < - typename style_type - > - void set_style ( - const style_type& style_ - ) - { - auto_mutex M(m); - style.reset(new style_type(style_)); - scrollable_region::set_style(style_.get_scrollable_region_style()); - parent.invalidate_rectangle(rect); - } - - template <typename T> - void get_selected ( - T& list - ) const - { - auto_mutex M(m); - list.clear(); - for (unsigned long i = 0; i < items.size(); ++i) - { - if (items[i].is_selected) - { - unsigned long idx = i; - list.enqueue(idx); - } - } - } - - template <typename T> - void load ( - const T& list - ) - { - auto_mutex M(m); - items.clear(); - unsigned long i = 0; - items.set_max_size(list.size()); - items.set_size(list.size()); - list.reset(); - unsigned long max_width = 0; - unsigned long total_height = 0; - while (list.move_next()) - { - items[i].is_selected = false; - items[i].name = list.element(); - mfont->compute_size(items[i].name,items[i].width, items[i].height); - - if (items[i].width > max_width) - max_width = items[i].width; - total_height += items[i].height; - - ++i; - } - set_total_rect_size(max_width, total_height); - - parent.invalidate_rectangle(rect); - last_selected = 0; - } - - const S& operator[] ( - unsigned long index - ) const; - - bool multiple_select_enabled ( - ) const; - - void enable_multiple_select ( - ); - - void disable_multiple_select ( - ); - - template < - typename T - > - void set_double_click_handler ( - T& object, - void (T::*eh)(unsigned long index) - ) { auto_mutex M(m); event_handler = make_mfp(object,eh); } - - void set_double_click_handler ( - const any_function<void(unsigned long)>& eh - ) { auto_mutex M(m); event_handler = eh; } - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*eh)(unsigned long index) - ) { auto_mutex M(m); single_click_event_handler = make_mfp(object,eh); } - - void set_click_handler ( - const any_function<void(unsigned long)>& eh - ) { auto_mutex M(m); single_click_event_handler = eh; } - - bool at_start ( - ) const; - - void reset ( - ) const; - - bool current_element_valid ( - ) const; - - const S& element ( - ) const; - - const S& element ( - ); - - bool move_next ( - ) const; - - size_t size ( - ) const; - - unsigned long get_selected ( - ) const; - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - private: - - void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ); - - void draw ( - const canvas& c - ) const; - - template <typename SS> - struct data - { - SS name; - bool is_selected; - unsigned long width; - unsigned long height; - }; - - bool ms_enabled; - array<data<S> > items; - any_function<void(unsigned long)> event_handler; - any_function<void(unsigned long)> single_click_event_handler; - unsigned long last_selected; - - std::unique_ptr<list_box_style> style; - - // restricted functions - list_box(list_box&); // copy constructor - list_box& operator=(list_box&); // assignment operator - }; - } - typedef list_box_helper::list_box<std::string> list_box; - typedef list_box_helper::list_box<std::wstring> wlist_box; - typedef list_box_helper::list_box<dlib::ustring> ulist_box; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // function open_file_box() -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - namespace open_file_box_helper - { - class box_win : public drawable_window - { - public: - box_win ( - const std::string& title, - bool has_text_field = false - ); - - ~box_win ( - ); - - void set_click_handler ( - const any_function<void(const std::string&)>& event_handler_ - ) - { - auto_mutex M(wm); - event_handler = event_handler_; - } - - private: - - void set_sizes( - ); - - void on_window_resized ( - ); - - void deleter_thread ( - ); - - void enter_folder ( - const std::string& folder_name - ); - - void on_dirs_click ( - unsigned long idx - ); - - void on_files_click ( - unsigned long idx - ); - - void on_files_double_click ( - unsigned long - ); - - void on_cancel_click ( - ); - - void on_open_click ( - ); - - void on_path_button_click ( - toggle_button& btn - ); - - bool set_dir ( - const std::string& dir - ); - - void on_root_click ( - ); - - on_close_return_code on_window_close ( - ); - - label lbl_dirs; - label lbl_files; - label lbl_file_name; - list_box lb_dirs; - list_box lb_files; - button btn_ok; - button btn_cancel; - toggle_button btn_root; - text_field tf_file_name; - std::string path; - std::string prefix; - int cur_dir; - - any_function<void(const std::string&)> event_handler; - sequence<std::unique_ptr<toggle_button> >::kernel_2a_c sob; - }; - } - - template < - typename T - > - void open_file_box ( - T& object, - void (T::*event_handler)(const std::string&) - ) - { - using namespace open_file_box_helper; - box_win* win = new box_win("Open File",true); - win->set_click_handler(make_mfp(object,event_handler)); - } - - inline void open_file_box ( - const any_function<void(const std::string&)>& event_handler - ) - { - using namespace open_file_box_helper; - box_win* win = new box_win("Open File",true); - win->set_click_handler(event_handler); - } - - template < - typename T - > - void open_existing_file_box ( - T& object, - void (T::*event_handler)(const std::string&) - ) - { - using namespace open_file_box_helper; - box_win* win = new box_win("Open File"); - win->set_click_handler(make_mfp(object,event_handler)); - } - - inline void open_existing_file_box ( - const any_function<void(const std::string&)>& event_handler - ) - { - using namespace open_file_box_helper; - box_win* win = new box_win("Open File"); - win->set_click_handler(event_handler); - } - - template < - typename T - > - void save_file_box ( - T& object, - void (T::*event_handler)(const std::string&) - ) - { - using namespace open_file_box_helper; - box_win* win = new box_win("Save File",true); - win->set_click_handler(make_mfp(object,event_handler)); - } - - inline void save_file_box ( - const any_function<void(const std::string&)>& event_handler - ) - { - using namespace open_file_box_helper; - box_win* win = new box_win("Save File",true); - win->set_click_handler(event_handler); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class menu_bar -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class menu_bar : public drawable - { - /*! - INITIAL VALUE - - menus.size() == 0 - - open_menu == 0 - - CONVENTION - - size() == menus.size() - - all menu data is stored in menus - - menus[x].name == the name of the xth menu - - if (menus[x].underline_pos != std::string::npos) then - - menus[x].underline_pos == the position of the character in the - menu name that should be underlined - - menus[x].underline_p1 != menus[x].underline_p2 - and these two points define the underline bar - - else - - menus[x].underline_p1 == menus[x].underline_p2 - - menus[x].menu == menu(x) - - menus[x].rect == the rectangle in which menus[x].name is drawn - - menus[x].bgrect == the rectangle for the xth menu button - - - if (there is an open menu on the screen) then - - open_menu == the index of the open menu from menus - - else - - open_menu == menus.size() - !*/ - - public: - menu_bar( - drawable_window& w - ); - - ~menu_bar(); - - // this function does nothing - void set_pos(long,long){} - - void set_main_font ( - const std::shared_ptr<font>& f - ); - - void set_number_of_menus ( - unsigned long num - ); - - unsigned long number_of_menus ( - ) const; - - void set_menu_name ( - unsigned long idx, - const std::string name, - char underline_ch = '\0' - ); - - void set_menu_name ( - unsigned long idx, - const std::wstring name, - char underline_ch = '\0' - ); - - void set_menu_name ( - unsigned long idx, - const dlib::ustring name, - char underline_ch = '\0' - ); - - const std::string menu_name ( - unsigned long idx - ) const; - - const std::wstring menu_wname ( - unsigned long idx - ) const; - - const dlib::ustring menu_uname ( - unsigned long idx - ) const; - - popup_menu& menu ( - unsigned long idx - ); - - const popup_menu& menu ( - unsigned long idx - ) const; - - protected: - - void on_window_resized ( - ); - - void draw ( - const canvas& c - ) const; - - void on_window_moved ( - ); - - void on_focus_lost ( - ); - - void on_mouse_down ( - unsigned long btn, - unsigned long , - long x, - long y, - bool - ); - - void on_mouse_move ( - unsigned long , - long x, - long y - ); - - void on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - - private: - - void show_menu ( - unsigned long i - ); - - void hide_menu ( - ); - - void on_popup_hide ( - ); - - void compute_menu_geometry ( - ); - - void adjust_position ( - ); - - struct menu_data - { - menu_data():underline_pos(dlib::ustring::npos){} - - dlib::ustring name; - dlib::ustring::size_type underline_pos; - popup_menu menu; - rectangle rect; - rectangle bgrect; - point underline_p1; - point underline_p2; - }; - - array<menu_data> menus; - unsigned long open_menu; - - // restricted functions - menu_bar(menu_bar&); // copy constructor - menu_bar& operator=(menu_bar&); // assignment operator - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class directed_graph_drawer -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template <typename graph_type> - class directed_graph_drawer : public zoomable_region - { - /*! - INITIAL VALUE - - edge_selected == false - - mouse_drag == false - - selected_node == 0 - - graph_.number_of_nodes() == 0 - - external_graph.number_of_nodes() == 0 - - radius == 25 - - last_mouse_click_in_display == false - - CONVENTION - - radius == the radius of the nodes when they aren't zoomed - - external_graph and graph_ have the same graph structure - - external_graph == graph() - - external_graph.node(i) == graph_node(i) - - - if (one of the nodes is selected) then - - selected_node < graph_.number_of_nodes() - - graph_.node(selected_node) == the selected node - - else - - selected_node == graph_.number_of_nodes() - - - if (the user is dragging a node with the mouse) then - - mouse_drag == true - - drag_offset == the vector from the mouse position to the - center of the node - - else - - mouse_drag == false - - - if (the user has selected an edge) then - - edge_selected == true - - the parent node is graph_.node(selected_edge_parent) - - the child node is graph_.node(selected_edge_parent) - - else - - edge_selected == false - - - for all valid i: - - graph_.node(i).data.p == the center of the node in graph space - - graph_.node(i).data.name == node_label(i) - - graph_.node(i).data.color == node_color(i) - - graph_.node(i).data.str_rect == a rectangle sized to contain graph_.node(i).data.name - - - if (the last mouse click in our parent window as in our display_rect_ ) then - - last_mouse_click_in_display == true - - else - - last_mouse_click_in_display == false - !*/ - - public: - directed_graph_drawer ( - drawable_window& w - ) : - zoomable_region(w,MOUSE_CLICK | MOUSE_WHEEL | KEYBOARD_EVENTS), - radius(25), - edge_selected(false), - last_mouse_click_in_display(false) - { - mouse_drag = false; - selected_node = 0; - - // Whenever you make your own drawable (or inherit from draggable or button_action) - // you have to remember to call this function to enable the events. The idea - // here is that you can perform whatever setup you need to do to get your - // object into a valid state without needing to worry about event handlers - // triggering before you are ready. - enable_events(); - } - - ~directed_graph_drawer ( - ) - { - // Disable all further events for this drawable object. We have to do this - // because we don't want draw() events coming to this object while or after - // it has been destructed. - disable_events(); - - // Tell the parent window to redraw its area that previously contained this - // drawable object. - parent.invalidate_rectangle(rect); - } - - void clear_graph ( - ) - { - auto_mutex M(m); - graph_.clear(); - external_graph.clear(); - parent.invalidate_rectangle(display_rect()); - } - - const typename graph_type::node_type& graph_node ( - unsigned long i - ) const - { - DLIB_ASSERT ( i < number_of_nodes() , - "\tgraph_type::node_type& directed_graph_drawer::graph_node(i)" - << "\n\ti: " << i - << "\n\tnumber_of_nodes(): " << number_of_nodes() - ); - return external_graph.node(i); - } - - typename graph_type::node_type& graph_node ( - unsigned long i - ) - { - DLIB_ASSERT ( i < number_of_nodes() , - "\tgraph_type::node_type& directed_graph_drawer::graph_node(i)" - << "\n\ti: " << i - << "\n\tnumber_of_nodes(): " << number_of_nodes() - ); - return external_graph.node(i); - } - - const graph_type& graph ( - ) const - { - return external_graph; - } - - void save_graph ( - std::ostream& out - ) - { - auto_mutex M(m); - serialize(external_graph, out); - serialize(graph_, out); - parent.invalidate_rectangle(display_rect()); - } - - void load_graph ( - std::istream& in - ) - { - auto_mutex M(m); - deserialize(external_graph, in); - deserialize(graph_, in); - parent.invalidate_rectangle(display_rect()); - } - - unsigned long number_of_nodes ( - ) const - { - auto_mutex M(m); - return graph_.number_of_nodes(); - } - - void set_node_label ( - unsigned long i, - const std::string& label - ) - { - set_node_label(i, convert_mbstring_to_wstring(label)); - } - - void set_node_label ( - unsigned long i, - const std::wstring& label - ) - { - set_node_label(i, convert_wstring_to_utf32(label)); - } - - void set_node_label ( - unsigned long i, - const dlib::ustring& label - ) - { - auto_mutex M(m); - DLIB_ASSERT ( i < number_of_nodes() , - "\tvoid directed_graph_drawer::set_node_label(i,label)" - << "\n\ti: " << i - << "\n\tlabel: " << narrow(label) - << "\n\tnumber_of_nodes(): " << number_of_nodes() - ); - graph_.node(i).data.name = label.c_str(); - unsigned long width, height; - mfont->compute_size(label,width,height); - graph_.node(i).data.str_rect = rectangle(width,height); - parent.invalidate_rectangle(display_rect()); - } - - void set_node_color ( - unsigned long i, - rgb_pixel color - ) - { - auto_mutex M(m); - DLIB_ASSERT ( i < number_of_nodes() , - "\tvoid directed_graph_drawer::set_node_color(i,label)" - << "\n\ti: " << i - << "\n\tnumber_of_nodes(): " << number_of_nodes() - ); - graph_.node(i).data.color = color; - parent.invalidate_rectangle(display_rect()); - } - - rgb_pixel node_color ( - unsigned long i - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( i < number_of_nodes() , - "\trgb_pixel directed_graph_drawer::node_color(i)" - << "\n\ti: " << i - << "\n\tnumber_of_nodes(): " << number_of_nodes() - ); - return graph_.node(i).data.color; - } - - const std::string node_label ( - unsigned long i - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( i < number_of_nodes() , - "\tconst std::ustring directed_graph_drawer::node_label(i)" - << "\n\ti: " << i - << "\n\tnumber_of_nodes(): " << number_of_nodes() - ); - return narrow(graph_.node(i).data.name); - } - - const std::wstring node_wlabel ( - unsigned long i - ) const - { - return convert_utf32_to_wstring(node_ulabel(i)); - } - - const dlib::ustring node_ulabel ( - unsigned long i - ) const - { - auto_mutex M(m); - DLIB_ASSERT ( i < number_of_nodes() , - "\tconst std::ustring directed_graph_drawer::node_label(i)" - << "\n\ti: " << i - << "\n\tnumber_of_nodes(): " << number_of_nodes() - ); - return graph_.node(i).data.name.c_str(); - } - - template < - typename T - > - void set_node_selected_handler ( - T& object, - void (T::*event_handler_)(unsigned long) - ) - { - auto_mutex M(m); - node_selected_handler = make_mfp(object,event_handler_); - } - - void set_node_selected_handler ( - const any_function<void(unsigned long)>& event_handler_ - ) - { - auto_mutex M(m); - node_selected_handler = event_handler_; - } - - template < - typename T - > - void set_node_deselected_handler ( - T& object, - void (T::*event_handler_)(unsigned long) - ) - { - auto_mutex M(m); - node_deselected_handler = make_mfp(object,event_handler_); - } - - void set_node_deselected_handler ( - const any_function<void(unsigned long)>& event_handler_ - ) - { - auto_mutex M(m); - node_deselected_handler = event_handler_; - } - - template < - typename T - > - void set_node_deleted_handler ( - T& object, - void (T::*event_handler_)() - ) - { - auto_mutex M(m); - node_deleted_handler = make_mfp(object,event_handler_); - } - - void set_node_deleted_handler ( - const any_function<void()>& event_handler_ - ) - { - auto_mutex M(m); - node_deleted_handler = event_handler_; - } - - template < - typename T - > - void set_graph_modified_handler ( - T& object, - void (T::*event_handler_)() - ) - { - auto_mutex M(m); - graph_modified_handler = make_mfp(object,event_handler_); - } - - void set_graph_modified_handler ( - const any_function<void()>& event_handler_ - ) - { - auto_mutex M(m); - graph_modified_handler = event_handler_; - } - - protected: - - void on_keydown ( - unsigned long key, - bool , - unsigned long - ) - { - // ignore all keyboard input if the last thing the user clicked on - // wasn't the display area - if (last_mouse_click_in_display == false) - return; - - // if a node is selected - if (selected_node != graph_.number_of_nodes()) - { - // deselect the node if the user hits escape - if (key == base_window::KEY_ESC) - { - parent.invalidate_rectangle(display_rect()); - if (node_deselected_handler.is_set()) - node_deselected_handler(selected_node); - selected_node = graph_.number_of_nodes(); - } - - // delete the node if the user hits delete - if (key == base_window::KEY_DELETE || key == base_window::KEY_BACKSPACE) - { - parent.invalidate_rectangle(display_rect()); - graph_.remove_node(selected_node); - external_graph.remove_node(selected_node); - selected_node = graph_.number_of_nodes(); - mouse_drag = false; - if (graph_modified_handler.is_set()) - graph_modified_handler(); - if (node_deleted_handler.is_set()) - node_deleted_handler(); - } - } - - // if an edge is selected - if (edge_selected) - { - // deselect the node if the user hits escape - if (key == base_window::KEY_ESC) - { - parent.invalidate_rectangle(display_rect()); - edge_selected = false; - } - - // delete the node if the user hits delete - if (key == base_window::KEY_DELETE || key == base_window::KEY_BACKSPACE) - { - parent.invalidate_rectangle(display_rect()); - graph_.remove_edge(selected_edge_parent, selected_edge_child); - external_graph.remove_edge(selected_edge_parent, selected_edge_child); - edge_selected = false; - - if (graph_modified_handler.is_set()) - graph_modified_handler(); - } - } - } - - - void on_mouse_move ( - unsigned long state, - long x, - long y - ) - { - if (mouse_drag) - { - const point p(nearest_point(display_rect(),point(x,y))); - - point center = drag_offset + p; - graph_.node(selected_node).data.p = gui_to_graph_space(center); - parent.invalidate_rectangle(display_rect()); - } - else - { - zoomable_region::on_mouse_move(state,x,y); - } - - // check if the mouse isn't being dragged anymore - if ((state & base_window::LEFT) == 0) - { - mouse_drag = false; - } - } - - void on_mouse_up ( - unsigned long btn, - unsigned long state, - long x, - long y - ) - { - mouse_drag = false; - zoomable_region::on_mouse_up(btn,state,x,y); - } - - void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ) - { - bool redraw = false; - - if (display_rect().contains(x,y) && - (btn == base_window::RIGHT || btn == base_window::LEFT) && - (state & base_window::SHIFT) == 0 ) - { - // start out saying no edge is selected - if (edge_selected) - { - edge_selected = false; - redraw = true; - } - - bool click_hit_node = false; - dlib::vector<double,2> p(gui_to_graph_space(point(x,y))); - // check if this click is on an existing node - for (unsigned long i = 0; i < graph_.number_of_nodes(); ++i) - { - dlib::vector<double,2> n(graph_.node(i).data.p); - if ((p-n).length() < radius) - { - click_hit_node = true; - point center = graph_to_gui_space(graph_.node(i).data.p); - mouse_drag = true; - drag_offset = center - point(x,y); - - // only do something if the click isn't on the currently - // selected node - if (selected_node != i) - { - // send out the deselected event if appropriate - if (selected_node != graph_.number_of_nodes() && node_deselected_handler.is_set()) - node_deselected_handler(selected_node); - - selected_node = i; - redraw = true; - if (node_selected_handler.is_set()) - node_selected_handler(selected_node); - } - break; - } - } - - // if the click didn't hit any node then make sure nothing is selected - if (click_hit_node == false && selected_node != graph_.number_of_nodes()) - { - if (node_deselected_handler.is_set()) - node_deselected_handler(selected_node); - selected_node = graph_.number_of_nodes(); - redraw = true; - } - - - // check if this click is on an edge if we didn't click on a node - if (click_hit_node == false) - { - for (unsigned long n = 0; n < graph_.number_of_nodes() && edge_selected == false; ++n) - { - const dlib::vector<double,2> parent_center(graph_to_gui_space(graph_.node(n).data.p)); - for (unsigned long e = 0; e < graph_.node(n).number_of_children() && edge_selected == false; ++e) - { - const dlib::vector<double,2> child_center(graph_to_gui_space(graph_.node(n).child(e).data.p)); - - rectangle area; - area += parent_center; - area += child_center; - // if the point(x,y) is between the two nodes then lets consider it further - if (area.contains(point(x,y))) - { - p = point(x,y); - const dlib::vector<double> z(0,0,1); - // find the distance from the line between the two nodes - const dlib::vector<double,2> perpendicular(z.cross(parent_center-child_center).normalize()); - double distance = std::abs((child_center-p).dot(perpendicular)); - if (distance < 8) - { - edge_selected = true; - selected_edge_parent = n; - selected_edge_child = graph_.node(n).child(e).index(); - redraw = true; - } - } - } - } - } - - - // if the click didn't land on any node then add a new one if this was - // a right mouse button click - if (click_hit_node == false && btn == base_window::RIGHT) - { - const unsigned long n = graph_.add_node(); - external_graph.add_node(); - - graph_.node(n).data.p = gui_to_graph_space(point(x,y)); - - redraw = true; - selected_node = n; - mouse_drag = false; - if (graph_modified_handler.is_set()) - graph_modified_handler(); - - if (node_selected_handler.is_set()) - node_selected_handler(selected_node); - - } - else if (selected_node == graph_.number_of_nodes()) - { - // in this case the click landed in the white area between nodes - zoomable_region::on_mouse_down( btn, state, x, y, is_double_click); - } - } - - // If the user is shift clicking with the mouse then see if we - // should add a new edge. - if (display_rect().contains(x,y) && - btn == base_window::LEFT && - (state & base_window::SHIFT) && - selected_node != graph_.number_of_nodes() ) - { - dlib::vector<double,2> p(gui_to_graph_space(point(x,y))); - // check if this click is on an existing node - for (unsigned long i = 0; i < graph_.number_of_nodes(); ++i) - { - dlib::vector<double,2> n(graph_.node(i).data.p); - if ((p-n).length() < radius) - { - // add the edge if it doesn't already exist and isn't an edge back to - // the same node - if (graph_.has_edge(selected_node,i) == false && selected_node != i && - graph_.has_edge(i, selected_node) == false) - { - graph_.add_edge(selected_node,i); - external_graph.add_edge(selected_node,i); - redraw = true; - - if (graph_modified_handler.is_set()) - graph_modified_handler(); - } - break; - } - } - } - - - if (redraw) - parent.invalidate_rectangle(display_rect()); - - - if (display_rect().contains(x,y) == false) - last_mouse_click_in_display = false; - else - last_mouse_click_in_display = true; - } - - void draw ( - const canvas& c - ) const - { - zoomable_region::draw(c); - - rectangle area = c.intersect(display_rect()); - if (area.is_empty() == true) - return; - - - if (enabled) - fill_rect(c,display_rect(),255); - else - fill_rect(c,display_rect(),128); - - - const unsigned long rad = static_cast<unsigned long>(radius*zoom_scale()); - point center; - - - // first draw all the edges - for (unsigned long i = 0; i < graph_.number_of_nodes(); ++i) - { - center = graph_to_gui_space(graph_.node(i).data.p); - const rectangle circle_area(centered_rect(center,2*(rad+8),2*(rad+8))); - - // draw lines to all this node's parents - const dlib::vector<double> z(0,0,1); - for (unsigned long j = 0; j < graph_.node(i).number_of_parents(); ++j) - { - point p(graph_to_gui_space(graph_.node(i).parent(j).data.p)); - - rgb_pixel color(0,0,0); - // if this is the selected edge then draw it with red instead of black - if (edge_selected && selected_edge_child == i && selected_edge_parent == graph_.node(i).parent(j).index()) - { - color.red = 255; - // we need to be careful when drawing this line to not draw it over the node dots since it - // has a different color from them and would look weird - dlib::vector<double,2> v(p-center); - v = v.normalize()*rad; - draw_line(c,center+v,p-v ,color, area); - } - else - { - draw_line(c,center,p ,color, area); - } - - - // draw the triangle pointing to this node - if (area.intersect(circle_area).is_empty() == false) - { - dlib::vector<double,2> v(p-center); - v = v.normalize(); - - dlib::vector<double,2> cross = z.cross(v).normalize(); - dlib::vector<double,2> r(center + v*rad); - for (double i = 0; i < 8*zoom_scale(); i += 0.1) - draw_line(c,(r+v*i)+cross*i, (r+v*i)-cross*i,color,area); - } - } - } - - - // now draw all the node dots - for (unsigned long i = 0; i < graph_.number_of_nodes(); ++i) - { - center = graph_to_gui_space(graph_.node(i).data.p); - const rectangle circle_area(centered_rect(center,2*(rad+8),2*(rad+8))); - - // draw the actual dot for this node - if (area.intersect(circle_area).is_empty()==false) - { - rgb_alpha_pixel color; - assign_pixel(color, graph_.node(i).data.color); - // this node is in area so lets draw it and all of it's edges as well - draw_solid_circle(c,center,rad-3,color,area); - color.alpha = 240; - draw_circle(c,center,rad-3,color,area); - color.alpha = 200; - draw_circle(c,center,rad-2.5,color,area); - color.alpha = 160; - draw_circle(c,center,rad-2.0,color,area); - color.alpha = 120; - draw_circle(c,center,rad-1.5,color,area); - color.alpha = 80; - draw_circle(c,center,rad-1.0,color,area); - color.alpha = 40; - draw_circle(c,center,rad-0.5,color,area); - - } - - - if (i == selected_node) - draw_circle(c,center,rad+5,rgb_pixel(0,0,255),area); - } - - - // now draw all the strings last - for (unsigned long i = 0; i < graph_.number_of_nodes(); ++i) - { - center = graph_to_gui_space(graph_.node(i).data.p); - rectangle circle_area(centered_rect(center,2*rad+3,2*rad+3)); - if (area.intersect(circle_area).is_empty()==false) - { - rgb_pixel color = graph_.node(i).data.color; - // invert this color - color.red = 255-color.red; - color.green = 255-color.green; - color.blue = 255-color.blue; - sout << i; - unsigned long width, height; - mfont->compute_size(sout.str(),width,height); - rectangle str_rect(centered_rect(center, width,height)); - if (circle_area.contains(str_rect)) - { - mfont->draw_string(c,str_rect,sout.str(),color,0,std::string::npos,area); - - // draw the label for this node if it isn't empty - if(graph_.node(i).data.name.size() > 0) - { - rectangle str_rect(graph_.node(i).data.str_rect); - str_rect = centered_rect(center.x(), center.y()-rad-mfont->height(), str_rect.width(), str_rect.height()); - mfont->draw_string(c,str_rect,graph_.node(i).data.name,0,0,std::string::npos,area); - } - } - sout.str(""); - } - } - } - - private: - - struct data - { - data() : color(0,0,0) {} - vector<double> p; - dlib::ustring name; - rectangle str_rect; - rgb_pixel color; - }; - - friend void serialize(const data& item, std::ostream& out) - { - serialize(item.p, out); - serialize(item.name, out); - serialize(item.str_rect, out); - serialize(item.color, out); - } - - friend void deserialize(data& item, std::istream& in) - { - deserialize(item.p, in); - deserialize(item.name, in); - deserialize(item.str_rect, in); - deserialize(item.color, in); - } - - mutable std::ostringstream sout; - - const double radius; - unsigned long selected_node; - bool mouse_drag; // true if the user is dragging a node - point drag_offset; - - bool edge_selected; - unsigned long selected_edge_parent; - unsigned long selected_edge_child; - - any_function<void(unsigned long)> node_selected_handler; - any_function<void(unsigned long)> node_deselected_handler; - any_function<void()> node_deleted_handler; - any_function<void()> graph_modified_handler; - - graph_type external_graph; - // rebind the graph_ type to make us a graph_ of data structs - typename graph_type::template rebind<data,char, typename graph_type::mem_manager_type>::other graph_; - - bool last_mouse_click_in_display; - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class text_grid -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class text_grid : public scrollable_region - { - /*! - INITIAL VALUE - - has_focus == false - - vertical_scroll_increment() == 10 - - horizontal_scroll_increment() == 10 - - border_color_ == rgb_pixel(128,128,128) - - CONVENTION - - grid.nr() == row_height.size() - - grid.nc() == col_width.size() - - border_color() == border_color_ - - text(r,c) == grid[r][c].text - - text_color(r,c) == grid[r][c].text_color - - background_color(r,c) == grid[r][c].bg_color - - - if (the user has clicked on this widget and caused one of the - boxes to have input focus) then - - has_focus == true - - grid[active_row][active_col] == the active text box - - cursor_pos == the position of the cursor in the above box - - if (the cursor should be displayed) then - - show_cursor == true - - else - - show_cursor == false - - else - - has_focus == false - !*/ - - public: - text_grid ( - drawable_window& w - ); - - ~text_grid ( - ); - - void set_grid_size ( - unsigned long rows, - unsigned long cols - ); - - unsigned long number_of_columns ( - ) const; - - unsigned long number_of_rows ( - ) const; - - int next_free_user_event_number ( - ) const; - - rgb_pixel border_color ( - ) const; - - void set_border_color ( - rgb_pixel color - ); - - const std::string text ( - unsigned long row, - unsigned long col - ) const; - - const std::wstring wtext ( - unsigned long row, - unsigned long col - ) const; - - const dlib::ustring utext ( - unsigned long row, - unsigned long col - ) const; - - void set_text ( - unsigned long row, - unsigned long col, - const std::string& str - ); - - void set_text ( - unsigned long row, - unsigned long col, - const std::wstring& str - ); - - void set_text ( - unsigned long row, - unsigned long col, - const dlib::ustring& str - ); - - const rgb_pixel text_color ( - unsigned long row, - unsigned long col - ) const; - - void set_text_color ( - unsigned long row, - unsigned long col, - const rgb_pixel color - ); - - const rgb_pixel background_color ( - unsigned long row, - unsigned long col - ) const; - - void set_background_color ( - unsigned long row, - unsigned long col, - const rgb_pixel color - ); - - bool is_editable ( - unsigned long row, - unsigned long col - ) const; - - void set_editable ( - unsigned long row, - unsigned long col, - bool editable - ); - - void set_column_width ( - unsigned long col, - unsigned long width - ); - - void set_row_height ( - unsigned long row, - unsigned long height - ); - - void disable ( - ); - - void hide ( - ); - - template < - typename T - > - void set_text_modified_handler ( - T& object, - void (T::*eh)(unsigned long, unsigned long) - ) { text_modified_handler = make_mfp(object,eh); } - - void set_text_modified_handler ( - const any_function<void(unsigned long, unsigned long)>& eh - ) { text_modified_handler = eh; } - - private: - - void on_user_event ( - int num - ); - - void timer_action ( - ); - /*! - ensures - - flips the state of show_cursor - !*/ - - void compute_bg_rects ( - ); - - void compute_total_rect ( - ); - - void on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - - 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_focus_lost ( - ); - - void draw ( - const canvas& c - ) const; - - rectangle get_text_rect ( - unsigned long row, - unsigned long col - ) const; - - rectangle get_bg_rect ( - unsigned long row, - unsigned long col - ) const; - - struct data_type - { - data_type(): text_color(0,0,0), bg_color(255,255,255), - first(0), is_editable(true) - {} - - dlib::ustring text; - rgb_pixel text_color; - rgb_pixel bg_color; - rectangle bg_rect; - dlib::ustring::size_type first; - bool is_editable; - }; - - void drop_input_focus ( - ); - - void move_cursor ( - long row, - long col, - long new_cursor_pos - ); - - array2d<data_type> grid; - array<unsigned long> col_width; - array<unsigned long> row_height; - bool has_focus; - long active_col; - long active_row; - long cursor_pos; - bool show_cursor; - bool recent_cursor_move; - timer<text_grid> cursor_timer; - rgb_pixel border_color_; - any_function<void(unsigned long, unsigned long)> text_modified_handler; - }; - -// ---------------------------------------------------------------------------------------- - - class image_display : public scrollable_region - { - /*! - INITIAL VALUE - - img.size() == 0 - - overlay_rects.size() == 0 - - overlay_lines.size() == 0 - - drawing_rect == false - - rect_is_selected == false - - CONVENTION - - img == the image this object displays - - overlay_rects == the overlay rectangles this object displays - - overlay_lines == the overlay lines this object displays - - - if (drawing_rect) then - - the user is drawing a rectangle on the screen and is - thus holding down CTRL and the left mouse button. - - rect_anchor == the point on the screen where the user - clicked to begin drawing the rectangle. - - rect_to_draw == the rectangle which should appear on the screen. - - - if (rect_is_selected) then - - selected_rect == the index in overlay_rects of the user selected - rectangle. - - last_right_click_pos == the last place we saw the user right click - the mouse. - - parts_menu.is_enabled() == true - - if (it is actually a part of this rect that is selected) then - - selected_part_name == the name of the part in overlay_rects[selected_rect].parts - that is selected. - - else - - selected_part_name.size() == 0 - - else - - parts_menu.is_enabled() == false - - selected_part_name.size() == 0 - - - if (moving_overlay) then - - moving_rect == the index in overlay_rects that the move applies to. - - if (moving_what == MOVING_PART) then - - moving_part_name == the name of the part in - overlay_rects[moving_rect] that is being moved around with the - mouse. - - else - - moving_what will tell us which side of the rectangle in - overlay_rects[moving_rect] is being moved by the mouse. - !*/ - - public: - - image_display( - drawable_window& w - ); - - ~image_display( - ); - - template < - typename image_type - > - void set_image ( - const image_type& new_img - ) - { - auto_mutex M(m); - - // if the new image has a different size when compared to the previous image - // then we should readjust the total rectangle size. - if (num_rows(new_img) != img.nr() || num_columns(new_img) != img.nc()) - { - if (zoom_in_scale != 1) - set_total_rect_size(num_columns(new_img)*zoom_in_scale, num_rows(new_img)*zoom_in_scale); - else - set_total_rect_size(num_columns(new_img)/zoom_out_scale, num_rows(new_img)/zoom_out_scale); - } - else - { - parent.invalidate_rectangle(rect); - } - - highlighted_rect = std::numeric_limits<unsigned long>::max(); - rect_is_selected = false; - parts_menu.disable(); - assign_image_scaled(img,new_img); - } - - virtual void set_pos ( - long x, - long y - ) - { - auto_mutex lock(m); - scrollable_region::set_pos(x,y); - parts_menu.set_rect(rect); - } - - virtual void set_size ( - unsigned long width, - unsigned long height - ) - { - auto_mutex lock(m); - scrollable_region::set_size(width,height); - parts_menu.set_rect(rect); - } - - struct overlay_rect - { - overlay_rect() :crossed_out(false) { assign_pixel(color, 0);} - - template <typename pixel_type> - overlay_rect(const rectangle& r, pixel_type p) - : rect(r),crossed_out(false) { assign_pixel(color, p); } - - template <typename pixel_type> - overlay_rect(const rectangle& r, pixel_type p, const std::string& l) - : rect(r),label(l),crossed_out(false) { assign_pixel(color, p); } - - template <typename pixel_type> - overlay_rect(const rectangle& r, pixel_type p, const std::string& l, const std::map<std::string,point>& parts_) - : rect(r),label(l),parts(parts_),crossed_out(false) { assign_pixel(color, p); } - - rectangle rect; - rgb_alpha_pixel color; - std::string label; - std::map<std::string,point> parts; - bool crossed_out; - }; - - struct overlay_line - { - overlay_line() { assign_pixel(color, 0);} - - template <typename pixel_type> - overlay_line(const point& p1_, const point& p2_, pixel_type p) - : p1(p1_), p2(p2_) { assign_pixel(color, p); } - - point p1; - point p2; - rgb_alpha_pixel color; - }; - - struct overlay_circle - { - overlay_circle():radius(0) { assign_pixel(color, 0);} - - template <typename pixel_type> - overlay_circle(const point& center_, const int radius_, pixel_type p) - : center(center_), radius(radius_) { assign_pixel(color, p); } - - template <typename pixel_type> - overlay_circle(const point& center_, const int radius_, pixel_type p, const std::string& l) - : center(center_), radius(radius_), label(l) { assign_pixel(color, p); } - - point center; - int radius; - rgb_alpha_pixel color; - std::string label; - }; - - void add_overlay ( - const overlay_rect& overlay - ); - - void add_overlay ( - const overlay_line& overlay - ); - - void add_overlay ( - const overlay_circle& overlay - ); - - void add_overlay ( - const std::vector<overlay_rect>& overlay - ); - - void add_overlay ( - const std::vector<overlay_line>& overlay - ); - - void add_overlay ( - const std::vector<overlay_circle>& overlay - ); - - void clear_overlay ( - ); - - rectangle get_image_display_rect ( - ) const; - - std::vector<overlay_rect> get_overlay_rects ( - ) const; - - void set_default_overlay_rect_label ( - const std::string& label - ); - - std::string get_default_overlay_rect_label ( - ) const; - - void set_default_overlay_rect_color ( - const rgb_alpha_pixel& color - ); - - rgb_alpha_pixel get_default_overlay_rect_color ( - ) const; - - template < - typename T - > - void set_overlay_rects_changed_handler ( - T& object, - void (T::*event_handler_)() - ) - { - auto_mutex M(m); - event_handler = make_mfp(object,event_handler_); - } - - void set_overlay_rects_changed_handler ( - const any_function<void()>& event_handler_ - ) - { - auto_mutex M(m); - event_handler = event_handler_; - } - - template < - typename T - > - void set_overlay_rect_selected_handler ( - T& object, - void (T::*event_handler_)(const overlay_rect& orect) - ) - { - auto_mutex M(m); - orect_selected_event_handler = make_mfp(object,event_handler_); - } - - void set_overlay_rect_selected_handler ( - const any_function<void(const overlay_rect& orect)>& event_handler_ - ) - { - auto_mutex M(m); - orect_selected_event_handler = event_handler_; - } - - template < - typename T - > - void set_image_clicked_handler ( - T& object, - void (T::*event_handler_)(const point& p, bool is_double_click, unsigned long btn) - ) - { - auto_mutex M(m); - image_clicked_handler = make_mfp(object,event_handler_); - } - - void set_image_clicked_handler ( - const any_function<void(const point& p, bool is_double_click, unsigned long btn)>& event_handler_ - ) - { - auto_mutex M(m); - image_clicked_handler = event_handler_; - } - - void add_labelable_part_name ( - const std::string& name - ); - - void clear_labelable_part_names ( - ); - - void enable_overlay_editing ( - ) { auto_mutex M(m); overlay_editing_enabled = true; } - - void disable_overlay_editing ( - ) - { - auto_mutex M(m); - overlay_editing_enabled = false; - rect_is_selected = false; - drawing_rect = false; - parent.invalidate_rectangle(rect); - } - - bool overlay_editing_is_enabled ( - ) const { auto_mutex M(m); return overlay_editing_enabled; } - - private: - - void draw ( - const canvas& c - ) const; - - void on_wheel_up ( - unsigned long state - ); - - void on_wheel_down ( - unsigned long state - ); - - 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_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - - void on_part_add ( - const std::string& part_name - ); - - rectangle get_rect_on_screen ( - unsigned long idx - ) const; - - rectangle get_rect_on_screen ( - rectangle orect - ) const; - - rgb_alpha_pixel invert_pixel (const rgb_alpha_pixel& p) const - { return rgb_alpha_pixel(255-p.red, 255-p.green, 255-p.blue, p.alpha); } - - virtual int next_free_user_event_number ( - ) const { return scrollable_region::next_free_user_event_number()+1; } - // The reason for using user actions here rather than just having the timer just call - // what it needs directly is to avoid a potential deadlock during destruction of this widget. - void timer_event_unhighlight_rect() - { - highlight_timer.stop(); - parent.trigger_user_event(this,scrollable_region::next_free_user_event_number()); - } - void on_user_event (int num) - { - // ignore this user event if it isn't for us - if (num != scrollable_region::next_free_user_event_number()) - return; - if (highlighted_rect < overlay_rects.size()) - { - highlighted_rect = std::numeric_limits<unsigned long>::max(); - parent.invalidate_rectangle(rect); - } - } - - - array2d<rgb_alpha_pixel> img; - - - std::vector<overlay_rect> overlay_rects; - std::vector<overlay_line> overlay_lines; - std::vector<overlay_circle> overlay_circles; - - long zoom_in_scale; - long zoom_out_scale; - bool drawing_rect; - point rect_anchor; - rectangle rect_to_draw; - bool rect_is_selected; - std::string selected_part_name; - unsigned long selected_rect; - rgb_alpha_pixel default_rect_color; - std::string default_rect_label; - any_function<void()> event_handler; - any_function<void(const overlay_rect& orect)> orect_selected_event_handler; - any_function<void(const point& p, bool is_double_click, unsigned long btn)> image_clicked_handler; - popup_menu_region parts_menu; - point last_right_click_pos; - const double part_width; - std::set<std::string> part_names; - bool overlay_editing_enabled; - timer<image_display> highlight_timer; - unsigned long highlighted_rect; - bool holding_shift_key; - - bool moving_overlay; - unsigned long moving_rect; - enum { - MOVING_RECT_LEFT, - MOVING_RECT_TOP, - MOVING_RECT_RIGHT, - MOVING_RECT_BOTTOM, - MOVING_PART - } moving_what; - std::string moving_part_name; - - // restricted functions - image_display(image_display&); // copy constructor - image_display& operator=(image_display&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - - class perspective_display : public drawable, noncopyable - { - public: - - perspective_display( - drawable_window& w - ); - - ~perspective_display( - ); - - virtual void set_size ( - unsigned long width, - unsigned long height - ); - - struct overlay_line - { - overlay_line() { assign_pixel(color, 0);} - - overlay_line(const vector<double>& p1_, const vector<double>& p2_) - : p1(p1_), p2(p2_) { assign_pixel(color, 255); } - - template <typename pixel_type> - overlay_line(const vector<double>& p1_, const vector<double>& p2_, pixel_type p) - : p1(p1_), p2(p2_) { assign_pixel(color, p); } - - vector<double> p1; - vector<double> p2; - rgb_pixel color; - }; - - struct overlay_dot - { - overlay_dot() { assign_pixel(color, 0);} - - overlay_dot(const vector<double>& p_) - : p(p_) { assign_pixel(color, 255); } - - template <typename pixel_type> - overlay_dot(const vector<double>& p_, pixel_type color_) - : p(p_) { assign_pixel(color, color_); } - - vector<double> p; - rgb_pixel color; - }; - - - void add_overlay ( - const std::vector<overlay_line>& overlay - ); - - void add_overlay ( - const std::vector<overlay_dot>& overlay - ); - - void clear_overlay ( - ); - - template < - typename T - > - void set_dot_double_clicked_handler ( - T& object, - void (T::*event_handler_)(const vector<double>&) - ) - { - auto_mutex M(m); - dot_clicked_event_handler = make_mfp(object,event_handler_); - } - - void set_dot_double_clicked_handler ( - const any_function<void(const vector<double>&)>& event_handler_ - ); - - private: - - void draw ( - const canvas& c - ) const; - - void on_wheel_up ( - unsigned long state - ); - - void on_wheel_down ( - unsigned long state - ); - - void on_mouse_down ( - unsigned long btn, - unsigned long state, - long x, - long y, - bool is_double_click - ); - - void on_mouse_move ( - unsigned long state, - long x, - long y - ); - - static bool compare_second ( - const std::pair<overlay_dot,float>& a, - const std::pair<overlay_dot,float>& b - ) { return a.second < b.second; } - - - point last; - std::vector<overlay_line> overlay_lines; - std::vector<overlay_dot> overlay_dots; - - camera_transform tform; - vector<double> sum_pts; - vector<double> max_pts; - any_function<void(const vector<double>&)> dot_clicked_event_handler; - mutable array2d<float> depth; - }; - -// ---------------------------------------------------------------------------------------- - - class perspective_window : public drawable_window, noncopyable - { - public: - - typedef perspective_display::overlay_line overlay_line; - typedef perspective_display::overlay_dot overlay_dot; - - perspective_window( - ) : disp(*this) - { - set_size(100,100); - on_window_resized(); - show(); - } - - perspective_window( - const std::vector<dlib::vector<double> >& point_cloud - ) : - disp(*this) - { - set_size(100,100); - on_window_resized(); - add_overlay(point_cloud); - show(); - } - - perspective_window( - const std::vector<dlib::vector<double> >& point_cloud, - const std::string& title - ) : - disp(*this) - { - set_size(100,100); - on_window_resized(); - add_overlay(point_cloud); - set_title(title); - show(); - } - - ~perspective_window( - ) - { - // You should always call close_window() in the destructor of window - // objects to ensure that no events will be sent to this window while - // it is being destructed. - close_window(); - } - - void add_overlay ( - const std::vector<overlay_line>& overlay - ) - { - disp.add_overlay(overlay); - } - - void add_overlay ( - const std::vector<overlay_dot>& overlay - ) - { - disp.add_overlay(overlay); - } - - void clear_overlay ( - ) - { - disp.clear_overlay(); - } - - template <typename pixel_type> - void add_overlay(const vector<double>& p1, const vector<double>& p2, pixel_type p) - { - add_overlay(std::vector<overlay_line>(1,overlay_line(p1,p2,p))); - } - - void add_overlay(const std::vector<dlib::vector<double> >& d) - { - add_overlay(d, 255); - } - - template <typename pixel_type> - void add_overlay(const std::vector<dlib::vector<double> >& d, pixel_type p) - { - std::vector<overlay_dot> temp; - temp.resize(d.size()); - for (unsigned long i = 0; i < temp.size(); ++i) - temp[i] = overlay_dot(d[i], p); - - add_overlay(temp); - } - - template < - typename T - > - void set_dot_double_clicked_handler ( - T& object, - void (T::*event_handler_)(const vector<double>&) - ) - { - disp.set_dot_double_clicked_handler(object,event_handler_); - } - - void set_dot_double_clicked_handler ( - const any_function<void(const vector<double>&)>& event_handler_ - ) - { - disp.set_dot_double_clicked_handler(event_handler_); - } - - private: - - void on_window_resized( - ) - { - drawable_window::on_window_resized(); - unsigned long width, height; - get_size(width,height); - disp.set_pos(0,0); - disp.set_size(width, height); - } - - perspective_display disp; - }; - -// ---------------------------------------------------------------------------------------- - - class image_window : public drawable_window - { - public: - - typedef image_display::overlay_rect overlay_rect; - typedef image_display::overlay_line overlay_line; - typedef image_display::overlay_circle overlay_circle; - - image_window( - ); - - template < typename image_type > - image_window( - const image_type& img - ) : - gui_img(*this), - window_has_closed(false), - have_last_click(false), - mouse_btn(0), - clicked_signaler(this->wm), - have_last_keypress(false), - tie_input_events(false) - { - gui_img.set_image_clicked_handler(*this, &image_window::on_image_clicked); - gui_img.disable_overlay_editing(); - set_image(img); - show(); - } - - template < typename image_type > - image_window( - const image_type& img, - const std::string& title - ) : - gui_img(*this), - window_has_closed(false), - have_last_click(false), - mouse_btn(0), - clicked_signaler(this->wm), - have_last_keypress(false), - tie_input_events(false) - { - gui_img.set_image_clicked_handler(*this, &image_window::on_image_clicked); - gui_img.disable_overlay_editing(); - set_image(img); - set_title(title); - show(); - } - - - ~image_window( - ); - - template < typename image_type > - void set_image ( - const image_type& img - ) - { - const unsigned long padding = scrollable_region_style_default().get_border_size(); - auto_mutex M(wm); - gui_img.set_image(img); - - // Only ever mess with the size of the window if the user is giving us an image - // that is a different size. Otherwise we assume that they will have already - // sized the window to whatever they feel is reasonable for an image of the - // current size. - if (previous_image_size != get_rect(img)) - { - const rectangle r = gui_img.get_image_display_rect(); - if (image_rect != r) - { - // set the size of this window to match the size of the input image - set_size(r.width()+padding*2,r.height()+padding*2); - - // call this to make sure everything else is setup properly - on_window_resized(); - - image_rect = r; - } - previous_image_size = get_rect(img); - } - } - - void add_overlay ( - const overlay_rect& overlay - ); - - template <typename pixel_type> - void add_overlay(const rectangle& r, pixel_type p) - { add_overlay(image_display::overlay_rect(r,p)); } - - void add_overlay(const rectangle& r) - { add_overlay(image_display::overlay_rect(r,rgb_pixel(255,0,0))); } - - template <typename pixel_type> - void add_overlay(const rectangle& r, pixel_type p, const std::string& l) - { add_overlay(image_display::overlay_rect(r,p,l)); } - - template <typename pixel_type> - void add_overlay(const std::vector<rectangle>& r, pixel_type p) - { - std::vector<overlay_rect> temp; - temp.resize(r.size()); - for (unsigned long i = 0; i < temp.size(); ++i) - temp[i] = overlay_rect(r[i], p); - - add_overlay(temp); - } - - void add_overlay(const std::vector<rectangle>& r) - { add_overlay(r, rgb_pixel(255,0,0)); } - - void add_overlay( - const full_object_detection& object, - const std::vector<std::string>& part_names - ) - { - - add_overlay(overlay_rect(object.get_rect(), rgb_pixel(255,0,0))); - - std::vector<overlay_circle> temp; - temp.reserve(object.num_parts()); - for (unsigned long i = 0; i < object.num_parts(); ++i) - { - if (object.part(i) != OBJECT_PART_NOT_PRESENT) - { - if (i < part_names.size()) - temp.push_back(overlay_circle(object.part(i), 7, rgb_pixel(0,255,0), part_names[i])); - else - temp.push_back(overlay_circle(object.part(i), 7, rgb_pixel(0,255,0))); - } - } - - add_overlay(temp); - } - - void add_overlay( - const full_object_detection& object - ) - { - std::vector<std::string> part_names; - add_overlay(object, part_names); - } - - void add_overlay( - const std::vector<full_object_detection>& objects, - const std::vector<std::string>& part_names - ) - { - std::vector<overlay_rect> rtemp; - rtemp.reserve(objects.size()); - for (unsigned long i = 0; i < objects.size(); ++i) - { - rtemp.push_back(overlay_rect(objects[i].get_rect(), rgb_pixel(255,0,0))); - } - - add_overlay(rtemp); - - std::vector<overlay_circle> temp; - - for (unsigned long i = 0; i < objects.size(); ++i) - { - for (unsigned long j = 0; j < objects[i].num_parts(); ++j) - { - if (objects[i].part(j) != OBJECT_PART_NOT_PRESENT) - { - if (j < part_names.size()) - temp.push_back(overlay_circle(objects[i].part(j), 7, rgb_pixel(0,255,0),part_names[j])); - else - temp.push_back(overlay_circle(objects[i].part(j), 7, rgb_pixel(0,255,0))); - } - } - } - - add_overlay(temp); - } - - void add_overlay( - const std::vector<full_object_detection>& objects - ) - { - std::vector<std::string> part_names; - add_overlay(objects, part_names); - } - - void add_overlay ( - const overlay_line& overlay - ); - - void add_overlay ( - const overlay_circle& overlay - ); - - template <typename pixel_type> - void add_overlay(const point& p1, const point& p2, pixel_type p) - { add_overlay(image_display::overlay_line(p1,p2,p)); } - - void add_overlay ( - const std::vector<overlay_rect>& overlay - ); - - void add_overlay ( - const std::vector<overlay_line>& overlay - ); - - void add_overlay ( - const std::vector<overlay_circle>& overlay - ); - - void clear_overlay ( - ); - - bool get_next_double_click ( - point& p, - unsigned long& mouse_button - ); - - void tie_events ( - ); - - void untie_events ( - ); - - bool events_tied ( - ) const; - - bool get_next_double_click ( - point& p - ) - { - unsigned long mouse_button; - return get_next_double_click(p, mouse_button); - } - - bool get_next_keypress ( - unsigned long& key, - bool& is_printable, - unsigned long& state - ); - - bool get_next_keypress ( - unsigned long& key, - bool& is_printable - ) - { - unsigned long state; - return get_next_keypress(key,is_printable,state); - } - - private: - - virtual base_window::on_close_return_code on_window_close( - ); - - void on_window_resized( - ); - - void on_image_clicked ( - const point& p, - bool is_double_click, - unsigned long btn - ); - - virtual void on_keydown ( - unsigned long key, - bool is_printable, - unsigned long state - ); - - // restricted functions - image_window(image_window&); - image_window& operator= (image_window&); - - image_display gui_img; - rectangle image_rect; - rectangle previous_image_size; - bool window_has_closed; - bool have_last_click; - point last_clicked_point; - unsigned long mouse_btn; - rsignaler clicked_signaler; - - bool have_last_keypress; - unsigned long next_key; - bool next_is_printable; - unsigned long next_state; - bool tie_input_events; - }; - -// ---------------------------------------------------------------------------------------- - -} - -#ifdef NO_MAKEFILE -#include "widgets.cpp" -#endif - -#endif // DLIB_WIDGETs_ - diff --git a/ml/dlib/dlib/gui_widgets/widgets_abstract.h b/ml/dlib/dlib/gui_widgets/widgets_abstract.h deleted file mode 100644 index 2b4dc4486..000000000 --- a/ml/dlib/dlib/gui_widgets/widgets_abstract.h +++ /dev/null @@ -1,3461 +0,0 @@ -// Copyright (C) 2005 Davis E. King (davis@dlib.net), Keita Mochizuki -// License: Boost Software License See LICENSE.txt for the full license. - -#undef DLIB_WIDGETs_ABSTRACT_ -#ifdef DLIB_WIDGETs_ABSTRACT_ - -#include "fonts_abstract.h" -#include "drawable_abstract.h" -#include "base_widgets_abstract.h" - -#include "../gui_core.h" -#include <string> -#include <map> -#include "../interfaces/enumerable.h" -#include "style_abstract.h" -#include "../image_processing/full_object_detection_abstract.h" - -namespace dlib -{ - - /*! - GENERAL REMARKS - This component is a collection of various windowing widgets such as buttons, - labels, text boxes, and so on. This component also includes the drawable - interface, drawable_window, and font handling objects. The file you are - currently viewing defines all the high level graphical widgets which are - provided by this component that can appear in a drawable_window. To view - the specifications for the other members of this component look at - fonts_abstract.h, base_widgets_abstract.h, and drawable_abstract.h - - THREAD SAFETY - All objects and functions defined in this file are thread safe. You may - call them from any thread without serializing access to them. - - EVENT HANDLERS - Note that all event handlers, including the user registered callback - functions, are executed in the event handling thread. Additionally, - the drawable::m mutex will always be locked while these event handlers - are running. Also, don't rely on get_thread_id() always returning the - same ID from inside event handlers. - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // function open_file_box(), open_existing_file_box(), and save_file_box() -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - void open_file_box ( - T& object, - void (T::*event_handler)(const std::string&) - ); - /*! - requires - - event_handler == a valid pointer to a member function of object T. - ensures - - Displays a window titled "Open File" that will allow the user to select a - file. - - The displayed window will start out showing the directory get_current_dir() - (i.e. it starts in the current working directory) - - The event_handler function is called on object if the user selects - a file. If the user closes the window without selecting a file - then nothing occurs. - !*/ - - void open_file_box ( - const any_function<void(const std::string&)>& event_handler - ); - /*! - ensures - - Displays a window titled "Open File" that will allow the user to select a - file. - - The displayed window will start out showing the directory get_current_dir() - (i.e. it starts in the current working directory) - - The event_handler function is called if the user selects - a file. If the user closes the window without selecting a file - then nothing occurs. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - void open_existing_file_box ( - T& object, - void (T::*event_handler)(const std::string&) - ); - /*! - requires - - event_handler == a valid pointer to a member function of object T. - ensures - - Displays a window titled "Open File" that will allow the user to select - a file. But only a file that already exists. - - The displayed window will start out showing the directory get_current_dir() - (i.e. it starts in the current working directory) - - The event_handler function is called on object if the user selects - a file. If the user closes the window without selecting a file - then nothing occurs. - !*/ - - void open_existing_file_box ( - const any_function<void(const std::string&)>& event_handler - ); - /*! - ensures - - Displays a window titled "Open File" that will allow the user to select - a file. But only a file that already exists. - - The displayed window will start out showing the directory get_current_dir() - (i.e. it starts in the current working directory) - - The event_handler function is called if the user selects - a file. If the user closes the window without selecting a file - then nothing occurs. - !*/ - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - void save_file_box ( - T& object, - void (T::*event_handler)(const std::string&) - ); - /*! - requires - - event_handler == a valid pointer to a member function of object T. - ensures - - Displays a window titled "Save File" that will allow the user to select - a file. - - The displayed window will start out showing the directory get_current_dir() - (i.e. it starts in the current working directory) - - The event_handler function is called on object if the user selects - a file. If the user closes the window without selecting a file - then nothing occurs. - !*/ - - void save_file_box ( - const any_function<void(const std::string&)>& event_handler - ); - /*! - ensures - - Displays a window titled "Save File" that will allow the user to select - a file. - - The displayed window will start out showing the directory get_current_dir() - (i.e. it starts in the current working directory) - - The event_handler function is called if the user selects - a file. If the user closes the window without selecting a file - then nothing occurs. - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // function message_box() -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - void message_box ( - const std::string& title, - const std::string& message - ); - /*! - ensures - - displays a message box with the given title and message. It will have a - single button and when the user clicks it the message box will go away. - - this function does not block but instead returns immediately. - !*/ - - void message_box_blocking ( - const std::string& title, - const std::string& message - ); - /*! - ensures - - displays a message box with the given title and message. It will have a - single button and when the user clicks it the message box will go away. - - this function blocks until the user clicks on the message box and - causes it to go away. - !*/ - - template < - typename T - > - void message_box ( - const std::string& title, - const std::string& message, - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler == a valid pointer to a member function of object T. - ensures - - Displays a message box with the given title and message. It will have a - single button and when the user clicks it the message box will go away. - - The event_handler function is called on object when the user clicks - ok or otherwise closes the message box window. - - this function does not block but instead returns immediately. - !*/ - - void message_box ( - const std::string& title, - const std::string& message, - const any_function<void()>& event_handler - ); - /*! - ensures - - Displays a message box with the given title and message. It will have a - single button and when the user clicks it the message box will go away. - - The event_handler function is called when the user clicks - ok or otherwise closes the message box window. - - this function does not block but instead returns immediately. - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class label -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class label : public drawable - { - /*! - INITIAL VALUE - text() == "" - the text color will be black - - WHAT THIS OBJECT REPRESENTS - This object represents a simple text label. The size of the label - is automatically set to be just big enough to contain its text. - !*/ - - public: - - label( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~label( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_text (const std::wstring& text); - void set_text (const dlib::ustring& text); - void set_text ( - const std::string& text - ); - /*! - ensures - - #text() == text - throws - - std::bad_alloc - !*/ - - const std::wstring wtext () const; - const dlib::ustring utext () const; - const std::string text ( - ) const; - /*! - ensures - - returns the text of this label - throws - - std::bad_alloc - !*/ - - void set_text_color ( - const rgb_pixel color - ); - /*! - ensures - - #text_color() == color - !*/ - - const rgb_pixel text_color ( - ) const; - /*! - ensures - - returns the color used to draw the text in this widget - !*/ - - private: - - // restricted functions - label(label&); // copy constructor - label& operator=(label&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class toggle_button -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class toggle_button : public button_action - { - /*! - INITIAL VALUE - name() == "" - is_checked() == false - - WHAT THIS OBJECT REPRESENTS - This object represents a simple two state toggle button. Is is either - in the checked or unchecked state and when a user clicks on it it toggles its - state. - - When this object is disabled it means it will not respond to user clicks. - !*/ - - public: - - toggle_button( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~toggle_button( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_name (const std::wstring& name); - void set_name (const dlib::ustring& name); - void set_name ( - const std::string& name - ); - /*! - ensures - - #name() == name - - this toggle_button has been resized such that it is big enough to contain - the new name. - throws - - std::bad_alloc - !*/ - - void set_size ( - unsigned long width_, - unsigned long height_ - ); - /*! - ensures - - if (width and height are big enough to contain the name of this button) then - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this button stays the - same but its width and height are modified - !*/ - - void set_tooltip_text (const std::wstring& text); - void set_tooltip_text (const dlib::ustring& text); - void set_tooltip_text ( - const std::string& text - ); - /*! - ensures - - #tooltip_text() == text - - enables the tooltip for this toggle_button - !*/ - - const dlib::ustring tooltip_utext () const; - const std::wstring tooltip_wtext () const; - const std::string tooltip_text ( - ) const; - /*! - ensures - - returns the text that is displayed in the tooltip for this toggle_button - !*/ - - template < - typename style_type - > - void set_style ( - const style_type& style - ); - /*! - requires - - style_type == a type that inherits from toggle_button_style - ensures - - this toggle_button object will draw itself using the given - button style - !*/ - - bool is_checked ( - ) const; - /*! - ensures - - if (this box is currently checked) then - - returns true - - else - - returns false - !*/ - - const std::wstring wname () const; - const dlib::ustring uname () const; - const std::string name ( - ) const; - /*! - ensures - - returns the name of this toggle_button. The name is a string - that appears to the right of the actual check box. - throws - - std::bad_alloc - !*/ - - void set_checked ( - ); - /*! - ensures - - #is_checked() == true - !*/ - - void set_unchecked ( - ); - /*! - ensures - - #is_checked() == false - !*/ - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the toggle_button is - toggled by the user. - - this event is NOT triggered by calling set_checked() or set_unchecked(). - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_click_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when the toggle_button is - toggled by the user. - - this event is NOT triggered by calling set_checked() or set_unchecked(). - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler)(toggle_button& self) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T. - ensures - - the event_handler function is called on object when the toggle_button is - toggled by the user. self will be a reference to the toggle_button object - that the user clicked. - - this event is NOT triggered by calling set_checked() or set_unchecked(). - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_sourced_click_handler ( - const any_function<void(toggle_button& self)>& event_handler - ); - /*! - ensures - - the event_handler function is called when the toggle_button is - toggled by the user. self will be a reference to the toggle_button object - that the user clicked. - - this event is NOT triggered by calling set_checked() or set_unchecked(). - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - toggle_button(toggle_button&); // copy constructor - toggle_button& operator=(toggle_button&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class text_field -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class text_field : public drawable - { - /*! - INITIAL VALUE - - text() == "" - - width() == 10 - - height() == a height appropriate for the font used. The text color will - be black. - - has_input_focus() == false - - WHAT THIS OBJECT REPRESENTS - This object represents a simple one line text input field. - !*/ - - public: - - text_field( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~text_field( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - template < - typename style_type - > - void set_style ( - const style_type& style - ); - /*! - requires - - style_type == a type that inherits from text_field_style - ensures - - this text_field object will draw itself using the given - text field style - !*/ - - void set_text (const std::wstring& text); - void set_text (const dlib::ustring& text); - void set_text ( - const std::string& text - ); - /*! - requires - - text.find_first_of('\n') == std::string::npos - (i.e. there aren't any new lines in text) - ensures - - #text() == text - throws - - std::bad_alloc - !*/ - - const std::wstring wtext () const; - const dlib::ustring utext () const; - const std::string text ( - ) const; - /*! - ensures - - returns the text of this text_field - throws - - std::bad_alloc - !*/ - - void set_width ( - unsigned long width_ - ); - /*! - ensures - - if (width >= 10) then - - #width() == width_ - - #height() == height() - - #top() == top() - - #left() == left() - - i.e. The width of this drawable is set to the given width but - nothing else changes. - !*/ - - void give_input_focus ( - ); - /*! - ensures - - #has_input_focus() == true - !*/ - - bool has_input_focus ( - ); - /*! - ensures - - Returns true if this txt field has input keyboard focus. If this - is the case then it means that when the user types on the keyboard - the output will appear inside the text field. - !*/ - - void select_all_text ( - ); - /*! - ensures - - causes all the text in the text field to become selected. - (note that it doesn't give input focus) - !*/ - - void set_text_color ( - const rgb_pixel color - ); - /*! - ensures - - #text_color() == color - !*/ - - const rgb_pixel text_color ( - ) const; - /*! - ensures - - returns the color used to draw the text in this widget - !*/ - - void set_background_color ( - const rgb_pixel color - ); - /*! - ensures - - #background_color() == color - !*/ - - const rgb_pixel background_color ( - ) const; - /*! - ensures - - returns the color used to fill in the background of this widget - !*/ - - template < - typename T - > - void set_text_modified_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the text - in this text_field is modified by the user. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_text_modified_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when the text in this text_field - is modified by the user. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_enter_key_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when this text field - has input focus and the user hits the enter key on their keyboard. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_enter_key_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when this text field has input - focus and the user hits the enter key on their keyboard. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_focus_lost_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when this object - loses input focus due to the user clicking outside the text field - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_focus_lost_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when this object loses input - focus due to the user clicking outside the text field - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - text_field(text_field&); // copy constructor - text_field& operator=(text_field&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class text_box -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class text_box : public scrollable_region - { - /*! - INITIAL VALUE - - text() == "" - - The text color will be black. - - width() == 100 - - height() == 100 - - WHAT THIS OBJECT REPRESENTS - This object represents a simple multi-line text input box. - !*/ - - public: - - text_box( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~text_box( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - template < - typename style_type - > - void set_style ( - const style_type& style - ); - /*! - requires - - style_type == a type that inherits from text_box_style - ensures - - this text_box object will draw itself using the given - text box style - !*/ - - void set_text (const std::wstring& text); - void set_text (const dlib::ustring& text); - void set_text ( - const std::string& text - ); - /*! - ensures - - #text() == text - throws - - std::bad_alloc - !*/ - - const std::wstring wtext () const; - const dlib::ustring utext () const; - const std::string text ( - ) const; - /*! - ensures - - returns the text of this text_box - throws - - std::bad_alloc - !*/ - - void set_size ( - unsigned long width, - unsigned long height - ); - /*! - ensures - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this widget stays the - same but its width and height are modified - !*/ - - void set_text_color ( - const rgb_pixel color - ); - /*! - ensures - - #text_color() == color - !*/ - - const rgb_pixel text_color ( - ) const; - /*! - ensures - - returns the color used to draw the text in this widget - !*/ - - void set_background_color ( - const rgb_pixel color - ); - /*! - ensures - - #background_color() == color - !*/ - - const rgb_pixel background_color ( - ) const; - /*! - ensures - - returns the color used to fill in the background of this widget - !*/ - - template < - typename T - > - void set_text_modified_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the text - in this text_box is modified by the user. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_text_modified_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when the text in this text_box - is modified by the user. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_enter_key_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when this text box - has input focus and the user hits the enter key on their keyboard. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_enter_key_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when this text box has input - focus and the user hits the enter key on their keyboard. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_focus_lost_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when this object - loses input focus due to the user clicking outside the text box - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_focus_lost_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when this object loses input - focus due to the user clicking outside the text box - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - text_box(text_box&); // copy constructor - text_box& operator=(text_box&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class check_box -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class check_box : public toggle_button - { - /*! - This is just a toggle button with the style set to - toggle_button_style_check_box. - !*/ - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class radio_button -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class radio_button : public toggle_button - { - /*! - This is just a toggle button with the style set to - toggle_button_style_radio_button. - !*/ - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class tabbed_display -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class tabbed_display : public drawable - { - /*! - INITIAL VALUE - number_of_tabs() == 1 - selected_tab() == 0 - - WHAT THIS OBJECT REPRESENTS - This object represents a row of tabs that are user selectable. - - When this object is disabled it means it will not respond to user clicks. - !*/ - - public: - - tabbed_display( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~tabbed_display( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_size ( - unsigned long width_, - unsigned long height_ - ); - /*! - ensures - - if (width and height are big enough to contain the tabs) then - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this widget stays the - same but its width and height are modified - !*/ - - void set_number_of_tabs ( - unsigned long num - ); - /*! - requires - - num > 0 - ensures - - #number_of_tabs() == num - - no tabs have any widget_groups associated with them. - - for all valid idx: - - #tab_name(idx) == "" - throws - - std::bad_alloc - !*/ - - unsigned long selected_tab ( - ) const; - /*! - ensures - - returns the index of the currently selected tab - !*/ - - unsigned long number_of_tabs ( - ) const; - /*! - ensures - - returns the number of tabs in this tabbed_display - !*/ - - const std::wstring& tab_wname (unsigned long idx) const; - const dlib::ustring& tab_uname (unsigned long idx) const; - const std::string& tab_name ( - unsigned long idx - ) const; - /*! - requires - - idx < number_of_tabs() - ensures - - returns a const reference to the name of the tab given by idx - !*/ - - void set_tab_name (unsigned long idx, const std::wstring& new_name); - void set_tab_name (unsigned long idx, const dlib::ustring& new_name); - void set_tab_name ( - unsigned long idx, - const std::string& new_name - ); - /*! - requires - - idx < number_of_tabs() - ensures - - #tab_name(idx) == new_name - throws - - std::bad_alloc - !*/ - - void set_tab_group ( - unsigned long idx, - widget_group& group - ); - /*! - requires - - idx < number_of_tabs() - ensures - - if (is_hidden()) then - - group.is_hidden() == true - - else - - whenever the tab with index idx is selected group.is_hidden() == false - - whenever the tab with index idx is deselected group.is_hidden() == true - - whenever the position of *this changes the position of group will be - updated so that it is still inside the tabbed_display. The position of group - will also be updated after this call to set_tab_group(). - - any previous calls to set_tab_group() with this index are overridden by this - new call. (i.e. you can only have one widget_group associated with a single - tab at a time) - !*/ - - void fit_to_contents ( - ); - /*! - ensures - - Adjusts the size this tabbed_display so that it nicely contains - all of its widget_group objects. - - does not change the position of this object. - (i.e. the upper left corner of get_rect() remains at the same position) - !*/ - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler)(unsigned long new_idx, unsigned long old_idx) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - The event_handler function is called on object when the user clicks - on a tab that isn't already selected. new_idx will give the index of - the newly selected tab and old_idx will give the index of the tab - that was previously selected. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_click_handler ( - const any_function<void(unsigned long new_idx, unsigned long old_idx)>& eh - ); - /*! - ensures - - The event_handler function is called when the user clicks on a tab - that isn't already selected. new_idx will give the index of the - newly selected tab and old_idx will give the index of the tab that - was previously selected. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - tabbed_display(tabbed_display&); // copy constructor - tabbed_display& operator=(tabbed_display&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class named_rectangle -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class named_rectangle : public drawable - { - /*! - INITIAL VALUE - name() == "" - - WHAT THIS OBJECT REPRESENTS - This object represents a simple named rectangle. - !*/ - - public: - - named_rectangle( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~named_rectangle( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_size ( - unsigned long width_, - unsigned long height_ - ); - /*! - ensures - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this widget stays the - same but its width and height are modified - !*/ - - void wrap_around ( - const rectangle& rect - ); - /*! - ensures - - This object will be repositioned and sized so that it fits - around the given rectangle. - !*/ - - void set_name (const std::wstring& name); - void set_name (const dlib::ustring& name); - void set_name ( - const std::string& name - ); - /*! - ensures - - #name() == name - throws - - std::bad_alloc - !*/ - - const std::wstring wname () const; - const dlib::ustring uname () const; - const std::string name ( - ) const; - /*! - ensures - - returns the name of this named_rectangle - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - named_rectangle(named_rectangle&); // copy constructor - named_rectangle& operator=(named_rectangle&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class mouse_tracker -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class mouse_tracker : public draggable - { - /*! - INITIAL VALUE - draggable_area() == rectangle(0,0,500,500) - - WHAT THIS OBJECT REPRESENTS - This object represents a simple draggable box that displays the - current location of the mouse. - - Also, if you hold shift and left click on the parent window then the - mouse_tracker will place a single red pixel where you clicked and will - display the mouse position relative to that point. - !*/ - - public: - - mouse_tracker( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~mouse_tracker( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - private: - - // restricted functions - mouse_tracker(mouse_tracker&); // copy constructor - mouse_tracker& operator=(mouse_tracker&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class list_box -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class list_box : public scrollable_region, - public enumerable<const std::string> - { - /*! - INITIAL VALUE - multiple_select_enabled() == false - size() == 0 - - ENUMERATION ORDER - The enumerator will iterate over the elements in the list_box from - the 0th element to the (size()-1)th element. i.e. (*this)[0] to - (*this)[size()-1]. - - WHAT THIS OBJECT REPRESENTS - This object represents a simple textual list box. It contains a - vertical list of strings which the user may select from. - !*/ - - public: - - list_box( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~list_box( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - template < - typename style_type - > - void set_style ( - const style_type& style - ); - /*! - requires - - style_type == a type that inherits from list_box_style - ensures - - this list_box object will draw itself using the given style - !*/ - - void set_size ( - unsigned long width_, - unsigned long height_ - ); - /*! - ensures - - #width() == width_ - - #height() == height_ - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this widget stays the - same but its width and height are modified - !*/ - - bool is_selected ( - unsigned long index - ) const; - /*! - requires - - index < size() - ensures - - if (the item given by index is currently selected) then - - returns true - - else - - returns false - !*/ - - void select ( - unsigned long index - ); - /*! - requires - - index < size() - ensures - - #is_selected(index) == true - !*/ - - void unselect ( - unsigned long index - ); - /*! - requires - - index < size() - ensures - - #is_selected(index) == false - !*/ - - template <typename T> - void get_selected ( - T& list - ) const; - /*! - requires - - T == an implementation of dlib/queue/queue_kernel_abstract.h - - T::type == unsigned long - ensures - - #list == a list of all the currently selected indices for this list_box. - !*/ - - unsigned long get_selected ( - ) const; - /*! - requires - - multiple_select_enabled() == false - ensures - - if (there is currently something selected) then - - returns the index of the selected item - - else - - returns size() - !*/ - - template <typename T> - void load ( - const T& list - ); - /*! - requires - - T == compatible with dlib::enumerable<std::string> - ensures - - #size() == list.size() - - Copies all the strings from list into *this in the order in which they are enumerated. - (i.e. The first one goes into (*this)[0], the second into (*this)[1], and so on...) - !*/ - - const std::string& operator[] ( - unsigned long index - ) const; - /*! - requires - - index < size() - ensures - - returns the name of the indexth item/row in this list box. - !*/ - - bool multiple_select_enabled ( - ) const; - /*! - ensures - - if (this object will allow the user to select more than one item at a time) then - - returns true - - else - - returns false - !*/ - - void enable_multiple_select ( - ); - /*! - ensures - - #multiple_select_enabled() == true - !*/ - - void disable_multiple_select ( - ); - /*! - ensures - - #multiple_select_enabled() == false - !*/ - - template < - typename T - > - void set_double_click_handler ( - T& object, - void (T::*event_handler)(unsigned long index) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T. - ensures - - The event_handler function is called on object when the user double - clicks on one of the rows in this list box. index gives the row - number for the item the user clicked. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_double_click_handler ( - const any_function<void(unsigned long index)>& event_handler - ); - /*! - ensures - - The event_handler function is called when the user double clicks on - one of the rows in this list box. index gives the row number for - the item the user clicked. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_click_handler ( - T& object, - void (T::*event_handler)(unsigned long index) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T. - ensures - - The event_handler function is called on object when the user - clicks on one of the rows in this list box. index gives the row - number for the item the user clicked. (Note that the second click - in a double click triggers the double click handler above instead - of this event) - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_click_handler ( - const any_function<void(unsigned long index)>& event_handler - ); - /*! - ensures - - The event_handler function is called when the user clicks on one - of the rows in this list box. index gives the row number for the - item the user clicked. (Note that the second click in a double - click triggers the double click handler above instead of this event) - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - list_box(list_box&); // copy constructor - list_box& operator=(list_box&); // assignment operator - }; - - class wlist_box : public scrollable_region, - public enumerable<const std::wstring>; - /*! - same as list_box except for std::wstring instead of std::string - !*/ - - class ulist_box : public scrollable_region, - public enumerable<const dlib::ustring>; - /*! - same as list_box except for dlib::ustring instead of std::string - !*/ - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - // class menu_bar -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class menu_bar : public drawable - { - /*! - INITIAL VALUE - - number_of_menus() == 0 - - WHAT THIS OBJECT REPRESENTS - This object represents a menu bar that appears at the top of a - window. - !*/ - - public: - - menu_bar( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~menu_bar( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_number_of_menus ( - unsigned long num - ); - /*! - ensures - - #number_of_menus() == num - !*/ - - unsigned long number_of_menus ( - ) const; - /*! - ensures - - returns the number of menus in this menu_bar - !*/ - - void set_menu_name (unsigned long idx, const std::wstring name, char underline_ch = '\0'); - void set_menu_name (unsigned long idx, const dlib::ustring name, char underline_ch = '\0'); - void set_menu_name ( - unsigned long idx, - const std::string name, - char underline_ch = '\0' - ); - /*! - requires - - idx < number_of_menus() - ensures - - #menu_name(idx) == name - - if (underline_ch is present in name) then - - The menu with index idx will have the first underline_ch character - in its name underlined and users will be able to activate the menu - by hitting alt+underline_char - !*/ - - const std::wstring menu_wname (unsigned long idx) const; - const dlib::ustring menu_uname (unsigned long idx) const; - const std::string menu_name ( - unsigned long idx - ) const; - /*! - requires - - idx < number_of_menus() - ensures - - returns the name of the menu with index idx - !*/ - - popup_menu& menu ( - unsigned long idx - ); - /*! - requires - - idx < number_of_menus() - ensures - - returns a non-const reference to the popup_menu for the menu with - index idx. - !*/ - - const popup_menu& menu ( - unsigned long idx - ) const; - /*! - requires - - idx < number_of_menus() - ensures - - returns a const reference to the popup_menu for the menu with - index idx. - !*/ - - private: - - // restricted functions - menu_bar(menu_bar&); // copy constructor - menu_bar& operator=(menu_bar&); // assignment operator - - }; - -// ---------------------------------------------------------------------------------------- - - template < - typename graph_type - > - class directed_graph_drawer : public zoomable_region - { - /*! - REQUIREMENTS ON graph_type - - must be an implementation of directed_graph/directed_graph_kernel_abstract.h - - INITIAL VALUE - - get_graph().size() == 0 - - WHAT THIS OBJECT REPRESENTS - This object represents a graphical widget that allows the user to draw - a directed graph. - - The user can create nodes by right clicking on the draw area and add - edges by selecting a node (via left clicking on it) and then holding - shift and clicking on the node that is to be the child node of the - selected node. - !*/ - - public: - - directed_graph_drawer ( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~directed_graph_drawer ( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - const graph_type& graph ( - ) const; - /*! - requires - - drawable::m is locked - ensures - - returns a const reference to the graph that this widget has been drawing - !*/ - - unsigned long number_of_nodes ( - ) const; - /*! - ensures - - returns graph().number_of_nodes() - !*/ - - void clear_graph ( - ); - /*! - ensures - - #number_of_nodes() == 0 - !*/ - - const typename graph_type::node_type& graph_node ( - unsigned long i - ) const; - /*! - requires - - drawable::m is locked - - i < number_of_nodes() - ensures - - returns a const reference to get_graph().node(i) - !*/ - - typename graph_type::node_type& graph_node ( - unsigned long i - ); - /*! - requires - - drawable::m is locked - - i < number_of_nodes() - ensures - - returns a non-const reference to get_graph().node(i) - !*/ - - void save_graph ( - std::ostream& out - ); - /*! - ensures - - saves the state of the graph to the output stream. Does so in a - way that not only preserves the state of the graph this->graph() - but also preserves the graphical layout of the graph in this - GUI widget. - - Also, the first part of the saved state is a serialized - version of this->graph(). Thus, you can deserialize just the - this->graph() object from the serialized data if you like. - !*/ - - void load_graph ( - std::istream& in - ); - /*! - ensures - - loads a saved graph from the given input stream. - !*/ - - void set_node_label (unsigned long i, const std::wstring& label); - void set_node_label (unsigned long i, const dlib::ustring& label); - void set_node_label ( - unsigned long i, - const std::string& label - ); - /*! - requires - - i < number_of_nodes() - ensures - - #node_label(i) == label - !*/ - - void set_node_color ( - unsigned long i, - rgb_pixel color - ); - /*! - requires - - i < number_of_nodes() - ensures - - #node_color(i) == color - !*/ - - rgb_pixel node_color ( - unsigned long i - ) const; - /*! - requires - - i < number_of_nodes() - ensures - - returns the color used to draw node graph_node(i) - !*/ - - const std::wstring node_wlabel (unsigned long i) const; - const dlib::ustring node_ulabel (unsigned long i) const; - const std::string node_label ( - unsigned long i - ) const; - /*! - requires - - i < number_of_nodes() - ensures - - returns the text label for node graph_node(i) - !*/ - - template < - typename T - > - void set_node_selected_handler ( - T& object, - void (T::*event_handler)(unsigned long node_index) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the user selects - a node. - - node_index == the index of the node that was selected - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_node_selected_handler ( - const any_function<void(unsigned long node_index)>& event_handler - ); - /*! - ensures - - the event_handler function is called when the user selects - a node. - - node_index == the index of the node that was selected - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_node_deselected_handler ( - T& object, - void (T::*event_handler)(unsigned long node_index) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the user - deselects a node. - - node_index == the index of the node that was deselected - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_node_deselected_handler ( - const any_function<void(unsigned long node_index)>& event_handler - ); - /*! - ensures - - the event_handler function is called when the user deselects a node. - - node_index == the index of the node that was deselected - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_node_deleted_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the user - deletes a node. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_node_deleted_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when the user deletes a node. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - template < - typename T - > - void set_graph_modified_handler ( - T& object, - void (T::*event_handler)() - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the user - modifies the graph (i.e. adds or removes a node or edge) - - the event_handler function is not called when the user just - moves nodes around on the screen. - - This event is always dispatched before any more specific event - that results from the user modifying the graph. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_graph_modified_handler ( - const any_function<void()>& event_handler - ); - /*! - ensures - - the event_handler function is called when the user modifies - the graph (i.e. adds or removes a node or edge) - - the event_handler function is not called when the user just - moves nodes around on the screen. - - This event is always dispatched before any more specific event - that results from the user modifying the graph. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - directed_graph_drawer(directed_graph_drawer&); // copy constructor - directed_graph_drawer& operator=(directed_graph_drawer&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - - class text_grid : public scrollable_region - { - /*! - INITIAL VALUE - - vertical_scroll_increment() == 10 - - horizontal_scroll_increment() == 10 - - border_color() == rgb_pixel(128,128,128) - - number_of_columns() == 0 - - number_of_rows() == 0 - - WHAT THIS OBJECT REPRESENTS - This object represents a simple grid of square text fields that - looks more or less like a spreadsheet grid. - !*/ - - public: - - text_grid ( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - throws - - std::bad_alloc - - dlib::thread_error - !*/ - - virtual ~text_grid ( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_grid_size ( - unsigned long rows, - unsigned long cols - ); - /*! - ensures - - #number_of_rows() == rows - - #number_of_columns() == cols - - for all valid r and c: - - #text(r,c) == "" - - #text_color(r,c) == rgb_pixel(0,0,0) - - #background_color(r,c) == rgb_pixel(255,255,255) - - #is_editable(r,c) == true - !*/ - - unsigned long number_of_columns ( - ) const; - /*! - ensures - - returns the number of columns contained in this grid - !*/ - - unsigned long number_of_rows ( - ) const; - /*! - ensures - - returns the number of rows contained in this grid - !*/ - - rgb_pixel border_color ( - ) const; - /*! - ensures - - returns the color of the lines drawn between the grid elements - !*/ - - void set_border_color ( - rgb_pixel color - ); - /*! - ensures - - #border_color() == color - !*/ - - const std::wstring wtext (unsigned long row, unsigned long col) const; - const dlib::ustring utext (unsigned long row, unsigned long col) const; - const std::string text ( - unsigned long row, - unsigned long col - ) const; - /*! - requires - - row < number_of_rows() - - col < number_of_columns() - ensures - - returns the text in the given grid location - !*/ - - void set_text (unsigned long row, unsigned long col, const std::wstring& str); - void set_text (unsigned long row, unsigned long col, const dlib::ustring& str); - void set_text ( - unsigned long row, - unsigned long col, - const std::string& str - ); - /*! - requires - - row < number_of_rows() - - col < number_of_columns() - ensures - - #text(row,col) == str - !*/ - - const rgb_pixel text_color ( - unsigned long row, - unsigned long col - ) const; - /*! - requires - - row < number_of_rows() - - col < number_of_columns() - ensures - - returns the color of the text in the given grid location - !*/ - - void set_text_color ( - unsigned long row, - unsigned long col, - const rgb_pixel color - ); - /*! - requires - - row < number_of_rows() - - col < number_of_columns() - ensures - - #text_color(row,col) == color - !*/ - - const rgb_pixel background_color ( - unsigned long row, - unsigned long col - ) const; - /*! - requires - - row < number_of_rows() - - col < number_of_columns() - ensures - - returns the background color of the given grid location - !*/ - - void set_background_color ( - unsigned long row, - unsigned long col, - const rgb_pixel color - ); - /*! - requires - - row < number_of_rows() - - col < number_of_columns() - ensures - - #background_color(row,col) == color - !*/ - - bool is_editable ( - unsigned long row, - unsigned long col - ) const; - /*! - requires - - row < number_of_rows() - - col < number_of_columns() - ensures - - if (the given grid location is editable by the user) then - - returns true - - else - - returns false - !*/ - - void set_editable ( - unsigned long row, - unsigned long col, - bool editable - ); - /*! - requires - - row < number_of_rows() - - col < number_of_columns() - ensures - - #is_editable(row,col) == editable - !*/ - - void set_column_width ( - unsigned long col, - unsigned long width - ); - /*! - requires - - col < number_of_columns() - ensures - - the given column will be displayed such that it is width pixels wide - !*/ - - void set_row_height ( - unsigned long row, - unsigned long height - ); - /*! - requires - - row < number_of_rows() - ensures - - the given row will be displayed such that it is height pixels wide - !*/ - - template < - typename T - > - void set_text_modified_handler ( - T& object, - void (T::*event_handler)(unsigned long row, unsigned long col) - ); - /*! - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the user selects - a node. - - row == row will give the row of the grid item that was modified - - col == col will give the column of the grid item that was modified - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - void set_text_modified_handler ( - const any_function<void(unsigned long row, unsigned long col)>& event_handler - ); - /*! - ensures - - the event_handler function is called when the user selects a node. - - row == row will give the row of the grid item that was modified - - col == col will give the column of the grid item that was modified - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - !*/ - - private: - - // restricted functions - text_grid(text_grid&); // copy constructor - text_grid& operator=(text_grid&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - - class image_display : public scrollable_region - { - /*! - INITIAL VALUE - - This object isn't displaying anything. - - get_overlay_rects().size() == 0 - - get_default_overlay_rect_label() == "" - - get_default_overlay_rect_color() == rgb_alpha_pixel(255,0,0,255) (i.e. RED) - - This object does not have any user labelable parts defined. - - overlay_editing_is_enabled() == true - - WHAT THIS OBJECT REPRESENTS - This object represents an image inside a scrollable region. - You give it an image to display by calling set_image(). - This widget also allows you to add rectangle and line overlays that - will be drawn on top of the image. - - If you hold the Ctrl key you can zoom in and out using the mouse wheel. - You can also add new overlay rectangles by holding shift, left clicking, - and dragging the mouse. Additionally, you can delete an overlay rectangle - by double clicking on it and hitting delete or backspace. Finally, you - can also add part labels (if they have been defined by calling add_labelable_part_name()) - by selecting an overlay rectangle with the mouse and then right clicking - on the part. If you want to move any rectangle or an object part then - shift+right click and drag it. - - Finally, if you hold Ctrl and left click an overlay rectangle it will - change its label to get_default_overlay_rect_label() and color to - get_default_overlay_rect_color(). - - The image is drawn such that: - - the pixel img[0][0] is the upper left corner of the image. - - the pixel img[img.nr()-1][0] is the lower left corner of the image. - - the pixel img[0][img.nc()-1] is the upper right corner of the image. - - the pixel img[img.nr()-1][img.nc()-1] is the lower right corner of the image. - !*/ - - public: - - image_display( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - !*/ - - ~image_display( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - template < - typename image_type - > - void set_image ( - const image_type& new_img - ); - /*! - requires - - image_type == an implementation of array2d/array2d_kernel_abstract.h or - a dlib::matrix or something convertible to a matrix via mat() - - pixel_traits<typename image_type::type> must be defined - ensures - - #*this widget is now displaying the given image new_img. - !*/ - - struct overlay_rect - { - /*! - WHAT THIS OBJECT REPRESENTS - This object represents a rectangle that is drawn on top of the - image shown by this object. Each rectangle is represented by - a rectangle object as well as a color and text label. The label - is drawn below the lower right corner of the rectangle. - - Moreover, the rectangle can have sub-parts. Each part is listed - in the parts member variable. This variable maps the name of the - part to its position. - - Rectangles with crossed_out == true will be drawn with an X through - them. - !*/ - - rectangle rect; - rgb_alpha_pixel color; - std::string label; - std::map<std::string,point> parts; - bool crossed_out; - - overlay_rect( - ); - /*! - ensures - - #color == rgb_alpha_pixel(0,0,0,0) - - #rect == rectangle() - - #label.size() == 0 - - #crossed_out == false - !*/ - - template <typename pixel_type> - overlay_rect( - const rectangle& r, - pixel_type p - ); - /*! - ensures - - #rect == r - - performs assign_pixel(color, p) - - #label.size() == 0 - - #crossed_out == false - !*/ - - template <typename pixel_type> - overlay_rect( - const rectangle& r, - pixel_type p, - const std::string& l - ); - /*! - ensures - - #rect == r - - performs assign_pixel(color, p) - - #label == l - - #crossed_out == false - !*/ - - template <typename pixel_type> - overlay_rect( - const rectangle& r, - pixel_type p, - const std::string& l, - const std::map<std::string,point>& parts_ - ); - /*! - ensures - - #rect == r - - performs assign_pixel(color, p) - - #label == l - - #parts == parts_ - - #crossed_out == false - !*/ - - }; - - struct overlay_line - { - /*! - WHAT THIS OBJECT REPRESENTS - This object represents a line that is drawn on top of the - image shown by this object. Each line is represented by - its two end points (p1 and p2) as well as a color. - !*/ - - point p1; - point p2; - rgb_alpha_pixel color; - - overlay_line( - ); - /*! - ensures - - #color == rgb_alpha_pixel(0,0,0,0) - - #p1 == point() - - #p2 == point() - !*/ - - template <typename pixel_type> - overlay_line( - const point& p1_, - const point& p2_, - pixel_type p - ); - /*! - ensures - - performs assign_pixel(color, p) - - #p1 == p1_ - - #p2 == p2_ - !*/ - - }; - - struct overlay_circle - { - /*! - WHAT THIS OBJECT REPRESENTS - This object represents a circle that is drawn on top of the - image shown by this object. Each circle is represented by - its center, radius, and color. It can also have an optional - text label which will appear below the circle. - !*/ - - point center; - int radius; - rgb_alpha_pixel color; - std::string label; - - overlay_circle( - ); - /*! - ensures - - #center == point(0,0) - - #radius == 0 - - #color == rgb_alpha_pixel(0,0,0,0) - - #label.size() == 0 - !*/ - - template <typename pixel_type> - overlay_circle( - const point& center_, - const int radius_, - pixel_type p - ); - /*! - ensures - - performs assign_pixel(color, p) - - #center == center_ - - #radius == radius_ - !*/ - - template <typename pixel_type> - overlay_circle( - const point& center_, - const int radius_, - pixel_type p, - const std::string& label_ - ); - /*! - ensures - - performs assign_pixel(color, p) - - #center == center_ - - #radius == radius_ - - #label == label_ - !*/ - - }; - - void add_overlay ( - const overlay_rect& overlay - ); - /*! - ensures - - adds the given overlay rectangle into this object such - that it will be displayed. - !*/ - - void add_overlay ( - const overlay_line& overlay - ); - /*! - ensures - - adds the given overlay line into this object such - that it will be displayed. - !*/ - - void add_overlay ( - const overlay_circle& overlay - ); - /*! - ensures - - adds the given overlay circle into this object such - that it will be displayed. - !*/ - - void add_overlay ( - const std::vector<overlay_rect>& overlay - ); - /*! - ensures - - adds the given set of overlay rectangles into this object such - that they will be displayed. - !*/ - - void add_overlay ( - const std::vector<overlay_line>& overlay - ); - /*! - ensures - - adds the given set of overlay lines into this object such - that they will be displayed. - !*/ - - void add_overlay ( - const std::vector<overlay_circle>& overlay - ); - /*! - ensures - - adds the given set of overlay circles into this object such - that they will be displayed. - !*/ - - void clear_overlay ( - ); - /*! - ensures - - removes all overlays from this object. - - #get_overlay_rects().size() == 0 - !*/ - - std::vector<overlay_rect> get_overlay_rects ( - ) const; - /*! - ensures - - returns a copy of all the overlay_rect objects currently displayed. - !*/ - - void set_default_overlay_rect_label ( - const std::string& label - ); - /*! - ensures - - #get_default_overlay_rect_label() == label - !*/ - - std::string get_default_overlay_rect_label ( - ) const; - /*! - ensures - - returns the label given to new overlay rectangles created by the user - (i.e. when the user holds shift and adds them with the mouse) - !*/ - - void set_default_overlay_rect_color ( - const rgb_alpha_pixel& color - ); - /*! - ensures - - #get_default_overlay_rect_color() == color - !*/ - - rgb_alpha_pixel get_default_overlay_rect_color ( - ) const; - /*! - ensures - - returns the color given to new overlay rectangles created by the user - (i.e. when the user holds shift and adds them with the mouse) - !*/ - - void add_labelable_part_name ( - const std::string& name - ); - /*! - ensures - - adds a user labelable part with the given name. If the name has - already been added then this function has no effect. - - These parts can be added by the user by selecting an overlay box - and then right clicking anywhere in it. A popup menu will appear - listing the parts. The user can then click a part name and it will - add it into the overlay_rect::parts variable and also show it on the - screen. - !*/ - - void clear_labelable_part_names ( - ); - /*! - ensures - - removes all use labelable parts. Calling this function undoes - all previous calls to add_labelable_part_name(). Therefore, the - user won't be able to label any parts after clear_labelable_part_names() - is called. - !*/ - - rectangle get_image_display_rect ( - ) const; - /*! - ensures - - returns a rectangle R that tells you how big the image inside the - display is when it appears on the screen. Note that it takes the - current zoom level into account. - - R.width() == the width of the displayed image - - R.height() == the height of the displayed image - - R.tl_corner() == (0,0) - !*/ - - void enable_overlay_editing ( - ); - /*! - ensures - - #overlay_editing_is_enabled() == true - !*/ - - void disable_overlay_editing ( - ); - /*! - ensures - - #overlay_editing_is_enabled() == false - !*/ - - bool overlay_editing_is_enabled ( - ) const; - /*! - ensures - - if this function returns true then it is possible for the user to add or - remove overlay objects (e.g. rectangles) using the mouse and keyboard. - If it returns false then the overlay is not user editable. - !*/ - - template < - typename T - > - void set_overlay_rects_changed_handler ( - T& object, - void (T::*event_handler)() - ); - /* - requires - - event_handler is a valid pointer to a member function in T - ensures - - the event_handler function is called on object when the user adds, - removes, or modifies an overlay rectangle. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - */ - - void set_overlay_rects_changed_handler ( - const any_function<void()>& event_handler - ); - /* - ensures - - the event_handler function is called when the user adds or removes - an overlay rectangle. - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - */ - - template < - typename T - > - void set_overlay_rect_selected_handler ( - T& object, - void (T::*event_handler)(const overlay_rect& orect) - ); - /* - requires - - event_handler is a valid pointer to a member function in T - ensures - - The event_handler function is called on object when the user selects - an overlay rectangle by double clicking on it. The selected rectangle - will be passed to event_handler(). - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - */ - - void set_overlay_rect_selected_handler ( - const any_function<void(const overlay_rect& orect)>& event_handler - ); - /* - ensures - - The event_handler function is called when the user selects an overlay - rectangle by double clicking on it. The selected rectangle will be - passed to event_handler(). - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - */ - - template < - typename T - > - void set_image_clicked_handler ( - T& object, - void (T::*event_handler)(const point& p, bool is_double_click, unsigned long btn) - ); - /* - requires - - event_handler is a valid pointer to a member function in T - ensures - - The event_handler function is called on object when the user left clicks - anywhere on the image. When they do so this callback is called with the - location of the image pixel which was clicked. The is_double_click bool - will also tell you if it was a double click or single click. - - btn == the button that was released. (either base_window::LEFT, base_window::MIDDLE, or base_window::RIGHT) - - any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - throws - - std::bad_alloc - */ - - void set_image_clicked_handler ( - const any_function<void(const point& p, bool is_double_click, unsigned long btn)>& event_handler - ); - /* - ensures - - The event_handler function is called when the user left clicks anywhere - on the image. When they do so this callback is called with the location - of the image pixel which was clicked. The is_double_click bool will also - tell you if it was a double click or single click. - - btn == the button that was released. (either base_window::LEFT, base_window::MIDDLE, or base_window::RIGHT) - - Any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this event at a - time) - throws - - std::bad_alloc - */ - - private: - - // restricted functions - image_display(image_display&); // copy constructor - image_display& operator=(image_display&); // assignment operator - }; - -// ---------------------------------------------------------------------------------------- - - class image_window : public drawable_window - { - /*! - INITIAL VALUE - - initially, this object is visible on the screen - - events_tied() == false - - WHAT THIS OBJECT REPRESENTS - This is a simple window that is just a container for an image_display. - It exists to make it easy to throw image_displays onto the screen - without having to put together your own drawable_window objects. - !*/ - public: - - typedef image_display::overlay_rect overlay_rect; - typedef image_display::overlay_line overlay_line; - typedef image_display::overlay_circle overlay_circle; - - image_window( - ); - /*! - ensures - - this object is properly initialized - !*/ - - template <typename image_type> - image_window( - const image_type& img - ); - /*! - requires - - image_type == an implementation of array2d/array2d_kernel_abstract.h or - a dlib::matrix or something convertible to a matrix via mat() - - pixel_traits<typename image_type::type> must be defined - ensures - - this object is properly initialized - - #*this window is now displaying the given image img. - !*/ - - template < typename image_type> - image_window( - const image_type& img, - const std::string& title - ); - /*! - requires - - image_type == an implementation of array2d/array2d_kernel_abstract.h or - a dlib::matrix or something convertible to a matrix via mat() - - pixel_traits<typename image_type::type> must be defined - ensures - - this object is properly initialized - - #*this window is now displaying the given image img. - - The title of the window will be set to the given title string. - !*/ - - ~image_window( - ); - /*! - ensures - - any resources associated with this object have been released - !*/ - - template <typename image_type> - void set_image ( - const image_type& img - ); - /*! - requires - - image_type == an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits<typename image_type::type> must be defined - ensures - - #*this window is now displaying the given image img. - !*/ - - void add_overlay ( - const overlay_rect& overlay - ); - /*! - ensures - - adds the given overlay rectangle into this object such - that it will be displayed. - !*/ - - template <typename pixel_type> - void add_overlay( - const rectangle& r, - pixel_type p = rgb_pixel(255,0,0) - ); - /*! - ensures - - performs: add_overlay(overlay_rect(r,p)); - !*/ - - template <typename pixel_type> - void add_overlay( - const rectangle& r, - pixel_type p, - const std::string& l - ); - /*! - ensures - - performs: add_overlay(overlay_rect(r,p,l)); - !*/ - - template <typename pixel_type> - void add_overlay( - const std::vector<rectangle>& r, - pixel_type p = rgb_pixel(255,0,0) - ); - /*! - ensures - - adds the given set of rectangles into this object such - that they will be displayed with the color specific by p. - !*/ - - void add_overlay( - const full_object_detection& object, - const std::vector<std::string>& part_names - ); - /*! - ensures - - adds the given full_object_detection to the overlays - and shows it on the screen. This includes any of its - parts that are not set equal to OBJECT_PART_NOT_PRESENT. - - for all valid i < part_names.size(): - - the part object.part(i) will be labeled with the string - part_names[i]. - !*/ - - void add_overlay( - const full_object_detection& object - ); - /*! - ensures - - adds the given full_object_detection to the overlays - and shows it on the screen. This includes any of its - parts that are not set equal to OBJECT_PART_NOT_PRESENT. - !*/ - - void add_overlay( - const std::vector<full_object_detection>& objects, - const std::vector<std::string>& part_names - ); - /*! - ensures - - calling this function is equivalent to calling the following - sequence of functions, for all valid i: - - add_overlay(objects[i], part_names); - !*/ - - void add_overlay( - const std::vector<full_object_detection>& objects - ); - /*! - ensures - - calling this function is equivalent to calling the following - sequence of functions, for all valid i: - - add_overlay(objects[i]); - !*/ - - void add_overlay ( - const overlay_line& overlay - ); - /*! - ensures - - adds the given overlay line into this object such - that it will be displayed. - !*/ - - void add_overlay ( - const overlay_circle& overlay - ); - /*! - ensures - - adds the given overlay circle into this object such - that it will be displayed. - !*/ - - template <typename pixel_type> - void add_overlay( - const point& p1, - const point& p2, - pixel_type p - ); - /*! - ensures - - performs: add_overlay(overlay_line(p1,p2,p)); - !*/ - - void add_overlay ( - const std::vector<overlay_rect>& overlay - ); - /*! - ensures - - adds the given set of overlay rectangles into this object such - that they will be displayed. - !*/ - - void add_overlay ( - const std::vector<overlay_line>& overlay - ); - /*! - ensures - - adds the given set of overlay lines into this object such - that they will be displayed. - !*/ - - void add_overlay ( - const std::vector<overlay_circle>& overlay - ); - /*! - ensures - - adds the given set of overlay circles into this object such - that they will be displayed. - !*/ - - void clear_overlay ( - ); - /*! - ensures - - removes all overlays from this object. - !*/ - - void tie_events ( - ); - /*! - ensures - - #events_tied() == true - !*/ - - void untie_events ( - ); - /*! - ensures - - #events_tied() == false - !*/ - - bool events_tied ( - ) const; - /*! - ensures - - returns true if and only if the get_next_double_click() and - get_next_keypress() events are tied together. If they are tied it means - that you can use a loop of the following form to listen for both events - simultaneously: - while (mywindow.get_next_double_click(p) || mywindow.get_next_keypress(key,printable)) - { - if (p.x() < 0) - // Do something with the keyboard event - else - // Do something with the mouse event - } - !*/ - - bool get_next_double_click ( - point& p - ); - /*! - ensures - - This function blocks until the user double clicks on the image or the - window is closed by the user. It will also unblock for a keyboard key - press if events_tied() == true. - - if (this function returns true) then - - This means the user double clicked the mouse. - - #p == the next image pixel the user clicked. - - else - - #p == point(-1,1) - !*/ - - bool get_next_double_click ( - point& p, - unsigned long& mouse_button - ); - /*! - ensures - - This function blocks until the user double clicks on the image or the - window is closed by the user. It will also unblock for a keyboard key - press if events_tied() == true. - - if (this function returns true) then - - This means the user double clicked the mouse. - - #p == the next image pixel the user clicked. - - #mouse_button == the mouse button which was used to double click. - This will be either dlib::base_window::LEFT, - dlib::base_window::MIDDLE, or dlib::base_window::RIGHT - - else - - #p == point(-1,1) - (Note that this point is outside any possible image) - !*/ - - bool get_next_keypress ( - unsigned long& key, - bool& is_printable, - unsigned long& state - ); - /*! - ensures - - This function blocks until the user presses a keyboard key or the - window is closed by the user. It will also unblock for a mouse double - click if events_tied() == true. - - if (this function returns true) then - - This means the user pressed a keyboard key. - - The keyboard button press is recorded into #key, #is_printable, and - #state. In particular, these variables are populated with the three - identically named arguments to the base_window::on_keydown(key,is_printable,state) - event. - !*/ - - bool get_next_keypress ( - unsigned long& key, - bool& is_printable - ); - /*! - ensures - - This function blocks until the user presses a keyboard key or the - window is closed by the user. It will also unblock for a mouse double - click if events_tied() == true. - - This function is the equivalent to calling get_next_keypress(key,is_printable,temp) - and then discarding temp. - !*/ - - private: - - // restricted functions - image_window(image_window&); - image_window& operator= (image_window&); - }; - -// ---------------------------------------------------------------------------------------- - - class perspective_display : public drawable, noncopyable - { - /*! - WHAT THIS OBJECT REPRESENTS - This object is a tool for displaying 3D point clouds on a screen. You can - navigate the display with the mouse. Left click and drag rotates the - camera around the displayed data. Scrolling the mouse wheel zooms and - shift+left click (or just right click) and drag pans the view around. - !*/ - - public: - - perspective_display( - drawable_window& w - ); - /*! - ensures - - #*this is properly initialized - - #*this has been added to window w - - #parent_window() == w - !*/ - - ~perspective_display( - ); - /*! - ensures - - all resources associated with *this have been released - !*/ - - void set_size ( - unsigned long width, - unsigned long height - ); - /*! - ensures - - #width() == width - - #height() == height - - #top() == top() - - #left() == left() - - i.e. The location of the upper left corner of this widget stays the - same but its width and height are modified. - !*/ - - struct overlay_line - { - /*! - WHAT THIS OBJECT REPRESENTS - This object represents a line that is drawn on the screen. Each line - is represented by its two end points (p1 and p2) as well as a color. - !*/ - - overlay_line() { assign_pixel(color, 0);} - - overlay_line(const vector<double>& p1_, const vector<double>& p2_) - : p1(p1_), p2(p2_) { assign_pixel(color, 255); } - - template <typename pixel_type> - overlay_line(const vector<double>& p1_, const vector<double>& p2_, pixel_type p) - : p1(p1_), p2(p2_) { assign_pixel(color, p); } - - vector<double> p1; - vector<double> p2; - rgb_pixel color; - }; - - struct overlay_dot - { - /*! - WHAT THIS OBJECT REPRESENTS - This object represents a dot that is drawn on the screen. Each dot is - represented by one point and a color. - !*/ - - overlay_dot() { assign_pixel(color, 0);} - - overlay_dot(const vector<double>& p_) - : p(p_) { assign_pixel(color, 255); } - - template <typename pixel_type> - overlay_dot(const vector<double>& p_, pixel_type color_) - : p(p_) { assign_pixel(color, color_); } - - vector<double> p; // The location of the dot - rgb_pixel color; - }; - - void add_overlay ( - const std::vector<overlay_line>& overlay - ); - /*! - ensures - - Adds the given overlay lines into this object such that it will be - displayed. - !*/ - - void add_overlay ( - const std::vector<overlay_dot>& overlay - ); - /*! - ensures - - Adds the given overlay dots into this object such that it will be - displayed. - !*/ - - void clear_overlay ( - ); - /*! - ensures - - Removes all overlays from this object. The display will be empty. - !*/ - - template <typename T> - void set_dot_double_clicked_handler ( - T& object, - void (T::*event_handler)(const vector<double>&) - ); - /* - requires - - event_handler is a valid pointer to a member function in T - ensures - - The event_handler function is called on object when the user double - clicks on one of the overlay dots. The selected dot will be passed to - event_handler(). - - Any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - */ - - void set_dot_double_clicked_handler ( - const any_function<void(const vector<double>&)>& event_handler - ); - /* - ensures - - The event_handler function is called when the user double clicks on one - of the overlay dots. The selected dot will be passed to event_handler(). - - Any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - */ - }; - -// ---------------------------------------------------------------------------------------- - - class perspective_window : public drawable_window, noncopyable - { - /*! - WHAT THIS OBJECT REPRESENTS - This is a simple window that is just a container for a perspective_display. - It exists to make it easy to throw perspective_displays onto the screen - without having to put together your own drawable_window objects. - !*/ - public: - - typedef perspective_display::overlay_line overlay_line; - typedef perspective_display::overlay_dot overlay_dot; - - perspective_window( - ); - /*! - ensures - - The window is displayed on the screen and is 100x100 pixels in size. - !*/ - - perspective_window( - const std::vector<dlib::vector<double> >& point_cloud - ); - /*! - ensures - - The window is displayed on the screen and is 100x100 pixels in size. - - This window will have point_cloud added to it via add_overlay() and the - points will all be white. - !*/ - - perspective_window( - const std::vector<dlib::vector<double> >& point_cloud, - const std::string& title - ); - /*! - ensures - - The window is displayed on the screen and is 100x100 pixels in size. - - This window will have point_cloud added to it via add_overlay() and the - points will all be white. - - The title of the window will be set to the given title string. - !*/ - - ~perspective_window( - ); - /*! - ensures - - any resources associated with this object have been released - !*/ - - void add_overlay ( - const std::vector<overlay_line>& overlay - ); - /*! - ensures - - Adds the given overlay lines into this object such that it will be - displayed. - !*/ - - void add_overlay ( - const std::vector<overlay_dot>& overlay - ); - /*! - ensures - - Adds the given overlay dots into this object such that it will be - displayed. - !*/ - - void clear_overlay ( - ); - /*! - ensures - - Removes all overlays from this object. The display will be empty. - !*/ - - void add_overlay( - const std::vector<dlib::vector<double> >& d - ); - /*! - ensures - - Adds the given dots into this object such that it will be - displayed. They will be colored white. - !*/ - - template <typename pixel_type> - void add_overlay( - const std::vector<dlib::vector<double> >& d, - pixel_type p - ); - /*! - ensures - - Adds the given dots into this object such that it will be - displayed. They will be colored by pixel color p. - !*/ - - template <typename pixel_type> - void add_overlay( - const vector<double>& p1, - const vector<double>& p2, - pixel_type color - ); - /*! - ensures - - Adds an overlay line going from p1 to p2 with the given color. - !*/ - - template < typename T > - void set_dot_double_clicked_handler ( - T& object, - void (T::*event_handler)(const vector<double>&) - ); - /* - requires - - event_handler is a valid pointer to a member function in T - ensures - - The event_handler function is called on object when the user double - clicks on one of the overlay dots. The selected dot will be passed to - event_handler(). - - Any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - */ - - void set_dot_double_clicked_handler ( - const any_function<void(const vector<double>&)>& event_handler - ); - /* - ensures - - The event_handler function is called when the user double clicks on one - of the overlay dots. The selected dot will be passed to event_handler(). - - Any previous calls to this function are overridden by this new call. - (i.e. you can only have one event handler associated with this - event at a time) - */ - - }; - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_WIDGETs_ABSTRACT_ - |