GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Canvas.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2011-2017 Michael Goffioul
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <QApplication>
28 #include <QBitmap>
29 #include <QCursor>
30 #include <QInputDialog>
31 #include <QList>
32 #include <QMouseEvent>
33 #include <QWheelEvent>
34 #include <QRectF>
35 
36 #include "Backend.h"
37 #include "Canvas.h"
38 #include "ContextMenu.h"
39 #include "GLCanvas.h"
40 #include "QtHandlesUtils.h"
41 
42 #include "annotation-dialog.h"
43 
44 #include "gl2ps-print.h"
45 #include "oct-opengl.h"
46 #include "octave-qt-link.h"
47 
48 #include "builtin-defun-decls.h"
49 
50 namespace QtHandles
51 {
52 
53  void
54  Canvas::redraw (bool sync)
55  {
56  QWidget *w = qWidget ();
57 
58  if (w)
59  {
60  if (sync)
61  w->repaint ();
62  else
63  w->update ();
64  }
65  }
66 
67  void
68  Canvas::blockRedraw (bool block)
69  {
70  m_redrawBlocked = block;
71  }
72 
73  void
75  {
76  QWidget *w = qWidget ();
77 
78  if (w)
79  {
80  static QCursor origCursor = w->cursor ();
81 
82  switch (mode)
83  {
84  case PanMode:
85  case RotateMode:
86  w->setCursor (Qt::OpenHandCursor);
87  break;
88 
89  case ZoomInMode:
90  w->setCursor (QPixmap (":/images/zoom-in.png"));
91  break;
92 
93  case ZoomOutMode:
94  w->setCursor (QPixmap (":/images/zoom-out.png"));
95  break;
96 
97  default:
98  w->setCursor (origCursor);
99  break;
100  }
101  }
102  }
103 
104  void
105  Canvas::print (const QString& file_cmd, const QString& term)
106  {
109 
110  if (obj.valid_object ())
111  {
112  graphics_object figObj (obj.get_ancestor ("figure"));
113 
114  gl2ps_print (figObj, file_cmd.toStdString (), term.toStdString ());
115  }
116  }
117 
118  /*
119  Two updateCurrentPoint() routines are required:
120  1) Used for QMouseEvents where cursor position data is in callback from Qt.
121  2) Used for QKeyEvents where cursor position must be determined.
122  */
123  void
125  const graphics_object& obj, QMouseEvent* event)
126  {
128 
129  gh_manager::post_set (fig.get_handle (), "currentpoint",
130  Utils::figureCurrentPoint (fig, event), false);
131 
132  Matrix children = obj.get_properties ().get_children ();
133  octave_idx_type num_children = children.numel ();
134 
135  for (int i = 0; i < num_children; i++)
136  {
137  graphics_object childObj (gh_manager::get_object (children(i)));
138 
139  if (childObj.isa ("axes"))
140  {
141  axes::properties& ap = Utils::properties<axes> (childObj);
142  Matrix x_zlim = ap.get_transform_zlim ();
143  graphics_xform x_form = ap.get_transform ();
144 
145  ColumnVector p1 = x_form.untransform (event->x (), event->y (),
146  x_zlim(0));
147  ColumnVector p2 = x_form.untransform (event->x (), event->y (),
148  x_zlim(1));
149 
150  Matrix cp (2, 3, 0.0);
151 
152  cp(0,0) = p1(0); cp(0,1) = p1(1); cp(0,2) = p1(2);
153  cp(1,0) = p2(0); cp(1,1) = p2(1); cp(1,2) = p2(2);
154 
155  gh_manager::post_set (childObj.get_handle (), "currentpoint", cp,
156  false);
157  }
158  }
159  }
160 
161  void
163  const graphics_object& obj)
164  {
166 
167  gh_manager::post_set (fig.get_handle (), "currentpoint",
168  Utils::figureCurrentPoint (fig), false);
169 
170  Matrix children = obj.get_properties ().get_children ();
171  octave_idx_type num_children = children.numel ();
172 
173  for (int i = 0; i < num_children; i++)
174  {
175  graphics_object childObj (gh_manager::get_object (children(i)));
176 
177  if (childObj.isa ("axes"))
178  {
179  // FIXME: QCursor::pos() may give inaccurate results with asynchronous
180  // window systems like X11 over ssh.
181  QWidget *w = qWidget ();
182  QPoint p = w->mapFromGlobal (QCursor::pos ());
183  axes::properties& ap = Utils::properties<axes> (childObj);
184  Matrix x_zlim = ap.get_transform_zlim ();
185  graphics_xform x_form = ap.get_transform ();
186 
187  ColumnVector p1 = x_form.untransform (p.x (), p.y (), x_zlim(0));
188  ColumnVector p2 = x_form.untransform (p.x (), p.y (), x_zlim(1));
189 
190  Matrix cp (2, 3, 0.0);
191 
192  cp(0,0) = p1(0); cp(0,1) = p1(1); cp(0,2) = p1(2);
193  cp(1,0) = p2(0); cp(1,1) = p2(1); cp(1,2) = p2(2);
194 
195  gh_manager::post_set (childObj.get_handle (), "currentpoint", cp,
196  false);
197  }
198  }
199  }
200 
201  void
203  {
204  Ffeval (ovl ("annotation").append (args));
205 
206  redraw ();
207  }
208 
209  void
211  {
213 
215 
216  if (go.valid_object ())
217  {
218  figure::properties& fp = Utils::properties<figure> (go);
219 
220  graphics_handle ah = fp.get_currentaxes ();
221 
223 
224  if (ax.valid_object ())
225  {
226  axes::properties& ap = Utils::properties<axes> (ax);
227 
228  if (ap.handlevisibility_is ("on"))
229  {
230  ap.set_visible (! ap.is_visible ());
231 
232  redraw (true);
233  }
234  }
235  }
236  }
237 
238  void
240  {
242 
244 
245  if (go.valid_object ())
246  {
247  figure::properties& fp = Utils::properties<figure> (go);
248 
249  graphics_handle ah = fp.get_currentaxes ();
250 
252 
253  if (ax.valid_object ())
254  {
255  axes::properties& ap = Utils::properties<axes> (ax);
256 
258 
259  // If any grid is off, then turn them all on. If they are all
260  // on, then turn them off.
261 
262  std::string state = ((ap.get_xgrid () == "off"
263  || ap.get_ygrid () == "off"
264  || ap.get_zgrid () == "off")
265  ? "on" : "off");
266 
267  ap.set_xgrid (state);
268  ap.set_ygrid (state);
269  ap.set_zgrid (state);
270 
271  redraw (true);
272  }
273  }
274  }
275 
276  static void
278  {
279  ap.clear_zoom_stack ();
280 
281  ap.set_xlimmode ("auto");
282  ap.set_ylimmode ("auto");
283  ap.set_zlimmode ("auto");
284  }
285 
286  void
288  {
290 
292 
293  if (go.valid_object ())
294  {
295  figure::properties& fp = Utils::properties<figure> (go);
296 
297  graphics_handle ah = fp.get_currentaxes ();
298 
300 
301  if (ax.valid_object ())
302  {
303  axes::properties& ap = Utils::properties<axes> (ax);
304 
305  autoscale_axes (ap);
306 
307  redraw (true);
308  }
309  }
310  }
311 
312  void
314  {
315  if (! m_redrawBlocked)
316  {
318 
319  draw (m_handle);
320 
321  if ((m_mouseMode == ZoomInMode && m_mouseAxes.ok ()) || m_rectMode)
323  }
324  }
325 
326  static bool
328  {
329  // Getting pan mode property:
330  octave_value ov_pm
331  = Utils::properties<figure> (figObj).get___pan_mode__ ();
332 
333  octave_scalar_map pm = ov_pm.scalar_map_value ();
334 
335  return pm.contents ("Enable").string_value () == "on";
336  }
337 
338  static std::string
339  pan_mode (const graphics_object figObj)
340  {
341  // Getting pan mode property:
342  octave_value ov_pm
343  = Utils::properties<figure> (figObj).get___pan_mode__ ();
344 
345  octave_scalar_map pm = ov_pm.scalar_map_value ();
346 
347  return pm.contents ("Motion").string_value ();
348  }
349 
350  static bool
352  {
353  // Getting zoom mode property:
354  octave_value ov_zm
355  = Utils::properties<figure> (figObj).get___zoom_mode__ ();
356 
357  octave_scalar_map zm = ov_zm.scalar_map_value ();
358 
359  return zm.contents ("Enable").string_value () == "on";
360  }
361 
362  static std::string
363  zoom_mode (const graphics_object figObj)
364  {
365  // Getting zoom mode property:
366  octave_value ov_zm
367  = Utils::properties<figure> (figObj).get___zoom_mode__ ();
368 
369  octave_scalar_map zm = ov_zm.scalar_map_value ();
370 
371  return zm.contents ("Motion").string_value ();
372  }
373 
374  void
375  Canvas::select_object (graphics_object obj, QMouseEvent* event,
376  graphics_object &currentObj, graphics_object &axesObj,
377  bool axes_only, std::vector<std::string> omit)
378  {
379  QList<graphics_object> axesList;
380  Matrix children = obj.get_properties ().get_all_children ();
381  octave_idx_type num_children = children.numel ();
382 
383  for (int i = 0; i < num_children; i++)
384  {
385  graphics_object childObj (gh_manager::get_object (children(i)));
386 
387  if (childObj.isa ("axes"))
388  {
389  auto p = omit.begin ();
390  bool omitfound = false;
391  while (p != omit.end () && ! omitfound)
392  {
393  omitfound = (childObj.get ("tag").string_value () == *p);
394  p++;
395  }
396  if (! omitfound)
397  axesList.append (childObj);
398  }
399  else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel")
400  || childObj.isa ("uibuttongroup"))
401  {
402  Matrix bb = childObj.get_properties ().get_boundingbox (false);
403  QRectF r (bb(0), bb(1), bb(2), bb(3));
404 
405  r.adjust (-5, -5, 5, 5);
406 
407 #if (HAVE_QT4)
408  bool rect_contains_pos = r.contains (event->posF ());
409 #else
410  bool rect_contains_pos = r.contains (event->localPos ());
411 #endif
412  if (rect_contains_pos)
413  {
414  currentObj = childObj;
415  break;
416  }
417  }
418  }
419 
420  if (axes_only)
421  {
422  QPoint pt = event->pos ();
423 
424  for (QList<graphics_object>::ConstIterator it = axesList.begin ();
425  it != axesList.end (); ++it)
426  {
427  const axes::properties& ap =
428  dynamic_cast<const axes::properties&> ((*it).get_properties ());
429 
430  ColumnVector p0 = ap.pixel2coord (pt.x (), pt.y ());
431  Matrix xlim = ap.get_xlim ().matrix_value ();
432  Matrix ylim = ap.get_ylim ().matrix_value ();
433 
434  if (xlim(0) < p0(0) && xlim(1) > p0(0)
435  && ylim(0) < p0(1) && ylim(1) > p0(1))
436  {
437  axesObj = *it;
438  return;
439  }
440  }
441  }
442  else if (! currentObj)
443  {
444  for (QList<graphics_object>::ConstIterator it = axesList.begin ();
445  it != axesList.end (); ++it)
446  {
447  graphics_object go = selectFromAxes (*it, event->pos ());
448 
449  if (go)
450  {
451  currentObj = go;
452  axesObj = *it;
453  }
454  // FIXME: is this really necessary? the axes object should
455  // have been selected through selectFromAxes anyway
456  else if (it->get_properties ().is_hittest ())
457  {
458  Matrix bb = it->get_properties ().get_boundingbox (true);
459  QRectF r (bb(0), bb(1), bb(2), bb(3));
460 
461 #if defined (HAVE_QT4)
462  bool rect_contains_pos = r.contains (event->posF ());
463 #else
464  bool rect_contains_pos = r.contains (event->localPos ());
465 #endif
466  if (rect_contains_pos)
467  axesObj = *it;
468  }
469 
470  if (axesObj && currentObj)
471  break;
472  }
473  }
474  }
475 
476  void
477  Canvas::canvasMouseMoveEvent (QMouseEvent* event)
478  {
481 
482  if (m_mouseMode != NoMode && (ax.valid_object () || m_mouseMode == TextMode))
483  {
484  switch (m_mouseMode)
485  {
486  case RotateMode:
487  {
488  axes::properties& ap = Utils::properties<axes> (ax);
489 
490  ap.rotate3d (m_mouseCurrent.x (), event->x (),
491  m_mouseCurrent.y (), event->y ());
492 
493  // Update current mouse position
494  m_mouseCurrent = event->pos ();
495 
496  // Force immediate redraw
497  redraw (true);
498  }
499  break;
500  case TextMode:
501  case ZoomInMode:
502  case ZoomOutMode:
503  m_mouseCurrent = event->pos ();
504  redraw (true);
505  break;
506 
507  case PanMode:
508  {
509  axes::properties& ap = Utils::properties<axes> (ax);
510 
511  graphics_object figObj (ax.get_ancestor ("figure"));
512 
513  std::string mode = pan_mode (figObj);
514 
516  m_mouseCurrent.y ());
517  ColumnVector p1 = ap.pixel2coord (event->x (),
518  event->y ());
519 
520  ap.translate_view (mode, p0(0), p1(0), p0(1), p1(1));
521 
522  // Update current mouse position
523  m_mouseCurrent = event->pos ();
524 
525  // Force immediate redraw
526  redraw (true);
527  }
528 
529  default:
530  break;
531  }
532  }
533  else if (m_mouseMode == NoMode)
534  {
536 
537  if (obj.valid_object ())
538  {
539  graphics_object figObj (obj.get_ancestor ("figure"));
540 
541  if (figObj.valid_object () &&
542  ! figObj.get ("windowbuttonmotionfcn").is_empty ())
543  {
544  updateCurrentPoint (figObj, obj, event);
545  gh_manager::post_callback (figObj.get_handle (),
546  "windowbuttonmotionfcn");
547  }
548  }
549  }
550 
551  // Update mouse coordinates in the figure window status bar
553  graphics_object figObj = obj.get_ancestor ("figure");
554 
555  if (figObj.valid_object () && obj.valid_object ())
556  {
557  graphics_object currentObj, axesObj;
558  std::vector<std::string> omit = {"legend", "colorbar", "scribeoverlay"};
559  select_object (obj, event, currentObj, axesObj, true, omit);
560 
561  if (axesObj.valid_object ())
562  {
563  // FIXME: should we use signal/slot mechanism instead of
564  // directly calling parent fig methods
565  Figure* fig =
566  dynamic_cast<Figure*> (Backend::toolkitObject (figObj));
567  axes::properties& ap = Utils::properties<axes> (axesObj);
568 
569  if (fig)
570  fig->updateStatusBar (ap.pixel2coord (event->x (), event->y ()));
571  }
572  }
573  }
574 
575  void
577  {
578  // same processing as normal click, but event type is MouseButtonDblClick
579  canvasMousePressEvent (event);
580  }
581 
582  static double
583  button_number (QMouseEvent *event)
584  {
585  double retval = 0;
586 
587  switch (event->button ())
588  {
589  case Qt::LeftButton:
590  retval = 1;
591  break;
592 
593  case Qt::MidButton:
594  retval = 2;
595  break;
596 
597  case Qt::RightButton:
598  retval = 3;
599  break;
600 
601  default:
602  break;
603  }
604 
605  return retval;
606  }
607 
608  void
609  Canvas::canvasMousePressEvent (QMouseEvent* event)
610  {
613 
614  bool isdblclick = (event->type () == QEvent::MouseButtonDblClick);
615 
616  if (obj.valid_object ())
617  {
618  graphics_object figObj (obj.get_ancestor ("figure"));
619  graphics_object currentObj, axesObj;
620 
621  select_object (obj, event, currentObj, axesObj);
622 
623  if (axesObj)
624  {
625  if (axesObj.get_properties ().handlevisibility_is ("on")
626  && axesObj.get_properties ().get_tag () != "legend"
627  && axesObj.get_properties ().get_tag () != "colorbar")
628  Utils::properties<figure> (figObj)
629  .set_currentaxes (axesObj.get_handle ().as_octave_value ());
630  if (! currentObj)
631  currentObj = axesObj;
632  }
633 
634  if (! currentObj)
635  currentObj = obj;
636 
637  if (currentObj.get_properties ().handlevisibility_is ("on"))
638  Utils::properties<figure> (figObj)
639  .set_currentobject (currentObj.get_handle ().as_octave_value ());
640  else
641  Utils::properties<figure> (figObj).set_currentobject (
643 
644  Figure* fig = dynamic_cast<Figure*> (Backend::toolkitObject (figObj));
645 
646  MouseMode newMouseMode = NoMode;
647 
648  if (fig)
649  newMouseMode = fig->mouseMode ();
650 
651  switch (newMouseMode)
652  {
653  case NoMode:
654  gh_manager::post_set (figObj.get_handle (), "selectiontype",
655  Utils::figureSelectionType (event, isdblclick), false);
656 
657  updateCurrentPoint (figObj, obj, event);
658 
659  gh_manager::post_callback (figObj.get_handle (),
660  "windowbuttondownfcn",
661  button_number (event));
662 
663  if (currentObj.get ("buttondownfcn").is_empty ())
664  {
665  graphics_object parentObj =
666  gh_manager::get_object (currentObj.get_parent ());
667 
668  if (parentObj.valid_object () && parentObj.isa ("hggroup"))
670  "buttondownfcn",
671  button_number (event));
672  }
673  else
674  gh_manager::post_callback (currentObj.get_handle (),
675  "buttondownfcn",
676  button_number (event));
677 
678  if (event->button () == Qt::RightButton)
679  ContextMenu::executeAt (currentObj.get_properties (),
680  event->globalPos ());
681  break;
682 
683  case TextMode:
684  {
685  if (event->modifiers () == Qt::NoModifier)
686  {
687  switch (event->buttons ())
688  {
689  case Qt::LeftButton:
690  m_mouseAnchor = m_mouseCurrent = event->pos ();
691  m_mouseMode = newMouseMode;
692  m_rectMode = true;
693  }
694  }
695  redraw (false);
696  }
697  break;
698 
699  case PanMode:
700  case RotateMode:
701  case ZoomInMode:
702  case ZoomOutMode:
703  if (axesObj && axesObj.get_properties ().handlevisibility_is ("on"))
704  {
705  bool redraw_figure = true;
706 
707  if (isdblclick)
708  {
709  if (event->button () == Qt::LeftButton)
710  {
711  axes::properties& ap = Utils::properties<axes> (axesObj);
712 
713  autoscale_axes (ap);
714  }
715  else
716  {
717  redraw_figure = false;
718  }
719  }
720  else if (event->modifiers () == Qt::NoModifier)
721  {
722  switch (event->buttons ())
723  {
724  case Qt::LeftButton:
725  m_mouseAnchor = m_mouseCurrent = event->pos ();
726  m_mouseAxes = axesObj.get_handle ();
727  m_mouseMode = newMouseMode;
728  m_clickMode = newMouseMode == ZoomInMode;
729  break;
730 
731  case Qt::RightButton:
732  if (newMouseMode == ZoomInMode)
733  {
734  m_mouseAnchor = m_mouseCurrent = event->pos ();
735  m_mouseAxes = axesObj.get_handle ();
736  m_mouseMode = newMouseMode;
737  m_clickMode = false;
738  }
739 
740  break;
741 
742  case Qt::MidButton:
743  {
744  axes::properties& ap =
745  Utils::properties<axes> (axesObj);
746 
747  autoscale_axes (ap);
748  }
749  break;
750 
751  default:
752  redraw_figure = false;
753  break;
754  }
755  }
756  else if (event->modifiers () == Qt::ShiftModifier)
757  {
758  switch (event->buttons ())
759  {
760  case Qt::LeftButton:
761  if (newMouseMode == ZoomInMode)
762  {
763  m_mouseAnchor = m_mouseCurrent = event->pos ();
764  m_mouseAxes = axesObj.get_handle ();
765  m_mouseMode = newMouseMode;
766  m_clickMode = false;
767  }
768  break;
769 
770  default:
771  redraw_figure = false;
772  break;
773  }
774  }
775 
776  if (redraw_figure)
777  redraw (false);
778  }
779  break;
780 
781  default:
782  break;
783  }
784  }
785 
786  }
787 
788  void
789  Canvas::canvasMouseReleaseEvent (QMouseEvent* event)
790  {
792  && m_mouseAxes.ok ())
793  {
796 
797  if (ax.valid_object ())
798  {
799  axes::properties& ap = Utils::properties<axes> (ax);
800 
802 
803  graphics_object figObj (obj.get_ancestor ("figure"));
804 
805  std::string zm = zoom_mode (figObj);
806 
807  if (m_mouseAnchor == event->pos ())
808  {
809  double factor = m_clickMode ? 2.0 : 0.5;
810 
811  ColumnVector p1 = ap.pixel2coord (event->x (), event->y ());
812 
813  ap.zoom_about_point (zm, p1(0), p1(1), factor);
814  }
815  else if (m_mouseMode == ZoomInMode)
816  {
817  ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (),
818  m_mouseAnchor.y ());
819  ColumnVector p1 = ap.pixel2coord (event->x (),
820  event->y ());
821 
822  Matrix xl (1, 2, 0.0);
823  Matrix yl (1, 2, 0.0);
824 
825  xl(0) = std::min (p0(0), p1(0));
826  xl(1) = std::max (p0(0), p1(0));
827  yl(0) = std::min (p0(1), p1(1));
828  yl(1) = std::max (p0(1), p1(1));
829 
830  ap.zoom (zm, xl, yl);
831  }
832 
833  redraw (false);
834  }
835  }
836  else if (m_mouseMode == NoMode)
837  {
840 
841  if (obj.valid_object ())
842  {
843  graphics_object figObj (obj.get_ancestor ("figure"));
844 
845  updateCurrentPoint (figObj, obj, event);
846  gh_manager::post_callback (figObj.get_handle (),
847  "windowbuttonupfcn");
848  }
849  }
850  else if (m_mouseMode == TextMode)
851  {
853 
854  graphics_object figObj =
856  if (figObj.valid_object ())
857  {
858  QWidget *w = qWidget ();
859  if (w)
860  {
861  Matrix bb = figObj.get ("position").matrix_value ();
862  bb(0) = m_mouseAnchor.x () / bb(2);
863  bb(1) = 1.0 - (m_mouseAnchor.y () / bb(3));
864  bb(2) = (event->x () - m_mouseAnchor.x ()) / bb(2);
865  bb(3) = (m_mouseAnchor.y () - event->y ()) / bb(3);
866 
867  octave_value_list props = ovl ("textbox", bb);
868 
869  annotation_dialog anno_dlg (w, props);
870 
871  if (anno_dlg.exec () == QDialog::Accepted)
872  {
873  props = anno_dlg.get_properties ();
874  props.prepend (figObj.get_handle ().as_octave_value ());
875 
877  props);
878  }
879  }
880  }
881  }
882  m_rectMode = false;
885  }
886 
887  void
888  Canvas::canvasWheelEvent (QWheelEvent* event)
889  {
892 
893  if (obj.valid_object ())
894  {
896 
897  graphics_object axesObj;
898 
899  Matrix children = obj.get_properties ().get_children ();
900  octave_idx_type num_children = children.numel ();
901 
902  for (int i = 0; i < num_children; i++)
903  {
904  graphics_object childObj (gh_manager::get_object (children(i)));
905 
906  if (childObj.isa ("axes"))
907  {
908  graphics_object go = selectFromAxes (childObj, event->pos ());
909 
910  if (go)
911  {
912  axesObj = childObj;
913  break;
914  }
915  }
916  }
917 
918  if (axesObj)
919  {
920  MouseMode newMouseMode = NoMode;
921 
922  graphics_object figObj (obj.get_ancestor ("figure"));
923 
924  Figure* fig = dynamic_cast<Figure*> (Backend::toolkitObject (figObj));
925 
926  if (fig)
927  newMouseMode = fig->mouseMode ();
928 
929  if (axesObj.get_properties ().handlevisibility_is ("on"))
930  {
931  Utils::properties<figure> (figObj)
932  .set_currentaxes (axesObj.get_handle ().as_octave_value ());
933 
934  if (zoom_enabled (figObj))
935  {
936  if (event->delta () > 0)
937  newMouseMode = ZoomInMode;
938  else
939  newMouseMode = ZoomOutMode;
940 
941  mode = zoom_mode (figObj);
942  }
943  else if (pan_enabled (figObj))
944  {
945  newMouseMode = PanMode;
946 
947  mode = pan_mode (figObj);
948  }
949  }
950 
951  bool redrawFigure = true;
952 
953  switch (newMouseMode)
954  {
955  case ZoomInMode:
956  case ZoomOutMode:
957  {
958  axes::properties& ap = Utils::properties<axes> (axesObj);
959 
960  // Control how fast to zoom when using scroll wheel.
961  double wheel_zoom_speed = ap.get_mousewheelzoom ();
962 
963  // Determine if we're zooming in or out.
964  double factor = (newMouseMode == ZoomInMode
965  ? 1 / (1.0 - wheel_zoom_speed)
966  : 1.0 - wheel_zoom_speed);
967 
968  // FIXME: should we zoom about point for 2D plots?
969 
970  ap.zoom (mode, factor);
971  }
972  break;
973 
974  case PanMode:
975  {
976  axes::properties& ap = Utils::properties<axes> (axesObj);
977 
978  double factor = event->delta () > 0 ? 0.1 : -0.1;
979 
980  ap.pan (mode, factor);
981  }
982  break;
983 
984  default:
985  redrawFigure = false;
986  break;
987  }
988 
989  if (redrawFigure)
990  redraw (false);
991  }
992  }
993  }
994 
995  bool
996  Canvas::canvasKeyPressEvent (QKeyEvent* event)
997  {
998  if (m_eventMask & KeyPress)
999  {
1000  gh_manager::auto_lock lock;
1002 
1003  if (obj.valid_object ())
1004  {
1005  graphics_object figObj (obj.get_ancestor ("figure"));
1006 
1007  updateCurrentPoint (figObj, obj);
1008  }
1009 
1010  octave_scalar_map eventData = Utils::makeKeyEventStruct (event);
1011 
1012  gh_manager::post_set (m_handle, "currentcharacter",
1013  eventData.getfield ("Character"), false);
1014  gh_manager::post_callback (m_handle, "keypressfcn", eventData);
1015 
1016  return true;
1017  }
1018 
1019  return false;
1020  }
1021 
1022  bool
1024  {
1025  if (! event->isAutoRepeat () && (m_eventMask & KeyRelease))
1026  {
1027  gh_manager::post_callback (m_handle, "keyreleasefcn",
1028  Utils::makeKeyEventStruct (event));
1029 
1030  return true;
1031  }
1032 
1033  return false;
1034  }
1035 
1036  Canvas*
1037  Canvas::create (const std::string& /* name */, QWidget* parent,
1038  const graphics_handle& handle)
1039  {
1040  // Only OpenGL
1041  return new GLCanvas (parent, handle);
1042  }
1043 
1044 }
graphics_handle m_mouseAxes
Definition: Canvas.h:121
virtual QWidget * qWidget(void)=0
graphics_handle get_currentaxes(void) const
Definition: graphics.h:4011
void rotate3d(double x0, double x1, double y0, double y1, bool push_to_zoom_stack=true)
Definition: graphics.cc:7810
void set_ylimmode(const octave_value &val)
Definition: graphics.h:6640
bool handlevisibility_is(const std::string &v) const
Definition: graphics.h:2679
static void post_callback(const graphics_handle &h, const std::string &name, const octave_value &data=Matrix())
Definition: graphics.h:13910
bool is_visible(void) const
Definition: graphics.h:2704
octave_value get_xlim(void) const
Definition: graphics.h:5594
void select_object(graphics_object obj, QMouseEvent *event, graphics_object &currentObj, graphics_object &axesObj, bool axes_only=false, std::vector< std::string > omit=std::vector< std::string >())
Definition: Canvas.cc:375
bool isa(const std::string &go_name) const
Definition: graphics.h:3286
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).is_integer_type())
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
MouseMode
Definition: Figure.h:39
const octave_value & contents(const_iterator p) const
Definition: oct-map.h:190
Return the CPU time used by your Octave session The first output is the total time spent executing your process and is equal to the sum of second and third which are the number of CPU seconds spent executing in user mode and the number of CPU seconds spent executing in system mode
Definition: data.cc:6386
bool ok(void) const
Definition: oct-handle.h:109
graphics_handle m_handle
Definition: Canvas.h:115
void updateCurrentPoint(const graphics_object &fig, const graphics_object &obj, QMouseEvent *event)
Definition: Canvas.cc:124
void zoom(const std::string &mode, double factor, bool push_to_zoom_stack=true)
Definition: graphics.cc:7646
void set_visible(const octave_value &val)
Definition: graphics.h:2854
virtual Matrix get_boundingbox(bool=false, const Matrix &=Matrix()) const
Definition: graphics.h:2499
octave_value get_ylim(void) const
Definition: graphics.h:5639
void translate_view(const std::string &mode, double x0, double x1, double y0, double y1, bool push_to_zoom_stack=true)
Definition: graphics.cc:7764
void print(const QString &file_cmd, const QString &term)
Definition: Canvas.cc:105
void set_zgrid(const octave_value &val)
Definition: graphics.h:6770
Matrix figureCurrentPoint(const graphics_object &fig, QMouseEvent *event)
void redraw(bool sync=false)
Definition: Canvas.cc:54
void canvasToggleGrid(const graphics_handle &handle)
Definition: Canvas.cc:239
octave_value get(bool all=false) const
Definition: graphics.h:3211
virtual void drawZoomBox(const QPoint &p1, const QPoint &p2)=0
static void autoscale_axes(axes::properties &ap)
Definition: Canvas.cc:277
void canvasMouseDoubleClickEvent(QMouseEvent *event)
Definition: Canvas.cc:576
graphics_xform get_transform(void) const
Definition: graphics.h:4989
std::string get_zgrid(void) const
Definition: graphics.h:5677
void canvasToggleAxes(const graphics_handle &handle)
Definition: Canvas.cc:210
JNIEnv void * args
Definition: ov-java.cc:67
static void executeAt(const base_properties &props, const QPoint &pt)
Definition: ContextMenu.cc:113
void pan(const std::string &mode, double factor, bool push_to_zoom_stack=true)
Definition: graphics.cc:7793
void canvasMousePressEvent(QMouseEvent *event)
Definition: Canvas.cc:609
QPoint m_mouseAnchor
Definition: Canvas.h:119
void canvasWheelEvent(QWheelEvent *event)
Definition: Canvas.cc:888
bool canvasKeyPressEvent(QKeyEvent *event)
Definition: Canvas.cc:996
Matrix get_children(void) const
Definition: graphics.h:2517
void canvasMouseMoveEvent(QMouseEvent *event)
Definition: Canvas.cc:477
std::string string_value(bool force=false) const
Definition: ov.h:908
bool m_clickMode
Definition: Canvas.h:118
octave_scalar_map makeKeyEventStruct(QKeyEvent *event)
static bool zoom_enabled(const graphics_object figObj)
Definition: Canvas.cc:351
double get_mousewheelzoom(void) const
Definition: graphics.h:5707
void canvasAutoAxes(const graphics_handle &handle)
Definition: Canvas.cc:287
std::complex< double > w(std::complex< double > z, double relerr=0)
void gl2ps_print(const graphics_object &fig, const std::string &stream, const std::string &term)
Definition: gl2ps-print.cc:799
std::string get_ygrid(void) const
Definition: graphics.h:5635
QPoint m_mouseCurrent
Definition: Canvas.h:120
double tmp
Definition: data.cc:6300
octave_value retval
Definition: data.cc:6294
bool append
Definition: load-save.cc:1582
base_properties & get_properties(void)
Definition: graphics.h:3288
Definition: dMatrix.h:37
void zoom_about_point(const std::string &mode, double x, double y, double factor, bool push_to_zoom_stack=true)
Definition: graphics.cc:7617
MouseMode m_mouseMode
Definition: Canvas.h:117
graphics_object get_ancestor(const std::string &type) const
Definition: graphics.cc:3404
void updateStatusBar(ColumnVector pt)
Definition: Figure.cc:580
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:787
std::string get_xgrid(void) const
Definition: graphics.h:5590
void canvasPaintEvent(void)
Definition: Canvas.cc:313
static uint32_t state[624]
Definition: randmtzig.cc:184
void set_xgrid(const octave_value &val)
Definition: graphics.h:6445
void canvasMouseReleaseEvent(QMouseEvent *event)
Definition: Canvas.cc:789
ColumnVector untransform(double x, double y, double z, bool use_scale=true) const
Definition: graphics.cc:6635
bool valid_object(void) const
Definition: graphics.h:3306
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:228
static Object * toolkitObject(const graphics_object &go)
Definition: Backend.cc:199
std::string figureSelectionType(QMouseEvent *event, bool isDoubleClick)
bool canvasKeyReleaseEvent(QKeyEvent *event)
Definition: Canvas.cc:1023
ColumnVector pixel2coord(double px, double py) const
Definition: graphics.h:5037
virtual void draw(const graphics_handle &handle)=0
octave_scalar_map scalar_map_value(void) const
Definition: ov.cc:1699
void setCursor(MouseMode mode)
Definition: Canvas.cc:74
void set_xlimmode(const octave_value &val)
Definition: graphics.h:6472
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
void set_zlimmode(const octave_value &val)
Definition: graphics.h:6797
p
Definition: lu.cc:138
octave_handle graphics_handle
Definition: graphics.h:56
static bool pan_enabled(const graphics_object figObj)
Definition: Canvas.cc:327
Matrix get_all_children(void) const
Definition: graphics.h:2522
virtual graphics_object selectFromAxes(const graphics_object &ax, const QPoint &pt)=0
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the IEEE symbol NaN(Not a Number).NaN is the result of operations which do not produce a well defined 0 result.Common operations which produce a NaN are arithmetic with infinity ex($\infty-\infty $)
void clear_zoom_stack(bool do_unzoom=true)
Definition: graphics.cc:7916
static Canvas * create(const std::string &name, QWidget *parent, const graphics_handle &handle)
Definition: Canvas.cc:1037
static graphics_object get_object(double val)
Definition: graphics.h:13794
octave_value_list get_properties() const
MouseMode mouseMode(void)
Definition: Figure.cc:272
void annotation_callback(const octave_value_list &args)
Definition: Canvas.cc:202
static std::string pan_mode(const graphics_object figObj)
Definition: Canvas.cc:339
octave_value getfield(const std::string &key) const
Definition: oct-map.cc:171
OCTINTERP_API octave_value_list Ffeval(const octave_value_list &=octave_value_list(), int=0)
graphics_handle get_handle(void) const
Definition: graphics.h:3274
void set_ygrid(const octave_value &val)
Definition: graphics.h:6613
bool m_redrawBlocked
Definition: Canvas.h:116
static double button_number(QMouseEvent *event)
Definition: Canvas.cc:583
Matrix get_transform_zlim(void) const
Definition: graphics.h:4996
octave_value as_octave_value(void) const
Definition: oct-handle.h:76
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
octave_value_list & prepend(const octave_value &val)
Definition: ovl.cc:67
static std::string zoom_mode(const graphics_object figObj)
Definition: Canvas.cc:363
void blockRedraw(bool block=true)
Definition: Canvas.cc:68
static void post_set(const graphics_handle &h, const std::string &name, const octave_value &value, bool notify_toolkit=true)
Definition: graphics.h:13924
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:205