diff -r 7cc35bc348cc src/DLD-FUNCTIONS/fltk_backend.cc --- a/src/DLD-FUNCTIONS/fltk_backend.cc Sun Jun 28 08:51:41 2009 +0100 +++ b/src/DLD-FUNCTIONS/fltk_backend.cc Tue Jun 30 22:02:28 2009 +0200 @@ -180,6 +180,17 @@ } }; +inline +double force_in_range (const double x, const double lower, const double upper) +{ + if (x < lower) + { return lower; } + else if (x > upper) + { return upper; } + else + { return x; } +} + class plot_window : public Fl_Window { public: @@ -442,63 +453,114 @@ pixel2status (px0, py0, Fl::event_x (), Fl::event_y ()); if (Fl::event_button () == 1) { - canvas->zoom (true); - Matrix zoom_box (1,4,0); - zoom_box (0) = px0; - zoom_box (1) = py0; - zoom_box (2) = Fl::event_x (); - zoom_box (3) = Fl::event_y (); - canvas->set_zoom_box (zoom_box); - canvas->redraw_overlay (); + graphics_object ax = gh_manager::get_object (fp.get_currentaxes ()); + if (ax && ax.isa ("axes")) + { + axes::properties& ap = dynamic_cast (ax.get_properties ()); + + // Get current axes limits (FIXME: Handle 3D) + // FIXME: Do we need error checking here? + Matrix xlim = ap.get_xlim ().matrix_value (); + Matrix ylim = ap.get_ylim ().matrix_value (); + + // Get children axes limits + Matrix kids = ap.get_children (); + double minx = octave_Inf; + double maxx = -octave_Inf; + double min_pos_x = octave_Inf; + get_children_limits (minx, maxx, min_pos_x, kids, 'x'); + + double miny = octave_Inf; + double maxy = -octave_Inf; + double min_pos_y = octave_Inf; + get_children_limits (miny, maxy, min_pos_y, kids, 'y'); + + double x0, y0, x1, y1; + pixel2pos (px0, py0, x0, y0); + pixel2pos (Fl::event_x (), Fl::event_y (), x1, y1); + px0 = Fl::event_x (); + py0 = Fl::event_y (); + + double delta_x = x0 - x1; + if (delta_x > 0) + delta_x = std::min (xlim (1) + delta_x, maxx) - xlim (1); + else + delta_x = std::max (xlim (0) + delta_x, minx) - xlim (0); + xlim (0) = xlim (0) + delta_x; + xlim (1) = xlim (1) + delta_x; + + double delta_y = y0 - y1; + if (delta_y > 0) + delta_y = std::min (ylim (1) + delta_y, maxy) - ylim (1); + else + delta_y = std::max (ylim (0) + delta_y, miny) - ylim (0); + ylim (0) = ylim (0) + delta_y; + ylim (1) = ylim (1) + delta_y; + + ap.zoom (xlim, ylim); + mark_modified (); + } return 1; } break; + case FL_MOUSEWHEEL: + { + // Parameter controlling how fast we zoom. FIXME: Should this be user tweakable? + const double zoom_speed = 0.05; + + graphics_object ax = gh_manager::get_object (fp.get_currentaxes ()); + if (ax && ax.isa ("axes")) + { + axes::properties& ap = dynamic_cast (ax.get_properties ()); + + // Get current axes limits (FIXME: Handle 3D) + // FIXME: Do we need error checking here? + Matrix xlim = ap.get_xlim ().matrix_value (); + Matrix ylim = ap.get_ylim ().matrix_value (); + + // Get children axes limits + Matrix kids = ap.get_children (); + double minx = octave_Inf; + double maxx = -octave_Inf; + double min_pos_x = octave_Inf; + get_children_limits (minx, maxx, min_pos_x, kids, 'x'); + + double miny = octave_Inf; + double maxy = -octave_Inf; + double min_pos_y = octave_Inf; + get_children_limits (miny, maxy, min_pos_y, kids, 'y'); + + // Determine if we're zooming in or out + const double alpha = (Fl::event_dy () > 0) ? 1.0 + zoom_speed : 1.0 - zoom_speed; + + // Get the point we're zooming about + double x1, y1; + pixel2pos (Fl::event_x (), Fl::event_y (), x1, y1); + + // Perform the zooming + xlim (0) = x1 + alpha * (xlim (0) - x1); + xlim (1) = x1 + alpha * (xlim (1) - x1); + ylim (0) = y1 + alpha * (ylim (0) - y1); + ylim (1) = y1 + alpha * (ylim (1) - y1); + + // Make sure we stay within the range og the plot + xlim (0) = force_in_range (xlim (0), minx, maxx); + xlim (1) = force_in_range (xlim (1), minx, maxx); + ylim (0) = force_in_range (ylim (0), miny, maxy); + ylim (1) = force_in_range (ylim (1), miny, maxy); + + ap.zoom (xlim, ylim); + mark_modified (); + } + } + return 1; + case FL_RELEASE: if (Fl::event_button () == 1) { - // end of drag -- zoom - if (canvas->zoom ()) - { - canvas->zoom (false); - double x0,y0,x1,y1; - graphics_object ax = - gh_manager::get_object (fp.get_currentaxes ()); - if (ax && ax.isa ("axes")) - { - axes::properties& ap = - dynamic_cast (ax.get_properties ()); - pixel2pos (px0, py0, x0, y0); - pixel2pos (Fl::event_x (), Fl::event_y (), x1, y1); - Matrix xl (1,2,0); - Matrix yl (1,2,0); - if (x0 < x1) - { - xl(0) = x0; - xl(1) = x1; - } - else - { - xl(0) = x1; - xl(1) = x0; - } - - if (y0 < y1) - { - yl(0) = y0; - yl(1) = y1; - } - else - { - yl(0) = y1; - yl(1) = y0; - } - ap.zoom (xl, yl); - mark_modified (); - } - } // one click -- select axes - else if ( Fl::event_clicks () == 0) + if ( Fl::event_clicks () == 0) { std::cout << "ca="<< h0.value ()<<"\n"; if (h0.ok ()) diff -r 7cc35bc348cc src/graphics.cc --- a/src/graphics.cc Sun Jun 28 08:51:41 2009 +0100 +++ b/src/graphics.cc Tue Jun 30 22:02:28 2009 +0200 @@ -3458,7 +3458,7 @@ labels = c; } -static void +void get_children_limits (double& min_val, double& max_val, double& min_pos, const Matrix& kids, char limit_type) { diff -r 7cc35bc348cc src/graphics.h.in --- a/src/graphics.h.in Sun Jun 28 08:51:41 2009 +0100 +++ b/src/graphics.h.in Tue Jun 30 22:02:28 2009 +0200 @@ -3907,6 +3907,8 @@ void do_post_event (const graphics_event& e); }; +void get_children_limits (double& min_val, double& max_val, double& min_pos, + const Matrix& kids, char limit_type); // This function is NOT equivalent to the scripting language function gcf. OCTINTERP_API graphics_handle gcf (void);