35 #if defined (HAVE_CONFIG_H) 43 #if defined (HAVE_FLTK) 45 #if defined (HAVE_X_WINDOWS) 46 # include <X11/Xlib.h> 58 # define WIN32_LEAN_AND_MEAN 62 #include <FL/Fl_Box.H> 63 #include <FL/Fl_Button.H> 64 #include <FL/Fl_Choice.H> 65 #include <FL/Fl_File_Chooser.H> 66 #include <FL/Fl_Gl_Window.H> 68 #include <FL/Fl_Menu_Bar.H> 69 #include <FL/Fl_Menu_Button.H> 70 #include <FL/Fl_Output.H> 71 #include <FL/Fl_Window.H> 72 #include <FL/fl_ask.H> 73 #include <FL/fl_draw.H> 90 #include "builtin-defun-decls.h" 105 #define FLTK_GRAPHICS_TOOLKIT_NAME "fltk" 107 const char *help_text =
"\ 108 Keyboard Shortcuts\n\ 116 mouse wheel - zoom\n\ 117 right drag - rectangle zoom\n\ 118 left double click - autoscale\n\ 121 class OpenGL_fltk :
public Fl_Gl_Window
125 OpenGL_fltk (
int xx,
int yy,
int ww,
int hh,
double num)
126 : Fl_Gl_Window (xx, yy, ww, hh, nullptr), m_number (num), m_renderer (),
127 m_in_zoom (
false), m_zoom_box ()
129 #if defined (HAVE_OPENGL) 131 mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE);
137 ~OpenGL_fltk (
void) =
default;
146 bool zoom (
void) {
return m_in_zoom; }
147 void set_zoom_box (
const Matrix& zb) { m_zoom_box = zb; }
159 return m_renderer.get_pixels (
w (),
h ());
162 void resize (
int xx,
int yy,
int ww,
int hh)
164 #if defined (HAVE_OPENGL) 166 Fl_Gl_Window::resize (xx, yy, ww, hh);
176 bool renumber (
double new_number)
180 if (m_number != new_number)
182 m_number = new_number;
202 #if defined (HAVE_OPENGL) 206 glMatrixMode (GL_PROJECTION);
208 glViewport (0, 0,
w (),
h ());
224 void zoom_box_vertex (
void)
226 #if defined (HAVE_OPENGL) 228 glVertex2d (m_zoom_box(0),
h () - m_zoom_box(1));
229 glVertex2d (m_zoom_box(0),
h () - m_zoom_box(3));
230 glVertex2d (m_zoom_box(2),
h () - m_zoom_box(3));
231 glVertex2d (m_zoom_box(2),
h () - m_zoom_box(1));
232 glVertex2d (m_zoom_box(0),
h () - m_zoom_box(1));
244 #if defined (HAVE_OPENGL) 246 glMatrixMode (GL_MODELVIEW);
250 glMatrixMode (GL_PROJECTION);
253 gluOrtho2D (0.0,
w (), 0.0,
h ());
255 glPushAttrib (GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT);
256 glDisable (GL_DEPTH_TEST);
258 glBegin (GL_POLYGON);
259 glColor4f (0.45, 0.62, 0.81, 0.1);
264 glBegin (GL_LINE_STRIP);
265 glColor4f (0.45, 0.62, 0.81, 0.9);
270 glMatrixMode (GL_MODELVIEW);
272 glMatrixMode (GL_PROJECTION);
285 #if defined (HAVE_OPENGL) 290 cursor (FL_CURSOR_CROSS);
294 cursor (FL_CURSOR_DEFAULT);
309 void script_cb (Fl_Widget *,
void *data)
318 fltk_uimenu (
int xx,
int yy,
int ww,
int hh)
319 : m_menubar (new Fl_Menu_Bar (xx, yy, ww, hh))
322 int items_to_show (
void)
325 int len = m_menubar->size ();
327 for (
int t = 0;
t < len;
t++)
329 const Fl_Menu_Item *m
330 =
static_cast<const Fl_Menu_Item *
> (&(m_menubar->menu ()[
t]));
332 if (m->label () && m->visible ())
342 m_menubar->redraw ();
348 m_menubar->redraw ();
351 bool is_visible (
void)
353 return m_menubar->visible ();
356 int find_index_by_name (
const std::string& findname)
365 for (
int t = 0;
t < m_menubar->size ();
t++)
367 Fl_Menu_Item *m =
const_cast<Fl_Menu_Item *
> (&(m_menubar->menu ()[
t]));
371 if (! menupath.empty ())
373 menupath += m->label ();
375 if (menupath == findname)
383 size_t idx = menupath.find_last_of (
'/');
384 if (idx != std::string::npos)
385 menupath.erase (idx);
392 if (! itempath.empty ())
394 itempath += m->label ();
396 if (itempath == findname)
406 Matrix retval = do_find_uimenu_children (uimenu_childs);
413 Matrix retval = do_find_uimenu_children (uimenu_childs);
417 Matrix do_find_uimenu_children (
Matrix uimenu_childs)
const 429 uimenu_childs(
k) = uimenu_childs(ii);
443 retval(ii) = uimenu_childs (sidx(ii));
450 std::string fltk_label = uimenup.get___fltk_label__ ();
451 int idx = find_index_by_name (fltk_label.c_str ());
454 m_menubar->remove (idx);
459 std::string fltk_label = uimenup.get___fltk_label__ ();
460 if (! fltk_label.empty ())
463 const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
467 if (acc.length () > 0)
469 int key = FL_CTRL + acc[0];
470 item->shortcut (key);
478 std::string fltk_label = uimenup.get___fltk_label__ ();
479 if (! fltk_label.empty ())
482 =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
485 if (! uimenup.get_callback ().isempty ())
486 item->
callback (static_cast<Fl_Callback *> (script_cb),
487 static_cast<void *> (&uimenup));
489 item->callback (
nullptr, static_cast<void *> (
nullptr));
496 std::string fltk_label = uimenup.get___fltk_label__ ();
497 if (! fltk_label.empty ())
500 =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
503 if (uimenup.is_enable ())
513 std::string fltk_label = uimenup.get___fltk_label__ ();
514 if (! fltk_label.empty ())
517 =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
520 Matrix rgb = uimenup.get_foregroundcolor_rgb ();
522 uchar r =
static_cast<uchar
> (
std::floor (rgb (0) * 255));
523 uchar g =
static_cast<uchar
> (
std::floor (rgb (1) * 255));
524 uchar
b =
static_cast<uchar
> (
std::floor (rgb (2) * 255));
526 item->labelcolor (fl_rgb_color (r, g,
b));
536 std::string fltk_label = uimenup.get___fltk_label__ ();
537 if (! fltk_label.empty ())
539 int itemflags = 0, idx;
540 int curr_idx = find_index_by_name (fltk_label.c_str ());
542 for (idx = curr_idx - 1; idx >= 0; idx--)
545 =
const_cast<Fl_Menu_Item *
> (&m_menubar->menu () [idx]);
546 itemflags = item->flags;
551 if (idx >= 0 && idx < m_menubar->size ())
553 if (uimenup.is_separator ())
555 if (idx >= 0 && !(itemflags & FL_SUBMENU))
556 m_menubar->mode (idx, itemflags | FL_MENU_DIVIDER);
559 m_menubar->mode (idx, itemflags & (~FL_MENU_DIVIDER));
566 std::string fltk_label = uimenup.get___fltk_label__ ();
567 if (! fltk_label.empty ())
570 =
const_cast<Fl_Menu_Item *
> (m_menubar->find_item (fltk_label.c_str ()));
573 if (uimenup.is_visible ())
590 std::string fltk_label = uimenup.get___fltk_label__ ();
592 if (! fltk_label.empty ())
594 bool item_added =
false;
597 const Fl_Menu_Item *item
598 = m_menubar->find_item (fltk_label.c_str ());
603 size_t idx1 = fltk_label.find_last_of (
'(');
604 size_t idx2 = fltk_label.find_last_of (
')');
605 int len = idx2 - idx1;
609 std::string valstr = fltk_label.substr (idx1 + 1, len - 1);
610 fltk_label.erase (idx1, len + 1);
611 val = atoi (valstr.c_str ());
615 std::ostringstream valstream;
617 fltk_label +=
'(' + valstream.str () +
')';
621 Matrix uimenu_ch = find_uimenu_children (uimenup);
622 int len = uimenu_ch.
numel ();
626 if (len == 0 && uimenup.is_checked ())
627 flags += FL_MENU_TOGGLE + FL_MENU_VALUE;
628 m_menubar->add (fltk_label.c_str (),
629 0,
nullptr,
nullptr, flags);
633 while (! item_added);
634 uimenup.set___fltk_label__ (fltk_label);
640 std::vector<int> delayed_menus;
641 Matrix kids = find_uimenu_children (uimenup);
642 int len = kids.
numel ();
643 std::string fltk_label = uimenup.get___fltk_label__ ();
647 update_foregroundcolor (uimenup);
648 update_callback (uimenup);
649 update_accelerator (uimenup);
650 update_enable (uimenup);
651 update_visible (uimenup);
652 update_seperator (uimenup);
663 int pos = kprop.get_position ();
665 delayed_menus.push_back ((len - (ii + 1)));
674 for (
size_t ii = 0; ii < delayed_menus.size (); ii++)
683 update_position (kprop, ++count);
690 std::vector<int> delayed_menus;
691 Matrix kids = find_uimenu_children (figp);
692 int len = kids.
numel ();
705 int pos = kprop.get_position ();
707 delayed_menus.push_back ((len - (ii + 1)));
711 update_position (kprop, ++count);
717 for (
size_t ii = 0; ii < delayed_menus.size (); ii++)
726 update_position (kprop, ++count);
731 template <
typename T_prop>
732 void remove_from_menu (T_prop& prop)
736 kids = find_uimenu_children (prop);
737 int len = kids.
numel ();
747 remove_from_menu (kprop);
751 if (
type ==
"uimenu")
752 delete_entry (dynamic_cast<uimenu::properties&> (prop));
753 else if (
type ==
"figure")
759 fltk_uimenu (
const fltk_uimenu&) =
delete;
761 fltk_uimenu operator = (
const fltk_uimenu&) =
delete;
770 Fl_Menu_Bar *m_menubar;
773 #if defined (HAVE_X_WINDOWS) 775 xerror_handler (Display *, XErrorEvent *)
781 class plot_window :
public Fl_Window
783 friend class fltk_uimenu;
789 : Fl_Window (xx, yy, ww, hh + m_menu_h + m_status_h + 2,
"octave"),
790 m_window_label (), m_fp (xfp), m_uimenu (nullptr), m_canvas (nullptr),
791 m_autoscale (nullptr), m_togglegrid (nullptr), m_panzoom (nullptr),
792 m_rotate (nullptr), m_help (nullptr), m_status (nullptr),
793 m_resize_dummy (nullptr), m_ax_obj (), m_pos_x (0), m_pos_y (0)
795 callback (window_close, static_cast<void *> (
this));
799 m_resize_dummy =
new Fl_Box (5 * m_status_h, m_menu_h,
800 ww - 5 * m_status_h, hh);
804 resizable (m_resize_dummy);
814 m_uimenu =
new fltk_uimenu (0, 0, ww, m_menu_h);
815 m_canvas =
new OpenGL_fltk (0, m_menu_h, ww, hh,
number ());
821 int toolbar_y = m_menu_h + hh + 1;
822 m_status =
new Fl_Output (5 * m_status_h, toolbar_y,
823 ww - 5 * m_status_h, m_status_h,
"");
825 m_status->textcolor (FL_BLACK);
826 m_status->color (FL_GRAY);
827 m_status->textfont (FL_COURIER);
828 m_status->textsize (10);
829 m_status->box (FL_ENGRAVED_BOX);
831 m_autoscale =
new Fl_Button (0, toolbar_y, m_status_h, m_status_h,
"A");
832 m_autoscale->callback (button_callback, static_cast<void *> (
this));
833 m_autoscale->tooltip (
"Autoscale");
835 m_togglegrid =
new Fl_Button (m_status_h, toolbar_y, m_status_h, m_status_h,
"G");
836 m_togglegrid->callback (button_callback, static_cast<void *> (
this));
837 m_togglegrid->tooltip (
"Toggle Grid");
839 m_panzoom =
new Fl_Button (2* m_status_h, toolbar_y, m_status_h, m_status_h,
"P");
840 m_panzoom->callback (button_callback, static_cast<void *> (
this));
841 m_panzoom->tooltip (
"Mouse Pan/Zoom");
843 m_rotate =
new Fl_Button (3 * m_status_h, toolbar_y, m_status_h, m_status_h,
"R");
844 m_rotate->callback (button_callback, static_cast<void *> (
this));
845 m_rotate->tooltip (
"Mouse Rotate");
847 m_help =
new Fl_Button (4 * m_status_h, toolbar_y, m_status_h, m_status_h,
"?");
848 m_help->callback (button_callback, static_cast<void *> (
this));
849 m_help->tooltip (
"Help");
854 m_uimenu->add_to_menu (m_fp);
855 if (m_fp.menubar_is (
"none") || ! m_uimenu->items_to_show ())
858 update_boundingbox (
internal);
860 if (m_fp.is_visible ())
872 #if defined (HAVE_X_WINDOWS) 877 if (show_gui_msgs.empty ())
878 XSetErrorHandler (xerror_handler);
881 if (m_fp.get_currentaxes ().ok ())
890 plot_window (
const plot_window&) =
delete;
892 plot_window& operator = (
const plot_window&) =
delete;
904 double number (
void) {
return m_fp.get___myhandle__ ().value (); }
906 void renumber (
double new_number)
909 error (
"unable to renumber figure");
911 if (m_canvas->renumber (new_number))
917 m_canvas->print (cmd, term);
922 return m_canvas->get_pixels ();
925 void show_menubar (
void)
928 update_toolbar_position ();
931 void hide_menubar (
void)
934 update_toolbar_position ();
945 std::string fltk_label = uimenup.get___fltk_label__ ();
952 case base_properties::ID_BEINGDELETED:
953 m_uimenu->remove_from_menu (uimenup);
956 case base_properties::ID_VISIBLE:
957 m_uimenu->update_visible (uimenup);
960 case uimenu::properties::ID_ACCELERATOR:
961 m_uimenu->update_accelerator (uimenup);
964 case uimenu::properties::ID_CALLBACK:
965 m_uimenu->update_callback (uimenup);
968 case uimenu::properties::ID_CHECKED:
969 m_uimenu->add_to_menu (figp);
972 case uimenu::properties::ID_ENABLE:
973 m_uimenu->update_enable (uimenup);
976 case uimenu::properties::ID_FOREGROUNDCOLOR:
977 m_uimenu->update_foregroundcolor (uimenup);
980 case uimenu::properties::ID_LABEL:
981 m_uimenu->add_to_menu (figp);
984 case uimenu::properties::ID_POSITION:
985 m_uimenu->add_to_menu (figp);
988 case uimenu::properties::ID_SEPARATOR:
989 m_uimenu->update_seperator (uimenup);
993 if (m_uimenu->items_to_show ())
1000 void show_canvas (
void)
1002 if (! m_canvas->can_do ())
1003 error (
"unable to plot due to insufficient OpenGL support");
1004 else if (m_fp.is_visible ())
1007 m_canvas->make_current ();
1011 void hide_canvas (
void)
1020 void update_toolbar_position ()
1022 int old_canvas_h = m_canvas->h ();
1025 update_boundingbox (
true);
1026 m_canvas->resize (0, menu_dy (),
w (), old_canvas_h);
1028 int toolbar_y = m_canvas->h () + menu_dy () + 1;
1029 m_autoscale->position (0, toolbar_y);
1030 m_togglegrid->position (m_status_h, toolbar_y);
1031 m_panzoom->position (2 * m_status_h, toolbar_y);
1032 m_rotate->position (3 * m_status_h, toolbar_y);
1033 m_help->position (4 * m_status_h, toolbar_y);
1034 m_status->resize (5 * m_status_h, toolbar_y,
1035 w () - 5 * m_status_h, m_status_h);
1043 pos(1) += menu_dy ();
1044 pos(3) -= menu_dy () + m_status_h + 2;
1051 outerpos(1) -= menu_dy ();
1052 outerpos(3) += menu_dy () + m_status_h + 2;
1061 void update_boundingbox (
bool internal)
1063 Matrix bb = m_fp.get_boundingbox (
internal);
1065 bb = position2outerposition (bb);
1066 resize (bb(0), bb(1), bb(2), bb(3));
1069 void mark_modified (
void)
1071 m_canvas->redraw ();
1074 void set_name (
void)
1076 m_window_label = m_fp.get_title ();
1077 label (m_window_label.c_str ());
1090 static const int m_status_h = 20;
1093 static const int m_menu_h = 25;
1095 fltk_uimenu *m_uimenu;
1097 OpenGL_fltk *m_canvas;
1099 Fl_Button *m_autoscale;
1100 Fl_Button *m_togglegrid;
1101 Fl_Button *m_panzoom;
1102 Fl_Button *m_rotate;
1104 Fl_Output *m_status;
1106 Fl_Box *m_resize_dummy;
1114 static void window_close (Fl_Widget *,
void *data)
1117 args(0) =
static_cast<plot_window *
> (data)->
number ();
1122 static void button_callback (Fl_Widget *ww,
void *data)
1124 static_cast<plot_window *
> (data)->button_press (ww, data);
1127 void button_press (Fl_Widget *widg,
void *)
1129 if (widg == m_autoscale)
1131 else if (widg == m_togglegrid)
1133 else if (widg == m_panzoom)
1134 m_fp.set___mouse_mode__ (
"pan");
1135 else if (widg == m_rotate)
1136 m_fp.set___mouse_mode__ (
"rotate");
1137 else if (widg == m_help)
1138 fl_message (
"%s", help_text);
1144 if (m_ax_obj && m_ax_obj.
isa (
"axes")
1165 void axis_auto (
void)
1168 if (m_fp.get_currentaxes ().ok ())
1170 args(0) = m_fp.get_currentaxes ().as_octave_value ();
1177 void toggle_grid (
void)
1180 if (m_fp.get_currentaxes ().ok ())
1181 args(0) = m_fp.get_currentaxes ().as_octave_value ();
1187 void pixel2pos (
const graphics_handle& ax,
int px,
int py,
double& xx,
1196 if (ax && ax.
isa (
"axes"))
1209 int len = kids.
numel ();
1211 for (
int k = 0;
k < len;
k++)
1223 if (bb(0) <= px && px < (bb(0)+bb(2))
1224 && bb(1) <= py && py < (bb(1)+bb(3)))
1231 return m_fp.get_currentaxes ();
1235 int px1 = -1,
int py1 = -1)
1241 int px1 = -1,
int py1 = -1)
1243 double x0, y0, x1, y1;
1245 std::stringstream cbuf;
1248 pixel2pos (ax, px0, py0, x0, y0);
1249 cbuf <<
'[' << x0 <<
", " << y0 <<
']';
1252 pixel2pos (ax, px1, py1, x1, y1);
1253 cbuf <<
" -> ["<< x1 <<
", " << y1 <<
']';
1256 m_status->value (cbuf.str ().c_str ());
1261 if (ax && ax.
isa (
"axes"))
1265 std::stringstream cbuf;
1270 cbuf <<
"[azimuth: " << v(0) <<
", elevation: " << v(1) <<
']';
1272 m_status->value (cbuf.str ().c_str ());
1276 void set_currentpoint (
int px,
int py)
1278 if (! m_fp.is_beingdeleted ())
1281 m_fp.set_currentpoint (pos);
1285 rp.set_currentfigure (m_fp.get___myhandle__ ().value ());
1311 ap.set_currentpoint (pos);
1312 if (ap.get_tag () !=
"legend" && ap.get_tag () !=
"colorbar")
1313 m_fp.set_currentaxes (ap.get___myhandle__ ().value ());
1319 if (m_uimenu->is_visible ())
1333 std::ostringstream tmp_str;
1335 if (e_key == FL_Escape)
1337 else if (e_key == FL_Tab)
1339 else if (e_key == FL_Caps_Lock)
1340 key_str =
"capslock";
1341 else if (e_key == FL_Shift_L || e_key == FL_Shift_R)
1343 else if (e_key == FL_Control_L || e_key == FL_Control_R)
1344 key_str =
"control";
1345 else if (e_key == FL_Meta_L || e_key == FL_Meta_R)
1346 key_str =
"windows";
1347 else if (e_key == FL_Alt_L || e_key == FL_Alt_R)
1349 else if (e_key == 32)
1351 else if (e_key == FL_Enter)
1353 else if (e_key == FL_BackSpace)
1354 key_str =
"backspace";
1355 else if (e_key == FL_Print)
1356 key_str =
"printscreen";
1357 else if (e_key == FL_Pause)
1359 else if (e_key == FL_Home)
1361 else if (e_key == FL_End)
1363 else if (e_key == FL_Insert)
1365 else if (e_key == FL_Page_Up)
1367 else if (e_key == FL_Delete)
1369 else if (e_key == FL_Page_Down)
1370 key_str =
"pagedown";
1371 else if (e_key == FL_Left)
1372 key_str =
"leftarrow";
1373 else if (e_key == FL_Up)
1374 key_str =
"uparrow";
1375 else if (e_key == FL_Right)
1376 key_str =
"rightarrow";
1377 else if (e_key == FL_Down)
1378 key_str =
"downarrow";
1379 else if (e_key == FL_Num_Lock)
1380 key_str =
"numlock";
1381 else if (e_key == 0xffaf)
1383 else if (e_key == 0xffaa)
1384 key_str =
"multiply";
1385 else if (e_key == 0xffad)
1386 key_str =
"subtract";
1387 else if (e_key == 0xffab)
1389 else if (e_key == 0xff8d)
1391 else if (e_key == 0xffac)
1392 key_str =
"separator";
1393 else if (e_key >= 0xffb0 && e_key <= 0xffb9)
1395 tmp_str <<
"numpad" << (e_key - 0xffb0);
1396 key_str = tmp_str.str ();
1398 else if (e_key >= (FL_F + 1) && e_key <= (FL_F + 12))
1400 tmp_str <<
'f' << (e_key - FL_F);
1401 key_str = tmp_str.str ();
1403 else if (e_key ==
',')
1405 else if (e_key ==
'.')
1407 else if (e_key ==
'-')
1409 else if (e_key ==
'^' || e_key ==
'+' || e_key ==
'#' 1410 || e_key ==
'<' || e_key == 0xfe03 )
1412 else if (isalnum (e_key))
1413 key_str = std::tolower (e_key);
1414 else if (isprint (e_text[0]))
1421 Cell modifier2cell (
int e_state)
1425 if (e_state & FL_SHIFT)
1427 if (e_state & FL_CTRL)
1429 if (e_state & FL_ALT)
1431 if (e_state & FL_COMMAND)
1436 void resize (
int xx,
int yy,
int ww,
int hh)
1438 Fl_Window::resize (xx, yy, ww, hh);
1473 bool rotate_enabled (
void)
1485 if (event == FL_FOCUS)
1490 if (! m_fp.is_beingdeleted ())
1497 static bool key_resent_detected =
false;
1504 static int last_event_key = 0;
1505 static char last_event_text = 0;
1507 int e_key = Fl::event_key ();
1508 char e_text = Fl::event_text ()[0];
1509 key_resent_detected = (e_key == last_event_key
1510 && std::tolower (last_event_text) == std::tolower (e_text)
1511 && ((islower (last_event_text) && isupper (e_text))
1512 || (isupper (last_event_text) && islower (e_text))));
1514 last_event_key = e_key;
1515 last_event_text = e_text;
1521 int e_key = Fl::event_key ();
1522 const char *e_text = Fl::event_text ();
1523 int e_state = Fl::event_state ();
1528 if (! m_fp.get_keypressfcn ().isempty ()
1532 if (Fl::event_inside (m_canvas))
1534 m_pos_x = Fl::event_x ();
1535 m_pos_y = Fl::event_y () - menu_dy ();
1537 set_currentpoint (m_pos_x, m_pos_y);
1539 gh = pixel2axes_or_ca (m_pos_x, m_pos_y);
1544 set_axes_currentpoint (m_ax_obj, m_pos_x, m_pos_y);
1548 m_fp.execute_keypressfcn (evt);
1566 m_fp.set___mouse_mode__ (
"pan");
1571 m_fp.set___mouse_mode__ (
"rotate");
1579 int e_key = Fl::event_key ();
1580 int e_state = Fl::event_state ();
1582 if (key_resent_detected && Fl::event_length () == 1)
1587 tmp_e_text[0] = Fl::event_text ()[0];
1590 if (std::islower (tmp_e_text[0]))
1591 tmp_e_text[0] = std::toupper (tmp_e_text[0]);
1593 tmp_e_text[0] = std::tolower (tmp_e_text[0]);
1594 evt = format_key_event (e_key, tmp_e_text, e_state);
1598 const char *e_text = Fl::event_text ();
1599 evt = format_key_event (e_key, e_text, e_state);
1602 if (! m_fp.get_keyreleasefcn ().isempty ()
1604 m_fp.execute_keyreleasefcn (evt);
1611 if (Fl::event_inside (m_canvas))
1615 pixel2status (pixel2axes_or_ca (Fl::event_x (),
1616 Fl::event_y () - menu_dy ()),
1617 Fl::event_x (), Fl::event_y () - menu_dy ());
1621 m_pos_x = Fl::event_x ();
1622 m_pos_y = Fl::event_y () - menu_dy ();
1624 set_currentpoint (m_pos_x, m_pos_y);
1626 if (Fl::event_clicks ())
1627 m_fp.set_selectiontype (
"open");
1628 else if (Fl::event_button () == FL_MIDDLE_MOUSE
1629 || (Fl::event_button () == FL_LEFT_MOUSE
1630 && Fl::event_shift ()))
1631 m_fp.set_selectiontype (
"extend");
1632 else if (Fl::event_button () == FL_RIGHT_MOUSE
1633 || (Fl::event_button () == FL_LEFT_MOUSE
1634 && Fl::event_ctrl ()))
1635 m_fp.set_selectiontype (
"alt");
1637 m_fp.set_selectiontype (
"normal");
1639 gh = pixel2axes_or_ca (m_pos_x, m_pos_y);
1644 set_axes_currentpoint (m_ax_obj, m_pos_x, m_pos_y);
1649 if (! m_fp.get_windowbuttondownfcn ().isempty ())
1650 m_fp.execute_windowbuttondownfcn (Fl::event_button ());
1657 if (! props.get_buttondownfcn ().isempty ())
1658 props.execute_buttondownfcn (Fl::event_button ());
1662 else if (! m_fp.get_buttondownfcn ().isempty ())
1663 m_fp.execute_buttondownfcn (Fl::event_button ());
1668 if (! m_fp.get_windowbuttonmotionfcn ().isempty ())
1670 set_currentpoint (Fl::event_x (), Fl::event_y () - menu_dy ());
1671 m_fp.execute_windowbuttonmotionfcn ();
1674 if (Fl::event_button () == 1)
1676 if (m_ax_obj && m_ax_obj.
isa (
"axes"))
1683 if (ap.get_tag () !=
"legend")
1685 if (rotate_enabled ())
1686 view2status (m_ax_obj);
1688 pixel2status (m_ax_obj, m_pos_x, m_pos_y,
1690 Fl::event_y () - menu_dy ());
1692 double x0, y0, x1, y1;
1694 pixel2pos (m_ax_obj, m_pos_x, m_pos_y, x0, y0);
1695 pixel2pos (m_ax_obj, Fl::event_x (),
1696 Fl::event_y () - menu_dy (),
1705 else if (rotate_enabled ())
1708 daz = (Fl::event_x () - m_pos_x) / pos(2) * 360;
1709 del = (Fl::event_y () - menu_dy () - m_pos_y)
1717 Matrix pos = ap.get_position ().matrix_value ();
1718 pos(0) +=
double (Fl::event_x () - m_pos_x)
1720 pos(1) -=
double (Fl::event_y () - menu_dy () - m_pos_y)
1722 ap.set_position (pos);
1725 m_pos_x = Fl::event_x ();
1726 m_pos_y = Fl::event_y () - menu_dy ();
1731 else if (Fl::event_button () == 3)
1733 pixel2status (m_ax_obj, m_pos_x, m_pos_y,
1734 Fl::event_x (), Fl::event_y () - menu_dy ());
1736 zoom_box(0) = m_pos_x;
1737 zoom_box(1) = m_pos_y;
1738 zoom_box(2) = Fl::event_x ();
1739 zoom_box(3) = Fl::event_y () - menu_dy ();
1740 m_canvas->set_zoom_box (zoom_box);
1741 m_canvas->zoom (
true);
1754 if (ax && ax.
isa (
"axes"))
1760 double wheel_zoom_speed = ap.get_mousewheelzoom ();
1763 const double factor = (Fl::event_dy () < 0
1764 ? 1 / (1.0 - wheel_zoom_speed)
1765 : 1.0 - wheel_zoom_speed);
1769 pixel2pos (ax, Fl::event_x (), Fl::event_y () - menu_dy (),
1783 if (! m_fp.get_windowbuttonupfcn ().isempty ())
1785 set_currentpoint (Fl::event_x (), Fl::event_y () - menu_dy ());
1786 m_fp.execute_windowbuttonupfcn ();
1789 if ((Fl::event_button () == 1) && Fl::event_clicks ())
1792 set_on_ax_obj (
"xlimmode",
"auto");
1793 set_on_ax_obj (
"ylimmode",
"auto");
1794 set_on_ax_obj (
"zlimmode",
"auto");
1798 if (Fl::event_button () == 3)
1801 if (m_canvas->zoom ())
1803 m_canvas->zoom (
false);
1805 if (m_ax_obj && m_ax_obj.
isa (
"axes"))
1809 pixel2pos (m_ax_obj, m_pos_x, m_pos_y, x0, y0);
1810 int pos_x1 = Fl::event_x ();
1811 int pos_y1 = Fl::event_y () - menu_dy ();
1812 pixel2pos (m_ax_obj, pos_x1, pos_y1, x1, y1);
1815 int dx =
abs (m_pos_x - pos_x1);
1816 int dy =
abs (m_pos_y - pos_y1);
1818 if ((dx > 4) && (dy > 4))
1840 ap.
zoom (
"both", xl, yl);
1855 class figure_manager
1859 figure_manager (
void) =
default;
1865 figure_manager (
const figure_manager&) =
delete;
1867 figure_manager& operator = (
const figure_manager&) =
delete;
1869 ~figure_manager (
void)
1874 static bool instance_ok (
void)
1879 instance =
new figure_manager ();
1882 error (
"unable to create figure_manager object!");
1887 static void close_all (
void)
1890 instance->do_close_all ();
1896 instance->do_new_window (fp);
1899 static void delete_window (
int idx)
1902 instance->do_delete_window (idx);
1905 static void delete_window (
const std::string& idx_str)
1907 delete_window (str2idx (idx_str));
1910 static void renumber_figure (
const std::string& idx_str,
double new_number)
1913 instance->do_renumber_figure (str2idx (idx_str), new_number);
1916 static void toggle_window_visibility (
int idx,
bool is_visible)
1919 instance->do_toggle_window_visibility (idx, is_visible);
1922 static void toggle_window_visibility (
const std::string& idx_str,
1925 toggle_window_visibility (str2idx (idx_str), is_visible);
1928 static void mark_modified (
int idx)
1931 instance->do_mark_modified (idx);
1936 mark_modified (hnd2idx (
gh));
1939 static void set_name (
int idx)
1942 instance->do_set_name (idx);
1947 set_name (str2idx (idx_str));
1952 return instance_ok () ? instance->do_get_size (idx) :
Matrix ();
1964 instance->do_print (hnd2idx (
gh), cmd, term);
1971 retval = instance->do_get_pixels (hnd2idx (
gh));
1980 instance->do_uimenu_update (hnd2idx (figh), uimenuh,
id);
1987 instance->do_update_canvas (hnd2idx (
gh), ca);
1990 static void update_boundingbox (
const std::string& fig_idx_str,
1994 instance->do_update_boundingbox (str2idx (fig_idx_str),
internal);
1997 static void toggle_menubar_visibility (
const std::string& fig_idx_str,
1998 bool menubar_is_figure)
2001 instance->do_toggle_menubar_visibility (str2idx (fig_idx_str),
2007 static figure_manager *instance;
2011 static int curr_index;
2013 typedef std::map<int, plot_window*> window_map;
2015 typedef window_map::iterator wm_iterator;;
2021 void do_close_all (
void)
2024 for (win = windows.begin (); win != windows.end (); win++)
2031 int idx = figprops2idx (fp);
2033 if (idx >= 0 && windows.find (idx) == windows.end ())
2035 Matrix pos = fp.get_outerposition ().matrix_value ();
2036 bool internal =
false;
2038 if (pos(2) != -1.0 && pos(3) != -1.0)
2049 idx2figprops (curr_index, fp);
2051 windows[curr_index++] =
new plot_window (pos(0), pos(1), pos(2), pos(3),
2056 void do_delete_window (
int idx)
2058 wm_iterator win = windows.find (idx);
2060 if (win != windows.end ())
2063 windows.erase (win);
2067 void do_renumber_figure (
int idx,
double new_number)
2069 wm_iterator win = windows.find (idx);
2071 if (win != windows.end ())
2072 win->second->renumber (new_number);
2075 void do_toggle_window_visibility (
int idx,
bool is_visible)
2077 wm_iterator win = windows.find (idx);
2079 if (win != windows.end ())
2083 win->second->show ();
2084 win->second->show_canvas ();
2087 win->second->hide ();
2092 void do_toggle_menubar_visibility (
int fig_idx,
bool menubar_is_figure)
2094 wm_iterator win = windows.find (fig_idx);
2096 if (win != windows.end ())
2098 if (menubar_is_figure)
2099 win->second->show_menubar ();
2101 win->second->hide_menubar ();
2103 win->second->redraw ();
2107 void do_mark_modified (
int idx)
2109 wm_iterator win = windows.find (idx);
2111 if (win != windows.end ())
2113 win->second->mark_modified ();
2117 void do_set_name (
int idx)
2119 wm_iterator win = windows.find (idx);
2121 if (win != windows.end ())
2122 win->second->set_name ();
2125 Matrix do_get_size (
int idx)
2129 wm_iterator win = windows.find (idx);
2131 if (win != windows.end ())
2133 sz(0) = win->second->w ();
2134 sz(1) = win->second->h ();
2142 wm_iterator win = windows.find (idx);
2144 if (win != windows.end ())
2145 win->second->print (cmd, term);
2151 wm_iterator win = windows.find (idx);
2153 if (win != windows.end ())
2154 retval = win->second->get_pixels ();
2161 wm_iterator win = windows.find (idx);
2163 if (win != windows.end ())
2164 win->second->uimenu_update (
gh,
id);
2169 wm_iterator win = windows.find (idx);
2171 if (win != windows.end ())
2174 win->second->show_canvas ();
2176 win->second->hide_canvas ();
2180 void do_update_boundingbox (
int idx,
bool internal)
2182 wm_iterator win = windows.find (idx);
2184 if (win != windows.end ())
2185 win->second->update_boundingbox (
internal);
2191 if (clstr.find (fltk_idx_header,0) == 0)
2193 std::istringstream istr (clstr.substr (fltk_idx_header.size ()));
2198 error (
"figure_manager: could not recognize fltk index");
2203 std::ostringstream ind_str;
2204 ind_str << fltk_idx_header << idx;
2205 fp.set___plot_stream__ (ind_str.str ());
2210 if (fp.get___graphics_toolkit__ () == FLTK_GRAPHICS_TOOLKIT_NAME)
2219 error (
"figure_manager: figure is not fltk");
2222 static int hnd2idx (
double h)
2225 if (fobj && fobj.
isa (
"figure"))
2229 return figprops2idx (fp);
2232 error (
"figure_manager: H (= %g) is not a figure",
h);
2237 return hnd2idx (fh.
value ());
2241 figure_manager *figure_manager::instance =
nullptr;
2243 std::string figure_manager::fltk_idx_header=
"fltk index=";
2244 int figure_manager::curr_index = 1;
2254 m_interpreter (interp), input_event_hook_fcn_id ()
2256 Fl::visual (FL_RGB);
2259 ~fltk_graphics_toolkit (
void) =
default;
2261 bool is_valid (
void)
const {
return true; }
2265 if (go.
isa (
"figure")
2266 || go.
isa (
"uimenu"))
2268 if (go.
isa (
"uimenu"))
2269 update (go, uimenu::properties::ID_LABEL);
2279 if (go.
isa (
"figure"))
2296 if (go.
isa (
"uimenu"))
2297 fltk_label = dynamic_cast<const uimenu::properties&>
2301 else if (go.
isa (
"figure") || go.
isa (
"uicontextmenu"))
2304 error (
"invalid parent object\n");
2306 uimenup.set___fltk_label__ (fltk_label);
2312 if (go.
isa (
"figure"))
2323 case base_properties::ID_VISIBLE:
2324 figure_manager::toggle_window_visibility (ov.
string_value (),
2328 case figure::properties::ID_MENUBAR:
2329 figure_manager::toggle_menubar_visibility
2333 case figure::properties::ID_CURRENTAXES:
2334 figure_manager::update_canvas (go.
get_handle (),
2335 fp.get_currentaxes ());
2338 case figure::properties::ID_NAME:
2339 case figure::properties::ID_NUMBERTITLE:
2343 case figure::properties::ID_INTEGERHANDLE:
2347 figure_manager::renumber_figure (
tmp,
gh.
value ());
2348 figure_manager::set_name (
tmp);
2352 case figure::properties::ID_POSITION:
2353 figure_manager::update_boundingbox (ov.
string_value (),
true);
2356 case figure::properties::ID_OUTERPOSITION:
2357 figure_manager::update_boundingbox (ov.
string_value (),
false);
2362 else if (go.
isa (
"uimenu"))
2364 if (
id == uimenu::properties::ID_LABEL)
2365 uimenu_set___fltk_label__ (go);
2376 if (obj && obj.
isa (
"root"))
2384 if (fobj && fobj.
isa (
"figure"))
2388 if (fp.get___graphics_toolkit__ ()
2389 == FLTK_GRAPHICS_TOOLKIT_NAME)
2390 figure_manager::new_window (fp);
2395 figure_manager::mark_modified (go.
get_handle ());
2404 figure_manager::print (go.
get_handle (), file_cmd, term);
2409 return figure_manager::get_pixels (go.
get_handle ());
2440 m_interpreter.munlock (
"__init_fltk__");
2444 Fremove_input_event_hook (args, 0);
2447 figure_manager::close_all ();
2453 input_event_hook_fcn_id =
id;
2471 #if defined (HAVE_FLTK) 2491 #if defined (HAVE_FLTK) 2493 error (
"__init_fltk__: no graphics DISPLAY available");
2500 fltk_graphics_toolkit *fltk =
new fltk_graphics_toolkit (interp);
2509 fltk->set_input_event_hook_id (
id);
2515 octave_unused_parameter (interp);
OCTINTERP_API octave_value_list feval(const std::string &name, const octave_value_list &args=octave_value_list(), int nargout=0)
void load_toolkit(const graphics_toolkit &tk)
std::string string_value(bool force=false) const
virtual void set(const caseless_str &, const octave_value &)
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
graphics_handle get_handle(void) const
identity matrix If supplied two scalar respectively For allows like xample val
for fields that display a single number
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
octave_value_list & append(const octave_value &val)
static bool display_available(void)
virtual void draw(const graphics_object &go, bool toplevel=true)
octave_int< T > mod(const octave_int< T > &x, const octave_int< T > &y)
void error(const char *fmt,...)
std::complex< T > floor(const std::complex< T > &x)
void zoom(const std::string &mode, double factor, bool push_to_zoom_stack=true)
Array< octave_idx_type > sort_rows_idx(sortmode mode=ASCENDING) const
Sort by rows returns only indices.
void translate_view(const std::string &mode, double x0, double x1, double y0, double y1, bool push_to_zoom_stack=true)
graphics_xform get_transform(void) const
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function t
virtual Matrix get_boundingbox(bool=false, const Matrix &=Matrix()) const
Matrix get_children(void) const
OCTAVE_EXPORT octave_value_list F__fltk_check__(const octave_value_list &, int)
ColumnVector pixel2coord(double px, double py) const
static std::string getenv(const std::string &name)
bool isa(const std::string &go_name) const
static octave_idx_type get_size(double d, const std::string &who)
bool valid_object(void) const
#define DEFMETHOD_DLD(name, interp_name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin method.
nd deftypefn *std::string name
virtual octave_value get(const caseless_str &pname) const
octave_value get(bool all=false) const
bool set(const octave_value &val, bool do_run=true, bool do_notify_toolkit=true)
std::complex< double > w(std::complex< double > z, double relerr=0)
static bool toolkit_loaded
void gl2ps_print(const graphics_object &fig, const std::string &stream, const std::string &term)
void rotate_view(double delta_az, double delta_el, bool push_to_zoom_stack=true)
#define panic_impossible()
base_properties & get_properties(void)
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
graphics_handle get_parent(void) const
Matrix get_all_children(void) const
octave_scalar_map scalar_map_value(void) const
const octave_value & contents(const_iterator p) const
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 assign(const std::string &k, const octave_value &val)
static graphics_handle lookup(double val)
static bool pan_enabled(const graphics_object figObj)
static graphics_object get_object(double val)
static std::string pan_mode(const graphics_object figObj)
bool is_string(void) const
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin function.
octave_idx_type numel(void) const
Number of elements in the array.
octave_idx_type length(void) const
graphics_object get_ancestor(const std::string &type) const
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
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
nd group nd example For each display the value
Matrix matrix_value(bool frc_str_conv=false) const
virtual property get_property(const caseless_str &pname)