changeset 10792:91342260063e

mouse rotation for fltk backend
author Shai Ayal <shaiay@users.sourceforge.net>
date Mon, 19 Jul 2010 06:17:54 +0300
parents 3140cb7a05a1
children be55736a0783
files src/ChangeLog src/DLD-FUNCTIONS/fltk_backend.cc src/graphics.cc src/graphics.h.in
diffstat 4 files changed, 107 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2010-07-18  Kai Habel <kai.habel@gmx.de>
+        * DLD-FUNCTIONS/fltk_backend.cc: Add mode for mouse rotation.
+        (view2status): new function
+        * src/graphics.cc: Remove limitations for zooming and translation.
+        (axes::properties::rotate_view): new function
+        
 2010-07-17  Rik <octave@nomad.inbox5.com>
 
         * DLD-FUNCTIONS/balance.cc, DLD-FUNCTIONS/ccolamd.cc,
--- a/src/DLD-FUNCTIONS/fltk_backend.cc
+++ b/src/DLD-FUNCTIONS/fltk_backend.cc
@@ -69,6 +69,8 @@
 const char* help_text = "\
 Keyboard Shortcuts\n\
 a - autoscale\n\
+p - pan/zoom\n\
+r - rotate\n\
 g - toggle grid\n\
 \n\
 Mouse\n\
@@ -219,8 +221,7 @@
 public:
   plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp)
     : Fl_Window (xx, yy, ww, hh, "octave"), window_label (), shift (0),
-      fp (xfp), canvas (0), autoscale (0), togglegrid (0), help (0),
-      status (0)
+      fp (xfp), canvas (0), autoscale (0), togglegrid (0), panzoom (0), rotate (0), help (0), status (0)
   {
     callback (window_close, static_cast<void*> (this));
 
@@ -245,8 +246,24 @@
                    "G");
       togglegrid->callback (button_callback, static_cast<void*> (this));
 
+      panzoom = new
+        Fl_Button (2 * status_h,
+                   hh - status_h,
+                   status_h,
+                   status_h,
+                   "P");
+      panzoom->callback (button_callback, static_cast<void*> (this));
+      
+      rotate = new
+        Fl_Button (3 * status_h,
+                   hh - status_h,
+                   status_h,
+                   status_h,
+                   "R");
+      rotate->callback (button_callback, static_cast<void*> (this));
+      
       help = new
