comparison libinterp/dldfcn/__init_fltk__.cc @ 18958:c9f960441513

Overhaul FLTK plotting and printing * gl2ps-renderer.cc: Force execution of GL commands before gl2psEndPage to avoid missing primitives in output. Enable error output of gl2ps, check return value of gl2psBeginPage for error. * __init_fltk__.cc: Avoid redraw of the OpenGL and the plot window if not needed. Let FLTK do the resizing of the canvas, the menubar and the statusbar. This was done by creating a resize_dummy and set this as resizable for the plot_window group. Previously this was done inside draw(). Avoid timing issues with fltk_maxtime (removed) and other hacks with multiple Fl::check and redraw () calls. You can use flush and glFlush if you really need to force a immediate redraw. Remove print_mode in draw () and print directly without waiting that FLTK flushes its buffers. This fixes bug #42458 and #40215 Manually placement of the toolbar is only done once when hiding or showing the menubar. (update_toolbar_position) set(gcf, "position", [x, y, w, h]) is now handled by figure::properties::ID_POSITION which calls update_position * __add_default_menu__.m: Remove now unneeded hacks for the menubar.
author Andreas Weber <andy.weber.aw@gmail.com>
date Sat, 26 Jul 2014 10:09:48 +0200
parents 6113e0c6920b
children 52e01aa1fe8b
comparison
equal deleted inserted replaced
18955:914c3ce73665 18958:c9f960441513
1 /* 1 /*
2 2
3 Copyright (C) 2007-2013 Shai Ayal 3 Copyright (C) 2007-2013 Shai Ayal
4 Copyright (C) 2014 Andreas Weber
4 5
5 This file is part of Octave. 6 This file is part of Octave.
6 7
7 Octave is free software; you can redistribute it and/or modify it 8 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 under the terms of the GNU General Public License as published by the
89 #include "toplev.h" 90 #include "toplev.h"
90 #include "variables.h" 91 #include "variables.h"
91 92
92 #define FLTK_GRAPHICS_TOOLKIT_NAME "fltk" 93 #define FLTK_GRAPHICS_TOOLKIT_NAME "fltk"
93 94
94 // Give FLTK no more than 0.01 sec to do its stuff.
95 static double fltk_maxtime = 1e-2;
96
97 const char* help_text = "\ 95 const char* help_text = "\
98 Keyboard Shortcuts\n\ 96 Keyboard Shortcuts\n\
99 a - autoscale\n\ 97 a - autoscale\n\
100 p - pan/zoom\n\ 98 p - pan/zoom\n\
101 r - rotate\n\ 99 r - rotate\n\
111 class OpenGL_fltk : public Fl_Gl_Window 109 class OpenGL_fltk : public Fl_Gl_Window
112 { 110 {
113 public: 111 public:
114 OpenGL_fltk (int xx, int yy, int ww, int hh, double num) 112 OpenGL_fltk (int xx, int yy, int ww, int hh, double num)
115 : Fl_Gl_Window (xx, yy, ww, hh, 0), number (num), renderer (), 113 : Fl_Gl_Window (xx, yy, ww, hh, 0), number (num), renderer (),
116 in_zoom (false), zoom_box (), print_mode (false) 114 in_zoom (false), zoom_box ()
117 { 115 {
118 // Ask for double buffering and a depth buffer. 116 // Ask for double buffering and a depth buffer.
119 mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE); 117 mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE);
120 } 118 }
121 119
131 bool zoom (void) { return in_zoom; } 129 bool zoom (void) { return in_zoom; }
132 void set_zoom_box (const Matrix& zb) { zoom_box = zb; } 130 void set_zoom_box (const Matrix& zb) { zoom_box = zb; }
133 131
134 void print (const std::string& cmd, const std::string& term) 132 void print (const std::string& cmd, const std::string& term)
135 { 133 {
136 print_mode = true; 134 #ifdef HAVE_GL2PS_H
137 print_cmd = cmd; 135 FILE *fp;
138 print_term = term; 136 fp = octave_popen (cmd.c_str (), "w");
137 glps_renderer rend (fp, term);
138 rend.draw (gh_manager::get_object (number), cmd);
139 octave_pclose (fp);
140 #else
141 error ("fltk: printing not available without gl2ps library");
142 #endif
139 } 143 }
140 144
141 void resize (int xx, int yy, int ww, int hh) 145 void resize (int xx, int yy, int ww, int hh)
142 { 146 {
143 Fl_Gl_Window::resize (xx, yy, ww, hh); 147 Fl_Gl_Window::resize (xx, yy, ww, hh);
144 setup_viewport (ww, hh);
145 redraw ();
146 } 148 }
147 149
148 bool renumber (double new_number) 150 bool renumber (double new_number)
149 { 151 {
150 bool retval = false; 152 bool retval = false;
163 opengl_renderer renderer; 165 opengl_renderer renderer;
164 bool in_zoom; 166 bool in_zoom;
165 // (x1,y1,x2,y2) 167 // (x1,y1,x2,y2)
166 Matrix zoom_box; 168 Matrix zoom_box;
167 169
168 bool print_mode;
169 std::string print_cmd;
170 std::string print_term;
171
172 void setup_viewport (int ww, int hh)
173 {
174 glMatrixMode (GL_PROJECTION);
175 glLoadIdentity ();
176 glViewport (0, 0, ww, hh);
177 }
178
179 void draw (void) 170 void draw (void)
180 { 171 {
181 if (! valid ()) 172 if (! valid ())
182 { 173 {
183 valid (1); 174 glMatrixMode (GL_PROJECTION);
184 setup_viewport (w (), h ()); 175 glLoadIdentity ();
185 } 176 glViewport (0, 0, w (), h ());
186 177 }
187 if (print_mode) 178
188 { 179 renderer.draw (gh_manager::get_object (number));
189 #ifdef HAVE_GL2PS_H 180
190 FILE *fp = octave_popen (print_cmd.c_str (), "w"); 181 if (zoom ())
191 glps_renderer rend (fp, print_term); 182 overlay ();
192
193 rend.draw (gh_manager::get_object (number), print_cmd);
194
195 octave_pclose (fp);
196 print_mode = false;
197 #else
198 print_mode = false;
199 error ("fltk: printing not available without gl2ps library");
200 return;
201 #endif
202 }
203 else
204 {
205 renderer.draw (gh_manager::get_object (number));
206
207 if (zoom ())
208 overlay ();
209 }
210 } 183 }
211 184
212 void zoom_box_vertex (void) 185 void zoom_box_vertex (void)
213 { 186 {
214 glVertex2d (zoom_box(0), h () - zoom_box(1)); 187 glVertex2d (zoom_box(0), h () - zoom_box(1));
280 class fltk_uimenu 253 class fltk_uimenu
281 { 254 {
282 public: 255 public:
283 fltk_uimenu (int xx, int yy, int ww, int hh) 256 fltk_uimenu (int xx, int yy, int ww, int hh)
284 { 257 {
285 menubar = new 258 menubar = new Fl_Menu_Bar (xx, yy, ww, hh);
286 Fl_Menu_Bar (xx, yy, ww, hh);
287 } 259 }
288 260
289 int items_to_show (void) 261 int items_to_show (void)
290 { 262 {
291 //returns the number of visible menu items 263 //returns the number of visible menu items
303 } 275 }
304 276
305 void show (void) 277 void show (void)
306 { 278 {
307 menubar->show (); 279 menubar->show ();
280 menubar->redraw ();
308 } 281 }
309 282
310 void hide (void) 283 void hide (void)
311 { 284 {
312 menubar->hide (); 285 menubar->hide ();
286 menubar->redraw ();
313 } 287 }
314 288
315 bool is_visible (void) 289 bool is_visible (void)
316 { 290 {
317 return menubar->visible (); 291 return menubar->visible ();
690 class plot_window : public Fl_Window 664 class plot_window : public Fl_Window
691 { 665 {
692 friend class fltk_uimenu; 666 friend class fltk_uimenu;
693 public: 667 public:
694 plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp) 668 plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp)
695 : Fl_Window (xx, yy - menu_h, ww, hh + menu_h + status_h, "octave"), 669 : Fl_Window (xx, yy, ww, hh + menu_h + status_h + 2, "octave"),
696 window_label (), shift (0), ndim (2), fp (xfp), canvas (0), 670 window_label (), shift (0), ndim (2), fp (xfp), canvas (0),
697 autoscale (0), togglegrid (0), panzoom (0), rotate (0), help (0), 671 autoscale (0), togglegrid (0), panzoom (0), rotate (0), help (0),
698 status (0), ax_obj (), pos_x (0), pos_y (0) 672 status (0), resize_dummy (0), ax_obj (), pos_x (0), pos_y (0)
699 { 673 {
700 callback (window_close, static_cast<void*> (this)); 674 callback (window_close, static_cast<void*> (this));
701 size_range (4*status_h, 2*status_h);
702 675
703 // FIXME: The function below is only available in FLTK >= 1.3 676 // FIXME: The function below is only available in FLTK >= 1.3
704 // At some point support for FLTK 1.1 will be dropped in Octave. 677 // At some point support for FLTK 1.1 will be dropped in Octave.
705 // At that point this function should be uncommented. 678 // At that point this function should be uncommented.
706 // The current solution is to call xclass() before show() for each window. 679 // The current solution is to call xclass() before show() for each window.
707 // Set WM_CLASS which allows window managers to properly group related 680 // Set WM_CLASS which allows window managers to properly group related
708 // windows. Otherwise, the class is just "FLTK" 681 // windows. Otherwise, the class is just "FLTK"
709 //default_xclass ("Octave"); 682 //default_xclass ("Octave");
710 683
711 begin (); 684 uimenu = new fltk_uimenu (0, 0, ww, menu_h);
712 { 685 canvas = new OpenGL_fltk (0, menu_h, ww, hh, number ());
713 // bbox of plot canvas = [xx, yy, ww, hh]; 686
714 // (xx, yy) = UL coordinate relative to UL window. 687 // The bottom toolbar is a composite of "autoscale", "togglegrid",
715 688 // "panzoom", "rotate", "help", and "status". Only "status" should be resized.
716 canvas = new OpenGL_fltk (0, menu_h, ww, hh, number ()); 689
717 690 int toolbar_y = menu_h + hh + 1;
718 uimenu = new fltk_uimenu (0, 0, ww, menu_h); 691 status = new Fl_Output (5 * status_h + 1, toolbar_y, ww - 5 * status_h - 1, status_h, "");
719 uimenu->hide (); 692
720 693 status->textcolor (FL_BLACK);
721 // Toolbar is a composite of "bottom", "autoscale", "togglegrid", 694 status->color (FL_GRAY);
722 // "panzoom", "rotate", "help", and "status". 695 status->textfont (FL_COURIER);
723 696 status->textsize (10);
724 yy = hh + menu_h; 697 status->box (FL_ENGRAVED_BOX);
725 bottom = new Fl_Box (0, yy, ww, status_h); 698
726 bottom->box (FL_FLAT_BOX); 699 autoscale = new Fl_Button (0, toolbar_y, status_h, status_h, "A");
727 700 autoscale->callback (button_callback, static_cast<void*> (this));
728 ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ())); 701 autoscale->tooltip ("Autoscale");
729 702
730 autoscale = new Fl_Button (0, yy, status_h, status_h, "A"); 703 togglegrid = new Fl_Button (status_h, toolbar_y, status_h, status_h, "G");
731 autoscale->callback (button_callback, static_cast<void*> (this)); 704 togglegrid->callback (button_callback, static_cast<void*> (this));
732 autoscale->tooltip ("Autoscale"); 705 togglegrid->tooltip ("Toggle Grid");
733 706
734 togglegrid = new Fl_Button (status_h, yy, status_h, 707 panzoom = new Fl_Button (2* status_h, toolbar_y, status_h, status_h, "P");
735 status_h, "G"); 708 panzoom->callback (button_callback, static_cast<void*> (this));
736 togglegrid->callback (button_callback, static_cast<void*> (this)); 709 panzoom->tooltip ("Mouse Pan/Zoom");
737 togglegrid->tooltip ("Toggle Grid"); 710
738 711 rotate = new Fl_Button (3 * status_h, toolbar_y, status_h, status_h, "R");
739 panzoom = new Fl_Button (2 * status_h, yy, status_h, 712 rotate->callback (button_callback, static_cast<void*> (this));
740 status_h, "P"); 713 rotate->tooltip ("Mouse Rotate");
741 panzoom->callback (button_callback, static_cast<void*> (this)); 714
742 panzoom->tooltip ("Mouse Pan/Zoom"); 715 // get dimensions, de-/activate rotate button, set gui_mode
743 716 gui_mode = rotate_zoom;
744 rotate = new Fl_Button (3 * status_h, yy, status_h, 717 update_gui_mode ();
745 status_h, "R"); 718
746 rotate->callback (button_callback, static_cast<void*> (this)); 719 help = new Fl_Button (4 * status_h, toolbar_y, status_h, status_h, "?");
747 rotate->tooltip ("Mouse Rotate"); 720 help->callback (button_callback, static_cast<void*> (this));
748 721 help->tooltip ("Help");
749 if (ndim == 2) 722
750 rotate->deactivate (); 723 // The size of the resize_dummy box also determines the minimum window size
751 724 resize_dummy = new Fl_Box(5 * status_h + 1, menu_h + 1, ww - 5 * status_h - 1, hh);
752 help = new Fl_Button (4 * status_h, yy, status_h, 725 // read on http://fltk.org/articles.php?L415+I0+T+M1000+P1 how resizable works
753 status_h, "?"); 726 resizable (resize_dummy);
754 help->callback (button_callback, static_cast<void*> (this)); 727
755 help->tooltip ("Help"); 728 end ();
756 729
757 status = new Fl_Output (5 * status_h, yy, 730 if (fp.is_visible ())
758 ww > 2*status_h ? ww - status_h : 0, 731 {
759 status_h, ""); 732 // FIXME: This code should be removed when Octave drops support
760 733 // for FLTK 1.1. Search for default_xclass in this file to find
761 status->textcolor (FL_BLACK); 734 // code that should be uncommented to take its place.
762 status->color (FL_GRAY); 735 //
763 status->textfont (FL_COURIER); 736 // Set WM_CLASS which allows window managers to properly group
764 status->textsize (10); 737 // related windows. Otherwise, the class is just "FLTK"
765 status->box (FL_ENGRAVED_BOX); 738 xclass ("Octave");
766 739
767 // This allows us to have a valid OpenGL context right away. 740 show ();
768 canvas->mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE);
769 if (fp.is_visible ())
770 {
771 // FIXME: This code should be removed when Octave drops support
772 // for FLTK 1.1. Search for default_xclass in this file to find
773 // code that should be uncommented to take its place.
774 //
775 // Set WM_CLASS which allows window managers to properly group
776 // related windows. Otherwise, the class is just "FLTK"
777 xclass ("Octave");
778
779 show ();
780 741
781 #if defined (HAVE_X_WINDOWS) 742 #if defined (HAVE_X_WINDOWS)
782 std::string show_gui_msgs 743 std::string show_gui_msgs
783 = octave_env::getenv ("OCTAVE_SHOW_GUI_MESSAGES"); 744 = octave_env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
784 745
785 // Installing our handler suppresses the messages. 746 // Installing our handler suppresses the messages.
786 if (show_gui_msgs.empty ()) 747 if (show_gui_msgs.empty ())
787 XSetErrorHandler (xerror_handler); 748 XSetErrorHandler (xerror_handler);
788 #endif 749 #endif
789 750
790 if (fp.get_currentaxes ().ok ()) 751 if (fp.get_currentaxes ().ok ())
791 show_canvas (); 752 show_canvas ();
792 else 753 else
793 hide_canvas (); 754 hide_canvas ();
794 } 755 }
795 }
796 end ();
797
798 status->show ();
799 autoscale->show ();
800 togglegrid->show ();
801 panzoom->show ();
802 rotate->show ();
803 756
804 set_name (); 757 set_name ();
805 resizable (canvas); 758
806 gui_mode = (ndim == 3 ? rotate_zoom : pan_zoom);
807 uimenu->add_to_menu (fp); 759 uimenu->add_to_menu (fp);
808 if (uimenu->items_to_show ()) 760 if (!uimenu->items_to_show ())
809 show_menubar ();
810 else
811 hide_menubar (); 761 hide_menubar ();
812 } 762 }
813 763
814 ~plot_window (void) 764 ~plot_window (void)
815 { 765 {
816 canvas->hide ();
817 status->hide ();
818 uimenu->hide ();
819 this->hide (); 766 this->hide ();
820 } 767 }
821 768
822 double number (void) { return fp.get___myhandle__ ().value (); } 769 double number (void) { return fp.get___myhandle__ ().value (); }
823 770
833 } 780 }
834 781
835 void print (const std::string& cmd, const std::string& term) 782 void print (const std::string& cmd, const std::string& term)
836 { 783 {
837 canvas->print (cmd, term); 784 canvas->print (cmd, term);
838
839 // Print immediately so the output file will exist when the drawnow
840 // command is done.
841 mark_modified ();
842 Fl::wait (fltk_maxtime);
843 } 785 }
844 786
845 void show_menubar (void) 787 void show_menubar (void)
846 { 788 {
847 if (!uimenu->is_visible ()) 789 uimenu->show ();
848 { 790 update_toolbar_position ();
849 // FIXME: Toolbar and menubar do not update
850 uimenu->show ();
851 mark_modified ();
852 }
853 } 791 }
854 792
855 void hide_menubar (void) 793 void hide_menubar (void)
856 { 794 {
857 if (uimenu->is_visible ()) 795 uimenu->hide ();
858 { 796 update_toolbar_position ();
859 // FIXME: Toolbar and menubar do not update
860 uimenu->hide ();
861 mark_modified ();
862 }
863 } 797 }
864 798
865 void uimenu_update (const graphics_handle& gh, int id) 799 void uimenu_update (const graphics_handle& gh, int id)
866 { 800 {
867 graphics_object uimenu_obj = gh_manager::get_object (gh); 801 graphics_object uimenu_obj = gh_manager::get_object (gh);
920 854
921 if (uimenu->items_to_show ()) 855 if (uimenu->items_to_show ())
922 show_menubar (); 856 show_menubar ();
923 else 857 else
924 hide_menubar (); 858 hide_menubar ();
925
926 mark_modified ();
927 } 859 }
928 } 860 }
929 861
930 void show_canvas (void) 862 void show_canvas (void)
931 { 863 {
939 void hide_canvas (void) 871 void hide_canvas (void)
940 { 872 {
941 canvas->hide (); 873 canvas->hide ();
942 } 874 }
943 875
876 // Move the toolbar at the bottom of the plot_window.
877 // The only reason for moving the toolbar is hiding and
878 // showing the menubar. All other resizing is done by fltk.
879
880 void update_toolbar_position ()
881 {
882 int old_canvas_h = canvas->h ();
883 size(w (), old_canvas_h + menu_dy () + status_h + 2);
884 canvas->resize (0, menu_dy (), w (), old_canvas_h);
885
886 int toolbar_y = canvas->h () + menu_dy () + 1;
887 autoscale->position (0, toolbar_y);
888 togglegrid->position (status_h, toolbar_y);
889 panzoom->position (2 * status_h, toolbar_y);
890 rotate->position (3 * status_h, toolbar_y);
891 help->position (4 * status_h, toolbar_y);
892 status->resize (5 * status_h + 1, toolbar_y, w () - 5 * status_h - 1, status_h);
893
894 init_sizes();
895 redraw ();
896 }
897
898 // Called from figure::properties::ID_POSITION
899 // (someone has requested a position change with set(h, "position", [...]))
900 // ww and hh refers to the canvas size, not the plot_window size.
901
902 void update_position (int xx, int yy, int ww, int hh)
903 {
904 Fl_Window::resize (xx, yy + menu_dy (), ww, hh + menu_dy () + status_h + 2);
905 }
906
944 void mark_modified (void) 907 void mark_modified (void)
945 { 908 {
946 damage (FL_DAMAGE_ALL); 909 canvas->redraw ();
947 canvas->damage (FL_DAMAGE_ALL); 910 }
911
912 void update_gui_mode (void)
913 {
948 ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ())); 914 ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ()));
949 915
950 if (ndim == 3) 916 if (ndim == 3)
951 rotate->activate (); 917 rotate->activate ();
952 else if (ndim == 2 && gui_mode == rotate_zoom) 918 else // ndim == 2
953 { 919 {
954 rotate->deactivate (); 920 rotate->deactivate ();
955 gui_mode = pan_zoom; 921 gui_mode = pan_zoom;
956 } 922 }
957 } 923 }
985 951
986 // Status area height. 952 // Status area height.
987 static const int status_h = 20; 953 static const int status_h = 20;
988 954
989 // Menu height 955 // Menu height
990 static const int menu_h = 20; 956 static const int menu_h = 25;
991 957
992 // Window callback. 958 // Window callback.
993 static void window_close (Fl_Widget*, void* data) 959 static void window_close (Fl_Widget*, void* data)
994 { 960 {
995 octave_value_list args; 961 octave_value_list args;
1021 fl_message ("%s", help_text); 987 fl_message ("%s", help_text);
1022 } 988 }
1023 989
1024 fltk_uimenu* uimenu; 990 fltk_uimenu* uimenu;
1025 OpenGL_fltk* canvas; 991 OpenGL_fltk* canvas;
1026 Fl_Box* bottom;
1027 Fl_Button* autoscale; 992 Fl_Button* autoscale;
1028 Fl_Button* togglegrid; 993 Fl_Button* togglegrid;
1029 Fl_Button* panzoom; 994 Fl_Button* panzoom;
1030 Fl_Button* rotate; 995 Fl_Button* rotate;
1031 Fl_Button* help; 996 Fl_Button* help;
1032 Fl_Output* status; 997 Fl_Output* status;
998 Fl_Box* resize_dummy;
1033 graphics_object ax_obj; 999 graphics_object ax_obj;
1034 int pos_x; 1000 int pos_x;
1035 int pos_y; 1001 int pos_y;
1036 1002
1037 void axis_auto (void) 1003 void axis_auto (void)
1121 pixel2pos (ax, px1, py1, x1, y1); 1087 pixel2pos (ax, px1, py1, x1, y1);
1122 cbuf << " -> ["<< x1 << ", " << y1 << "]"; 1088 cbuf << " -> ["<< x1 << ", " << y1 << "]";
1123 } 1089 }
1124 1090
1125 status->value (cbuf.str ().c_str ()); 1091 status->value (cbuf.str ().c_str ());
1126 status->redraw ();
1127 } 1092 }
1128 1093
1129 void view2status (graphics_object ax) 1094 void view2status (graphics_object ax)
1130 { 1095 {
1131 if (ax && ax.isa ("axes")) 1096 if (ax && ax.isa ("axes"))
1138 Matrix v (1,2,0); 1103 Matrix v (1,2,0);
1139 v = ap.get ("view").matrix_value (); 1104 v = ap.get ("view").matrix_value ();
1140 cbuf << "[azimuth: " << v(0) << ", elevation: " << v(1) << "]"; 1105 cbuf << "[azimuth: " << v(0) << ", elevation: " << v(1) << "]";
1141 1106
1142 status->value (cbuf.str ().c_str ()); 1107 status->value (cbuf.str ().c_str ());
1143 status->redraw ();
1144 } 1108 }
1145 } 1109 }
1146 1110
1147 void set_currentpoint (int px, int py) 1111 void set_currentpoint (int px, int py)
1148 { 1112 {
1228 mod.append (std::string ("alt")); 1192 mod.append (std::string ("alt"));
1229 1193
1230 return Cell (mod); 1194 return Cell (mod);
1231 } 1195 }
1232 1196
1233 void resize (int xx,int yy,int ww,int hh) 1197 void resize (int xx, int yy, int ww, int hh)
1234 { 1198 {
1235 Fl_Window::resize (xx, yy, ww, hh); 1199 Fl_Window::resize (xx, yy, ww, hh);
1236 1200
1237 Matrix pos (1,4,0); 1201 Matrix pos (1,4,0);
1238 pos(0) = xx; 1202 pos(0) = xx;
1239 pos(1) = yy + menu_dy (); 1203 pos(1) = yy + menu_dy ();
1240 pos(2) = ww; 1204 pos(2) = canvas->w ();
1241 pos(3) = hh - menu_dy () - status_h; 1205 pos(3) = canvas->h ();
1242 1206
1243 fp.set_boundingbox (pos, true); 1207 fp.set_position (pos, false);
1244 }
1245
1246 void draw (void)
1247 {
1248 // FIXME: Toolbar and menubar do not update properly
1249 Matrix pos = fp.get_boundingbox (true);
1250 int canvas_h = pos(3);
1251 int canvas_w = pos(2);
1252 int canvas_y = menu_dy ();
1253 int toolbar_y = menu_dy () + canvas_h;
1254 pos(1) = pos(1) - menu_dy ();
1255 pos(3) = pos(3) + menu_dy () + status_h;
1256
1257 Fl_Window::resize (pos(0), pos(1), pos(2), pos(3));
1258
1259 bottom->resize (0, toolbar_y, status_h, status_h);
1260 autoscale->resize (0, toolbar_y, status_h, status_h);
1261 togglegrid->resize (status_h, toolbar_y, status_h, status_h);
1262 panzoom->resize (2 * status_h, toolbar_y, status_h, status_h);
1263 rotate->resize (3 * status_h, toolbar_y, status_h, status_h);
1264 help->resize (4 * status_h, toolbar_y, status_h, status_h);
1265 status->resize (5 * status_h, toolbar_y, pos(2) - 4 * status_h, status_h);
1266 if (canvas->valid ())
1267 canvas->resize (0, canvas_y, canvas_w, canvas_h);
1268
1269 return Fl_Window::draw ();
1270 } 1208 }
1271 1209
1272 int handle (int event) 1210 int handle (int event)
1273 { 1211 {
1274 graphics_handle gh; 1212 graphics_handle gh;
1421 zoom_box (1) = pos_y; 1359 zoom_box (1) = pos_y;
1422 zoom_box (2) = Fl::event_x (); 1360 zoom_box (2) = Fl::event_x ();
1423 zoom_box (3) = Fl::event_y () - menu_dy (); 1361 zoom_box (3) = Fl::event_y () - menu_dy ();
1424 canvas->set_zoom_box (zoom_box); 1362 canvas->set_zoom_box (zoom_box);
1425 canvas->zoom (true); 1363 canvas->zoom (true);
1426 canvas->redraw (); 1364 mark_modified ();
1427 } 1365 }
1428 1366
1429 break; 1367 break;
1430 1368
1431 case FL_MOUSEWHEEL: 1369 case FL_MOUSEWHEEL:
1651 { 1589 {
1652 if (instance_ok ()) 1590 if (instance_ok ())
1653 instance->do_update_canvas (hnd2idx (gh), ca); 1591 instance->do_update_canvas (hnd2idx (gh), ca);
1654 } 1592 }
1655 1593
1656 static void toggle_menubar_visibility (int fig_idx, bool menubar_is_figure) 1594 static void update_position (const std::string& fig_idx_str,
1595 const Matrix pos)
1657 { 1596 {
1658 if (instance_ok ()) 1597 if (instance_ok ())
1659 instance->do_toggle_menubar_visibility (fig_idx, menubar_is_figure); 1598 instance->do_update_position (str2idx (fig_idx_str), pos);
1660 } 1599 }
1661 1600
1662 static void toggle_menubar_visibility (const std::string& fig_idx_str, 1601 static void toggle_menubar_visibility (const std::string& fig_idx_str,
1663 bool menubar_is_figure) 1602 bool menubar_is_figure)
1664 { 1603 {
1665 toggle_menubar_visibility (str2idx (fig_idx_str), menubar_is_figure); 1604 if (instance_ok ())
1605 instance->do_toggle_menubar_visibility (str2idx (fig_idx_str), menubar_is_figure);
1666 } 1606 }
1667 1607
1668 private: 1608 private:
1669 1609
1670 static figure_manager *instance; 1610 static figure_manager *instance;
1763 void do_mark_modified (int idx) 1703 void do_mark_modified (int idx)
1764 { 1704 {
1765 wm_iterator win = windows.find (idx); 1705 wm_iterator win = windows.find (idx);
1766 1706
1767 if (win != windows.end ()) 1707 if (win != windows.end ())
1768 win->second->mark_modified (); 1708 {
1709 win->second->mark_modified ();
1710 win->second->update_gui_mode ();
1711 }
1769 } 1712 }
1770 1713
1771 void do_set_name (int idx) 1714 void do_set_name (int idx)
1772 { 1715 {
1773 wm_iterator win = windows.find (idx); 1716 wm_iterator win = windows.find (idx);
1816 if (ca.ok ()) 1759 if (ca.ok ())
1817 win->second->show_canvas (); 1760 win->second->show_canvas ();
1818 else 1761 else
1819 win->second->hide_canvas (); 1762 win->second->hide_canvas ();
1820 } 1763 }
1764 }
1765
1766 void do_update_position (int idx, Matrix pos)
1767 {
1768 wm_iterator win = windows.find (idx);
1769
1770 if (win != windows.end ())
1771 win->second->update_position (pos(0), pos(1), pos(2), pos(3));
1821 } 1772 }
1822 1773
1823 static int str2idx (const caseless_str& clstr) 1774 static int str2idx (const caseless_str& clstr)
1824 { 1775 {
1825 int ind; 1776 int ind;
1903 == FLTK_GRAPHICS_TOOLKIT_NAME) 1854 == FLTK_GRAPHICS_TOOLKIT_NAME)
1904 figure_manager::new_window (fp); 1855 figure_manager::new_window (fp);
1905 } 1856 }
1906 } 1857 }
1907 } 1858 }
1908
1909 // it seems that we have to call Fl::check twice to get everything drawn
1910 Fl::check ();
1911 Fl::check (); 1859 Fl::check ();
1912 } 1860 }
1913 1861
1914 return 0; 1862 return 0;
1915 } 1863 }
2012 graphics_handle gh = fp.get___myhandle__ (); 1960 graphics_handle gh = fp.get___myhandle__ ();
2013 figure_manager::renumber_figure (tmp, gh.value ()); 1961 figure_manager::renumber_figure (tmp, gh.value ());
2014 figure_manager::set_name (tmp); 1962 figure_manager::set_name (tmp);
2015 } 1963 }
2016 break; 1964 break;
1965 case figure::properties::ID_POSITION:
1966 {
1967 std::string tmp = ov.string_value ();
1968 Matrix pos = fp.get_position ().matrix_value ();
1969 figure_manager::update_position (tmp, pos);
1970 }
1971 break;
2017 } 1972 }
2018 } 1973 }
2019 } 1974 }
2020 else if (go.isa ("uimenu")) 1975 else if (go.isa ("uimenu"))
2021 { 1976 {
2028 } 1983 }
2029 1984
2030 void redraw_figure (const graphics_object& go) const 1985 void redraw_figure (const graphics_object& go) const
2031 { 1986 {
2032 figure_manager::mark_modified (go.get_handle ()); 1987 figure_manager::mark_modified (go.get_handle ());
2033
2034 __fltk_redraw__ ();
2035 } 1988 }
2036 1989
2037 void print_figure (const graphics_object& go, 1990 void print_figure (const graphics_object& go,
2038 const std::string& term, 1991 const std::string& term,
2039 const std::string& file_cmd, bool /*mono*/, 1992 const std::string& file_cmd, bool /*mono*/,
2040 const std::string& /*debug_file*/) const 1993 const std::string& /*debug_file*/) const
2041 { 1994 {
2042 figure_manager::print (go.get_handle (), file_cmd, term); 1995 figure_manager::print (go.get_handle (), file_cmd, term);
2043 redraw_figure (go);
2044 } 1996 }
2045 1997
2046 Matrix get_canvas_size (const graphics_handle& fh) const 1998 Matrix get_canvas_size (const graphics_handle& fh) const
2047 { 1999 {
2048 return figure_manager::get_size (fh); 2000 return figure_manager::get_size (fh);
2049 } 2001 }
2050 2002
2003 /*
2051 double get_screen_resolution (void) const 2004 double get_screen_resolution (void) const
2052 { 2005 {
2053 // FLTK doesn't give this info. 2006 // FLTK doesn't give this info.
2054 return 72.0; 2007 return 72.0;
2055 } 2008
2009 // FIXME: FLTK >= 1.3.0 could do this with Fl::screen_dpi (h, v, n)
2010 // but do we need it?
2011 }
2012 */
2056 2013
2057 Matrix get_screen_size (void) const 2014 Matrix get_screen_size (void) const
2058 { 2015 {
2059 Matrix sz (1, 2, 0.0); 2016 Matrix sz (1, 2, 0.0);
2060 sz(0) = Fl::w (); 2017 sz(0) = Fl::w ();
2066 { 2023 {
2067 if (toolkit_loaded) 2024 if (toolkit_loaded)
2068 { 2025 {
2069 munlock ("__init_fltk__"); 2026 munlock ("__init_fltk__");
2070 2027
2071 figure_manager::close_all ();
2072
2073 octave_value_list args = input_event_hook_fcn_id; 2028 octave_value_list args = input_event_hook_fcn_id;
2074 args.append (false); 2029 args.append (false);
2075 Fremove_input_event_hook (args, 0); 2030 Fremove_input_event_hook (args, 0);
2076
2077 input_event_hook_fcn_id = octave_value_list (); 2031 input_event_hook_fcn_id = octave_value_list ();
2078 2032
2079 // FIXME: ??? 2033 figure_manager::close_all ();
2080 Fl::wait (fltk_maxtime);
2081 } 2034 }
2082 } 2035 }
2083 2036
2084 void set_input_event_hook_id (const octave_value_list& id) 2037 void set_input_event_hook_id (const octave_value_list& id)
2085 { 2038 {
2136 #else 2089 #else
2137 error ("__init_fltk__: not available without OpenGL and FLTK libraries"); 2090 error ("__init_fltk__: not available without OpenGL and FLTK libraries");
2138 #endif 2091 #endif
2139 2092
2140 return octave_value (); 2093 return octave_value ();
2141 }
2142
2143 DEFUN_DLD (__fltk_maxtime__, args, ,
2144 "-*- texinfo -*-\n\
2145 @deftypefn {Loadable Function} {@var{maxtime} =} __fltk_maxtime__ ()\n\
2146 @deftypefnx {Loadable Function} {} __fltk_maxtime__ (@var{maxtime})\n\
2147 Undocumented internal function.\n\
2148 @end deftypefn")
2149 {
2150 #ifdef HAVE_FLTK
2151 octave_value retval = fltk_maxtime;
2152
2153 if (args.length () == 1)
2154 {
2155 if (args(0).is_real_scalar ())
2156 fltk_maxtime = args(0).double_value ();
2157 else
2158 error ("argument must be a real scalar");
2159 }
2160
2161 return retval;
2162 #else
2163 error ("__fltk_maxtime__: not available without OpenGL and FLTK libraries");
2164 return octave_value ();
2165 #endif
2166 } 2094 }
2167 2095
2168 DEFUN_DLD (__have_fltk__, , , 2096 DEFUN_DLD (__have_fltk__, , ,
2169 "-*- texinfo -*-\n\ 2097 "-*- texinfo -*-\n\
2170 @deftypefn {Loadable Function} {@var{FLTK_available} =} __have_fltk__ ()\n\ 2098 @deftypefn {Loadable Function} {@var{FLTK_available} =} __have_fltk__ ()\n\