Mercurial > octave
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\ |