-        Fl_Button (2*status_h,
+        Fl_Button (4 * status_h,
                    hh - status_h,
                    status_h,
                    status_h,
@@ -254,7 +271,7 @@
       help->callback (button_callback, static_cast<void*> (this));
 
       status = new
-        Fl_Output (3*status_h,
+        Fl_Output (5 * status_h,
                    hh - status_h,
                    ww > 2*status_h ? ww - status_h : 0,
                    status_h, "");
@@ -279,11 +296,13 @@
     status->show ();
     autoscale->show ();
     togglegrid->show ();
+    panzoom->show ();
+    rotate->show ();
 
     set_name ();
     resizable (canvas);
     size_range (4*status_h, 2*status_h);
-
+    gui_mode = 1;
   }
 
   ~plot_window (void)
@@ -328,6 +347,10 @@
   // Mod keys status
   int shift;
 
+  // Interactive Mode
+  // 1...pan/zoom, 2...rotate/zoom
+  int gui_mode;
+  
   // Figure properties.
   figure::properties& fp;
 
@@ -355,6 +378,12 @@
 
     if (widg == togglegrid)
       toggle_grid ();
+    
+    if (widg == panzoom)
+      gui_mode = 1;
+    
+    if (widg == rotate)
+      gui_mode = 2;
 
     if (widg == help)
       fl_message ("%s", help_text);
@@ -363,6 +392,8 @@
   OpenGL_fltk* canvas;
   Fl_Button* autoscale;
   Fl_Button* togglegrid;
+  Fl_Button* panzoom;
+  Fl_Button* rotate;
   Fl_Button* help;
   Fl_Output* status;
 
@@ -382,7 +413,7 @@
     feval ("grid", args);
     mark_modified ();
   }
-
+  
   void pixel2pos 
   (graphics_handle ax, int px, int py, double& xx, double& yy) const
   {
@@ -441,7 +472,8 @@
   {
     double x0, y0, x1, y1;
     std::stringstream cbuf;
-
+    cbuf.precision (4);
+    cbuf.width (6);
     pixel2pos (ax, px0, py0, x0, y0);
     cbuf << "[" << x0 << ", " << y0 << "]";
     if (px1 >= 0)
@@ -454,6 +486,24 @@
     status->redraw ();
   }
 
+  void view2status (graphics_object ax)
+  {
+     if (ax && ax.isa ("axes"))
+       {
+         axes::properties& ap = 
+           dynamic_cast<axes::properties&> (ax.get_properties ());
+         std::stringstream cbuf;
+         cbuf.precision (4);
+         cbuf.width (6);
+         Matrix v (1,2,0);
+         v = ap.get("view").matrix_value();
+         cbuf << "[azimuth: " << v(0) << ", elevation: " << v(1) << "]";
+    
+         status->value (cbuf.str ().c_str ());
+         status->redraw ();
+       }
+  }
+  
   void set_currentpoint (int px, int py)
   {
     Matrix pos (1,2,0);
@@ -583,6 +633,16 @@
             case 'G':
               toggle_grid ();
             break;
+
+            case 'p':
+            case 'P':
+              gui_mode = 1;
+            break;
+
+            case 'r':
+            case 'R':
+              gui_mode = 2;
+            break;
             }
         }
         break;
@@ -624,7 +684,6 @@
         break;
 
       case FL_DRAG:
-        pixel2status (ax0, px0, py0, Fl::event_x (), Fl::event_y ());
         if (fp.get_windowbuttonmotionfcn ().is_defined ())
           {
             set_currentpoint (Fl::event_x (), Fl::event_y ());
@@ -635,22 +694,37 @@
           {
             if (ax0 && ax0.isa ("axes"))
               {
+                if (gui_mode == 1)
+                  pixel2status (ax0, px0, py0, Fl::event_x (), Fl::event_y ());
+                else
+                  view2status (ax0);
                 axes::properties& ap = 
                   dynamic_cast<axes::properties&> (ax0.get_properties ());
               
                 double x0, y0, x1, y1;
+                Matrix pos = fp.get_position ().matrix_value ();
                 pixel2pos (ax0, px0, py0, x0, y0);
                 pixel2pos (ax0, Fl::event_x (), Fl::event_y (), x1, y1);
+                
+                if (gui_mode == 1)
+                  ap.translate_view (x0 - x1, y0 - y1);
+                else if (gui_mode == 2)
+                  {
+                    double daz, del;
+                    daz = (Fl::event_x () - px0) / pos(2) * 360;
+                    del = (Fl::event_y () - py0) / pos(3) * 360;
+                    ap.rotate_view (del, daz);
+                  }
+
                 px0 = Fl::event_x ();
                 py0 = Fl::event_y ();
-
-                ap.translate_view (x0 - x1, y0 - y1);
                 mark_modified ();
               }
             return 1;
           }
         else if (Fl::event_button () == 3)
           {
+            pixel2status (ax0, px0, py0, Fl::event_x (), Fl::event_y ());
             Matrix zoom_box (1,4,0);
             zoom_box (0) = px0;
             zoom_box (1) = py0;
--- a/src/graphics.cc
+++ b/src/graphics.cc
@@ -4231,12 +4231,6 @@
   ylims (0) = y + factor * (ylims (0) - y);
   ylims (1) = y + factor * (ylims (1) - y);
               
-  // Make sure we stay within the range og the plot
-  xlims (0) = force_in_range (xlims (0), minx, maxx);
-  xlims (1) = force_in_range (xlims (1), minx, maxx);
-  ylims (0) = force_in_range (ylims (0), miny, maxy);
-  ylims (1) = force_in_range (ylims (1), miny, maxy);
-
   zoom (xlims, ylims, push_to_zoom_stack);
 }
 
@@ -4280,25 +4274,27 @@
   double min_pos_y = octave_Inf;
   get_children_limits (miny, maxy, min_pos_y, kids, 'y');
   
-  // Make sure we don't exceed the borders
-  if (delta_x > 0)
-    delta_x = std::min (xlims (1) + delta_x, maxx) - xlims (1);
-  else
-    delta_x = std::max (xlims (0) + delta_x, minx) - xlims (0);
-  xlims (0) = xlims (0) + delta_x;
-  xlims (1) = xlims (1) + delta_x;
-                
-  if (delta_y > 0)
-    delta_y = std::min (ylims (1) + delta_y, maxy) - ylims (1);
-  else
-    delta_y = std::max (ylims (0) + delta_y, miny) - ylims (0);
-  ylims (0) = ylims (0) + delta_y;
-  ylims (1) = ylims (1) + delta_y;
+  xlims (0) += delta_x;
+  xlims (1) += delta_x;
+  ylims (0) += delta_y;
+  ylims (1) += delta_y;
                 
   zoom (xlims, ylims, false);
 }
 
 void
+axes::properties::rotate_view (double delta_el, double delta_az)
+{
+  Matrix v = get_view ().matrix_value ();
+
+  v (1) += delta_el;
+  v (0) -= delta_az;
+
+  set_view(v);
+  update_transform();
+}
+
+void
 axes::properties::unzoom (void)
 {
   if (zoom_stack.size () >= 4)
--- a/src/graphics.h.in
+++ b/src/graphics.h.in
@@ -2912,6 +2912,7 @@
                            bool push_to_zoom_stack = true);
     void zoom (const Matrix& xl, const Matrix& yl, bool push_to_zoom_stack = true);
     void translate_view (double delta_x, double delta_y);
+    void rotate_view (double delta_az, double delta_el);
     void unzoom (void);
     void clear_zoom_stack (void);