26 #if defined (HAVE_CONFIG_H)
30 #include <QApplication>
33 #include <QInputDialog>
35 #include <QMouseEvent>
36 #include <QWheelEvent>
49 #include "builtin-defun-decls.h"
79 octave::resource_manager& rmgr =
m_octave_qobj.get_resource_manager ();
81 QIcon icon = rmgr.icon (name);
83 return QCursor (icon.pixmap (22, 22), hot_x, hot_y);
88 QImage cdata,
Matrix hotspot)
91 QCursor cursor = Qt::ArrowCursor;
98 cursor = Qt::ArrowCursor;
100 if (fallback ==
"arrow")
101 cursor = Qt::ArrowCursor;
102 else if (fallback ==
"botl")
103 cursor =
make_cursor (
"bottom_left_corner", 5, 16);
104 else if (fallback ==
"botr")
105 cursor =
make_cursor (
"bottom_right_corner", 16, 16);
106 else if (fallback ==
"bottom")
108 else if (fallback ==
"circle")
110 else if (fallback ==
"cross" || fallback ==
"crosshair")
112 else if (fallback ==
"custom")
114 if (hotspot(0) > cdata.width () || hotspot(0) < 1.0
115 || hotspot(1) > cdata.height () || hotspot(1) < 1.0)
116 hotspot =
Matrix (1, 2, 1);
118 cursor = QCursor (QPixmap::fromImage (cdata),
119 static_cast<int> (hotspot(1) - 1),
120 static_cast<int> (hotspot(0) - 1));
122 else if (fallback ==
"fleur")
124 else if (fallback ==
"hand")
126 else if (fallback ==
"ibeam")
127 cursor = Qt::IBeamCursor;
128 else if (fallback ==
"left")
130 else if (fallback ==
"right")
132 else if (fallback ==
"top")
134 else if (fallback ==
"topl")
136 else if (fallback ==
"topr")
138 else if (fallback ==
"watch")
139 cursor = Qt::BusyCursor;
143 cursor = Qt::ArrowCursor;
155 cursor = Qt::IBeamCursor;
167 cursor = Qt::ArrowCursor;
170 w->setCursor (cursor);
181 const graphics_object& obj, QMouseEvent *event)
185 octave::autolock guard (gh_mgr.graphics_lock ());
190 Matrix children = obj.get_properties ().get_children ();
193 for (
int i = 0; i < num_children; i++)
195 graphics_object childObj (gh_mgr.get_object (children(i)));
197 if (childObj.isa (
"axes"))
200 Matrix x_zlim = ap.get_transform_zlim ();
201 graphics_xform x_form = ap.get_transform ();
203 ColumnVector p1 = x_form.untransform (event->x (), event->y (),
205 ColumnVector p2 = x_form.untransform (event->x (), event->y (),
210 cp(0, 0) = p1(0); cp(0, 1) = p1(1); cp(0, 2) = p1(2);
211 cp(1, 0) = p2(0); cp(1, 1) = p2(1); cp(1, 2) = p2(2);
213 emit
gh_set_event (childObj.get_handle (),
"currentpoint", cp,
221 const graphics_object& obj)
225 octave::autolock guard (gh_mgr.graphics_lock ());
230 Matrix children = obj.get_properties ().get_children ();
233 for (
int i = 0; i < num_children; i++)
235 graphics_object childObj (gh_mgr.get_object (children(i)));
237 if (childObj.isa (
"axes"))
242 QPoint p =
w->mapFromGlobal (QCursor::pos ());
244 Matrix x_zlim = ap.get_transform_zlim ();
245 graphics_xform x_form = ap.get_transform ();
247 ColumnVector p1 = x_form.untransform (p.x (), p.y (), x_zlim(0));
248 ColumnVector p2 = x_form.untransform (p.x (), p.y (), x_zlim(1));
252 cp(0, 0) = p1(0); cp(0, 1) = p1(1); cp(0, 2) = p1(2);
253 cp(1, 0) = p2(0); cp(1, 1) = p2(1); cp(1, 2) = p2(2);
255 emit
gh_set_event (childObj.get_handle (),
"currentpoint", cp,
264 octave::autolock guard (gh_mgr.graphics_lock ());
267 ap.clear_zoom_stack (
false);
269 ap.set_xlimmode (
"auto");
270 ap.set_ylimmode (
"auto");
271 ap.set_zlimmode (
"auto");
281 octave::autolock guard (gh_mgr.graphics_lock ());
295 = Utils::properties<figure> (figObj).get___pan_mode__ ();
307 = Utils::properties<figure> (figObj).get___pan_mode__ ();
319 = Utils::properties<figure> (figObj).get___zoom_mode__ ();
331 = Utils::properties<figure> (figObj).get___zoom_mode__ ();
340 graphics_object& currentObj, graphics_object& axesObj,
341 bool axes_only, std::vector<std::string> omit)
344 Matrix children = obj.get_properties ().get_all_children ();
349 for (
int i = 0; i < num_children; i++)
351 graphics_object childObj (gh_mgr.get_object (children(i)));
353 if (childObj.isa (
"axes"))
355 auto p = omit.begin ();
356 bool omitfound =
false;
357 while (p != omit.end () && ! omitfound)
359 omitfound = (childObj.get (
"tag").string_value () == *p);
363 axesList.append (childObj);
365 else if (childObj.isa (
"uicontrol") || childObj.isa (
"uipanel")
366 || childObj.isa (
"uibuttongroup") || childObj.isa (
"uitable"))
368 Matrix bb = childObj.get_properties ().get_boundingbox (
false);
369 QRectF
r (bb(0), bb(1), bb(2), bb(3));
371 r.adjust (-5, -5, 5, 5);
373 bool rect_contains_pos =
r.contains (event->localPos ());
374 if (rect_contains_pos)
376 currentObj = childObj;
384 QPoint pt =
event->pos ();
387 it != axesList.end (); ++it)
393 Matrix xlim = ap.get_xlim ().matrix_value ();
394 Matrix ylim = ap.get_ylim ().matrix_value ();
396 if (xlim(0) < p0(0) && xlim(1) > p0(0)
397 && ylim(0) < p0(1) && ylim(1) > p0(1))
404 else if (! currentObj)
407 it != axesList.end (); ++it)
418 else if (it->get_properties ().is_hittest ())
420 Matrix bb = it->get_properties ().get_boundingbox (
true);
421 QRectF
r (bb(0), bb(1), bb(2), bb(3));
425 r.adjust (-20, -20, 20, 20);
427 bool rect_contains_pos =
r.contains (event->localPos ());
428 if (rect_contains_pos)
432 if (axesObj && currentObj)
443 octave::autolock guard (gh_mgr.graphics_lock ());
445 graphics_object ax = gh_mgr.get_object (
m_mouseAxes);
476 graphics_object figObj (ax.get_ancestor (
"figure"));
478 std::string mode =
pan_mode (figObj);
485 ap.translate_view (mode, p0(0), p1(0), p0(1), p1(1));
500 graphics_object obj = gh_mgr.get_object (
m_handle);
502 if (obj.valid_object ())
504 graphics_object figObj (obj.get_ancestor (
"figure"));
506 if (figObj.valid_object ()
507 && ! figObj.get (
"windowbuttonmotionfcn").isempty ())
511 "windowbuttonmotionfcn");
517 graphics_object obj = gh_mgr.get_object (
m_handle);
518 graphics_object figObj = obj.get_ancestor (
"figure");
520 if (figObj.valid_object () && obj.valid_object ())
522 graphics_object currentObj, axesObj;
523 std::vector<std::string> omit = {
"legend",
"colorbar",
"scribeoverlay"};
526 if (axesObj.valid_object ())
552 switch (event->button ())
558 case Qt::MiddleButton:
562 case Qt::RightButton:
578 octave::autolock guard (gh_mgr.graphics_lock ());
580 graphics_object obj = gh_mgr.get_object (
m_handle);
582 bool isdblclick = (
event->type () == QEvent::MouseButtonDblClick);
584 if (obj.valid_object ())
586 graphics_object figObj (obj.get_ancestor (
"figure"));
591 graphics_object root = gh_mgr.get_object (0);
592 Utils::properties<root_figure> (root)
593 .set_currentfigure (figObj.get_handle ().as_octave_value ());
596 graphics_object currentObj, axesObj;
605 if (! currentObj.valid_object ())
607 else if (! currentObj.get_properties ().is_hittest ())
611 graphics_object tmpgo;
612 tmpgo = gh_mgr.get_object (currentObj.get_parent ());
613 while (tmpgo && ! tmpgo.get_properties ().is_hittest ())
614 tmpgo = gh_mgr.get_object (tmpgo.get_parent ());
616 if (tmpgo && tmpgo.get_handle () != 0.0)
619 currentObj = graphics_object ();
623 bool valid_axes = axesObj.valid_object ()
624 && axesObj.get_properties ().handlevisibility_is (
"on")
625 && axesObj.get_properties ().get_tag () !=
"legend"
626 && axesObj.get_properties ().get_tag () !=
"colorbar";
629 Utils::properties<figure> (figObj)
630 .set_currentaxes (axesObj.get_handle ().as_octave_value ());
639 switch (newMouseMode)
644 auto& fprop = Utils::properties<figure> (figObj);
647 && currentObj.get_properties ().handlevisibility_is (
"on"))
648 fprop.set_currentobject (currentObj.get_handle ()
649 .as_octave_value ());
651 fprop.set_currentobject (
Matrix ());
654 emit
gh_set_event (figObj.get_handle (),
"selectiontype",
661 "windowbuttondownfcn",
666 if (currentObj && ! currentObj.get (
"buttondownfcn").isempty ())
669 else if (figObj && ! figObj.get (
"buttondownfcn").isempty ())
674 if (currentObj && event->button () == Qt::RightButton)
676 currentObj.get_properties (),
677 event->globalPos ());
683 if (event->modifiers () == Qt::NoModifier)
685 switch (event->buttons ())
703 bool redraw_figure =
true;
707 if (event->button () == Qt::LeftButton)
715 redraw_figure =
false;
718 else if (event->modifiers () == Qt::NoModifier)
720 switch (event->buttons ())
729 case Qt::RightButton:
740 case Qt::MiddleButton:
743 Utils::properties<axes> (axesObj);
750 redraw_figure =
false;
754 else if (event->modifiers () == Qt::ShiftModifier)
756 switch (event->buttons ())
769 redraw_figure =
false;
794 octave::autolock guard (gh_mgr.graphics_lock ());
796 graphics_object ax = gh_mgr.get_object (
m_mouseAxes);
798 if (ax.valid_object ())
802 graphics_object obj = gh_mgr.get_object (
m_handle);
804 graphics_object figObj (obj.get_ancestor (
"figure"));
812 ColumnVector p1 = ap.pixel2coord (event->x (),
event->y ());
814 ap.zoom_about_point (zm, p1(0), p1(1), factor);
831 ap.zoom (zm, xl, yl);
839 octave::autolock guard (gh_mgr.graphics_lock ());
841 graphics_object obj = gh_mgr.get_object (
m_handle);
843 if (obj.valid_object ())
845 graphics_object figObj (obj.get_ancestor (
"figure"));
853 octave::autolock guard (gh_mgr.graphics_lock ());
855 graphics_object figObj
856 = gh_mgr.get_object (
m_handle).get_ancestor (
"figure");
858 if (figObj.valid_object ())
863 Matrix bb = figObj.get (
"position").matrix_value ();
873 if (anno_dlg.exec () == QDialog::Accepted)
876 props.
prepend (figObj.get_handle ().as_octave_value ());
879 ([=] (octave::interpreter& interp)
883 interp.feval (
"annotation", props);
901 octave::autolock guard (gh_mgr.graphics_lock ());
903 graphics_object obj = gh_mgr.get_object (
m_handle);
905 if (obj.valid_object ())
909 graphics_object figObj (obj.get_ancestor (
"figure"));
911 graphics_object axesObj;
913 Matrix children = obj.get_properties ().get_children ();
916 for (
int i = 0; i < num_children; i++)
918 graphics_object childObj (gh_mgr.get_object (children(i)));
920 if (childObj.isa (
"axes"))
922 #if defined (HAVE_QWHEELEVENT_POSITION)
923 QPoint pos =
event->position().toPoint ();
925 QPoint pos =
event->pos ();
946 if (axesObj.get_properties ().handlevisibility_is (
"on"))
948 Utils::properties<figure> (figObj)
949 .set_currentaxes (axesObj.get_handle ().as_octave_value ());
953 #if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
954 if (event->angleDelta().y () > 0)
956 if (event->delta () > 0)
972 bool redrawFigure =
true;
974 switch (newMouseMode)
982 double wheel_zoom_speed = ap.get_mousewheelzoom ();
986 ? 1 / (1.0 - wheel_zoom_speed)
987 : 1.0 - wheel_zoom_speed);
991 ap.zoom (mode, factor);
999 #if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
1000 double factor = (
event->angleDelta().y () > 0 ? 0.1 : -0.1);
1002 double factor = (
event->delta () > 0 ? 0.1 : -0.1);
1005 if (event->modifiers () == Qt::NoModifier
1006 && mode !=
"horizontal")
1007 ap.pan (
"vertical", factor);
1008 else if (event->modifiers () == Qt::ShiftModifier
1009 && mode !=
"vertical")
1010 ap.pan (
"horizontal", factor);
1015 redrawFigure =
false;
1023 if (! figObj.get (
"windowscrollwheelfcn").isempty ())
1039 octave::autolock guard (gh_mgr.graphics_lock ());
1041 graphics_object obj = gh_mgr.get_object (
m_handle);
1043 if (obj.valid_object ())
1045 graphics_object figObj (obj.get_ancestor (
"figure"));
1051 emit
gh_set_event (figObj.get_handle (),
"currentcharacter",
1052 eventData.
getfield (
"Character"),
false);
1070 octave::autolock guard (gh_mgr.graphics_lock ());
1072 graphics_object obj = gh_mgr.get_object (
m_handle);
1074 if (obj.valid_object ())
1076 graphics_object figObj (obj.get_ancestor (
"figure"));
1090 const std::string& )
1093 return new GLCanvas (oct_qobj, interp, handle, parent);
static std::string pan_mode(const graphics_object figObj)
static bool pan_enabled(const graphics_object figObj)
static double button_number(QMouseEvent *event)
static bool zoom_enabled(const graphics_object figObj)
static std::string zoom_mode(const graphics_object figObj)
static void autoscale_axes(gh_manager &gh_mgr, axes::properties &ap)
charNDArray max(char d, const charNDArray &m)
charNDArray min(char d, const charNDArray &m)
OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type numel(void) const
Number of elements in the array.
void select_object(graphics_object obj, QMouseEvent *event, graphics_object ¤tObj, graphics_object &axesObj, bool axes_only=false, std::vector< std::string > omit=std::vector< std::string >())
static Canvas * create(octave::base_qobject &oct_qobj, octave::interpreter &interp, const graphics_handle &handle, QWidget *parent, const std::string &name)
QCursor make_cursor(const QString &name, int hot_x=-1, int hot_y=-1)
octave::base_qobject & m_octave_qobj
void canvasMouseReleaseEvent(QMouseEvent *event)
octave::interpreter & m_interpreter
void canvasPaintEvent(void)
void canvasMouseDoubleClickEvent(QMouseEvent *event)
bool canvasKeyReleaseEvent(QKeyEvent *event)
virtual void draw(const graphics_handle &handle)=0
void redraw(bool sync=false)
void blockRedraw(bool block=true)
void interpreter_event(const octave::fcn_callback &fcn)
virtual void drawZoomBox(const QPoint &p1, const QPoint &p2)=0
void canvasWheelEvent(QWheelEvent *event)
void setCursor(MouseMode mode, std::string fallback, QImage cdata, Matrix hotspot)
graphics_handle m_mouseAxes
void gh_set_event(const graphics_handle &h, const std::string &name, const octave_value &value)
void gh_callback_event(const graphics_handle &h, const std::string &name)
virtual graphics_object selectFromAxes(const graphics_object &ax, const QPoint &pt)=0
void updateCurrentPoint(const graphics_object &fig, const graphics_object &obj, QMouseEvent *event)
virtual QWidget * qWidget(void)=0
void canvasMousePressEvent(QMouseEvent *event)
void canvasMouseMoveEvent(QMouseEvent *event)
bool canvasKeyPressEvent(QKeyEvent *event)
octave_value_list get_properties() const
const octave_value & contents(const_iterator p) const
octave_value getfield(const std::string &key) const
octave_value_list & prepend(const octave_value &val)
OCTINTERP_API octave_scalar_map scalar_map_value(void) const
std::string string_value(bool force=false) const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
octave_handle graphics_handle
std::complex< double > w(std::complex< double > z, double relerr=0)
Matrix figureCurrentPoint(const graphics_object &fig, QMouseEvent *event)
octave_scalar_map makeKeyEventStruct(QKeyEvent *event)
std::string figureSelectionType(QMouseEvent *event, bool isDoubleClick)
octave_scalar_map makeScrollEventStruct(QWheelEvent *event)
T::properties & properties(graphics_object obj)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.