|
|
|
|
|
|
|
#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" |
|
#include "../geometry/line.h" |
|
|
|
#ifdef _MSC_VER |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma warning(disable : 4355) |
|
#endif |
|
|
|
namespace dlib |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_; |
|
|
|
|
|
|
|
label(label&); |
|
label& operator=(label&); |
|
|
|
protected: |
|
|
|
void draw ( |
|
const canvas& c |
|
) const; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class toggle_button : public button_action |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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: |
|
|
|
|
|
toggle_button(toggle_button&); |
|
toggle_button& operator=(toggle_button&); |
|
|
|
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 : public drawable |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_)); |
|
|
|
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 |
|
) |
|
{ |
|
|
|
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()); } |
|
|
|
|
|
|
|
|
|
|
|
void move_cursor ( |
|
unsigned long pos |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rectangle get_text_rect ( |
|
) const; |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
text_field(text_field&); |
|
text_field& operator=(text_field&); |
|
|
|
|
|
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 : public scrollable_region |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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()); |
|
|
|
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 |
|
) |
|
{ |
|
|
|
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; |
|
} |
|
} |
|
|
|
|
|
|
|
void timer_action ( |
|
) { parent.trigger_user_event(this,scrollable_region::next_free_user_event_number()); } |
|
|
|
|
|
|
|
|
|
|
|
void move_cursor ( |
|
unsigned long pos |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rectangle get_text_rect ( |
|
) const; |
|
|
|
|
|
|
|
|
|
|
|
void adjust_total_rect ( |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
text_box(text_box&); |
|
text_box& operator=(text_box&); |
|
|
|
|
|
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 : public toggle_button |
|
{ |
|
public: |
|
check_box( |
|
drawable_window& w |
|
) : toggle_button(w) |
|
{ |
|
set_style(toggle_button_style_check_box()); |
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 : public drawable |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 ( |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
void draw_tab ( |
|
const rectangle& tab, |
|
const canvas& c |
|
) const; |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
tabbed_display(tabbed_display&); |
|
tabbed_display& operator=(tabbed_display&); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class named_rectangle : public drawable |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
named_rectangle(named_rectangle&); |
|
named_rectangle& operator=(named_rectangle&); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
mouse_tracker(mouse_tracker&); |
|
mouse_tracker& operator=(mouse_tracker&); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace list_box_helper{ |
|
template <typename S = std::string> |
|
class list_box : public scrollable_region, |
|
public enumerable<const S> |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
list_box(list_box&); |
|
list_box& operator=(list_box&); |
|
}; |
|
} |
|
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; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 : public drawable |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
menu_bar( |
|
drawable_window& w |
|
); |
|
|
|
~menu_bar(); |
|
|
|
|
|
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; |
|
|
|
|
|
menu_bar(menu_bar&); |
|
menu_bar& operator=(menu_bar&); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename graph_type> |
|
class directed_graph_drawer : public zoomable_region |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
|
|
enable_events(); |
|
} |
|
|
|
~directed_graph_drawer ( |
|
) |
|
{ |
|
|
|
|
|
|
|
disable_events(); |
|
|
|
|
|
|
|
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 |
|
) |
|
{ |
|
|
|
|
|
if (last_mouse_click_in_display == false) |
|
return; |
|
|
|
|
|
if (selected_node != graph_.number_of_nodes()) |
|
{ |
|
|
|
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(); |
|
} |
|
|
|
|
|
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 (edge_selected) |
|
{ |
|
|
|
if (key == base_window::KEY_ESC) |
|
{ |
|
parent.invalidate_rectangle(display_rect()); |
|
edge_selected = false; |
|
} |
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
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 ) |
|
{ |
|
|
|
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))); |
|
|
|
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); |
|
|
|
|
|
|
|
if (selected_node != i) |
|
{ |
|
|
|
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 (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; |
|
} |
|
|
|
|
|
|
|
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 (area.contains(point(x,y))) |
|
{ |
|
p = point(x,y); |
|
const dlib::vector<double> z(0,0,1); |
|
|
|
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 (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()) |
|
{ |
|
|
|
zoomable_region::on_mouse_down( btn, state, x, y, is_double_click); |
|
} |
|
} |
|
|
|
|
|
|
|
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))); |
|
|
|
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) |
|
{ |
|
|
|
|
|
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; |
|
|
|
|
|
|
|
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))); |
|
|
|
|
|
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 (edge_selected && selected_edge_child == i && selected_edge_parent == graph_.node(i).parent(j).index()) |
|
{ |
|
color.red = 255; |
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
|
|
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); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
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))); |
|
|
|
|
|
if (area.intersect(circle_area).is_empty()==false) |
|
{ |
|
rgb_alpha_pixel color; |
|
assign_pixel(color, graph_.node(i).data.color); |
|
|
|
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); |
|
} |
|
|
|
|
|
|
|
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; |
|
|
|
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); |
|
|
|
|
|
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; |
|
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; |
|
|
|
typename graph_type::template rebind<data,char, typename graph_type::mem_manager_type>::other graph_; |
|
|
|
bool last_mouse_click_in_display; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class text_grid : public scrollable_region |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 ( |
|
); |
|
|
|
|
|
|
|
|
|
|
|
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 |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 (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 dpoint& p1_, const dpoint& p2_, pixel_type p) |
|
: p1(p1_), p2(p2_) { assign_pixel(color, p); } |
|
|
|
dpoint p1; |
|
dpoint 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 double radius_, pixel_type p) |
|
: center(center_), radius(radius_) { assign_pixel(color, p); } |
|
|
|
template <typename pixel_type> |
|
overlay_circle(const point& center_, const double radius_, pixel_type p, const std::string& l) |
|
: center(center_), radius(radius_), label(l) { assign_pixel(color, p); } |
|
|
|
point center; |
|
double 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; } |
|
|
|
void zoom_in ( |
|
); |
|
|
|
void zoom_out ( |
|
); |
|
|
|
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; } |
|
|
|
|
|
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) |
|
{ |
|
|
|
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; |
|
|
|
|
|
image_display(image_display&); |
|
image_display& operator=(image_display&); |
|
}; |
|
|
|
|
|
|
|
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( |
|
) |
|
{ |
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
if (previous_image_size != get_rect(img)) |
|
{ |
|
const rectangle r = gui_img.get_image_display_rect(); |
|
if (image_rect != r) |
|
{ |
|
|
|
set_size(r.width()+padding*2,r.height()+padding*2); |
|
|
|
|
|
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 |
|
); |
|
|
|
template <typename pixel_type> |
|
void add_overlay(const line& l, pixel_type p) |
|
{ |
|
add_overlay(image_display::overlay_line(l.p1(),l.p2(),p)); |
|
} |
|
|
|
void add_overlay(const line& l) |
|
{ |
|
add_overlay(l, rgb_pixel(255,0,0)); |
|
} |
|
|
|
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 |
|
); |
|
|
|
|
|
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 |
|
|
|
|