From cab98cc10e96c137cdc660c3004b642c13fe81d7 Mon Sep 17 00:00:00 2001 From: Davis King Date: Mon, 7 Jan 2013 21:17:44 -0500 Subject: [PATCH] Added some features to the image display widgets to let the user easily get information about where the user is clicking. --- dlib/gui_widgets/widgets.cpp | 71 +++++++++++++++++++++++++++- dlib/gui_widgets/widgets.h | 72 ++++++++++++++++++++++++++++- dlib/gui_widgets/widgets_abstract.h | 65 ++++++++++++++++++++++++++ 3 files changed, 206 insertions(+), 2 deletions(-) diff --git a/dlib/gui_widgets/widgets.cpp b/dlib/gui_widgets/widgets.cpp index 6385f9ea0..769912d55 100644 --- a/dlib/gui_widgets/widgets.cpp +++ b/dlib/gui_widgets/widgets.cpp @@ -6085,6 +6085,20 @@ namespace dlib 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/(double)zoom_in_scale; + else if (zoom_out_scale != 1) + p = p*(double)zoom_out_scale; + + if (dlib::get_rect(img).contains(p)) + image_clicked_handler(p, is_double_click); + } + if (btn == base_window::RIGHT && rect_is_selected) { last_right_click_pos = point(x,y); @@ -6433,8 +6447,13 @@ namespace dlib image_window:: image_window( ) : - gui_img(*this) + gui_img(*this), + window_has_closed(false), + have_last_click(false), + clicked_signaler(this->wm) { + + gui_img.set_image_clicked_handler(*this, &image_window::on_image_clicked); // show this window on the screen show(); } @@ -6451,6 +6470,56 @@ namespace dlib 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_double_click ( + point& p + ) + { + auto_mutex lock(wm); + while (have_last_click == false && !window_has_closed) + { + clicked_signaler.wait(); + } + + if (window_has_closed) + return false; + + // Mark that we are taking the point click so the next call to get_next_click() + // will have to wait for another click. + have_last_click = false; + p = last_clicked_point; + return true; + } + +// ---------------------------------------------------------------------------------------- + + void image_window:: + on_image_clicked ( + const point& p, + bool is_double_click + ) + { + if (is_double_click) + { + have_last_click = true; + last_clicked_point = p; + clicked_signaler.signal(); + } + } + // ---------------------------------------------------------------------------------------- void image_window:: diff --git a/dlib/gui_widgets/widgets.h b/dlib/gui_widgets/widgets.h index d042121f9..ea70dcf6e 100644 --- a/dlib/gui_widgets/widgets.h +++ b/dlib/gui_widgets/widgets.h @@ -3430,6 +3430,26 @@ namespace dlib 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) + ) + { + auto_mutex M(m); + image_clicked_handler = make_mfp(object,event_handler_); + } + + void set_image_clicked_handler ( + const any_function& event_handler_ + ) + { + auto_mutex M(m); + image_clicked_handler = event_handler_; + } + void add_labelable_part_name ( const std::string& name ); @@ -3512,6 +3532,7 @@ namespace dlib std::string default_rect_label; any_function event_handler; any_function orect_selected_event_handler; + any_function image_clicked_handler; popup_menu_region parts_menu; point last_right_click_pos; const int part_width; @@ -3538,7 +3559,33 @@ namespace dlib template < typename image_type > image_window( const image_type& img - ) : gui_img(*this) { set_image(img); show(); } + ) : + gui_img(*this), + window_has_closed(false), + have_last_click(false), + clicked_signaler(this->wm) + { + gui_img.set_image_clicked_handler(*this, &image_window::on_image_clicked); + 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), + clicked_signaler(this->wm) + { + gui_img.set_image_clicked_handler(*this, &image_window::on_image_clicked); + set_image(img); + set_title(title); + show(); + } + ~image_window( ); @@ -3688,10 +3735,29 @@ namespace dlib void clear_overlay ( ); + 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. + - if (this function returns true) then + - #p == the next place the user clicked + !*/ + 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 + ); // restricted functions image_window(image_window&); @@ -3699,6 +3765,10 @@ namespace dlib image_display gui_img; rectangle image_rect; + bool window_has_closed; + bool have_last_click; + point last_clicked_point; + rsignaler clicked_signaler; }; // ---------------------------------------------------------------------------------------- diff --git a/dlib/gui_widgets/widgets_abstract.h b/dlib/gui_widgets/widgets_abstract.h index 31cff2db0..02ad349d3 100644 --- a/dlib/gui_widgets/widgets_abstract.h +++ b/dlib/gui_widgets/widgets_abstract.h @@ -2750,6 +2750,44 @@ namespace dlib - std::bad_alloc */ + template < + typename T + > + void set_image_clicked_handler ( + T& object, + void (T::*event_handler)(const point& p, bool is_double_click) + ); + /* + 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 + 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. + - 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& event_handler + ); + /* + ensures + - The event_handler function is called when the user 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. + - 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 @@ -2797,6 +2835,22 @@ namespace dlib - #*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 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( ); /*! @@ -2965,6 +3019,17 @@ namespace dlib - removes all overlays from this object. !*/ + 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. + - if (this function returns true) then + - #p == the next image pixel the user clicked. + !*/ + private: // restricted functions