37 #if defined (HAVE_CONFIG_H)
45 #if defined (HAVE_FLTK)
47 #if defined (HAVE_X_WINDOWS)
48 # include <X11/Xlib.h>
60 # define WIN32_LEAN_AND_MEAN
64 #include <FL/Fl_Box.H>
65 #include <FL/Fl_Button.H>
66 #include <FL/Fl_Choice.H>
67 #include <FL/Fl_File_Chooser.H>
68 #include <FL/Fl_Gl_Window.H>
70 #include <FL/Fl_Menu_Bar.H>
71 #include <FL/Fl_Menu_Button.H>
72 #include <FL/Fl_Output.H>
73 #include <FL/Fl_Window.H>
74 #include <FL/fl_ask.H>
75 #include <FL/fl_draw.H>
92 #include "builtin-defun-decls.h"
108 #define FLTK_GRAPHICS_TOOLKIT_NAME "fltk"
110 const char *help_text =
"\
111 Keyboard Shortcuts\n\
119 mouse wheel - zoom\n\
120 right drag - rectangle zoom\n\
121 left double click - autoscale\n\
124 class OpenGL_fltk :
public Fl_Gl_Window
128 OpenGL_fltk (
int xx,
int yy,
int ww,
int hh,
double num)
129 : Fl_Gl_Window (xx, yy, ww, hh, nullptr), m_number (num),
130 m_glfcns (), m_renderer (m_glfcns), m_in_zoom (false), m_zoom_box ()
132 #if defined (HAVE_OPENGL)
135 mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE);
144 ~OpenGL_fltk (
void) =
default;
153 bool zoom (
void) {
return m_in_zoom; }
154 void set_zoom_box (
const Matrix& zb) { m_zoom_box = zb; }
156 void print (
const std::string& cmd,
const std::string& term)
167 m_renderer.draw (gh_mgr.
get_object (m_number));
169 return m_renderer.get_pixels (
w (), h ());
172 void resize (
int xx,
int yy,
int ww,
int hh)
174 #if defined (HAVE_OPENGL)
176 Fl_Gl_Window::resize (xx, yy, ww, hh);
180 octave_unused_parameter (xx);
181 octave_unused_parameter (yy);
182 octave_unused_parameter (ww);
183 octave_unused_parameter (hh);
193 bool renumber (
double new_number)
197 if (m_number != new_number)
199 m_number = new_number;
220 #if defined (HAVE_OPENGL)
248 Matrix overlaycolor (3, 1);
249 overlaycolor(0) = 0.45;
250 overlaycolor(1) = 0.62;
251 overlaycolor(2) = 0.81;
252 double overlayalpha = 0.1;
253 Matrix bordercolor = overlaycolor;
254 double borderalpha = 0.9;
255 double borderwidth = 1.5;
258 m_zoom_box(0), m_zoom_box(1),
259 m_zoom_box(2), m_zoom_box(3),
260 overlaycolor, overlayalpha,
261 bordercolor, borderalpha, borderwidth);
264 int handle (
int event)
266 #if defined (HAVE_OPENGL)
271 cursor (FL_CURSOR_CROSS);
275 cursor (FL_CURSOR_DEFAULT);
279 return Fl_Gl_Window::handle (event);
283 octave_unused_parameter (event);
294 void script_cb (Fl_Widget *,
void *data)
303 fltk_uimenu (
int xx,
int yy,
int ww,
int hh)
304 : m_menubar (new Fl_Menu_Bar (xx, yy, ww, hh))
307 int items_to_show (
void)
310 int len = m_menubar->size ();
312 for (
int t = 0; t <
len; t++)
314 const Fl_Menu_Item *
m
315 =
static_cast<const Fl_Menu_Item *
> (&(m_menubar->menu ()[t]));
317 if (
m->label () &&
m->visible ())
327 m_menubar->redraw ();
333 m_menubar->redraw ();
336 bool is_visible (
void)
338 return m_menubar->visible ();
341 int find_index_by_name (
const std::string& findname)
349 std::string menupath;
350 for (
int t = 0; t < m_menubar->size (); t++)
352 Fl_Menu_Item *
m =
const_cast<Fl_Menu_Item *
> (&(m_menubar->menu ()[t]));
356 if (! menupath.empty ())
358 menupath +=
m->label ();
360 if (menupath == findname)
368 size_t idx = menupath.find_last_of (
'/');
369 if (idx != std::string::npos)
370 menupath.erase (idx);
376 std::string itempath = menupath;
377 if (! itempath.empty ())
379 itempath +=
m->label ();
381 if (itempath == findname)
391 Matrix retval = do_find_uimenu_children (uimenu_childs);
398 Matrix retval = do_find_uimenu_children (uimenu_childs);
402 Matrix do_find_uimenu_children (
Matrix uimenu_childs)
const
417 uimenu_childs(k) = uimenu_childs(ii);
422 uimenu_childs.
resize (k, 1);
429 retval(ii) = uimenu_childs (sidx(ii));
436 std::string fltk_label = uimenup.get___fltk_label__ ();
437 int idx = find_index_by_name (fltk_label.c_str ());
440 m_menubar->remove (idx);
445 std::string fltk_label = uimenup.get___fltk_label__ ();
446 if (! fltk_label.empty ())
448 Fl_Menu_Item *item =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
452 std::string acc = uimenup.get_accelerator ();
453 if (acc.length () > 0)
455 int key = FL_CTRL + acc[0];
456 item->shortcut (key);
464 std::string fltk_label = uimenup.get___fltk_label__ ();
465 if (! fltk_label.empty ())
468 =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
471 if (! uimenup.get_callback ().isempty ())
472 item->
callback (
static_cast<Fl_Callback *
> (script_cb),
473 static_cast<void *
> (&uimenup));
475 item->callback (
nullptr,
static_cast<void *
> (
nullptr));
482 std::string fltk_label = uimenup.get___fltk_label__ ();
483 if (! fltk_label.empty ())
486 =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
489 if (uimenup.is_enable ())
499 std::string fltk_label = uimenup.get___fltk_label__ ();
500 if (! fltk_label.empty ())
503 =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
506 Matrix rgb = uimenup.get_foregroundcolor_rgb ();
508 uchar
r =
static_cast<uchar
> (
std::floor (rgb (0) * 255));
509 uchar g =
static_cast<uchar
> (
std::floor (rgb (1) * 255));
510 uchar b =
static_cast<uchar
> (
std::floor (rgb (2) * 255));
512 item->labelcolor (fl_rgb_color (
r, g, b));
522 std::string fltk_label = uimenup.get___fltk_label__ ();
523 if (! fltk_label.empty ())
525 int itemflags = 0, idx;
526 int curr_idx = find_index_by_name (fltk_label.c_str ());
528 for (idx = curr_idx - 1; idx >= 0; idx--)
531 =
const_cast<Fl_Menu_Item *
> (&m_menubar->menu () [idx]);
532 itemflags = item->flags;
537 if (idx >= 0 && idx < m_menubar->size ())
539 if (uimenup.is_separator ())
541 if (! (itemflags & FL_SUBMENU))
542 m_menubar->mode (idx, itemflags | FL_MENU_DIVIDER);
545 m_menubar->mode (idx, itemflags & (~FL_MENU_DIVIDER));
552 std::string fltk_label = uimenup.get___fltk_label__ ();
553 if (! fltk_label.empty ())
556 =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
559 if (uimenup.is_visible ())
576 std::string fltk_label = uimenup.get___fltk_label__ ();
578 if (! fltk_label.empty ())
580 bool item_added =
false;
583 const Fl_Menu_Item *item
584 = m_menubar->find_item (fltk_label.c_str ());
589 size_t idx1 = fltk_label.find_last_of (
'(');
590 size_t idx2 = fltk_label.find_last_of (
')');
591 int len = idx2 - idx1;
595 std::string valstr = fltk_label.substr (idx1 + 1,
len - 1);
596 fltk_label.erase (idx1,
len + 1);
597 val = atoi (valstr.c_str ());
598 if (val > 0 && val < 99)
601 std::ostringstream valstream;
603 fltk_label +=
'(' + valstream.str () +
')';
607 Matrix uimenu_ch = find_uimenu_children (uimenup);
612 if (
len == 0 && uimenup.is_checked ())
613 flags += FL_MENU_TOGGLE + FL_MENU_VALUE;
614 m_menubar->add (fltk_label.c_str (),
615 0,
nullptr,
nullptr, flags);
619 while (! item_added);
620 uimenup.set___fltk_label__ (fltk_label);
626 std::vector<int> delayed_menus;
627 Matrix kids = find_uimenu_children (uimenup);
629 std::string fltk_label = uimenup.get___fltk_label__ ();
633 update_foregroundcolor (uimenup);
634 update_callback (uimenup);
635 update_accelerator (uimenup);
636 update_enable (uimenup);
637 update_visible (uimenup);
638 update_seperator (uimenup);
652 int pos = kprop.get_position ();
654 delayed_menus.push_back ((
len - (ii + 1)));
663 for (
size_t ii = 0; ii < delayed_menus.size (); ii++)
672 update_position (kprop, ++count);
679 std::vector<int> delayed_menus;
680 Matrix kids = find_uimenu_children (figp);
698 int pos = kprop.get_position ();
700 delayed_menus.push_back ((
len - (ii + 1)));
704 update_position (kprop, ++count);
710 for (
size_t ii = 0; ii < delayed_menus.size (); ii++)
719 update_position (kprop, ++count);
724 template <
typename T_prop>
725 void remove_from_menu (T_prop& prop)
728 std::string
type = prop.get_type ();
729 kids = find_uimenu_children (prop);
742 remove_from_menu (kprop);
746 if (
type ==
"uimenu")
748 else if (
type ==
"figure")
754 fltk_uimenu (
const fltk_uimenu&) =
delete;
756 fltk_uimenu operator = (
const fltk_uimenu&) =
delete;
765 Fl_Menu_Bar *m_menubar;
768 #if defined (HAVE_X_WINDOWS)
770 xerror_handler (Display *, XErrorEvent *)
776 class plot_window :
public Fl_Window
778 friend class fltk_uimenu;
784 : Fl_Window (xx, yy, ww, hh + m_menu_h + m_status_h + 2,
"octave"),
785 m_window_label (), m_fp (xfp), m_uimenu (nullptr), m_canvas (nullptr),
786 m_autoscale (nullptr), m_togglegrid (nullptr), m_panzoom (nullptr),
787 m_rotate (nullptr), m_help (nullptr), m_status (nullptr),
788 m_resize_dummy (nullptr), m_ax_obj (), m_pos_x (0), m_pos_y (0)
790 callback (window_close,
static_cast<void *
> (
this));
794 m_resize_dummy =
new Fl_Box (5 * m_status_h, m_menu_h,
795 ww - 5 * m_status_h, hh);
799 resizable (m_resize_dummy);
809 m_uimenu =
new fltk_uimenu (0, 0, ww, m_menu_h);
810 m_canvas =
new OpenGL_fltk (0, m_menu_h, ww, hh, number ());
816 int toolbar_y = m_menu_h + hh + 1;
817 m_status =
new Fl_Output (5 * m_status_h, toolbar_y,
818 ww - 5 * m_status_h, m_status_h,
"");
820 m_status->textcolor (FL_BLACK);
821 m_status->color (FL_GRAY);
822 m_status->textfont (FL_COURIER);
823 m_status->textsize (10);
824 m_status->box (FL_ENGRAVED_BOX);
826 m_autoscale =
new Fl_Button (0, toolbar_y, m_status_h, m_status_h,
"A");
827 m_autoscale->callback (button_callback,
static_cast<void *
> (
this));
828 m_autoscale->tooltip (
"Autoscale");
830 m_togglegrid =
new Fl_Button (m_status_h, toolbar_y, m_status_h, m_status_h,
"G");
831 m_togglegrid->callback (button_callback,
static_cast<void *
> (
this));
832 m_togglegrid->tooltip (
"Toggle Grid");
834 m_panzoom =
new Fl_Button (2* m_status_h, toolbar_y, m_status_h, m_status_h,
"P");
835 m_panzoom->callback (button_callback,
static_cast<void *
> (
this));
836 m_panzoom->tooltip (
"Mouse Pan/Zoom");
838 m_rotate =
new Fl_Button (3 * m_status_h, toolbar_y, m_status_h, m_status_h,
"R");
839 m_rotate->callback (button_callback,
static_cast<void *
> (
this));
840 m_rotate->tooltip (
"Mouse Rotate");
842 m_help =
new Fl_Button (4 * m_status_h, toolbar_y, m_status_h, m_status_h,
"?");
843 m_help->callback (button_callback,
static_cast<void *
> (
this));
844 m_help->tooltip (
"Help");
849 m_uimenu->add_to_menu (m_fp);
850 if (m_fp.menubar_is (
"none") || ! m_uimenu->items_to_show ())
853 update_boundingbox (
internal);
855 if (m_fp.is_visible ())
867 #if defined (HAVE_X_WINDOWS)
868 std::string show_gui_msgs
872 if (show_gui_msgs.empty ())
873 XSetErrorHandler (xerror_handler);
876 if (m_fp.get_currentaxes ().ok ())
885 plot_window (
const plot_window&) =
delete;
887 plot_window& operator = (
const plot_window&) =
delete;
899 double number (
void) {
return m_fp.get___myhandle__ ().value (); }
901 void renumber (
double new_number)
904 error (
"unable to renumber figure");
906 if (m_canvas->renumber (new_number))
910 void print (
const std::string& cmd,
const std::string& term)
912 m_canvas->print (cmd, term);
917 return m_canvas->get_pixels ();
920 void show_menubar (
void)
923 update_toolbar_position ();
926 void hide_menubar (
void)
929 update_toolbar_position ();
942 std::string fltk_label = uimenup.get___fltk_label__ ();
949 case base_properties::ID_BEINGDELETED:
950 m_uimenu->remove_from_menu (uimenup);
953 case base_properties::ID_VISIBLE:
954 m_uimenu->update_visible (uimenup);
957 case uimenu::properties::ID_ACCELERATOR:
958 m_uimenu->update_accelerator (uimenup);
961 case uimenu::properties::ID_CALLBACK:
962 m_uimenu->update_callback (uimenup);
965 case uimenu::properties::ID_CHECKED:
966 m_uimenu->add_to_menu (figp);
969 case uimenu::properties::ID_ENABLE:
970 m_uimenu->update_enable (uimenup);
973 case uimenu::properties::ID_FOREGROUNDCOLOR:
974 m_uimenu->update_foregroundcolor (uimenup);
977 case uimenu::properties::ID_LABEL:
978 m_uimenu->add_to_menu (figp);
981 case uimenu::properties::ID_POSITION:
982 m_uimenu->add_to_menu (figp);
985 case uimenu::properties::ID_SEPARATOR:
986 m_uimenu->update_seperator (uimenup);
990 if (m_uimenu->items_to_show ())
997 void show_canvas (
void)
999 if (! m_canvas->can_do ())
1000 error (
"unable to plot due to insufficient OpenGL support");
1001 else if (m_fp.is_visible ())
1004 m_canvas->make_current ();
1008 void hide_canvas (
void)
1017 void update_toolbar_position ()
1019 int old_canvas_h = m_canvas->h ();
1022 update_boundingbox (
true);
1023 m_canvas->resize (0, menu_dy (),
w (), old_canvas_h);
1025 int toolbar_y = m_canvas->h () + menu_dy () + 1;
1026 m_autoscale->position (0, toolbar_y);
1027 m_togglegrid->position (m_status_h, toolbar_y);
1028 m_panzoom->position (2 * m_status_h, toolbar_y);
1029 m_rotate->position (3 * m_status_h, toolbar_y);
1030 m_help->position (4 * m_status_h, toolbar_y);
1031 m_status->resize (5 * m_status_h, toolbar_y,
1032 w () - 5 * m_status_h, m_status_h);
1040 pos(1) += menu_dy ();
1041 pos(3) -= menu_dy () + m_status_h + 2;
1048 outerpos(1) -= menu_dy ();
1049 outerpos(3) += menu_dy () + m_status_h + 2;
1058 void update_boundingbox (
bool internal)
1060 Matrix bb = m_fp.get_boundingbox (
internal);
1062 bb = position2outerposition (bb);
1063 resize (bb(0), bb(1), bb(2), bb(3));
1066 void mark_modified (
void)
1068 m_canvas->redraw ();
1071 void set_name (
void)
1073 m_window_label = m_fp.get_title ();
1074 label (m_window_label.c_str ());
1081 std::string m_window_label;
1087 static const int m_status_h = 20;
1090 static const int m_menu_h = 25;
1092 fltk_uimenu *m_uimenu;
1094 OpenGL_fltk *m_canvas;
1096 Fl_Button *m_autoscale;
1097 Fl_Button *m_togglegrid;
1098 Fl_Button *m_panzoom;
1099 Fl_Button *m_rotate;
1101 Fl_Output *m_status;
1103 Fl_Box *m_resize_dummy;
1111 static void window_close (Fl_Widget *,
void *data)
1114 args(0) =
static_cast<plot_window *
> (data)->number ();
1119 static void button_callback (Fl_Widget *ww,
void *data)
1121 static_cast<plot_window *
> (data)->button_press (ww, data);
1124 void button_press (Fl_Widget *widg,
void *)
1126 if (widg == m_autoscale)
1128 else if (widg == m_togglegrid)
1130 else if (widg == m_panzoom)
1131 m_fp.set___mouse_mode__ (
"pan");
1132 else if (widg == m_rotate)
1133 m_fp.set___mouse_mode__ (
"rotate");
1134 else if (widg == m_help)
1135 fl_message (
"%s", help_text);
1138 void set_on_ax_obj (
const std::string&
name,
const std::string& value)
1141 if (m_ax_obj && m_ax_obj.
isa (
"axes")
1167 void axis_auto (
void)
1170 if (m_fp.get_currentaxes ().ok ())
1172 args(0) = m_fp.get_currentaxes ().as_octave_value ();
1179 void toggle_grid (
void)
1182 if (m_fp.get_currentaxes ().ok ())
1183 args(0) = m_fp.get_currentaxes ().as_octave_value ();
1189 void pixel2pos (
const graphics_handle& ax,
int px,
int py,
double& xx,
1194 pixel2pos (gh_mgr.
get_object (ax), px, py, xx, yy);
1200 if (ax && ax.
isa (
"axes"))
1217 for (
int k = 0; k <
len; k++)
1229 if (bb(0) <= px && px < (bb(0)+bb(2))
1230 && bb(1) <= py && py < (bb(1)+bb(3)))
1237 return m_fp.get_currentaxes ();
1241 int px1 = -1,
int py1 = -1)
1245 pixel2status (gh_mgr.
get_object (ax), px0, py0, px1, py1);
1249 int px1 = -1,
int py1 = -1)
1251 double x0, y0, x1, y1;
1253 std::stringstream cbuf;
1256 pixel2pos (ax, px0, py0, x0, y0);
1257 cbuf <<
'[' << x0 <<
", " << y0 <<
']';
1260 pixel2pos (ax, px1, py1, x1, y1);
1261 cbuf <<
" -> ["<< x1 <<
", " << y1 <<
']';
1264 m_status->value (cbuf.str ().c_str ());
1269 if (ax && ax.
isa (
"axes"))
1273 std::stringstream cbuf;
1278 cbuf <<
"[azimuth: " << v(0) <<
", elevation: " << v(1) <<
']';
1280 m_status->value (cbuf.str ().c_str ());
1284 void set_currentpoint (
int px,
int py)
1286 if (! m_fp.is_beingdeleted ())
1289 m_fp.set_currentpoint (pos);
1299 rp.set_currentfigure (m_fp.get___myhandle__ ().value ());
1325 ap.set_currentpoint (pos);
1326 if (ap.get_tag () !=
"legend" && ap.get_tag () !=
"colorbar")
1327 m_fp.set_currentaxes (ap.get___myhandle__ ().value ());
1333 if (m_uimenu->is_visible ())
1346 std::string key_str;
1347 std::ostringstream tmp_str;
1349 if (e_key == FL_Escape)
1351 else if (e_key == FL_Tab)
1353 else if (e_key == FL_Caps_Lock)
1354 key_str =
"capslock";
1355 else if (e_key == FL_Shift_L || e_key == FL_Shift_R)
1357 else if (e_key == FL_Control_L || e_key == FL_Control_R)
1358 key_str =
"control";
1359 else if (e_key == FL_Meta_L || e_key == FL_Meta_R)
1360 key_str =
"windows";
1361 else if (e_key == FL_Alt_L || e_key == FL_Alt_R)
1363 else if (e_key == 32)
1365 else if (e_key == FL_Enter)
1367 else if (e_key == FL_BackSpace)
1368 key_str =
"backspace";
1369 else if (e_key == FL_Print)
1370 key_str =
"printscreen";
1371 else if (e_key == FL_Pause)
1373 else if (e_key == FL_Home)
1375 else if (e_key == FL_End)
1377 else if (e_key == FL_Insert)
1379 else if (e_key == FL_Page_Up)
1381 else if (e_key == FL_Delete)
1383 else if (e_key == FL_Page_Down)
1384 key_str =
"pagedown";
1385 else if (e_key == FL_Left)
1386 key_str =
"leftarrow";
1387 else if (e_key == FL_Up)
1388 key_str =
"uparrow";
1389 else if (e_key == FL_Right)
1390 key_str =
"rightarrow";
1391 else if (e_key == FL_Down)
1392 key_str =
"downarrow";
1393 else if (e_key == FL_Num_Lock)
1394 key_str =
"numlock";
1395 else if (e_key == 0xffaf)
1397 else if (e_key == 0xffaa)
1398 key_str =
"multiply";
1399 else if (e_key == 0xffad)
1400 key_str =
"subtract";
1401 else if (e_key == 0xffab)
1403 else if (e_key == 0xff8d)
1405 else if (e_key == 0xffac)
1406 key_str =
"separator";
1407 else if (e_key >= 0xffb0 && e_key <= 0xffb9)
1409 tmp_str <<
"numpad" << (e_key - 0xffb0);
1410 key_str = tmp_str.str ();
1412 else if (e_key >= (FL_F + 1) && e_key <= (FL_F + 12))
1414 tmp_str <<
'f' << (e_key - FL_F);
1415 key_str = tmp_str.str ();
1417 else if (e_key ==
',')
1419 else if (e_key ==
'.')
1421 else if (e_key ==
'-')
1423 else if (e_key ==
'^' || e_key ==
'+' || e_key ==
'#'
1424 || e_key ==
'<' || e_key == 0xfe03 )
1426 else if (isalnum (e_key))
1427 key_str = std::tolower (e_key);
1428 else if (isprint (e_text[0]))
1435 Cell modifier2cell (
int e_state)
1439 if (e_state & FL_SHIFT)
1440 mod.append (std::string (
"shift"));
1441 if (e_state & FL_CTRL)
1442 mod.append (std::string (
"control"));
1443 if (e_state & FL_ALT)
1444 mod.append (std::string (
"alt"));
1445 if (e_state & FL_COMMAND)
1446 mod.append (std::string (
"command"));
1450 void resize (
int xx,
int yy,
int ww,
int hh)
1452 Fl_Window::resize (xx, yy, ww, hh);
1487 bool rotate_enabled (
void)
1497 int handle (
int event)
1499 if (event == FL_FOCUS)
1504 if (! m_fp.is_beingdeleted ())
1509 static bool key_resent_detected =
false;
1518 static int last_event_key = 0;
1519 static char last_event_text = 0;
1521 int e_key = Fl::event_key ();
1522 char e_text = Fl::event_text ()[0];
1523 key_resent_detected = (e_key == last_event_key
1524 && std::tolower (last_event_text) == std::tolower (e_text)
1525 && ((islower (last_event_text) && isupper (e_text))
1526 || (isupper (last_event_text) && islower (e_text))));
1528 last_event_key = e_key;
1529 last_event_text = e_text;
1535 int e_key = Fl::event_key ();
1536 const char *e_text = Fl::event_text ();
1537 int e_state = Fl::event_state ();
1540 m_fp.set_currentcharacter (std::string (e_text));
1542 if (! m_fp.get_keypressfcn ().isempty ()
1546 if (Fl::event_inside (m_canvas))
1548 m_pos_x = Fl::event_x ();
1549 m_pos_y = Fl::event_y () - menu_dy ();
1551 set_currentpoint (m_pos_x, m_pos_y);
1553 gh = pixel2axes_or_ca (m_pos_x, m_pos_y);
1558 set_axes_currentpoint (m_ax_obj, m_pos_x, m_pos_y);
1562 m_fp.execute_keypressfcn (evt);
1580 m_fp.set___mouse_mode__ (
"pan");
1585 m_fp.set___mouse_mode__ (
"rotate");
1593 int e_key = Fl::event_key ();
1594 int e_state = Fl::event_state ();
1596 if (key_resent_detected && Fl::event_length () == 1)
1601 tmp_e_text[0] = Fl::event_text ()[0];
1604 if (std::islower (tmp_e_text[0]))
1605 tmp_e_text[0] = std::toupper (tmp_e_text[0]);
1607 tmp_e_text[0] = std::tolower (tmp_e_text[0]);
1608 evt = format_key_event (e_key, tmp_e_text, e_state);
1612 const char *e_text = Fl::event_text ();
1613 evt = format_key_event (e_key, e_text, e_state);
1616 if (! m_fp.get_keyreleasefcn ().isempty ()
1618 m_fp.execute_keyreleasefcn (evt);
1625 if (Fl::event_inside (m_canvas))
1629 pixel2status (pixel2axes_or_ca (Fl::event_x (),
1630 Fl::event_y () - menu_dy ()),
1631 Fl::event_x (), Fl::event_y () - menu_dy ());
1635 m_pos_x = Fl::event_x ();
1636 m_pos_y = Fl::event_y () - menu_dy ();
1638 set_currentpoint (m_pos_x, m_pos_y);
1640 if (Fl::event_clicks ())
1641 m_fp.set_selectiontype (
"open");
1642 else if (Fl::event_button () == FL_MIDDLE_MOUSE
1643 || (Fl::event_button () == FL_LEFT_MOUSE
1644 && Fl::event_shift ()))
1645 m_fp.set_selectiontype (
"extend");
1646 else if (Fl::event_button () == FL_RIGHT_MOUSE
1647 || (Fl::event_button () == FL_LEFT_MOUSE
1648 && Fl::event_ctrl ()))
1649 m_fp.set_selectiontype (
"alt");
1651 m_fp.set_selectiontype (
"normal");
1653 gh = pixel2axes_or_ca (m_pos_x, m_pos_y);
1658 set_axes_currentpoint (m_ax_obj, m_pos_x, m_pos_y);
1663 if (! m_fp.get_windowbuttondownfcn ().isempty ())
1664 m_fp.execute_windowbuttondownfcn (Fl::event_button ());
1671 if (! props.get_buttondownfcn ().isempty ())
1672 props.execute_buttondownfcn (Fl::event_button ());
1676 else if (! m_fp.get_buttondownfcn ().isempty ())
1677 m_fp.execute_buttondownfcn (Fl::event_button ());
1682 if (! m_fp.get_windowbuttonmotionfcn ().isempty ())
1684 set_currentpoint (Fl::event_x (), Fl::event_y () - menu_dy ());
1685 m_fp.execute_windowbuttonmotionfcn ();
1688 if (Fl::event_button () == 1)
1690 if (m_ax_obj && m_ax_obj.
isa (
"axes"))
1695 if (ap.get_tag () !=
"legend")
1697 if (rotate_enabled ())
1698 view2status (m_ax_obj);
1700 pixel2status (m_ax_obj, m_pos_x, m_pos_y,
1702 Fl::event_y () - menu_dy ());
1704 double x0, y0, x1, y1;
1706 pixel2pos (m_ax_obj, m_pos_x, m_pos_y, x0, y0);
1707 pixel2pos (m_ax_obj, Fl::event_x (),
1708 Fl::event_y () - menu_dy (),
1717 else if (rotate_enabled ())
1720 daz = (Fl::event_x () - m_pos_x) / pos(2) * 360;
1721 del = (Fl::event_y () - menu_dy () - m_pos_y)
1729 Matrix pos = ap.get_position ().matrix_value ();
1730 pos(0) += double (Fl::event_x () - m_pos_x)
1732 pos(1) -= double (Fl::event_y () - menu_dy () - m_pos_y)
1734 ap.set_position (pos);
1737 m_pos_x = Fl::event_x ();
1738 m_pos_y = Fl::event_y () - menu_dy ();
1743 else if (Fl::event_button () == 3)
1745 pixel2status (m_ax_obj, m_pos_x, m_pos_y,
1746 Fl::event_x (), Fl::event_y () - menu_dy ());
1748 zoom_box(0) = m_pos_x;
1749 zoom_box(1) = m_pos_y;
1750 zoom_box(2) = Fl::event_x ();
1751 zoom_box(3) = Fl::event_y () - menu_dy ();
1752 m_canvas->set_zoom_box (zoom_box);
1753 m_canvas->zoom (
true);
1763 = gh_mgr.
get_object (pixel2axes_or_ca (Fl::event_x (),
1766 if (ax && ax.
isa (
"axes"))
1772 double wheel_zoom_speed = ap.get_mousewheelzoom ();
1775 const double factor = (Fl::event_dy () < 0
1776 ? 1 / (1.0 - wheel_zoom_speed)
1777 : 1.0 - wheel_zoom_speed);
1781 pixel2pos (ax, Fl::event_x (), Fl::event_y () - menu_dy (),
1795 if (! m_fp.get_windowbuttonupfcn ().isempty ())
1797 set_currentpoint (Fl::event_x (), Fl::event_y () - menu_dy ());
1798 m_fp.execute_windowbuttonupfcn ();
1801 if ((Fl::event_button () == 1) && Fl::event_clicks ())
1804 set_on_ax_obj (
"xlimmode",
"auto");
1805 set_on_ax_obj (
"ylimmode",
"auto");
1806 set_on_ax_obj (
"zlimmode",
"auto");
1810 if (Fl::event_button () == 3)
1813 if (m_canvas->zoom ())
1815 m_canvas->zoom (
false);
1817 if (m_ax_obj && m_ax_obj.
isa (
"axes"))
1821 pixel2pos (m_ax_obj, m_pos_x, m_pos_y, x0, y0);
1822 int pos_x1 = Fl::event_x ();
1823 int pos_y1 = Fl::event_y () - menu_dy ();
1824 pixel2pos (m_ax_obj, pos_x1, pos_y1, x1, y1);
1827 int dx =
abs (m_pos_x - pos_x1);
1828 int dy =
abs (m_pos_y - pos_y1);
1830 if ((dx > 4) && (dy > 4))
1852 ap.
zoom (
"both", xl, yl);
1863 return Fl_Window::handle (event);
1867 class figure_manager
1871 figure_manager (
void) =
default;
1877 figure_manager (
const figure_manager&) =
delete;
1879 figure_manager& operator = (
const figure_manager&) =
delete;
1881 ~figure_manager (
void)
1886 static bool instance_ok (
void)
1891 instance =
new figure_manager ();
1896 static void close_all (
void)
1899 instance->do_close_all ();
1905 instance->do_new_window (fp);
1908 static void delete_window (
int idx)
1911 instance->do_delete_window (idx);
1914 static void delete_window (
const std::string& idx_str)
1916 delete_window (str2idx (idx_str));
1919 static void renumber_figure (
const std::string& idx_str,
double new_number)
1922 instance->do_renumber_figure (str2idx (idx_str), new_number);
1925 static void toggle_window_visibility (
int idx,
bool is_visible)
1928 instance->do_toggle_window_visibility (idx, is_visible);
1931 static void toggle_window_visibility (
const std::string& idx_str,
1934 toggle_window_visibility (str2idx (idx_str), is_visible);
1937 static void mark_modified (
int idx)
1940 instance->do_mark_modified (idx);
1945 mark_modified (hnd2idx (gh));
1948 static void set_name (
int idx)
1951 instance->do_set_name (idx);
1954 static void set_name (
const std::string& idx_str)
1956 set_name (str2idx (idx_str));
1961 return instance_ok () ? instance->do_get_size (idx) :
Matrix ();
1970 const std::string& term)
1973 instance->do_print (hnd2idx (gh), cmd, term);
1980 retval = instance->do_get_pixels (hnd2idx (gh));
1989 instance->do_uimenu_update (hnd2idx (figh), uimenuh,
id);
1996 instance->do_update_canvas (hnd2idx (gh), ca);
1999 static void update_boundingbox (
const std::string& fig_idx_str,
2003 instance->do_update_boundingbox (str2idx (fig_idx_str),
internal);
2006 static void toggle_menubar_visibility (
const std::string& fig_idx_str,
2007 bool menubar_is_figure)
2010 instance->do_toggle_menubar_visibility (str2idx (fig_idx_str),
2016 static figure_manager *instance;
2020 static int curr_index;
2022 typedef std::map<int, plot_window*> window_map;
2024 typedef window_map::iterator wm_iterator;;
2028 static std::string fltk_idx_header;
2030 void do_close_all (
void)
2033 for (win = windows.begin (); win != windows.end (); win++)
2040 int idx = figprops2idx (fp);
2042 if (idx >= 0 && windows.find (idx) == windows.end ())
2044 Matrix pos = fp.get_outerposition ().matrix_value ();
2045 bool internal =
false;
2047 if (pos(2) != -1.0 && pos(3) != -1.0)
2058 idx2figprops (curr_index, fp);
2060 windows[curr_index++] =
new plot_window (pos(0), pos(1), pos(2), pos(3),
2065 void do_delete_window (
int idx)
2067 wm_iterator win = windows.find (idx);
2069 if (win != windows.end ())
2072 windows.erase (win);
2076 void do_renumber_figure (
int idx,
double new_number)
2078 wm_iterator win = windows.find (idx);
2080 if (win != windows.end ())
2081 win->second->renumber (new_number);
2084 void do_toggle_window_visibility (
int idx,
bool is_visible)
2086 wm_iterator win = windows.find (idx);
2088 if (win != windows.end ())
2092 win->second->show ();
2093 win->second->show_canvas ();
2096 win->second->hide ();
2101 void do_toggle_menubar_visibility (
int fig_idx,
bool menubar_is_figure)
2103 wm_iterator win = windows.find (fig_idx);
2105 if (win != windows.end ())
2107 if (menubar_is_figure)
2108 win->second->show_menubar ();
2110 win->second->hide_menubar ();
2112 win->second->redraw ();
2116 void do_mark_modified (
int idx)
2118 wm_iterator win = windows.find (idx);
2120 if (win != windows.end ())
2122 win->second->mark_modified ();
2126 void do_set_name (
int idx)
2128 wm_iterator win = windows.find (idx);
2130 if (win != windows.end ())
2131 win->second->set_name ();
2134 Matrix do_get_size (
int idx)
2138 wm_iterator win = windows.find (idx);
2140 if (win != windows.end ())
2142 sz(0) = win->second->w ();
2143 sz(1) = win->second->h ();
2149 void do_print (
int idx,
const std::string& cmd,
const std::string& term)
2151 wm_iterator win = windows.find (idx);
2153 if (win != windows.end ())
2154 win->second->print (cmd, term);
2160 wm_iterator win = windows.
find (idx);
2162 if (win != windows.end ())
2163 retval = win->second->get_pixels ();
2170 wm_iterator win = windows.
find (idx);
2172 if (win != windows.end ())
2173 win->second->uimenu_update (gh,
id);
2178 wm_iterator win = windows.
find (idx);
2180 if (win != windows.end ())
2183 win->second->show_canvas ();
2185 win->second->hide_canvas ();
2189 void do_update_boundingbox (
int idx,
bool internal)
2191 wm_iterator win = windows.
find (idx);
2193 if (win != windows.end ())
2194 win->second->update_boundingbox (
internal);
2200 if (clstr.find (fltk_idx_header,0) == 0)
2202 std::istringstream istr (clstr.substr (fltk_idx_header.size ()));
2207 error (
"figure_manager: could not recognize fltk index");
2212 std::ostringstream ind_str;
2213 ind_str << fltk_idx_header << idx;
2214 fp.set___plot_stream__ (ind_str.str ());
2219 if (fp.get___graphics_toolkit__ () == FLTK_GRAPHICS_TOOLKIT_NAME)
2228 error (
"figure_manager: figure is not fltk");
2231 static int hnd2idx (
double h)
2237 if (fobj && fobj.
isa (
"figure"))
2241 return figprops2idx (fp);
2244 error (
"figure_manager: H (= %g) is not a figure", h);
2249 return hnd2idx (fh.
value ());
2253 figure_manager *figure_manager::instance =
nullptr;
2255 std::string figure_manager::fltk_idx_header=
"fltk index=";
2256 int figure_manager::curr_index = 1;
2258 static bool toolkit_loaded =
false;
2266 m_interpreter (interp), input_event_hook_fcn_id ()
2268 Fl::visual (FL_RGB);
2271 ~fltk_graphics_toolkit (
void) =
default;
2273 bool is_valid (
void)
const {
return true; }
2277 if (go.
isa (
"figure")
2278 || go.
isa (
"uimenu"))
2280 if (go.
isa (
"uimenu"))
2281 update (go, uimenu::properties::ID_LABEL);
2291 if (go.
isa (
"figure"))
2306 std::string fltk_label = uimenup.get_label ();
2308 gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
2312 if (go.
isa (
"uimenu"))
2317 else if (go.
isa (
"figure") || go.
isa (
"uicontextmenu"))
2320 error (
"invalid parent object\n");
2322 uimenup.set___fltk_label__ (fltk_label);
2328 if (go.
isa (
"figure"))
2339 case base_properties::ID_VISIBLE:
2340 figure_manager::toggle_window_visibility (ov.
string_value (),
2344 case figure::properties::ID_MENUBAR:
2345 figure_manager::toggle_menubar_visibility
2349 case figure::properties::ID_CURRENTAXES:
2350 figure_manager::update_canvas (go.
get_handle (),
2351 fp.get_currentaxes ());
2354 case figure::properties::ID_NAME:
2355 case figure::properties::ID_NUMBERTITLE:
2359 case figure::properties::ID_INTEGERHANDLE:
2363 figure_manager::renumber_figure (tmp, gh.
value ());
2364 figure_manager::set_name (tmp);
2368 case figure::properties::ID_POSITION:
2369 figure_manager::update_boundingbox (ov.
string_value (),
true);
2372 case figure::properties::ID_OUTERPOSITION:
2373 figure_manager::update_boundingbox (ov.
string_value (),
false);
2378 else if (go.
isa (
"uimenu"))
2380 if (
id == uimenu::properties::ID_LABEL)
2381 uimenu_set___fltk_label__ (go);
2392 gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
2396 if (obj && obj.
isa (
"root"))
2405 if (fobj && fobj.
isa (
"figure"))
2410 if (fp.get___graphics_toolkit__ ()
2411 == FLTK_GRAPHICS_TOOLKIT_NAME)
2412 figure_manager::new_window (fp);
2417 figure_manager::mark_modified (go.
get_handle ());
2422 const std::string& term,
2423 const std::string& file_cmd,
2424 const std::string& )
const
2426 figure_manager::print (go.
get_handle (), file_cmd, term);
2431 return figure_manager::get_pixels (go.
get_handle ());
2462 m_interpreter.munlock (
"__init_fltk__");
2466 Fremove_input_event_hook (m_interpreter, args, 0);
2469 figure_manager::close_all ();
2475 input_event_hook_fcn_id = id;
2496 #if defined (HAVE_FLTK)
2504 octave_unused_parameter (interp);
2518 #if defined (HAVE_FLTK)
2522 error (
"__init_fltk__: no graphics DISPLAY available");
2523 else if (! toolkit_loaded)
2529 fltk_graphics_toolkit *fltk =
new fltk_graphics_toolkit (interp);
2532 toolkit_loaded =
true;
2539 fltk->set_input_event_hook_id (
id);
2545 octave_unused_parameter (interp);
static octave_value_list F__fltk_check__(octave::interpreter &interp, const octave_value_list &, int)
Array< octave_idx_type > sort_rows_idx(sortmode mode=ASCENDING) const
Sort by rows returns only indices.
octave_idx_type numel(void) const
Number of elements in the array.
Array< octave_idx_type > find(octave_idx_type n=-1, bool backward=false) const
Find indices of (at most n) nonzero elements.
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
void rotate_view(double delta_az, double delta_el, bool push_to_zoom_stack=true)
void zoom(const std::string &mode, double factor, bool push_to_zoom_stack=true)
graphics_xform get_transform(void) const
ColumnVector pixel2coord(double px, double py) const
void zoom_about_point(const std::string &mode, double x, double y, double factor, bool push_to_zoom_stack=true)
Matrix get_transform_zlim(void) const
void translate_view(const std::string &mode, double x0, double x1, double y0, double y1, bool push_to_zoom_stack=true)
Matrix get_children(void) const
Matrix get_all_children(void) const
virtual void set(const caseless_str &, const octave_value &)
virtual octave_value get(const caseless_str &pname) const
virtual property get_property(const caseless_str &pname)
virtual Matrix get_boundingbox(bool=false, const Matrix &=Matrix()) const
graphics_object get_object(double val) const
graphics_handle lookup(double val) const
octave_value get(bool all=false) const
graphics_object get_ancestor(const std::string &type) const
bool isa(const std::string &go_name) const
base_properties & get_properties(void)
graphics_handle get_handle(void) const
graphics_handle get_parent(void) const
bool valid_object(void) const
bool display_available(void) const
void load_toolkit(const graphics_toolkit &tk)
virtual void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
virtual void glLoadIdentity(void)
virtual void glMatrixMode(GLenum mode)
virtual void draw(const graphics_object &go, bool toplevel=true)
virtual void draw_zoom_box(int width, int height, int x1, int y1, int x2, int y2, const Matrix &overlaycolor, double overlayalpha, const Matrix &bordercolor, double borderalpha, double borderwidth)
static std::string getenv(const std::string &name)
const octave_value & contents(const_iterator p) const
void assign(const std::string &k, const octave_value &val)
octave_value_list & append(const octave_value &val)
octave_idx_type length(void) const
bool is_string(void) const
std::string string_value(bool force=false) const
octave_scalar_map scalar_map_value(void) const
Matrix matrix_value(bool frc_str_conv=false) const
bool set(const octave_value &val, bool do_run=true, bool do_notify_toolkit=true)
#define DEFMETHOD_DLD(name, interp_name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin method.
void error(const char *fmt,...)
#define panic_impossible()
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
OCTAVE_EXPORT octave_value_list Fdrawnow(octave::interpreter &interp, const octave_value_list &args, int)
std::complex< double > w(std::complex< double > z, double relerr=0)
static std::string pan_mode(const graphics_object figObj)
static bool pan_enabled(const graphics_object figObj)
std::complex< T > floor(const std::complex< T > &x)
gh_manager & __get_gh_manager__(const std::string &who)
void gl2ps_print(opengl_functions &glfcns, const graphics_object &fig, const std::string &stream, const std::string &term)
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
static octave_idx_type get_size(double d, const std::string &who)
octave_int< T > mod(const octave_int< T > &x, const octave_int< T > &y)
void draw(QDomElement &parent_elt, pdfpainter &painter)
octave_value::octave_value(const Array< char > &chm, char type) return retval