Mercurial > octave-nkf
changeset 11576:8ac9687dbe9f
rename backend to graphics_toolkit
line wrap: on
line diff
--- a/ChangeLog Wed Jan 19 21:16:13 2011 -0800 +++ b/ChangeLog Thu Jan 20 02:29:57 2011 -0500 @@ -1,3 +1,7 @@ +2011-01-20 John W. Eaton <jwe@octave.org> + + * configure.ac, NEWS: Update for backend -> graphics_toolkit change. + 2010-01-17 Rik <octave@nomad.inbox5.com> * NEWS: Add quadcc to list of new functions added.
--- a/NEWS Wed Jan 19 21:16:13 2011 -0800 +++ b/NEWS Thu Jan 20 02:29:57 2011 -0500 @@ -437,28 +437,28 @@ ** New graphics functions: - addlistener ezcontour gcbo refresh - addproperty ezcontourf ginput refreshdata - allchild ezmesh gtext specular - available_backends ezmeshc intwarning surfl - backend ezplot ishghandle trisurf - cla ezplot3 isocolors waitforbuttonpress - clabel ezpolar isonormals - comet ezsurf isosurface - dellistener findall linkprop - diffuse gcbf plotmatrix + addlistener ezcontour gcbo refresh + addproperty ezcontourf ginput refreshdata + allchild ezmesh gtext specular + available_graphics_toolkits ezmeshc intwarning surfl + graphics_toolkit ezplot ishghandle trisurf + cla ezplot3 isocolors waitforbuttonpress + clabel ezpolar isonormals + comet ezsurf isosurface + dellistener findall linkprop + diffuse gcbf plotmatrix ** New experimental OpenGL/FLTK based plotting system. An experimental plotting system based on OpenGL and the FLTK - toolkit is now part of Octave. This backend is disabled by + toolkit is now part of Octave. This graphics toolkit is disabled by default. You can switch to using it with the command - backend ("fltk") + graphics_toolkit ("fltk") for all future figures or for a particular figure with the command - backend (h, "fltk") + graphics_toolkit (h, "fltk") where "h" is a valid figure handle.
--- a/configure.ac Wed Jan 19 21:16:13 2011 -0800 +++ b/configure.ac Thu Jan 20 02:29:57 2011 -0500 @@ -2393,7 +2393,7 @@ if $native_graphics; then AC_MSG_WARN([]) AC_MSG_WARN([I didn't find gnuplot. Plotting commands will use the]) - AC_MSG_WARN([native graphics backend.]) + AC_MSG_WARN([native graphics toolkit.]) else AC_MSG_WARN([I didn't find gnuplot. It isn't necessary to have gnuplot]) AC_MSG_WARN([installed, but you won't be able to use any of Octave's])
--- a/doc/ChangeLog Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/ChangeLog Thu Jan 20 02:29:57 2011 -0500 @@ -1,3 +1,13 @@ +2011-01-20 John W. Eaton <jwe@octave.org> + + * faq/OctaveFAQ.texi, interpreter/doccheck/aspell-octave.en.pws, + interpreter/octave.texi, interpreter/plot.txi: Update for + backend -> graphics_toolkit change. + + * interpreter/interpimages.m, interpreter/geometryimages.m, + interpreter/sparseimages.m, interpreter/plotimages.m: + Call graphics_toolkit, not backend. + 2011-01-19 Rik <octave@nomad.inbox5.com> * interpreter/doccheck/aspell-octave.en.pws: Add new words to Octave
--- a/doc/faq/OctaveFAQ.texi Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/faq/OctaveFAQ.texi Thu Jan 20 02:29:57 2011 -0500 @@ -304,9 +304,9 @@ 3.2.N release in the future. This series brings the new features @itemize -@item OpenGL backend +@item OpenGL graphics toolkit -An experimental OpenGL graphics backend to replace the gnuplot +An experimental OpenGL graphics toolkit to replace the gnuplot. @item Object Orient Programming
--- a/doc/interpreter/contrib.txi Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/interpreter/contrib.txi Thu Jan 20 02:29:57 2011 -0500 @@ -147,10 +147,10 @@ @example @group -2008-04-02 David Bateman <dbateman@@free.fr> +2010-04-13 David Bateman <dbateman@@free.fr> - * graphics.cc (void gnuplot_backend::close_figure (const - octave_value&) const): Allow for an input and output stream. + * DLD-FUNCTIONS/regexp.cc (octregexp_list): Handle repeated matches + in the list of matches returned by pcre. @end group @end example
--- a/doc/interpreter/doccheck/aspell-octave.en.pws Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/interpreter/doccheck/aspell-octave.en.pws Thu Jan 20 02:29:57 2011 -0500 @@ -37,9 +37,6 @@ autoregressions autoscaled AWK -backend -Backends -backends bartlett Bateman BDF
--- a/doc/interpreter/geometryimages.m Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/interpreter/geometryimages.m Thu Jan 20 02:29:57 2011 -0500 @@ -17,7 +17,7 @@ ## <http://www.gnu.org/licenses/>. function geometryimages (nm, typ) - backend ("gnuplot"); + graphics_toolkit ("gnuplot"); set_print_size (); hide_output (); if (strcmp (typ, "png"))
--- a/doc/interpreter/interpimages.m Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/interpreter/interpimages.m Thu Jan 20 02:29:57 2011 -0500 @@ -17,7 +17,7 @@ ## <http://www.gnu.org/licenses/>. function interpimages (nm, typ) - backend ("gnuplot"); + graphics_toolkit ("gnuplot"); set_print_size (); hide_output (); if (strcmp (typ, "png"))
--- a/doc/interpreter/octave.texi Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/interpreter/octave.texi Thu Jan 20 02:29:57 2011 -0500 @@ -542,7 +542,7 @@ * Marker Styles:: * Callbacks:: * Object Groups:: -* Graphics Backends:: +* Graphics Toolkits:: Object Groups @@ -558,7 +558,7 @@ * Stem Series:: * Surface Group:: -Graphics Backends +Graphics Toolkits * Interaction with gnuplot::
--- a/doc/interpreter/plot.txi Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/interpreter/plot.txi Thu Jan 20 02:29:57 2011 -0500 @@ -34,14 +34,14 @@ Earlier versions of Octave provided plotting through the use of gnuplot. This capability is still available. But, a newer plotting capability is provided by access to OpenGL@. Which plotting system -is used is controlled by the @code{backend} function. (See @ref{Graphics -Backends}.) - -The function call @code{backend ("fltk")} selects the fltk/OpenGL system, and -@code{backend ("gnuplot")} selects the gnuplot system. -The two systems may be used selectively through the use of the @code{backend} -property of the graphics handle for each figure. This is -explained in @ref{Graphics Data Structures}. +is used is controlled by the @code{graphics_toolkit} function. (See +@ref{Graphics Toolkits}.) + +The function call @code{graphics_toolkit ("fltk")} selects the +fltk/OpenGL system, and @code{graphics_toolkit ("gnuplot")} selects the +gnuplot system. The two systems may be used selectively through the use +of the @code{graphics_toolkit} property of the graphics handle for each +figure. This is explained in @ref{Graphics Data Structures}. @node High-Level Plotting @section High-Level Plotting @@ -929,24 +929,30 @@ get (h, ""); error: get: ambiguous figure property name ; possible matches: -__backend__ currentobject paperposition toolbar -__enhanced__ deletefcn paperpositionmode type -__modified__ dockcontrols papersize uicontextmenu -__myhandle__ doublebuffer papertype units -__plot_stream__ filename paperunits userdata -alphamap handlevisibility parent visible -beingdeleted hittest pointer windowbuttondownfcn -busyaction integerhandle pointershapecdata windowbuttonmotionfcn -buttondownfcn interruptible pointershapehotspot windowbuttonupfcn -children inverthardcopy position windowbuttonwheelfcn -clipping keypressfcn renderer windowstyle -closerequestfcn keyreleasefcn renderermode wvisual -color menubar resize wvisualmode -colormap mincolormap resizefcn xdisplay -createfcn name selected xvisual -currentpoint nextplot selectionhighlight xvisualmode -currentaxes numbertitle selectiontype -currentcharacter paperorientation tag +__graphics_toolkit__ hittest resize +__enhanced__ integerhandle resizefcn +__modified__ interruptible selected +__myhandle__ inverthardcopy selectionhighlight +__plot_stream__ keypressfcn selectiontype +alphamap keyreleasefcn tag +beingdeleted menubar toolbar +busyaction mincolormap type +buttondownfcn name uicontextmenu +children nextplot units +clipping numbertitle userdata +closerequestfcn paperorientation visible +color paperposition windowbuttondownfcn +colormap paperpositionmode windowbuttonmotionfcn +createfcn papersize windowbuttonupfcn +currentaxes papertype windowbuttonwheelfcn +currentcharacter paperunits windowstyle +currentobject parent wvisual +currentpoint pointer wvisualmode +deletefcn pointershapecdata xdisplay +dockcontrols pointershapehotspot xvisual +doublebuffer position xvisualmode +filename renderer +handlevisibility renderermode @end smallexample The root figure has index 0. Its properties may be displayed by: @@ -1200,8 +1206,8 @@ The @code{figure} properties are: @table @code -@item __backend__ ---- The backend currently in use. +@item __graphics_toolkit__ +--- The graphics toolkit currently in use. @item __enhanced__ @@ -2442,7 +2448,7 @@ * Marker Styles:: * Callbacks:: * Object Groups:: -* Graphics Backends:: +* Graphics Toolkits:: @end menu @@ -3204,14 +3210,14 @@ Data source variables. @end table -@node Graphics Backends -@subsection Graphics Backends -@cindex graphics backends -@cindex backends, graphics - -@DOCSTRING(backend) - -@DOCSTRING(available_backends) +@node Graphics Toolkits +@subsection Graphics Toolkits +@cindex graphics toolkits +@cindex toolkits, graphics + +@DOCSTRING(graphics_toolkit) + +@DOCSTRING(available_graphics_toolkits) @menu * Interaction with gnuplot::
--- a/doc/interpreter/plotimages.m Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/interpreter/plotimages.m Thu Jan 20 02:29:57 2011 -0500 @@ -17,7 +17,7 @@ ## <http://www.gnu.org/licenses/>. function plotimages (nm, typ) - backend ("gnuplot"); + graphics_toolkit ("gnuplot"); set_print_size (); hide_output (); if (strcmp (typ, "png"))
--- a/doc/interpreter/sparseimages.m Wed Jan 19 21:16:13 2011 -0800 +++ b/doc/interpreter/sparseimages.m Thu Jan 20 02:29:57 2011 -0500 @@ -17,7 +17,7 @@ ## <http://www.gnu.org/licenses/>. function sparseimages (nm, typ) - backend ("gnuplot"); + graphics_toolkit ("gnuplot"); set_print_size (); if (strcmp (typ, "png")) set (0, "defaulttextfontname", "*");
--- a/scripts/ChangeLog Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/ChangeLog Thu Jan 20 02:29:57 2011 -0500 @@ -1,3 +1,15 @@ +2011-01-20 John W. Eaton <jwe@octave.org> + + * plot/ginput.m, plot/gnuplot_drawnow.m, plot/uiputfile.m, + plot/subplot.m, plot/axis.m, plot/colorbar.m, + plot/__print_parse_opts__.m, plot/uigetdir.m, + plot/__fltk_print__.m, plot/print.m, plot/__gnuplot_print__.m, + plot/uigetfile.m, plot/private/__actual_axis_position__.m: + Update for backend -> graphics_toolkit change. + + * plot/graphics_toolkit.m: Rename from backend.m. + * plot/module.mk (plot_FCN_FILES): Update list. + 2011-01-19 Rik <octave@nomad.inbox5.com>
--- a/scripts/plot/__fltk_print__.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/__fltk_print__.m Thu Jan 20 02:29:57 2011 -0500 @@ -110,7 +110,7 @@ pipeline = {sprintf("%s > %s", cmd, opts.name)}; case {"corel", "gif"} error ("print:unsupporteddevice", - "print.m: %s output is not available for the FLTK backend.", + "print.m: %s output is not available for the FLTK graphics toolkit", upper (opts.devopt)) case opts.ghostscript.device opts.ghostscript.source = "-";
--- a/scripts/plot/__gnuplot_print__.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/__gnuplot_print__.m Thu Jan 20 02:29:57 2011 -0500 @@ -138,7 +138,7 @@ endif otherwise error (sprintf ("print:no%soutput", opts.devopt), - "print.m: %s output is not available for the Gnuplot backend.", + "print.m: %s output is not available for the Gnuplot graphics toolkit", upper (opts.devopt)) endswitch
--- a/scripts/plot/__print_parse_opts__.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/__print_parse_opts__.m Thu Jan 20 02:29:57 2011 -0500 @@ -225,13 +225,13 @@ "eps", "ps", "ps", "pdf"}; if (isfigure (arg_st.figure)) - __backend__ = get (arg_st.figure, "__backend__"); + __graphics_toolkit__ = get (arg_st.figure, "__graphics_toolkit__"); else ## Allow tests when no figures are present. - __backend__ = get (0, "defaultfigure__backend__"); + __graphics_toolkit__ = get (0, "defaultfigure__graphics_toolkit__"); endif - if (strcmp (__backend__, "gnuplot") + if (strcmp (__graphics_toolkit__, "gnuplot") && __gnuplot_has_feature__ ("epslatex_implies_eps_filesuffix")) suffixes(strncmp (dev_list, "epslatex", 8)) = {"eps"}; endif @@ -322,7 +322,7 @@ paperposition = [0.25, 2.50, 8.00, 6.00] * 72; endif arg_st.canvas_size = paperposition(3:4); - if (strcmp (__backend__, "gnuplot") && ! arg_st.ghostscript.epscrop) + if (strcmp (__graphics_toolkit__, "gnuplot") && ! arg_st.ghostscript.epscrop) arg_st.ghostscript.pageoffset = paperposition(1:2) - 50; else arg_st.ghostscript.pageoffset = paperposition(1:2); @@ -594,7 +594,7 @@ ## "ps", "ps2", "psc", "psc2" ## ## eps, epsc, eps2, epsc2 are not included here because those are - ## are generated by the backend. + ## are generated by the graphics toolkit. aliases.bmp = "bmp32b"; aliases.pdf = "pdfwrite"; aliases.png = "png16m";
--- a/scripts/plot/axis.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/axis.m Thu Jan 20 02:29:57 2011 -0500 @@ -181,7 +181,7 @@ elseif (strcmpi (ax, "square")) set (ca, "plotboxaspectratio", [1, 1, 1]); elseif (strcmp (ax, "equal")) - if (strcmp (get (get (ca, "parent"), "__backend__"), "gnuplot")) + if (strcmp (get (get (ca, "parent"), "__grahpics_toolkit__"), "gnuplot")) ## FIXME - gnuplot applies the aspect ratio activepostionproperty. set (ca, "activepositionproperty", "position"); ## The following line is a trick used to trigger the recalculation of
--- a/scripts/plot/backend.m Wed Jan 19 21:16:13 2011 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -## Copyright (C) 2008-2011 Michael Goffioul -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {} backend (@var{name}) -## @deftypefnx {Function File} {} backend (@var{hlist}, @var{name}) -## Change the default graphics backend to @var{name}. If the backend is -## not already loaded, it is first initialized (initialization is done -## through the execution of @code{__init_@var{name}__}). -## -## When called with a list of figure handles, @var{hlist}, the backend is -## changed only for the listed figures. -## @seealso{available_backends} -## @end deftypefn - -function backend (varargin) - - name = ""; - hlist = []; - - if (nargin == 1) - if (ischar (varargin{1})) - name = varargin{1}; - else - error ("backend: invalid backend NAME"); - endif - elseif (nargin == 2) - if (isnumeric (varargin{1}) && ischar (varargin{2})) - hlist = varargin{1}; - name = varargin{2}; - elseif (ischar (varargin{2})) - error ("backend: invalid handle list"); - else - error ("backend: invalid backend NAME"); - endif - else - print_usage (); - endif - - if (! any (strcmp (available_backends (), name))) - feval (["__init_", name, "__"]); - if (! any (strcmp (available_backends (), name))) - error ("backend: backend was not correctly registered"); - endif - endif - - if (isempty (hlist)) - set (0, "defaultfigure__backend__", name); - else - for h = hlist(:)' - set (h, "__backend__", name); - endfor - endif - -endfunction
--- a/scripts/plot/colorbar.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/colorbar.m Thu Jan 20 02:29:57 2011 -0500 @@ -107,8 +107,8 @@ if (! deleting) ## FIXME - Matlab does not require the "position" property to be active. - ## Is there a way to determine the plotbox position for the gnuplot - ## backend with the outerposition is active? + ## Is there a way to determine the plotbox position for the + ## gnuplot graphics toolkit with the outerposition is active? set (ax, "activepositionproperty", "position"); obj = get (ax); obj.__my_handle__ = ax; @@ -274,7 +274,7 @@ else scale = [scale, 1]; endif - if (strcmp (get (cf, "__backend__"), "gnuplot") + if (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot") && strcmp (obj.activepositionproperty, "outerposition")) obj.outerposition = obj.outerposition .* [1, 1, scale]; off = 0.5 * (obj.outerposition (3:4) - __actual_axis_position__ (obj)(3:4));
--- a/scripts/plot/ginput.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/ginput.m Thu Jan 20 02:29:57 2011 -0500 @@ -32,13 +32,13 @@ f = gcf (); drawnow (); - backend = (get (f, "__backend__")); + toolkit = (get (f, "__graphics_toolkit__")); varargout = cell (1, nargout); if (nargin == 0) - [varargout{:}] = feval (strcat ("__", backend, "_ginput__"), f); + [varargout{:}] = feval (strcat ("__", toolkit, "_ginput__"), f); else - [varargout{:}] = feval (strcat ("__", backend, "_ginput__"), f, n); + [varargout{:}] = feval (strcat ("__", toolkit, "_ginput__"), f, n); endif endfunction
--- a/scripts/plot/gnuplot_drawnow.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/gnuplot_drawnow.m Thu Jan 20 02:29:57 2011 -0500 @@ -117,12 +117,13 @@ ## Generate the gnuplot "set terminal <term> ..." command. ## When "term" originates from print.m, it may include other options. if (nargin < 4) - ## This supports the gnuplot backend. + ## This supports the gnuplot graphics toolkit. term = gnuplot_default_term (); opts_str = ""; else ## Get the one word terminal id and save the remaining as options to - ## be passed on to gnuplot. The terminal may respect the backend. + ## be passed on to gnuplot. The terminal may respect the graphics + ## toolkit. [term, opts_str] = gnuplot_trim_term (term); term = lower (term); if (strcmpi (term, "lua")) @@ -149,7 +150,7 @@ if (! isempty (h) && isfigure (h)) - ## Generate gnuplot title string for backend plot windows. + ## Generate gnuplot title string for plot windows. if (output_to_screen (term) && ~strcmp (term, "dumb")) fig.numbertitle = get (h, "numbertitle"); fig.name = get (h, "name");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/graphics_toolkit.m Thu Jan 20 02:29:57 2011 -0500 @@ -0,0 +1,71 @@ +## Copyright (C) 2008-2011 Michael Goffioul +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {} graphics_toolkit (@var{name}) +## @deftypefnx {Function File} {} graphics_toolkit (@var{hlist}, @var{name}) +## Change the default graphics graphics toolkit to @var{name}. If the +## toolkit is not already loaded, it is first initialized by calling the +## function @code{__init_@var{name}__}. +## +## When called with a list of figure handles, @var{hlist}, the graphics +## toolkit is changed only for the listed figures. +## @seealso{available_graphics_toolkits} +## @end deftypefn + +function graphics_toolkit (varargin) + + name = ""; + hlist = []; + + if (nargin == 1) + if (ischar (varargin{1})) + name = varargin{1}; + else + error ("graphics_toolkit: invalid graphics toolkit NAME"); + endif + elseif (nargin == 2) + if (isnumeric (varargin{1}) && ischar (varargin{2})) + hlist = varargin{1}; + name = varargin{2}; + elseif (ischar (varargin{2})) + error ("graphics_toolkit: invalid handle list"); + else + error ("graphics_toolkit: invalid graphics toolkit NAME"); + endif + else + print_usage (); + endif + + if (! any (strcmp (available_graphics_toolkits (), name))) + feval (["__init_", name, "__"]); + if (! any (strcmp (available_graphics_toolkits (), name))) + error ("graphics_toolkit: %s toolkit was not correctly registered", + name); + endif + endif + + if (isempty (hlist)) + set (0, "defaultfigure__graphics_toolkit__", name); + else + for h = hlist(:)' + set (h, "__graphics_toolkit__", name); + endfor + endif + +endfunction
--- a/scripts/plot/module.mk Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/module.mk Thu Jan 20 02:29:57 2011 -0500 @@ -52,7 +52,7 @@ plot/area.m \ plot/axes.m \ plot/axis.m \ - plot/backend.m \ + plot/graphics_toolkit.m \ plot/bar.m \ plot/barh.m \ plot/box.m \
--- a/scripts/plot/print.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/print.m Thu Jan 20 02:29:57 2011 -0500 @@ -69,15 +69,15 @@ ## @itemx ps2 ## @itemx psc ## @itemx psc2 -## Postscript (level 1 and 2, mono and color). The FLTK backend -## generates Postscript level 3.0. +## Postscript (level 1 and 2, mono and color). The FLTK graphics +## toolkit generates Postscript level 3.0. ## ## @item eps ## @itemx eps2 ## @itemx epsc ## @itemx epsc2 ## Encapsulated postscript (level 1 and 2, mono and color). The FLTK -## backend generates Postscript level 3.0. +## graphic toolkit generates Postscript level 3.0. ## ## @item tex ## @itemx epslatex @@ -90,7 +90,7 @@ ## processed directly by @LaTeX{}. The other formats are intended to ## be included in a @LaTeX{} (or @TeX{}) document. The @code{tex} device ## is the same as the @code{epslatex} device. The @code{pdflatex} device -## is only available for the FLTK backend. +## is only available for the FLTK graphics toolkit. ## ## @item tikz ## Generate a @LaTeX{} file using PGF/TikZ@. For the FLTK the result is @@ -112,7 +112,7 @@ ## Microsoft Enhanced Metafile ## ## @item fig -## XFig. For the Gnuplot backend, the additional options +## XFig. For the Gnuplot graphics toolkit, the additional options ## @option{-textspecial} or @option{-textnormal} can be used to control ## whether the special flag should be set for the text in ## the figure (default is @option{-textnormal}). @@ -131,7 +131,7 @@ ## JPEG image ## ## @item gif -## GIF image (only available for the Gnuplot backend) +## GIF image (only available for the Gnuplot graphics toolkit) ## ## @item pbm ## PBMplus @@ -283,7 +283,7 @@ ## Modify properties as specified by options props = []; - ## backend tranlates figure position to eps bbox in points + ## graphics toolkit tranlates figure position to eps bbox in points fpos = get (opts.figure, "position"); props(1).h = opts.figure; props(1).name = "position"; @@ -316,7 +316,7 @@ endif if (opts.use_color < 0 - && ! strcmp (get (opts.figure, "__backend__"), "gnuplot")) + && ! strcmp (get (opts.figure, "__graphics_toolkit__"), "gnuplot")) color_props = {"color", "facecolor", "edgecolor", "colormap"}; for c = 1:numel(color_props) h = findall (opts.figure, "-property", color_props{c}); @@ -374,8 +374,8 @@ endif endif - ## call the backend print script - switch (get (opts.figure, "__backend__")) + ## call the graphcis toolkit print script + switch (get (opts.figure, "__graphics_toolkit__")) case "gnuplot" opts = __gnuplot_print__ (opts); otherwise
--- a/scripts/plot/private/__actual_axis_position__.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/private/__actual_axis_position__.m Thu Jan 20 02:29:57 2011 -0500 @@ -44,7 +44,7 @@ set (axis_obj.parent, "position", orig_fig_position) end_unwind_protect ## Get axes size in pixels - if (strcmp (get (axis_obj.parent, "__backend__"), "gnuplot") + if (strcmp (get (axis_obj.parent, "__graphics_toolkit__"), "gnuplot") && strcmp (axis_obj.activepositionproperty, "outerposition")) pos_in_pixels = axis_obj.outerposition .* fig_position([3, 4, 3, 4]); else @@ -76,7 +76,7 @@ pos_in_pixels = pos_in_pixels + dy*[0.0, 0.5, 0.0, -1.0]; endif pos = pos_in_pixels ./ fig_position([3, 4, 3, 4]); - elseif (strcmp (get (axis_obj.parent, "__backend__"), "gnuplot") + elseif (strcmp (get (axis_obj.parent, "__graphics_toolkit__"), "gnuplot") && strcmp (axis_obj.activepositionproperty, "outerposition")) pos = axis_obj.outerposition; else
--- a/scripts/plot/subplot.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/subplot.m Thu Jan 20 02:29:57 2011 -0500 @@ -168,7 +168,7 @@ "activepositionproperty", "outerposition"); endif - if (align_axes && strcmp (get (cf, "__backend__"), "gnuplot")) + if (align_axes && strcmp (get (cf, "__graphics_toolkit__"), "gnuplot")) set (tmp, "activepositionproperty", "position"); endif
--- a/scripts/plot/uigetdir.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/uigetdir.m Thu Jan 20 02:29:57 2011 -0500 @@ -38,13 +38,13 @@ endif - if (any (strcmp (available_backends(), "fltk"))) + if (any (strcmp (available_graphics_toolkits (), "fltk"))) if (!isdir (init_path)) init_path = fileparts (init_path); endif dirname = __fltk_uigetfile__ ("", dialog_name, init_path, [240, 120], "dir"); else - error ("uigetdir: fltk backend required."); + error ("uigetdir: fltk graphics toolkit required"); endif endfunction
--- a/scripts/plot/uigetfile.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/uigetfile.m Thu Jan 20 02:29:57 2011 -0500 @@ -150,10 +150,10 @@ error ("uigetfile: number of input arguments must be less than eight"); endif - if (any (cellfun(@(x)strcmp (x, "fltk"), available_backends))) + if (any (cellfun(@(x)strcmp (x, "fltk"), available_graphics_toolkits ()))) [retfile, retpath, retindex] = __fltk_uigetfile__ (outargs{:}); else - error ("uigetfile: fltk backend required."); + error ("uigetfile: fltk graphics toolkit required."); endif
--- a/scripts/plot/uiputfile.m Wed Jan 19 21:16:13 2011 -0800 +++ b/scripts/plot/uiputfile.m Thu Jan 20 02:29:57 2011 -0500 @@ -89,10 +89,10 @@ error ("uiputfile: number of input arguments must be less than four."); endif - if (any (cellfun(@(x)strcmp (x, "fltk"), available_backends))) + if (any (cellfun(@(x)strcmp (x, "fltk"), available_graphics_toolkits ()))) [retfile, retpath, retindex] = __fltk_uigetfile__ (outargs{:}); else - error ("uiputfile: fltk backend required."); + error ("uiputfile: fltk graphics toolkit required"); endif endfunction
--- a/src/ChangeLog Wed Jan 19 21:16:13 2011 -0800 +++ b/src/ChangeLog Thu Jan 20 02:29:57 2011 -0500 @@ -1,3 +1,12 @@ +2011-01-20 John W. Eaton <jwe@octave.org> + + * gl-render.h, graphics.cc, gl-render.cc, graphics.h.in: + Update for backend -> graphics_toolkit change. + + * DLD-FUNCTIONS/__init_fltk__.cc: Rename from fltk_backend.cc + Update for backend -> graphics_toolkit change. + * DLD-FUNCTIONS/module-files, Makefile.am: Update for renamed file. + 2011-01-19 Rik <octave@nomad.inbox5.com> * src/data.cc, src/input.cc, src/utils.cc: spellcheck docstrings.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/DLD-FUNCTIONS/__init_fltk__.cc Thu Jan 20 02:29:57 2011 -0500 @@ -0,0 +1,2124 @@ +/* + +Copyright (C) 2007-2011 Shai Ayal + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +/* + +To initialize: + + graphics_toolkit ("fltk"); + plot (randn (1e3, 1)); + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if defined (HAVE_FLTK) + +#include <map> +#include <set> +#include <sstream> +#include <iostream> + +#include <FL/Fl.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Choice.H> +#include <Fl/Fl_File_Chooser.H> +#include <FL/Fl_Gl_Window.H> +#include <FL/Fl_Menu_Bar.H> +#include <FL/Fl_Menu_Button.H> +#include <FL/Fl_Output.H> +#include <FL/Fl_Window.H> +#include <FL/fl_ask.H> +#include <FL/fl_draw.H> +#include <FL/gl.h> + +#include "cmd-edit.h" +#include "lo-ieee.h" + +#include "defun-dld.h" +#include "error.h" +#include "gl-render.h" +#include "gl2ps-renderer.h" +#include "graphics.h" +#include "parse.h" +#include "toplev.h" +#include "variables.h" + +#define FLTK_GRAPHICS_TOOLKIT_NAME "fltk" + +// Give FLTK no more than 0.01 sec to do its stuff. +static double fltk_maxtime = 1e-2; + +const char* help_text = "\ +Keyboard Shortcuts\n\ +a - autoscale\n\ +p - pan/zoom\n\ +r - rotate\n\ +g - toggle grid\n\ +\n\ +Mouse\n\ +left drag - pan\n\ +mouse wheel - zoom\n\ +right drag - rectangle zoom\n\ +left double click - autoscale\n\ +"; + +class OpenGL_fltk : public Fl_Gl_Window +{ +public: + OpenGL_fltk (int xx, int yy, int ww, int hh, double num) + : Fl_Gl_Window (xx, yy, ww, hh, 0), number (num), renderer (), + in_zoom (false), zoom_box (), print_fid (-1) + { + // Ask for double buffering and a depth buffer. + mode (FL_DEPTH | FL_DOUBLE); + } + + ~OpenGL_fltk (void) { } + + void zoom (bool z) + { + in_zoom = z; + if (! in_zoom) + hide_overlay (); + } + + bool zoom (void) { return in_zoom; } + void set_zoom_box (const Matrix& zb) { zoom_box = zb; } + + void print (const int fid, const std::string& term) + { + print_fid = fid; + print_term = term; + } + + void resize (int xx, int yy, int ww, int hh) + { + Fl_Gl_Window::resize (xx, yy, ww, hh); + setup_viewport (ww, hh); + redraw (); + } + +private: + double number; + opengl_renderer renderer; + bool in_zoom; + // (x1,y1,x2,y2) + Matrix zoom_box; + + int print_fid; + std::string print_term; + + void setup_viewport (int ww, int hh) + { + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + glViewport (0, 0, ww, hh); + } + + void draw (void) + { + if (! valid ()) + { + valid (1); + setup_viewport (w (), h ()); + } + + if ( print_fid > 0 ) + { + opengl_renderer *rend = new glps_renderer (print_fid, print_term); + rend->draw (gh_manager::lookup (number)); + print_fid = -1; + delete rend; + } + else + { + renderer.draw (gh_manager::lookup (number)); + + if (zoom ()) + overlay (); + } + } + + void zoom_box_vertex (void) + { + glVertex2d (zoom_box(0), h () - zoom_box(1)); + glVertex2d (zoom_box(0), h () - zoom_box(3)); + glVertex2d (zoom_box(2), h () - zoom_box(3)); + glVertex2d (zoom_box(2), h () - zoom_box(1)); + glVertex2d (zoom_box(0), h () - zoom_box(1)); + } + + void overlay (void) + { + glPushMatrix (); + + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluOrtho2D (0.0, w (), 0.0, h ()); + + glPushAttrib (GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT); + glDisable (GL_DEPTH_TEST); + + glBegin (GL_POLYGON); + glColor4f (0.45, 0.62, 0.81, 0.1); + zoom_box_vertex (); + glEnd (); + + glBegin (GL_LINE_STRIP); + glLineWidth (1.5); + glColor4f (0.45, 0.62, 0.81, 0.9); + zoom_box_vertex (); + glEnd (); + + glPopAttrib (); + glPopMatrix (); + } + + int handle (int event) + { + int retval = Fl_Gl_Window::handle (event); + + switch (event) + { + case FL_ENTER: + window ()->cursor (FL_CURSOR_CROSS); + return 1; + + case FL_LEAVE: + window ()->cursor (FL_CURSOR_DEFAULT); + return 1; + } + + return retval; + } +}; + +// Parameter controlling how fast we zoom when using the scrool wheel. +static double wheel_zoom_speed = 0.05; +// Parameter controlling the GUI mode. +static enum { pan_zoom, rotate_zoom, none } gui_mode; + +void script_cb(Fl_Widget*, void* data) + { + static_cast<uimenu::properties*> (data)->execute_callback (); + } + + +class fltk_uimenu +{ +public: + fltk_uimenu (int xx, int yy, int ww, int hh) + { + menubar = new + Fl_Menu_Bar(xx, yy, ww, hh); + } + + int items_to_show (void) + { + //returns the number of visible menu items + int len = menubar->size (); + int n = 0; + for (int t = 0; t < len; t++ ) + { + const Fl_Menu_Item *m = static_cast<const Fl_Menu_Item*>(&(menubar->menu ()[t])); + if ((m->label () != NULL) && m->visible ()) + n++; + } + + return n; + } + + void show (void) + { + menubar->show (); + } + + void hide (void) + { + menubar->hide (); + } + + bool is_visible (void) + { + return menubar->visible (); + } + + int find_index_by_name (std::string findname) + { + // This function is derived from Greg Ercolano's function + // int GetIndexByName(...), see: + // http://seriss.com/people/erco/fltk/#Menu_ChangeLabel + // He agreed via PM that it can be included in octave using GPLv3 + // Kai Habel (14.10.2010) + + std::string menupath; + for (int t = 0; t < menubar->size (); t++ ) + { + Fl_Menu_Item *m = const_cast<Fl_Menu_Item*>(&(menubar->menu ()[t])); + if (m->submenu ()) + { + // item has submenu + if (!menupath.empty ()) + menupath += "/"; + menupath += m->label (); + + if (menupath.compare (findname) == 0 ) + return (t); + } + else + { + // End of submenu? Pop back one level. + if (m->label () == NULL) + { + std::size_t idx = menupath.find_last_of ("/"); + if (idx != std::string::npos) + menupath.erase (idx); + else + menupath.clear (); + continue; + } + // Menu item? + std::string itempath = menupath; + if (!itempath.empty ()) + itempath += "/"; + itempath += m->label (); + + if (itempath.compare (findname) == 0) + return (t); + } + } + return (-1); + } + + Matrix find_uimenu_children (uimenu::properties& uimenup) const + { + Matrix uimenu_childs = uimenup.get_all_children (); + Matrix retval = do_find_uimenu_children (uimenu_childs); + return retval; + } + + Matrix find_uimenu_children (figure::properties& figp) const + { + Matrix uimenu_childs = figp.get_all_children (); + Matrix retval = do_find_uimenu_children (uimenu_childs); + return retval; + } + + Matrix do_find_uimenu_children (Matrix uimenu_childs) const + { + octave_idx_type k = 0; + + + Matrix pos = Matrix (uimenu_childs.numel (), 1); + + for (octave_idx_type ii = 0; ii < uimenu_childs.numel (); ii++) + { + graphics_object kidgo = gh_manager::get_object (uimenu_childs (ii)); + + if (kidgo.valid_object() && kidgo.isa ("uimenu")) + { + uimenu_childs(k) = uimenu_childs(ii); + pos(k++) = + dynamic_cast<uimenu::properties&> (kidgo.get_properties ()).get_position (); + } + } + + uimenu_childs.resize (k, 1); + pos.resize (k, 1); + Matrix retval = Matrix (k, 1); + // Don't know if this is the best method to sort. + // Can we avoid the for loop? + Array<octave_idx_type> sidx = pos.sort_rows_idx (DESCENDING); + for (octave_idx_type ii = 0; ii < k; ii++) + retval(ii) = uimenu_childs (sidx(ii)); + + return retval; + } + + void delete_entry(uimenu::properties& uimenup) + { + std::string fltk_label = uimenup.get_fltk_label (); + int idx = find_index_by_name (fltk_label.c_str ()); + + if (idx >= 0) + menubar->remove (idx); + } + + void update_accelerator (uimenu::properties& uimenup) + { + std::string fltk_label = uimenup.get_fltk_label (); + if (!fltk_label.empty ()) + { + Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); + if (item != NULL) + { + std::string acc = uimenup.get_accelerator (); + if (acc.length () > 0) + { + int key = FL_CTRL + acc[0]; + item->shortcut (key); + } + } + } + } + + void update_callback (uimenu::properties& uimenup) + { + std::string fltk_label = uimenup.get_fltk_label (); + if (!fltk_label.empty ()) + { + Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); + if (item != NULL) + { + if (!uimenup.get_callback ().is_empty ()) + item->callback(static_cast<Fl_Callback*>(script_cb), //callback + static_cast<void*>(&uimenup)); //callback data + else + item->callback(NULL, static_cast<void*>(0)); + } + } + } + + void update_enable (uimenu::properties& uimenup) + { + std::string fltk_label = uimenup.get_fltk_label (); + if (!fltk_label.empty ()) + { + Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); + if (item != NULL) + { + if (uimenup.is_enable ()) + item->activate (); + else + item->deactivate (); + } + } + } + + void update_foregroundcolor (uimenu::properties& uimenup) + { + std::string fltk_label = uimenup.get_fltk_label (); + if (!fltk_label.empty ()) + { + Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); + if (item != NULL) + { + Matrix rgb = uimenup.get_foregroundcolor_rgb (); + item->labelcolor(fl_rgb_color(static_cast<uchar>(floor (rgb(0)*255)), + static_cast<uchar>(floor (rgb(1)*255)), + static_cast<uchar>(floor (rgb(2)*255)))); + } + } + } + + void update_seperator (uimenu::properties& uimenup) + { + // Matlab places the separator before the current + // menu entry, while fltk places it after. So we need to find + // the previous item in this menu/submenu. (Kai) + std::string fltk_label = uimenup.get_fltk_label (); + if (!fltk_label.empty ()) + { + int itemflags = 0, idx; + int curr_idx = find_index_by_name(fltk_label.c_str ()); + + for (idx = curr_idx - 1; idx >= 0; idx--) + { + Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(&menubar->menu () [idx]); + itemflags = item->flags; + if (item->label () != NULL) + break; + } + + if ((idx >= 0) && (idx < menubar->size ())) + { + if (uimenup.is_separator ()) + { + if (idx >= 0 && !(itemflags & FL_SUBMENU)) + menubar->mode (idx, itemflags | FL_MENU_DIVIDER); + } + else + menubar->mode (idx, itemflags & (~FL_MENU_DIVIDER)); + } + } + } + + void update_visible (uimenu::properties& uimenup) + { + std::string fltk_label = uimenup.get_fltk_label (); + if (!fltk_label.empty ()) + { + Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); + if (item != NULL) + { + if (uimenup.is_visible ()) + item->show (); + else + item->hide (); + } + } + } + + void add_entry (uimenu::properties& uimenup) + { + + std::string fltk_label = uimenup.get_fltk_label (); + + if (!fltk_label.empty ()) + { + bool item_added = false; + do + { + const Fl_Menu_Item* item = menubar->find_item(fltk_label.c_str ()); + + if (item == NULL) + { + Matrix uimenu_ch = find_uimenu_children (uimenup); + int len = uimenu_ch.numel (); + int flags = 0; + if (len > 0) + flags = FL_SUBMENU; + if ((len == 0) && (uimenup.is_checked ())) + flags += FL_MENU_TOGGLE + FL_MENU_VALUE; + menubar->add(fltk_label.c_str (), 0, 0, 0, flags); + item_added = true; + } + else + { + //avoid duplicate menulabels + std::size_t idx1 = fltk_label.find_last_of ("("); + std::size_t idx2 = fltk_label.find_last_of (")"); + int len = idx2 - idx1; + int val = 1; + if (len > 0) + { + std::string valstr = fltk_label.substr (idx1 + 1, len - 1); + fltk_label.erase(idx1, len + 1); + val = atoi (valstr.c_str ()); + if ((val > 0) && (val < 99)) + val++; + } + std::ostringstream valstream; + valstream << val; + fltk_label += "(" + valstream.str () + ")"; + } + } + while (!item_added); + uimenup.set_fltk_label (fltk_label); + } + } + + void add_to_menu (uimenu::properties& uimenup) + { + Matrix kids = find_uimenu_children (uimenup); + int len = kids.length (); + std::string fltk_label = uimenup.get_fltk_label (); + + add_entry (uimenup); + update_foregroundcolor (uimenup); + update_callback (uimenup); + update_accelerator (uimenup); + update_enable (uimenup); + update_visible (uimenup); + update_seperator (uimenup); + + for (octave_idx_type ii = 0; ii < len; ii++) + { + graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1))); + if (kgo.valid_object ()) + { + uimenu::properties& kprop = dynamic_cast<uimenu::properties&>(kgo.get_properties ()); + add_to_menu (kprop); + } + } + } + + void add_to_menu (figure::properties& figp) + { + Matrix kids = find_uimenu_children (figp); + int len = kids.length (); + menubar->clear (); + for (octave_idx_type ii = 0; ii < len; ii++) + { + graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1))); + + if (kgo.valid_object ()) + { + uimenu::properties& kprop = dynamic_cast<uimenu::properties&>(kgo.get_properties ()); + add_to_menu (kprop); + } + } + } + + template <class T_prop> + void remove_from_menu (T_prop& prop) + { + Matrix kids; + std::string type = prop.get_type (); + kids = find_uimenu_children (prop); + int len = kids.length (); + + for (octave_idx_type ii = 0; ii < len; ii++) + { + graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1))); + + if (kgo.valid_object ()) + { + uimenu::properties kprop = dynamic_cast<uimenu::properties&>(kgo.get_properties ()); + remove_from_menu (kprop); + } + } + + if (type.compare("uimenu") == 0) + delete_entry(dynamic_cast<uimenu::properties&>(prop)); + else if (type.compare("figure") == 0) + menubar->clear (); + } + + ~fltk_uimenu() + { + delete menubar; + } + +private: + Fl_Menu_Bar* menubar; +}; + +class plot_window : public Fl_Window +{ + friend class fltk_uimenu; +public: + plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp) + : Fl_Window (xx, yy, ww, hh, "octave"), window_label (), shift (0), + ndim (2), fp (xfp), canvas (0), autoscale (0), togglegrid (0), + panzoom (0), rotate (0), help (0), status (0) + { + callback (window_close, static_cast<void*> (this)); + + begin (); + { + + uimenu = new + fltk_uimenu(0, 0, ww, menu_h); + uimenu->hide (); + + canvas = new + OpenGL_fltk (0, 0, ww , hh - status_h, number ()); + + bottom = new + Fl_Box (0, + hh - status_h, + ww, + status_h); + bottom->box(FL_FLAT_BOX); + + ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ())); + + autoscale = new + Fl_Button (0, + hh - status_h, + status_h, + status_h, + "A"); + autoscale->callback (button_callback, static_cast<void*> (this)); + autoscale->tooltip ("Autoscale"); + + togglegrid = new + Fl_Button (status_h, + hh - status_h, + status_h, + status_h, + "G"); + togglegrid->callback (button_callback, static_cast<void*> (this)); + togglegrid->tooltip ("Toggle Grid"); + + panzoom = new + Fl_Button (2 * status_h, + hh - status_h, + status_h, + status_h, + "P"); + panzoom->callback (button_callback, static_cast<void*> (this)); + panzoom->tooltip ("Mouse Pan/Zoom"); + + rotate = new + Fl_Button (3 * status_h, + hh - status_h, + status_h, + status_h, + "R"); + rotate->callback (button_callback, static_cast<void*> (this)); + rotate->tooltip ("Mouse Rotate"); + + if (ndim == 2) + rotate->deactivate (); + + help = new + Fl_Button (4 * status_h, + hh - status_h, + status_h, + status_h, + "?"); + help->callback (button_callback, static_cast<void*> (this)); + help->tooltip ("Help"); + + status = new + Fl_Output (5 * status_h, + hh - status_h, + ww > 2*status_h ? ww - status_h : 0, + status_h, ""); + + status->textcolor (FL_BLACK); + status->color (FL_GRAY); + status->textfont (FL_COURIER); + status->textsize (10); + status->box (FL_ENGRAVED_BOX); + + // This allows us to have a valid OpenGL context right away. + canvas->mode (FL_DEPTH | FL_DOUBLE ); + if (fp.is_visible ()) + { + show (); + if (fp.get_currentaxes ().ok()) + show_canvas (); + else + hide_canvas (); + } + } + end (); + + status->show (); + autoscale->show (); + togglegrid->show (); + panzoom->show (); + rotate->show (); + + set_name (); + resizable (canvas); + size_range (4*status_h, 2*status_h); + gui_mode = (ndim == 3 ? rotate_zoom : pan_zoom); + uimenu->add_to_menu (fp); + if (uimenu->items_to_show ()) + show_menubar (); + else + hide_menubar (); + } + + ~plot_window (void) + { + canvas->hide (); + status->hide (); + uimenu->hide (); + this->hide (); + delete canvas; + delete status; + delete uimenu; + } + + // FIXME -- this could change. + double number (void) { return fp.get___myhandle__ ().value (); } + + void print (const int fid, const std::string& term) + { + canvas->print (fid, term); + + // Print immediately so the output file will exist when the drawnow + // command is done. + mark_modified (); + Fl::wait (fltk_maxtime); + } + + void show_menubar (void) + { + int dm = menu_h; + if (uimenu->is_visible ()) + dm = 0; + canvas->resize (canvas->x (), + canvas->y () + dm, + canvas->w (), + canvas->h () - dm); + uimenu->show (); + mark_modified (); + } + + void hide_menubar (void) + { + int dm = menu_h; + if (!uimenu->is_visible ()) + dm = 0; + canvas->resize (canvas->x (), + canvas->y () - dm, + canvas->w (), + canvas->h () + dm); + uimenu->hide (); + mark_modified (); + } + + void uimenu_update(graphics_handle gh, int id) + { + graphics_object uimenu_obj = gh_manager::get_object (gh); + + if (uimenu_obj.valid_object () && uimenu_obj.isa ("uimenu")) + { + uimenu::properties& uimenup = + dynamic_cast<uimenu::properties&> (uimenu_obj.get_properties ()); + std::string fltk_label = uimenup.get_fltk_label(); + graphics_object fig = uimenu_obj.get_ancestor("figure"); + figure::properties& figp = + dynamic_cast<figure::properties&> (fig.get_properties ()); + + switch(id) + { + case base_properties::ID_BEINGDELETED: + uimenu->remove_from_menu (uimenup); + break; + case base_properties::ID_VISIBLE: + uimenu->update_visible (uimenup); + break; + case uimenu::properties::ID_ACCELERATOR: + uimenu->update_accelerator (uimenup); + break; + case uimenu::properties::ID_CALLBACK: + uimenu->update_callback (uimenup); + break; + case uimenu::properties::ID_CHECKED: + uimenu->add_to_menu (figp);//rebuilding entire menu + break; + case uimenu::properties::ID_ENABLE: + uimenu->update_enable (uimenup); + break; + case uimenu::properties::ID_FOREGROUNDCOLOR: + uimenu->update_foregroundcolor (uimenup); + break; + case uimenu::properties::ID_LABEL: + uimenu->add_to_menu (figp);//rebuilding entire menu + break; + case uimenu::properties::ID_POSITION: + uimenu->add_to_menu (figp);//rebuilding entire menu + break; + case uimenu::properties::ID_SEPARATOR: + uimenu->update_seperator (uimenup); + break; + } + + if (uimenu->items_to_show ()) + show_menubar (); + else + hide_menubar (); + + mark_modified(); + } + } + + void show_canvas (void) + { + canvas->show (); + canvas->make_current (); + } + + void hide_canvas (void) + { + canvas->hide (); + } + + void mark_modified (void) + { + damage (FL_DAMAGE_ALL); + canvas->damage (FL_DAMAGE_ALL); + ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ())); + + if (ndim == 3) + rotate->activate (); + else if ((ndim == 2) && (gui_mode == rotate_zoom)) + { + rotate->deactivate (); + gui_mode = pan_zoom; + } + } + + void set_name (void) + { + window_label = fp.get_title (); + label (window_label.c_str ()); + } + +private: + // window name -- this must exists for the duration of the window's + // life + std::string window_label; + + // Mod keys status + int shift; + + // Number of dimensions, 2 or 3. + int ndim; + + // Figure properties. + figure::properties& fp; + + // Status area height. + static const int status_h = 20; + + // Menu height + static const int menu_h = 20; + + // Window callback. + static void window_close (Fl_Widget*, void* data) + { + octave_value_list args; + args(0) = static_cast<plot_window*> (data)->number (); + feval ("close", args); + } + + // Button callbacks. + static void button_callback (Fl_Widget* ww, void* data) + { + static_cast<plot_window*> (data)->button_press (ww, data); + } + + void button_press (Fl_Widget* widg, void*) + { + if (widg == autoscale) + axis_auto (); + + if (widg == togglegrid) + toggle_grid (); + + if (widg == panzoom) + gui_mode = pan_zoom; + + if (widg == rotate && ndim == 3) + gui_mode = rotate_zoom; + + if (widg == help) + fl_message ("%s", help_text); + } + + fltk_uimenu* uimenu; + OpenGL_fltk* canvas; + Fl_Box* bottom; + Fl_Button* autoscale; + Fl_Button* togglegrid; + Fl_Button* panzoom; + Fl_Button* rotate; + Fl_Button* help; + Fl_Output* status; + + void axis_auto (void) + { + octave_value_list args; + args(0) = fp.get_currentaxes ().as_octave_value (); + args(1) = "auto"; + feval ("axis", args); + mark_modified (); + } + + void toggle_grid (void) + { + octave_value_list args; + if (fp.get_currentaxes ().ok ()) + args(0) = fp.get_currentaxes ().as_octave_value (); + + feval ("grid", args); + mark_modified (); + } + + void pixel2pos + (graphics_handle ax, int px, int py, double& xx, double& yy) const + { + pixel2pos ( gh_manager::get_object (ax), px, py, xx, yy); + } + + void pixel2pos + (graphics_object ax, int px, int py, double& xx, double& yy) const + { + if (ax && ax.isa ("axes")) + { + axes::properties& ap = + dynamic_cast<axes::properties&> (ax.get_properties ()); + ColumnVector pp = ap.pixel2coord (px, py); + xx = pp(0); + yy = pp(1); + } + } + + graphics_handle pixel2axes_or_ca (int px, int py ) + { + Matrix kids = fp.get_children (); + int len = kids.length (); + + for (int k = 0; k < len; k++) + { + graphics_handle hnd = gh_manager::lookup (kids(k)); + + if (hnd.ok ()) + { + graphics_object kid = gh_manager::get_object (hnd); + + if (kid.valid_object () && kid.isa ("axes")) + { + Matrix bb = kid.get_properties ().get_boundingbox (true); + + if (bb(0) <= px && px < (bb(0)+bb(2)) + && bb(1) <= py && py < (bb(1)+bb(3))) + { + return hnd; + } + } + } + } + return fp.get_currentaxes (); + } + + void pixel2status (graphics_handle ax, int px0, int py0, + int px1 = -1, int py1 = -1) + { + pixel2status (gh_manager::get_object (ax), px0, py0, px1, py1); + } + + void pixel2status (graphics_object ax, int px0, int py0, + int px1 = -1, int py1 = -1) + { + double x0, y0, x1, y1; + std::stringstream cbuf; + cbuf.precision (4); + cbuf.width (6); + pixel2pos (ax, px0, py0, x0, y0); + cbuf << "[" << x0 << ", " << y0 << "]"; + if (px1 >= 0) + { + pixel2pos (ax, px1, py1, x1, y1); + cbuf << " -> ["<< x1 << ", " << y1 << "]"; + } + + status->value (cbuf.str ().c_str ()); + status->redraw (); + } + + void view2status (graphics_object ax) + { + if (ax && ax.isa ("axes")) + { + axes::properties& ap = + dynamic_cast<axes::properties&> (ax.get_properties ()); + std::stringstream cbuf; + cbuf.precision (4); + cbuf.width (6); + Matrix v (1,2,0); + v = ap.get("view").matrix_value(); + cbuf << "[azimuth: " << v(0) << ", elevation: " << v(1) << "]"; + + status->value (cbuf.str ().c_str ()); + status->redraw (); + } + } + + void set_currentpoint (int px, int py) + { + if (!fp.is_beingdeleted ()) + { + Matrix pos (1,2,0); + pos(0) = px; + pos(1) = h () - status_h - menu_h - py; + fp.set_currentpoint (pos); + } + } + + void set_axes_currentpoint (graphics_object ax, int px, int py) + { + if (ax.valid_object ()) + { + axes::properties& ap = + dynamic_cast<axes::properties&> (ax.get_properties ()); + + double xx, yy; + pixel2pos (ax, px, py, xx, yy); + + Matrix pos (2,3,0); + pos(0,0) = xx; + pos(1,0) = yy; + pos(0,1) = xx; + pos(1,1) = yy; + + ap.set_currentpoint (pos); + } + } + + int key2shift (int key) + { + if (key == FL_Shift_L || key == FL_Shift_R) + return FL_SHIFT; + + if (key == FL_Control_L || key == FL_Control_R) + return FL_CTRL; + + if (key == FL_Alt_L || key == FL_Alt_R) + return FL_ALT; + + if (key == FL_Meta_L || key == FL_Meta_R) + return FL_META; + + return 0; + } + + int key2ascii (int key) + { + if (key < 256) return key; + if (key == FL_Tab) return '\t'; + if (key == FL_Enter) return 0x0a; + if (key == FL_BackSpace) return 0x08; + if (key == FL_Escape) return 0x1b; + + return 0; + } + + Cell modifier2cell () + { + string_vector mod; + + if (shift & FL_SHIFT) + mod.append (std::string ("shift")); + if (shift & FL_CTRL) + mod.append (std::string ("control")); + if (shift & FL_ALT || shift & FL_META) + mod.append (std::string ("alt")); + + return Cell (mod); + } + + void resize (int xx,int yy,int ww,int hh) + { + Fl_Window::resize (xx, yy, ww, hh); + + Matrix pos (1,4,0); + pos(0) = xx; + pos(1) = yy; + pos(2) = ww; + pos(3) = hh - status_h - menu_h; + + fp.set_position (pos); + } + + void draw (void) + { + Matrix pos = fp.get_position ().matrix_value (); + Fl_Window::resize (pos(0), pos(1) , pos(2), pos(3) + status_h + menu_h); + + return Fl_Window::draw (); + } + + int handle (int event) + { + static int px0,py0; + static graphics_object ax0; + + graphics_handle gh; + + graphics_object fig = gh_manager::get_object (fp.get___myhandle__ ()); + int retval = Fl_Window::handle (event); + + // We only handle events which are in the canvas area. + if (!Fl::event_inside(canvas)) + return retval; + + if (!fp.is_beingdeleted ()) + { + switch (event) + { + case FL_KEYDOWN: + { + int key = Fl::event_key (); + + shift |= key2shift (key); + int key_a = key2ascii (key); + if (key_a && fp.get_keypressfcn ().is_defined ()) + { + Octave_map evt; + evt.assign ("Character", octave_value (key_a)); + evt.assign ("Key", octave_value (std::tolower (key_a))); + evt.assign ("Modifier", octave_value (modifier2cell ())); + fp.execute_keypressfcn (evt); + } + switch (key) + { + case 'a': + case 'A': + axis_auto (); + break; + + case 'g': + case 'G': + toggle_grid (); + break; + + case 'p': + case 'P': + gui_mode = pan_zoom; + break; + + case 'r': + case 'R': + gui_mode = rotate_zoom; + break; + } + } + break; + + case FL_KEYUP: + { + int key = Fl::event_key (); + + shift &= (~key2shift (key)); + int key_a = key2ascii (key); + if (key_a && fp.get_keyreleasefcn ().is_defined ()) + { + Octave_map evt; + evt.assign ("Character", octave_value (key_a)); + evt.assign ("Key", octave_value (std::tolower (key_a))); + evt.assign ("Modifier", octave_value (modifier2cell ())); + fp.execute_keyreleasefcn (evt); + } + } + break; + + case FL_MOVE: + pixel2status (pixel2axes_or_ca (Fl::event_x (), Fl::event_y ()), + Fl::event_x (), Fl::event_y ()); + break; + + case FL_PUSH: + px0 = Fl::event_x (); + py0 = Fl::event_y (); + + set_currentpoint (Fl::event_x (), Fl::event_y ()); + + gh = pixel2axes_or_ca (px0, py0); + + if (gh.ok ()) + { + ax0 = gh_manager::get_object (gh); + set_axes_currentpoint (ax0, px0, py0); + } + + fp.execute_windowbuttondownfcn (); + + if (Fl::event_button () == 1 || Fl::event_button () == 3) + return 1; + + break; + + case FL_DRAG: + if (fp.get_windowbuttonmotionfcn ().is_defined ()) + { + set_currentpoint (Fl::event_x (), Fl::event_y ()); + fp.execute_windowbuttonmotionfcn (); + } + + if (Fl::event_button () == 1) + { + if (ax0 && ax0.isa ("axes")) + { + if (gui_mode == pan_zoom) + pixel2status (ax0, px0, py0, Fl::event_x (), Fl::event_y ()); + else + view2status (ax0); + axes::properties& ap = + dynamic_cast<axes::properties&> (ax0.get_properties ()); + + double x0, y0, x1, y1; + Matrix pos = fp.get_position ().matrix_value (); + pixel2pos (ax0, px0, py0, x0, y0); + pixel2pos (ax0, Fl::event_x (), Fl::event_y (), x1, y1); + + if (gui_mode == pan_zoom) + ap.translate_view (x0 - x1, y0 - y1); + else if (gui_mode == rotate_zoom) + { + double daz, del; + daz = (Fl::event_x () - px0) / pos(2) * 360; + del = (Fl::event_y () - py0) / pos(3) * 360; + ap.rotate_view (del, daz); + } + + px0 = Fl::event_x (); + py0 = Fl::event_y (); + mark_modified (); + } + return 1; + } + else if (Fl::event_button () == 3) + { + pixel2status (ax0, px0, py0, Fl::event_x (), Fl::event_y ()); + Matrix zoom_box (1,4,0); + zoom_box (0) = px0; + zoom_box (1) = py0; + zoom_box (2) = Fl::event_x (); + zoom_box (3) = Fl::event_y (); + canvas->set_zoom_box (zoom_box); + canvas->zoom (true); + canvas->redraw (); + } + + break; + + case FL_MOUSEWHEEL: + { + graphics_object ax = + gh_manager::get_object (pixel2axes_or_ca (Fl::event_x (), + Fl::event_y ())); + if (ax && ax.isa ("axes")) + { + axes::properties& ap = + dynamic_cast<axes::properties&> (ax.get_properties ()); + + // Determine if we're zooming in or out. + const double factor = + (Fl::event_dy () > 0) ? 1.0 + wheel_zoom_speed : 1.0 - wheel_zoom_speed; + + // Get the point we're zooming about. + double x1, y1; + pixel2pos (ax, Fl::event_x (), Fl::event_y (), x1, y1); + + ap.zoom_about_point (x1, y1, factor, false); + mark_modified (); + } + } + return 1; + + case FL_RELEASE: + if (fp.get_windowbuttonupfcn ().is_defined ()) + { + set_currentpoint (Fl::event_x (), Fl::event_y ()); + fp.execute_windowbuttonupfcn (); + } + + if (Fl::event_button () == 1) + { + if ( Fl::event_clicks () == 1) + { + if (ax0 && ax0.isa ("axes")) + { + axes::properties& ap = + dynamic_cast<axes::properties&> (ax0.get_properties ()); + ap.set_xlimmode("auto"); + ap.set_ylimmode("auto"); + ap.set_zlimmode("auto"); + mark_modified (); + } + } + } + if (Fl::event_button () == 3) + { + // End of drag -- zoom. + if (canvas->zoom ()) + { + canvas->zoom (false); + double x0,y0,x1,y1; + if (ax0 && ax0.isa ("axes")) + { + axes::properties& ap = + dynamic_cast<axes::properties&> (ax0.get_properties ()); + pixel2pos (ax0, px0, py0, x0, y0); + pixel2pos (ax0, Fl::event_x (), Fl::event_y (), x1, y1); + Matrix xl (1,2,0); + Matrix yl (1,2,0); + if (x0 < x1) + { + xl(0) = x0; + xl(1) = x1; + } + else + { + xl(0) = x1; + xl(1) = x0; + } + if (y0 < y1) + { + yl(0) = y0; + yl(1) = y1; + } + else + { + yl(0) = y1; + yl(1) = y0; + } + ap.zoom (xl, yl); + mark_modified (); + } + } + } + break; + } + } + + return retval; + } +}; + +class figure_manager +{ +public: + + static bool instance_ok (void) + { + bool retval = true; + + if (! instance) + instance = new figure_manager (); + + if (! instance) + { + ::error ("unable to create figure_manager object!"); + + retval = false; + } + + return retval; + } + + ~figure_manager (void) + { + close_all (); + } + + static void close_all (void) + { + if (instance_ok ()) + instance->do_close_all (); + } + + static void new_window (figure::properties& fp) + { + if (instance_ok ()) + instance->do_new_window (fp); + } + + static void delete_window (int idx) + { + if (instance_ok ()) + instance->do_delete_window (idx); + } + + static void delete_window (std::string idx_str) + { + delete_window (str2idx (idx_str)); + } + + static void toggle_window_visibility (int idx, bool is_visible) + { + if (instance_ok ()) + instance->do_toggle_window_visibility (idx, is_visible); + } + + static void toggle_window_visibility (std::string idx_str, bool is_visible) + { + toggle_window_visibility (str2idx (idx_str), is_visible); + } + + static void mark_modified (int idx) + { + if (instance_ok ()) + instance->do_mark_modified (idx); + } + + static void mark_modified (const graphics_handle& gh) + { + mark_modified (hnd2idx (gh)); + } + + static void set_name (int idx) + { + if (instance_ok ()) + instance->do_set_name (idx); + } + + static void set_name (std::string idx_str) + { + set_name (str2idx (idx_str)); + } + + static Matrix get_size (int idx) + { + return instance_ok () ? instance->do_get_size (idx) : Matrix (); + } + + static Matrix get_size (const graphics_handle& gh) + { + return get_size (hnd2idx (gh)); + } + + static void print (const graphics_handle& gh , const int fid, const std::string& term) + { + if (instance_ok ()) + instance->do_print (hnd2idx(gh), fid, term); + } + + static void uimenu_update (const graphics_handle& figh, const graphics_handle& uimenuh, const int id) + { + if (instance_ok ()) + instance->do_uimenu_update (hnd2idx(figh), uimenuh, id); + } + + static void update_canvas (const graphics_handle& gh, const graphics_handle& ca) + { + if (instance_ok ()) + instance->do_update_canvas (hnd2idx(gh), ca); + } + + static void toggle_menubar_visibility (int fig_idx, bool menubar_is_figure) + { + if (instance_ok ()) + instance->do_toggle_menubar_visibility (fig_idx, menubar_is_figure); + } + + static void toggle_menubar_visibility (std::string fig_idx_str, bool menubar_is_figure) + { + toggle_menubar_visibility (str2idx (fig_idx_str), menubar_is_figure); + } + +private: + + static figure_manager *instance; + + figure_manager (void) { } + + // No copying! + figure_manager (const figure_manager&); + figure_manager& operator = (const figure_manager&); + + // Singelton -- hide all of the above. + + static int curr_index; + typedef std::map<int, plot_window*> window_map; + typedef window_map::iterator wm_iterator;; + window_map windows; + + static std::string fltk_idx_header; + + void do_close_all (void) + { + wm_iterator win; + for (win = windows.begin (); win != windows.end (); win++) + delete win->second; + windows.clear (); + } + + void do_new_window (figure::properties& fp) + { + int x, y, w, h; + + int idx = figprops2idx (fp); + if (idx >= 0 && windows.find (idx) == windows.end ()) + { + default_size (x, y, w, h); + idx2figprops (curr_index , fp); + windows[curr_index++] = new plot_window (x, y, w, h, fp); + } + } + + void do_delete_window (int idx) + { + wm_iterator win; + if ((win = windows.find (idx)) != windows.end ()) + { + delete win->second; + windows.erase (win); + } + } + + void do_toggle_window_visibility (int idx, bool is_visible) + { + wm_iterator win; + if ((win = windows.find (idx)) != windows.end ()) + { + if (is_visible) + win->second->show (); + else + win->second->hide (); + + win->second->redraw (); + } + } + + void do_toggle_menubar_visibility (int fig_idx, bool menubar_is_figure) + { + wm_iterator win; + if ((win = windows.find (fig_idx)) != windows.end ()) + { + if (menubar_is_figure) + win->second->show_menubar (); + else + win->second->hide_menubar (); + + win->second->redraw (); + } + } + + void do_mark_modified (int idx) + { + wm_iterator win; + if ((win = windows.find (idx)) != windows.end ()) + { + win->second->mark_modified (); + } + } + + void do_set_name (int idx) + { + wm_iterator win; + if ((win = windows.find (idx)) != windows.end ()) + { + win->second->set_name (); + } + } + + Matrix do_get_size (int idx) + { + Matrix sz (1, 2, 0.0); + + wm_iterator win; + if ((win = windows.find (idx)) != windows.end ()) + { + sz(0) = win->second->w (); + sz(1) = win->second->h (); + } + + return sz; + } + + void do_print (int idx, const int fid, const std::string& term) + { + wm_iterator win; + if ((win = windows.find (idx)) != windows.end ()) + { + win->second->print (fid, term); + } + } + + void do_uimenu_update (int idx, graphics_handle gh, int id) + { + wm_iterator win; + if ((win = windows.find (idx)) != windows.end ()) + { + win->second->uimenu_update (gh, id); + } + } + + void do_update_canvas (int idx, graphics_handle ca) + { + wm_iterator win; + if ((win = windows.find (idx)) != windows.end ()) + { + if (ca.ok ()) + win->second->show_canvas (); + else + win->second->hide_canvas (); + } + } + + + // FIXME -- default size should be configurable. + void default_size (int& x, int& y, int& w, int& h) + { + x = 0; + y = 0; + w = 640; + h = 480; + } + + static int str2idx (const caseless_str clstr) + { + int ind; + if (clstr.find (fltk_idx_header,0) == 0) + { + std::istringstream istr (clstr.substr (fltk_idx_header.size ())); + if (istr >> ind) + return ind; + } + error ("figure_manager: could not recognize fltk index"); + return -1; + } + + void idx2figprops (int idx, figure::properties& fp) + { + std::ostringstream ind_str; + ind_str << fltk_idx_header << idx; + fp.set___plot_stream__ (ind_str.str ()); + } + + static int figprops2idx (const figure::properties& fp) + { + if (fp.get___graphics_toolkit__ () == FLTK_GRAPHICS_TOOLKIT_NAME) + { + octave_value ps = fp.get___plot_stream__ (); + if (ps.is_string ()) + return str2idx (ps.string_value ()); + else + return 0; + } + error ("figure_manager: figure is not fltk"); + return -1; + } + + static int hnd2idx (const double h) + { + graphics_object fobj = gh_manager::get_object (h); + if (fobj && fobj.isa ("figure")) + { + figure::properties& fp = + dynamic_cast<figure::properties&> (fobj.get_properties ()); + return figprops2idx (fp); + } + error ("figure_manager: H is not a figure"); + return -1; + } + + static int hnd2idx (const graphics_handle& fh) + { + return hnd2idx (fh.value ()); + } +}; + +figure_manager *figure_manager::instance = 0; + +std::string figure_manager::fltk_idx_header="fltk index="; +int figure_manager::curr_index = 1; + +static bool toolkit_registered = false; + +static int +__fltk_redraw__ (void) +{ + if (toolkit_registered) + { + // We scan all figures and add those which use FLTK. + graphics_object obj = gh_manager::get_object (0); + if (obj && obj.isa ("root")) + { + base_properties& props = obj.get_properties (); + Matrix children = props.get_all_children (); + + for (octave_idx_type n = 0; n < children.numel (); n++) + { + graphics_object fobj = gh_manager::get_object (children (n)); + if (fobj && fobj.isa ("figure")) + { + figure::properties& fp = + dynamic_cast<figure::properties&> (fobj.get_properties ()); + if (fp.get___graphics_toolkit__ () + == FLTK_GRAPHICS_TOOLKIT_NAME) + figure_manager::new_window (fp); + } + } + } + + // it seems that we have to call Fl::check twice to get everything drawn + Fl::check (); + Fl::check (); + } + + return 0; +} + +class fltk_graphics_toolkit : public base_graphics_toolkit +{ +public: + fltk_graphics_toolkit (void) + : base_graphics_toolkit (FLTK_GRAPHICS_TOOLKIT_NAME) { } + + ~fltk_graphics_toolkit (void) { } + + bool is_valid (void) const { return true; } + + void finalize (const graphics_object& go) + { + if (go.isa ("figure")) + { + octave_value ov = go.get (caseless_str ("__plot_stream__")); + + if (! ov.is_empty ()) + figure_manager::delete_window (ov.string_value ()); + } + } + + void uimenu_set_fltk_label(graphics_object uimenu_obj) + { + if (uimenu_obj.valid_object ()) + { + uimenu::properties& uimenup = + dynamic_cast<uimenu::properties&> (uimenu_obj.get_properties ()); + std::string fltk_label = uimenup.get_label (); + graphics_object go = gh_manager::get_object (uimenu_obj.get_parent ()); + if (go.isa ("uimenu")) + fltk_label = dynamic_cast<const uimenu::properties&> (go.get_properties ()).get_fltk_label () + + "/" + + fltk_label; + else if (go.isa ("figure")) + ; + else + error("unexpected parent object\n"); + + uimenup.set_fltk_label(fltk_label); + } + } + + void update (const graphics_object& go, int id) + { + if (go.isa ("figure")) + { + octave_value ov = go.get (caseless_str ("__plot_stream__")); + + if (! ov.is_empty ()) + { + const figure::properties& fp = + dynamic_cast<const figure::properties&> (go.get_properties ()); + + switch (id) + { + case base_properties::ID_VISIBLE: + figure_manager::toggle_window_visibility (ov.string_value (), fp.is_visible ()); + break; + case figure::properties::ID_MENUBAR: + figure_manager::toggle_menubar_visibility (ov.string_value (), fp.menubar_is("figure")); + break; + case figure::properties::ID_NAME: + case figure::properties::ID_CURRENTAXES: + figure_manager::update_canvas (go.get_handle (), fp.get_currentaxes ()); + break; + case figure::properties::ID_NUMBERTITLE: + figure_manager::set_name (ov.string_value ()); + break; + } + } + } + else if (go.isa ("uimenu")) + { + if (id == uimenu::properties::ID_LABEL) + uimenu_set_fltk_label (go); + + graphics_object fig = go.get_ancestor("figure"); + figure_manager::uimenu_update(fig.get_handle (), go.get_handle (), id); + } + } + + void redraw_figure (const graphics_object& go) const + { + figure_manager::mark_modified (go.get_handle ()); + + __fltk_redraw__ (); + } + + void print_figure (const graphics_object& go, + const std::string& term, + const std::string& file, bool /*mono*/, + const std::string& /*debug_file*/) const + { + int fid; + std::istringstream istr (file); + if (istr >> fid) + { + figure_manager::print (go.get_handle (), fid, term); + redraw_figure (go); + } + else + error ("fltk_graphics_toolkit: filename should be fid"); + } + + Matrix get_canvas_size (const graphics_handle& fh) const + { + return figure_manager::get_size (fh); + } + + double get_screen_resolution (void) const + { + // FLTK doesn't give this info. + return 72.0; + } + + Matrix get_screen_size (void) const + { + Matrix sz (1, 2, 0.0); + sz(0) = Fl::w (); + sz(1) = Fl::h (); + return sz; + } +}; + +// Initialize the fltk graphics toolkit. + +DEFUN_DLD (__init_fltk__, , , "") +{ + static bool remove_fltk_registered = false; + + if (! toolkit_registered) + { + mlock (); + + graphics_toolkit::register_toolkit (new fltk_graphics_toolkit); + toolkit_registered = true; + + octave_value_list args; + args(0) = "__fltk_redraw__"; + feval ("add_input_event_hook", args, 0); + + if (! remove_fltk_registered) + { + octave_add_atexit_function ("__remove_fltk__"); + + remove_fltk_registered = true; + } + } + + octave_value retval; + return retval; +} + +DEFUN_DLD (__fltk_redraw__, , , "") +{ + __fltk_redraw__ (); + + return octave_value (); +} + +// Delete the fltk graphics toolkit. + +DEFUN_DLD (__remove_fltk__, , , "") +{ + if (toolkit_registered) + { + munlock ("__init_fltk__"); + + figure_manager::close_all (); + graphics_toolkit::unregister_toolkit (FLTK_GRAPHICS_TOOLKIT_NAME); + toolkit_registered = false; + + octave_value_list args; + args(0) = "__fltk_redraw__"; + feval ("remove_input_event_hook", args, 0); + + // FIXME ??? + Fl::wait (fltk_maxtime); + } + + octave_value retval; + return retval; +} + +DEFUN_DLD (__fltk_maxtime__, args, ,"") +{ + octave_value retval = fltk_maxtime; + + if (args.length () == 1) + { + if (args(0).is_real_scalar ()) + fltk_maxtime = args(0).double_value (); + else + error ("argument must be a real scalar"); + } + + return retval; +} + +DEFUN_DLD (fltk_mouse_wheel_zoom, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{speed} =} fltk_mouse_wheel_zoom ()\n\ +@deftypefnx {Built-in Function} {} fltk_mouse_wheel_zoom (@var{speed})\n\ +Query or set the mouse wheel zoom factor in the fltk graphics toolkit.\n\ +@end deftypefn") +{ + octave_value retval = wheel_zoom_speed; + + if (args.length () == 1) + { + if (args(0).is_real_scalar ()) + wheel_zoom_speed = args(0).double_value (); + else + error ("fltk_mouse_wheel_zoom: SPEED must be a real scalar"); + } + + return retval; +} + +DEFUN_DLD (fltk_gui_mode, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{mode} =} fltk_gui_mode ()\n\ +@deftypefnx {Built-in Function} {} fltk_gui_mode (@var{mode})\n\ +Query or set the GUI mode for the fltk grahpics toolkit.\n\ +The @var{mode} argument can be one of the following strings:\n\ +@table @asis\n\ +@item '2d'\n\ +Allows panning and zooming of current axes.\n\ +\n\ +@item '3d'\n\ +Allows rotating and zooming of current axes.\n\ +\n\ +@item 'none'\n\ +Mouse inputs have no effect.\n\ +@end table\n\ +@end deftypefn") +{ + caseless_str mode_str; + + if (gui_mode == pan_zoom) + mode_str = "2d"; + else if (gui_mode == rotate_zoom) + mode_str = "3d"; + else + mode_str = "none"; + + + bool failed = false; + + if (args.length () == 1) + { + if (args(0).is_string ()) + { + mode_str = args(0).string_value (); + + if (mode_str.compare ("2d")) + gui_mode = pan_zoom; + else if (mode_str.compare ("3d")) + gui_mode = rotate_zoom; + else if (mode_str.compare ("none")) + gui_mode = none; + else + failed = true; + } + else + failed = true; + } + + if (failed) + error ("MODE must be one of the strings: ""2D"", ""3D"", or ""None""."); + + + return octave_value(mode_str); +} + +#include "file-ops.h" +DEFUN_DLD (__fltk_uigetfile__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __fltk_uigetfile__ (@dots{})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + // This function should be called by uigetfile.m + // Error checking should be done in uigetfile.m! + // + // Expected argument list + // args(0) ... FileFilter in fltk format + // args(1) ... Title + // args(2) ... Default Filename + // args(3) ... PostionValue [x,y] + // args(4) ... SelectValue "on"/"off"/"dir"/"create" + + std::string file_filter, title, default_name, multi; + if (args(0).is_string ()) + file_filter = args(0).string_value(); + + if (args(1).is_string ()) + title = args(1).string_value(); + + if (args(2).is_string ()) + default_name = args(2).string_value(); + + if (args(3).is_real_matrix ()) + Matrix pos = args(3).matrix_value(); + + int multi_type = Fl_File_Chooser::SINGLE; + std::string flabel = "Filename:"; + if (args(4).is_string ()) + { + multi = args(4).string_value(); + if (multi == "on") + multi_type = Fl_File_Chooser::MULTI; + else if (multi == "dir") + { + multi_type = Fl_File_Chooser::DIRECTORY; + flabel = "Directory:"; + } + else if (multi == "create") + multi_type = Fl_File_Chooser::CREATE; + } + + Fl_File_Chooser::filename_label = flabel.c_str (); + Fl_File_Chooser *fc = new Fl_File_Chooser(default_name.c_str (), file_filter.c_str (), multi_type, title.c_str ()); + fc->preview(0); + + if (multi_type == Fl_File_Chooser::CREATE) + fc->ok_label("Save"); + + fc->show(); + while (fc->shown ()) + { Fl::wait (); } + + octave_value_list fargs, retval; + + retval(0) = octave_value(0); + retval(1) = octave_value(0); + retval(2) = octave_value(0); + + if (fc->value() != NULL) + { + int file_count = fc->count (); + std::string fname; + std::string sep = file_ops::dir_sep_str (); + std::size_t idx; + + if ((file_count == 1) && (multi_type != Fl_File_Chooser::DIRECTORY)) + { + fname = fc->value (); + idx = fname.find_last_of(sep); + retval(0) = fname.substr(idx + 1); + } + else + { + Cell file_cell = Cell(file_count, 1); + for (octave_idx_type n = 1; n <= file_count; n++) + { + fname = fc->value (n); + idx = fname.find_last_of(sep); + file_cell(n - 1) = fname.substr(idx + 1); + } + retval(0) = file_cell; + } + + if (multi_type == Fl_File_Chooser::DIRECTORY) + retval(0) = std::string(fc->value ()); + else + { + retval(1) = std::string(fc->directory ()); + retval(2) = fc->filter_value(); + } + } + + return retval; +} + +#endif
--- a/src/DLD-FUNCTIONS/fltk_backend.cc Wed Jan 19 21:16:13 2011 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2124 +0,0 @@ -/* - -Copyright (C) 2007-2011 Shai Ayal - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -<http://www.gnu.org/licenses/>. - -*/ - -/* - -To initialize: - - backend ("fltk"); - plot (randn (1e3, 1)); - -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if defined (HAVE_FLTK) - -#include <map> -#include <set> -#include <sstream> -#include <iostream> - -#include <FL/Fl.H> -#include <FL/Fl_Box.H> -#include <FL/Fl_Button.H> -#include <FL/Fl_Choice.H> -#include <Fl/Fl_File_Chooser.H> -#include <FL/Fl_Gl_Window.H> -#include <FL/Fl_Menu_Bar.H> -#include <FL/Fl_Menu_Button.H> -#include <FL/Fl_Output.H> -#include <FL/Fl_Window.H> -#include <FL/fl_ask.H> -#include <FL/fl_draw.H> -#include <FL/gl.h> - -#include "cmd-edit.h" -#include "lo-ieee.h" - -#include "defun-dld.h" -#include "error.h" -#include "gl-render.h" -#include "gl2ps-renderer.h" -#include "graphics.h" -#include "parse.h" -#include "toplev.h" -#include "variables.h" - -#define FLTK_BACKEND_NAME "fltk" - -// Give FLTK no more than 0.01 sec to do its stuff. -static double fltk_maxtime = 1e-2; - -const char* help_text = "\ -Keyboard Shortcuts\n\ -a - autoscale\n\ -p - pan/zoom\n\ -r - rotate\n\ -g - toggle grid\n\ -\n\ -Mouse\n\ -left drag - pan\n\ -mouse wheel - zoom\n\ -right drag - rectangle zoom\n\ -left double click - autoscale\n\ -"; - -class OpenGL_fltk : public Fl_Gl_Window -{ -public: - OpenGL_fltk (int xx, int yy, int ww, int hh, double num) - : Fl_Gl_Window (xx, yy, ww, hh, 0), number (num), renderer (), - in_zoom (false), zoom_box (), print_fid (-1) - { - // Ask for double buffering and a depth buffer. - mode (FL_DEPTH | FL_DOUBLE); - } - - ~OpenGL_fltk (void) { } - - void zoom (bool z) - { - in_zoom = z; - if (! in_zoom) - hide_overlay (); - } - - bool zoom (void) { return in_zoom; } - void set_zoom_box (const Matrix& zb) { zoom_box = zb; } - - void print (const int fid, const std::string& term) - { - print_fid = fid; - print_term = term; - } - - void resize (int xx, int yy, int ww, int hh) - { - Fl_Gl_Window::resize (xx, yy, ww, hh); - setup_viewport (ww, hh); - redraw (); - } - -private: - double number; - opengl_renderer renderer; - bool in_zoom; - // (x1,y1,x2,y2) - Matrix zoom_box; - - int print_fid; - std::string print_term; - - void setup_viewport (int ww, int hh) - { - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - glViewport (0, 0, ww, hh); - } - - void draw (void) - { - if (! valid ()) - { - valid (1); - setup_viewport (w (), h ()); - } - - if ( print_fid > 0 ) - { - opengl_renderer *rend = new glps_renderer (print_fid, print_term); - rend->draw (gh_manager::lookup (number)); - print_fid = -1; - delete rend; - } - else - { - renderer.draw (gh_manager::lookup (number)); - - if (zoom ()) - overlay (); - } - } - - void zoom_box_vertex (void) - { - glVertex2d (zoom_box(0), h () - zoom_box(1)); - glVertex2d (zoom_box(0), h () - zoom_box(3)); - glVertex2d (zoom_box(2), h () - zoom_box(3)); - glVertex2d (zoom_box(2), h () - zoom_box(1)); - glVertex2d (zoom_box(0), h () - zoom_box(1)); - } - - void overlay (void) - { - glPushMatrix (); - - glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); - - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - gluOrtho2D (0.0, w (), 0.0, h ()); - - glPushAttrib (GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT); - glDisable (GL_DEPTH_TEST); - - glBegin (GL_POLYGON); - glColor4f (0.45, 0.62, 0.81, 0.1); - zoom_box_vertex (); - glEnd (); - - glBegin (GL_LINE_STRIP); - glLineWidth (1.5); - glColor4f (0.45, 0.62, 0.81, 0.9); - zoom_box_vertex (); - glEnd (); - - glPopAttrib (); - glPopMatrix (); - } - - int handle (int event) - { - int retval = Fl_Gl_Window::handle (event); - - switch (event) - { - case FL_ENTER: - window ()->cursor (FL_CURSOR_CROSS); - return 1; - - case FL_LEAVE: - window ()->cursor (FL_CURSOR_DEFAULT); - return 1; - } - - return retval; - } -}; - -// Parameter controlling how fast we zoom when using the scrool wheel. -static double wheel_zoom_speed = 0.05; -// Parameter controlling the GUI mode. -static enum { pan_zoom, rotate_zoom, none } gui_mode; - -void script_cb(Fl_Widget*, void* data) - { - static_cast<uimenu::properties*> (data)->execute_callback (); - } - - -class fltk_uimenu -{ -public: - fltk_uimenu (int xx, int yy, int ww, int hh) - { - menubar = new - Fl_Menu_Bar(xx, yy, ww, hh); - } - - int items_to_show (void) - { - //returns the number of visible menu items - int len = menubar->size (); - int n = 0; - for (int t = 0; t < len; t++ ) - { - const Fl_Menu_Item *m = static_cast<const Fl_Menu_Item*>(&(menubar->menu ()[t])); - if ((m->label () != NULL) && m->visible ()) - n++; - } - - return n; - } - - void show (void) - { - menubar->show (); - } - - void hide (void) - { - menubar->hide (); - } - - bool is_visible (void) - { - return menubar->visible (); - } - - int find_index_by_name (std::string findname) - { - // This function is derived from Greg Ercolano's function - // int GetIndexByName(...), see: - // http://seriss.com/people/erco/fltk/#Menu_ChangeLabel - // He agreed via PM that it can be included in octave using GPLv3 - // Kai Habel (14.10.2010) - - std::string menupath; - for (int t = 0; t < menubar->size (); t++ ) - { - Fl_Menu_Item *m = const_cast<Fl_Menu_Item*>(&(menubar->menu ()[t])); - if (m->submenu ()) - { - // item has submenu - if (!menupath.empty ()) - menupath += "/"; - menupath += m->label (); - - if (menupath.compare (findname) == 0 ) - return (t); - } - else - { - // End of submenu? Pop back one level. - if (m->label () == NULL) - { - std::size_t idx = menupath.find_last_of ("/"); - if (idx != std::string::npos) - menupath.erase (idx); - else - menupath.clear (); - continue; - } - // Menu item? - std::string itempath = menupath; - if (!itempath.empty ()) - itempath += "/"; - itempath += m->label (); - - if (itempath.compare (findname) == 0) - return (t); - } - } - return (-1); - } - - Matrix find_uimenu_children (uimenu::properties& uimenup) const - { - Matrix uimenu_childs = uimenup.get_all_children (); - Matrix retval = do_find_uimenu_children (uimenu_childs); - return retval; - } - - Matrix find_uimenu_children (figure::properties& figp) const - { - Matrix uimenu_childs = figp.get_all_children (); - Matrix retval = do_find_uimenu_children (uimenu_childs); - return retval; - } - - Matrix do_find_uimenu_children (Matrix uimenu_childs) const - { - octave_idx_type k = 0; - - - Matrix pos = Matrix (uimenu_childs.numel (), 1); - - for (octave_idx_type ii = 0; ii < uimenu_childs.numel (); ii++) - { - graphics_object kidgo = gh_manager::get_object (uimenu_childs (ii)); - - if (kidgo.valid_object() && kidgo.isa ("uimenu")) - { - uimenu_childs(k) = uimenu_childs(ii); - pos(k++) = - dynamic_cast<uimenu::properties&> (kidgo.get_properties ()).get_position (); - } - } - - uimenu_childs.resize (k, 1); - pos.resize (k, 1); - Matrix retval = Matrix (k, 1); - // Don't know if this is the best method to sort. - // Can we avoid the for loop? - Array<octave_idx_type> sidx = pos.sort_rows_idx (DESCENDING); - for (octave_idx_type ii = 0; ii < k; ii++) - retval(ii) = uimenu_childs (sidx(ii)); - - return retval; - } - - void delete_entry(uimenu::properties& uimenup) - { - std::string fltk_label = uimenup.get_fltk_label (); - int idx = find_index_by_name (fltk_label.c_str ()); - - if (idx >= 0) - menubar->remove (idx); - } - - void update_accelerator (uimenu::properties& uimenup) - { - std::string fltk_label = uimenup.get_fltk_label (); - if (!fltk_label.empty ()) - { - Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); - if (item != NULL) - { - std::string acc = uimenup.get_accelerator (); - if (acc.length () > 0) - { - int key = FL_CTRL + acc[0]; - item->shortcut (key); - } - } - } - } - - void update_callback (uimenu::properties& uimenup) - { - std::string fltk_label = uimenup.get_fltk_label (); - if (!fltk_label.empty ()) - { - Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); - if (item != NULL) - { - if (!uimenup.get_callback ().is_empty ()) - item->callback(static_cast<Fl_Callback*>(script_cb), //callback - static_cast<void*>(&uimenup)); //callback data - else - item->callback(NULL, static_cast<void*>(0)); - } - } - } - - void update_enable (uimenu::properties& uimenup) - { - std::string fltk_label = uimenup.get_fltk_label (); - if (!fltk_label.empty ()) - { - Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); - if (item != NULL) - { - if (uimenup.is_enable ()) - item->activate (); - else - item->deactivate (); - } - } - } - - void update_foregroundcolor (uimenu::properties& uimenup) - { - std::string fltk_label = uimenup.get_fltk_label (); - if (!fltk_label.empty ()) - { - Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); - if (item != NULL) - { - Matrix rgb = uimenup.get_foregroundcolor_rgb (); - item->labelcolor(fl_rgb_color(static_cast<uchar>(floor (rgb(0)*255)), - static_cast<uchar>(floor (rgb(1)*255)), - static_cast<uchar>(floor (rgb(2)*255)))); - } - } - } - - void update_seperator (uimenu::properties& uimenup) - { - // Matlab places the separator before the current - // menu entry, while fltk places it after. So we need to find - // the previous item in this menu/submenu. (Kai) - std::string fltk_label = uimenup.get_fltk_label (); - if (!fltk_label.empty ()) - { - int itemflags = 0, idx; - int curr_idx = find_index_by_name(fltk_label.c_str ()); - - for (idx = curr_idx - 1; idx >= 0; idx--) - { - Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(&menubar->menu () [idx]); - itemflags = item->flags; - if (item->label () != NULL) - break; - } - - if ((idx >= 0) && (idx < menubar->size ())) - { - if (uimenup.is_separator ()) - { - if (idx >= 0 && !(itemflags & FL_SUBMENU)) - menubar->mode (idx, itemflags | FL_MENU_DIVIDER); - } - else - menubar->mode (idx, itemflags & (~FL_MENU_DIVIDER)); - } - } - } - - void update_visible (uimenu::properties& uimenup) - { - std::string fltk_label = uimenup.get_fltk_label (); - if (!fltk_label.empty ()) - { - Fl_Menu_Item* item = const_cast<Fl_Menu_Item*>(menubar->find_item (fltk_label.c_str ())); - if (item != NULL) - { - if (uimenup.is_visible ()) - item->show (); - else - item->hide (); - } - } - } - - void add_entry (uimenu::properties& uimenup) - { - - std::string fltk_label = uimenup.get_fltk_label (); - - if (!fltk_label.empty ()) - { - bool item_added = false; - do - { - const Fl_Menu_Item* item = menubar->find_item(fltk_label.c_str ()); - - if (item == NULL) - { - Matrix uimenu_ch = find_uimenu_children (uimenup); - int len = uimenu_ch.numel (); - int flags = 0; - if (len > 0) - flags = FL_SUBMENU; - if ((len == 0) && (uimenup.is_checked ())) - flags += FL_MENU_TOGGLE + FL_MENU_VALUE; - menubar->add(fltk_label.c_str (), 0, 0, 0, flags); - item_added = true; - } - else - { - //avoid duplicate menulabels - std::size_t idx1 = fltk_label.find_last_of ("("); - std::size_t idx2 = fltk_label.find_last_of (")"); - int len = idx2 - idx1; - int val = 1; - if (len > 0) - { - std::string valstr = fltk_label.substr (idx1 + 1, len - 1); - fltk_label.erase(idx1, len + 1); - val = atoi (valstr.c_str ()); - if ((val > 0) && (val < 99)) - val++; - } - std::ostringstream valstream; - valstream << val; - fltk_label += "(" + valstream.str () + ")"; - } - } - while (!item_added); - uimenup.set_fltk_label (fltk_label); - } - } - - void add_to_menu (uimenu::properties& uimenup) - { - Matrix kids = find_uimenu_children (uimenup); - int len = kids.length (); - std::string fltk_label = uimenup.get_fltk_label (); - - add_entry (uimenup); - update_foregroundcolor (uimenup); - update_callback (uimenup); - update_accelerator (uimenup); - update_enable (uimenup); - update_visible (uimenup); - update_seperator (uimenup); - - for (octave_idx_type ii = 0; ii < len; ii++) - { - graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1))); - if (kgo.valid_object ()) - { - uimenu::properties& kprop = dynamic_cast<uimenu::properties&>(kgo.get_properties ()); - add_to_menu (kprop); - } - } - } - - void add_to_menu (figure::properties& figp) - { - Matrix kids = find_uimenu_children (figp); - int len = kids.length (); - menubar->clear (); - for (octave_idx_type ii = 0; ii < len; ii++) - { - graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1))); - - if (kgo.valid_object ()) - { - uimenu::properties& kprop = dynamic_cast<uimenu::properties&>(kgo.get_properties ()); - add_to_menu (kprop); - } - } - } - - template <class T_prop> - void remove_from_menu (T_prop& prop) - { - Matrix kids; - std::string type = prop.get_type (); - kids = find_uimenu_children (prop); - int len = kids.length (); - - for (octave_idx_type ii = 0; ii < len; ii++) - { - graphics_object kgo = gh_manager::get_object (kids (len - (ii + 1))); - - if (kgo.valid_object ()) - { - uimenu::properties kprop = dynamic_cast<uimenu::properties&>(kgo.get_properties ()); - remove_from_menu (kprop); - } - } - - if (type.compare("uimenu") == 0) - delete_entry(dynamic_cast<uimenu::properties&>(prop)); - else if (type.compare("figure") == 0) - menubar->clear (); - } - - ~fltk_uimenu() - { - delete menubar; - } - -private: - Fl_Menu_Bar* menubar; -}; - -class plot_window : public Fl_Window -{ - friend class fltk_uimenu; -public: - plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp) - : Fl_Window (xx, yy, ww, hh, "octave"), window_label (), shift (0), - ndim (2), fp (xfp), canvas (0), autoscale (0), togglegrid (0), - panzoom (0), rotate (0), help (0), status (0) - { - callback (window_close, static_cast<void*> (this)); - - begin (); - { - - uimenu = new - fltk_uimenu(0, 0, ww, menu_h); - uimenu->hide (); - - canvas = new - OpenGL_fltk (0, 0, ww , hh - status_h, number ()); - - bottom = new - Fl_Box (0, - hh - status_h, - ww, - status_h); - bottom->box(FL_FLAT_BOX); - - ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ())); - - autoscale = new - Fl_Button (0, - hh - status_h, - status_h, - status_h, - "A"); - autoscale->callback (button_callback, static_cast<void*> (this)); - autoscale->tooltip ("Autoscale"); - - togglegrid = new - Fl_Button (status_h, - hh - status_h, - status_h, - status_h, - "G"); - togglegrid->callback (button_callback, static_cast<void*> (this)); - togglegrid->tooltip ("Toggle Grid"); - - panzoom = new - Fl_Button (2 * status_h, - hh - status_h, - status_h, - status_h, - "P"); - panzoom->callback (button_callback, static_cast<void*> (this)); - panzoom->tooltip ("Mouse Pan/Zoom"); - - rotate = new - Fl_Button (3 * status_h, - hh - status_h, - status_h, - status_h, - "R"); - rotate->callback (button_callback, static_cast<void*> (this)); - rotate->tooltip ("Mouse Rotate"); - - if (ndim == 2) - rotate->deactivate (); - - help = new - Fl_Button (4 * status_h, - hh - status_h, - status_h, - status_h, - "?"); - help->callback (button_callback, static_cast<void*> (this)); - help->tooltip ("Help"); - - status = new - Fl_Output (5 * status_h, - hh - status_h, - ww > 2*status_h ? ww - status_h : 0, - status_h, ""); - - status->textcolor (FL_BLACK); - status->color (FL_GRAY); - status->textfont (FL_COURIER); - status->textsize (10); - status->box (FL_ENGRAVED_BOX); - - // This allows us to have a valid OpenGL context right away. - canvas->mode (FL_DEPTH | FL_DOUBLE ); - if (fp.is_visible ()) - { - show (); - if (fp.get_currentaxes ().ok()) - show_canvas (); - else - hide_canvas (); - } - } - end (); - - status->show (); - autoscale->show (); - togglegrid->show (); - panzoom->show (); - rotate->show (); - - set_name (); - resizable (canvas); - size_range (4*status_h, 2*status_h); - gui_mode = (ndim == 3 ? rotate_zoom : pan_zoom); - uimenu->add_to_menu (fp); - if (uimenu->items_to_show ()) - show_menubar (); - else - hide_menubar (); - } - - ~plot_window (void) - { - canvas->hide (); - status->hide (); - uimenu->hide (); - this->hide (); - delete canvas; - delete status; - delete uimenu; - } - - // FIXME -- this could change. - double number (void) { return fp.get___myhandle__ ().value (); } - - void print (const int fid, const std::string& term) - { - canvas->print (fid, term); - - // Print immediately so the output file will exist when the drawnow - // command is done. - mark_modified (); - Fl::wait (fltk_maxtime); - } - - void show_menubar (void) - { - int dm = menu_h; - if (uimenu->is_visible ()) - dm = 0; - canvas->resize (canvas->x (), - canvas->y () + dm, - canvas->w (), - canvas->h () - dm); - uimenu->show (); - mark_modified (); - } - - void hide_menubar (void) - { - int dm = menu_h; - if (!uimenu->is_visible ()) - dm = 0; - canvas->resize (canvas->x (), - canvas->y () - dm, - canvas->w (), - canvas->h () + dm); - uimenu->hide (); - mark_modified (); - } - - void uimenu_update(graphics_handle gh, int id) - { - graphics_object uimenu_obj = gh_manager::get_object (gh); - - if (uimenu_obj.valid_object () && uimenu_obj.isa ("uimenu")) - { - uimenu::properties& uimenup = - dynamic_cast<uimenu::properties&> (uimenu_obj.get_properties ()); - std::string fltk_label = uimenup.get_fltk_label(); - graphics_object fig = uimenu_obj.get_ancestor("figure"); - figure::properties& figp = - dynamic_cast<figure::properties&> (fig.get_properties ()); - - switch(id) - { - case base_properties::ID_BEINGDELETED: - uimenu->remove_from_menu (uimenup); - break; - case base_properties::ID_VISIBLE: - uimenu->update_visible (uimenup); - break; - case uimenu::properties::ID_ACCELERATOR: - uimenu->update_accelerator (uimenup); - break; - case uimenu::properties::ID_CALLBACK: - uimenu->update_callback (uimenup); - break; - case uimenu::properties::ID_CHECKED: - uimenu->add_to_menu (figp);//rebuilding entire menu - break; - case uimenu::properties::ID_ENABLE: - uimenu->update_enable (uimenup); - break; - case uimenu::properties::ID_FOREGROUNDCOLOR: - uimenu->update_foregroundcolor (uimenup); - break; - case uimenu::properties::ID_LABEL: - uimenu->add_to_menu (figp);//rebuilding entire menu - break; - case uimenu::properties::ID_POSITION: - uimenu->add_to_menu (figp);//rebuilding entire menu - break; - case uimenu::properties::ID_SEPARATOR: - uimenu->update_seperator (uimenup); - break; - } - - if (uimenu->items_to_show ()) - show_menubar (); - else - hide_menubar (); - - mark_modified(); - } - } - - void show_canvas (void) - { - canvas->show (); - canvas->make_current (); - } - - void hide_canvas (void) - { - canvas->hide (); - } - - void mark_modified (void) - { - damage (FL_DAMAGE_ALL); - canvas->damage (FL_DAMAGE_ALL); - ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ())); - - if (ndim == 3) - rotate->activate (); - else if ((ndim == 2) && (gui_mode == rotate_zoom)) - { - rotate->deactivate (); - gui_mode = pan_zoom; - } - } - - void set_name (void) - { - window_label = fp.get_title (); - label (window_label.c_str ()); - } - -private: - // window name -- this must exists for the duration of the window's - // life - std::string window_label; - - // Mod keys status - int shift; - - // Number of dimensions, 2 or 3. - int ndim; - - // Figure properties. - figure::properties& fp; - - // Status area height. - static const int status_h = 20; - - // Menu height - static const int menu_h = 20; - - // Window callback. - static void window_close (Fl_Widget*, void* data) - { - octave_value_list args; - args(0) = static_cast<plot_window*> (data)->number (); - feval ("close", args); - } - - // Button callbacks. - static void button_callback (Fl_Widget* ww, void* data) - { - static_cast<plot_window*> (data)->button_press (ww, data); - } - - void button_press (Fl_Widget* widg, void*) - { - if (widg == autoscale) - axis_auto (); - - if (widg == togglegrid) - toggle_grid (); - - if (widg == panzoom) - gui_mode = pan_zoom; - - if (widg == rotate && ndim == 3) - gui_mode = rotate_zoom; - - if (widg == help) - fl_message ("%s", help_text); - } - - fltk_uimenu* uimenu; - OpenGL_fltk* canvas; - Fl_Box* bottom; - Fl_Button* autoscale; - Fl_Button* togglegrid; - Fl_Button* panzoom; - Fl_Button* rotate; - Fl_Button* help; - Fl_Output* status; - - void axis_auto (void) - { - octave_value_list args; - args(0) = fp.get_currentaxes ().as_octave_value (); - args(1) = "auto"; - feval ("axis", args); - mark_modified (); - } - - void toggle_grid (void) - { - octave_value_list args; - if (fp.get_currentaxes ().ok ()) - args(0) = fp.get_currentaxes ().as_octave_value (); - - feval ("grid", args); - mark_modified (); - } - - void pixel2pos - (graphics_handle ax, int px, int py, double& xx, double& yy) const - { - pixel2pos ( gh_manager::get_object (ax), px, py, xx, yy); - } - - void pixel2pos - (graphics_object ax, int px, int py, double& xx, double& yy) const - { - if (ax && ax.isa ("axes")) - { - axes::properties& ap = - dynamic_cast<axes::properties&> (ax.get_properties ()); - ColumnVector pp = ap.pixel2coord (px, py); - xx = pp(0); - yy = pp(1); - } - } - - graphics_handle pixel2axes_or_ca (int px, int py ) - { - Matrix kids = fp.get_children (); - int len = kids.length (); - - for (int k = 0; k < len; k++) - { - graphics_handle hnd = gh_manager::lookup (kids(k)); - - if (hnd.ok ()) - { - graphics_object kid = gh_manager::get_object (hnd); - - if (kid.valid_object () && kid.isa ("axes")) - { - Matrix bb = kid.get_properties ().get_boundingbox (true); - - if (bb(0) <= px && px < (bb(0)+bb(2)) - && bb(1) <= py && py < (bb(1)+bb(3))) - { - return hnd; - } - } - } - } - return fp.get_currentaxes (); - } - - void pixel2status (graphics_handle ax, int px0, int py0, - int px1 = -1, int py1 = -1) - { - pixel2status (gh_manager::get_object (ax), px0, py0, px1, py1); - } - - void pixel2status (graphics_object ax, int px0, int py0, - int px1 = -1, int py1 = -1) - { - double x0, y0, x1, y1; - std::stringstream cbuf; - cbuf.precision (4); - cbuf.width (6); - pixel2pos (ax, px0, py0, x0, y0); - cbuf << "[" << x0 << ", " << y0 << "]"; - if (px1 >= 0) - { - pixel2pos (ax, px1, py1, x1, y1); - cbuf << " -> ["<< x1 << ", " << y1 << "]"; - } - - status->value (cbuf.str ().c_str ()); - status->redraw (); - } - - void view2status (graphics_object ax) - { - if (ax && ax.isa ("axes")) - { - axes::properties& ap = - dynamic_cast<axes::properties&> (ax.get_properties ()); - std::stringstream cbuf; - cbuf.precision (4); - cbuf.width (6); - Matrix v (1,2,0); - v = ap.get("view").matrix_value(); - cbuf << "[azimuth: " << v(0) << ", elevation: " << v(1) << "]"; - - status->value (cbuf.str ().c_str ()); - status->redraw (); - } - } - - void set_currentpoint (int px, int py) - { - if (!fp.is_beingdeleted ()) - { - Matrix pos (1,2,0); - pos(0) = px; - pos(1) = h () - status_h - menu_h - py; - fp.set_currentpoint (pos); - } - } - - void set_axes_currentpoint (graphics_object ax, int px, int py) - { - if (ax.valid_object ()) - { - axes::properties& ap = - dynamic_cast<axes::properties&> (ax.get_properties ()); - - double xx, yy; - pixel2pos (ax, px, py, xx, yy); - - Matrix pos (2,3,0); - pos(0,0) = xx; - pos(1,0) = yy; - pos(0,1) = xx; - pos(1,1) = yy; - - ap.set_currentpoint (pos); - } - } - - int key2shift (int key) - { - if (key == FL_Shift_L || key == FL_Shift_R) - return FL_SHIFT; - - if (key == FL_Control_L || key == FL_Control_R) - return FL_CTRL; - - if (key == FL_Alt_L || key == FL_Alt_R) - return FL_ALT; - - if (key == FL_Meta_L || key == FL_Meta_R) - return FL_META; - - return 0; - } - - int key2ascii (int key) - { - if (key < 256) return key; - if (key == FL_Tab) return '\t'; - if (key == FL_Enter) return 0x0a; - if (key == FL_BackSpace) return 0x08; - if (key == FL_Escape) return 0x1b; - - return 0; - } - - Cell modifier2cell () - { - string_vector mod; - - if (shift & FL_SHIFT) - mod.append (std::string ("shift")); - if (shift & FL_CTRL) - mod.append (std::string ("control")); - if (shift & FL_ALT || shift & FL_META) - mod.append (std::string ("alt")); - - return Cell (mod); - } - - void resize (int xx,int yy,int ww,int hh) - { - Fl_Window::resize (xx, yy, ww, hh); - - Matrix pos (1,4,0); - pos(0) = xx; - pos(1) = yy; - pos(2) = ww; - pos(3) = hh - status_h - menu_h; - - fp.set_position (pos); - } - - void draw (void) - { - Matrix pos = fp.get_position ().matrix_value (); - Fl_Window::resize (pos(0), pos(1) , pos(2), pos(3) + status_h + menu_h); - - return Fl_Window::draw (); - } - - int handle (int event) - { - static int px0,py0; - static graphics_object ax0; - - graphics_handle gh; - - graphics_object fig = gh_manager::get_object (fp.get___myhandle__ ()); - int retval = Fl_Window::handle (event); - - // We only handle events which are in the canvas area. - if (!Fl::event_inside(canvas)) - return retval; - - if (!fp.is_beingdeleted ()) - { - switch (event) - { - case FL_KEYDOWN: - { - int key = Fl::event_key (); - - shift |= key2shift (key); - int key_a = key2ascii (key); - if (key_a && fp.get_keypressfcn ().is_defined ()) - { - Octave_map evt; - evt.assign ("Character", octave_value (key_a)); - evt.assign ("Key", octave_value (std::tolower (key_a))); - evt.assign ("Modifier", octave_value (modifier2cell ())); - fp.execute_keypressfcn (evt); - } - switch (key) - { - case 'a': - case 'A': - axis_auto (); - break; - - case 'g': - case 'G': - toggle_grid (); - break; - - case 'p': - case 'P': - gui_mode = pan_zoom; - break; - - case 'r': - case 'R': - gui_mode = rotate_zoom; - break; - } - } - break; - - case FL_KEYUP: - { - int key = Fl::event_key (); - - shift &= (~key2shift (key)); - int key_a = key2ascii (key); - if (key_a && fp.get_keyreleasefcn ().is_defined ()) - { - Octave_map evt; - evt.assign ("Character", octave_value (key_a)); - evt.assign ("Key", octave_value (std::tolower (key_a))); - evt.assign ("Modifier", octave_value (modifier2cell ())); - fp.execute_keyreleasefcn (evt); - } - } - break; - - case FL_MOVE: - pixel2status (pixel2axes_or_ca (Fl::event_x (), Fl::event_y ()), - Fl::event_x (), Fl::event_y ()); - break; - - case FL_PUSH: - px0 = Fl::event_x (); - py0 = Fl::event_y (); - - set_currentpoint (Fl::event_x (), Fl::event_y ()); - - gh = pixel2axes_or_ca (px0, py0); - - if (gh.ok ()) - { - ax0 = gh_manager::get_object (gh); - set_axes_currentpoint (ax0, px0, py0); - } - - fp.execute_windowbuttondownfcn (); - - if (Fl::event_button () == 1 || Fl::event_button () == 3) - return 1; - - break; - - case FL_DRAG: - if (fp.get_windowbuttonmotionfcn ().is_defined ()) - { - set_currentpoint (Fl::event_x (), Fl::event_y ()); - fp.execute_windowbuttonmotionfcn (); - } - - if (Fl::event_button () == 1) - { - if (ax0 && ax0.isa ("axes")) - { - if (gui_mode == pan_zoom) - pixel2status (ax0, px0, py0, Fl::event_x (), Fl::event_y ()); - else - view2status (ax0); - axes::properties& ap = - dynamic_cast<axes::properties&> (ax0.get_properties ()); - - double x0, y0, x1, y1; - Matrix pos = fp.get_position ().matrix_value (); - pixel2pos (ax0, px0, py0, x0, y0); - pixel2pos (ax0, Fl::event_x (), Fl::event_y (), x1, y1); - - if (gui_mode == pan_zoom) - ap.translate_view (x0 - x1, y0 - y1); - else if (gui_mode == rotate_zoom) - { - double daz, del; - daz = (Fl::event_x () - px0) / pos(2) * 360; - del = (Fl::event_y () - py0) / pos(3) * 360; - ap.rotate_view (del, daz); - } - - px0 = Fl::event_x (); - py0 = Fl::event_y (); - mark_modified (); - } - return 1; - } - else if (Fl::event_button () == 3) - { - pixel2status (ax0, px0, py0, Fl::event_x (), Fl::event_y ()); - Matrix zoom_box (1,4,0); - zoom_box (0) = px0; - zoom_box (1) = py0; - zoom_box (2) = Fl::event_x (); - zoom_box (3) = Fl::event_y (); - canvas->set_zoom_box (zoom_box); - canvas->zoom (true); - canvas->redraw (); - } - - break; - - case FL_MOUSEWHEEL: - { - graphics_object ax = - gh_manager::get_object (pixel2axes_or_ca (Fl::event_x (), - Fl::event_y ())); - if (ax && ax.isa ("axes")) - { - axes::properties& ap = - dynamic_cast<axes::properties&> (ax.get_properties ()); - - // Determine if we're zooming in or out. - const double factor = - (Fl::event_dy () > 0) ? 1.0 + wheel_zoom_speed : 1.0 - wheel_zoom_speed; - - // Get the point we're zooming about. - double x1, y1; - pixel2pos (ax, Fl::event_x (), Fl::event_y (), x1, y1); - - ap.zoom_about_point (x1, y1, factor, false); - mark_modified (); - } - } - return 1; - - case FL_RELEASE: - if (fp.get_windowbuttonupfcn ().is_defined ()) - { - set_currentpoint (Fl::event_x (), Fl::event_y ()); - fp.execute_windowbuttonupfcn (); - } - - if (Fl::event_button () == 1) - { - if ( Fl::event_clicks () == 1) - { - if (ax0 && ax0.isa ("axes")) - { - axes::properties& ap = - dynamic_cast<axes::properties&> (ax0.get_properties ()); - ap.set_xlimmode("auto"); - ap.set_ylimmode("auto"); - ap.set_zlimmode("auto"); - mark_modified (); - } - } - } - if (Fl::event_button () == 3) - { - // End of drag -- zoom. - if (canvas->zoom ()) - { - canvas->zoom (false); - double x0,y0,x1,y1; - if (ax0 && ax0.isa ("axes")) - { - axes::properties& ap = - dynamic_cast<axes::properties&> (ax0.get_properties ()); - pixel2pos (ax0, px0, py0, x0, y0); - pixel2pos (ax0, Fl::event_x (), Fl::event_y (), x1, y1); - Matrix xl (1,2,0); - Matrix yl (1,2,0); - if (x0 < x1) - { - xl(0) = x0; - xl(1) = x1; - } - else - { - xl(0) = x1; - xl(1) = x0; - } - if (y0 < y1) - { - yl(0) = y0; - yl(1) = y1; - } - else - { - yl(0) = y1; - yl(1) = y0; - } - ap.zoom (xl, yl); - mark_modified (); - } - } - } - break; - } - } - - return retval; - } -}; - -class figure_manager -{ -public: - - static bool instance_ok (void) - { - bool retval = true; - - if (! instance) - instance = new figure_manager (); - - if (! instance) - { - ::error ("unable to create figure_manager object!"); - - retval = false; - } - - return retval; - } - - ~figure_manager (void) - { - close_all (); - } - - static void close_all (void) - { - if (instance_ok ()) - instance->do_close_all (); - } - - static void new_window (figure::properties& fp) - { - if (instance_ok ()) - instance->do_new_window (fp); - } - - static void delete_window (int idx) - { - if (instance_ok ()) - instance->do_delete_window (idx); - } - - static void delete_window (std::string idx_str) - { - delete_window (str2idx (idx_str)); - } - - static void toggle_window_visibility (int idx, bool is_visible) - { - if (instance_ok ()) - instance->do_toggle_window_visibility (idx, is_visible); - } - - static void toggle_window_visibility (std::string idx_str, bool is_visible) - { - toggle_window_visibility (str2idx (idx_str), is_visible); - } - - static void mark_modified (int idx) - { - if (instance_ok ()) - instance->do_mark_modified (idx); - } - - static void mark_modified (const graphics_handle& gh) - { - mark_modified (hnd2idx (gh)); - } - - static void set_name (int idx) - { - if (instance_ok ()) - instance->do_set_name (idx); - } - - static void set_name (std::string idx_str) - { - set_name (str2idx (idx_str)); - } - - static Matrix get_size (int idx) - { - return instance_ok () ? instance->do_get_size (idx) : Matrix (); - } - - static Matrix get_size (const graphics_handle& gh) - { - return get_size (hnd2idx (gh)); - } - - static void print (const graphics_handle& gh , const int fid, const std::string& term) - { - if (instance_ok ()) - instance->do_print (hnd2idx(gh), fid, term); - } - - static void uimenu_update (const graphics_handle& figh, const graphics_handle& uimenuh, const int id) - { - if (instance_ok ()) - instance->do_uimenu_update (hnd2idx(figh), uimenuh, id); - } - - static void update_canvas (const graphics_handle& gh, const graphics_handle& ca) - { - if (instance_ok ()) - instance->do_update_canvas (hnd2idx(gh), ca); - } - - static void toggle_menubar_visibility (int fig_idx, bool menubar_is_figure) - { - if (instance_ok ()) - instance->do_toggle_menubar_visibility (fig_idx, menubar_is_figure); - } - - static void toggle_menubar_visibility (std::string fig_idx_str, bool menubar_is_figure) - { - toggle_menubar_visibility (str2idx (fig_idx_str), menubar_is_figure); - } - -private: - - static figure_manager *instance; - - figure_manager (void) { } - - // No copying! - figure_manager (const figure_manager&); - figure_manager& operator = (const figure_manager&); - - // Singelton -- hide all of the above. - - static int curr_index; - typedef std::map<int, plot_window*> window_map; - typedef window_map::iterator wm_iterator;; - window_map windows; - - static std::string fltk_idx_header; - - void do_close_all (void) - { - wm_iterator win; - for (win = windows.begin (); win != windows.end (); win++) - delete win->second; - windows.clear (); - } - - void do_new_window (figure::properties& fp) - { - int x, y, w, h; - - int idx = figprops2idx (fp); - if (idx >= 0 && windows.find (idx) == windows.end ()) - { - default_size (x, y, w, h); - idx2figprops (curr_index , fp); - windows[curr_index++] = new plot_window (x, y, w, h, fp); - } - } - - void do_delete_window (int idx) - { - wm_iterator win; - if ((win = windows.find (idx)) != windows.end ()) - { - delete win->second; - windows.erase (win); - } - } - - void do_toggle_window_visibility (int idx, bool is_visible) - { - wm_iterator win; - if ((win = windows.find (idx)) != windows.end ()) - { - if (is_visible) - win->second->show (); - else - win->second->hide (); - - win->second->redraw (); - } - } - - void do_toggle_menubar_visibility (int fig_idx, bool menubar_is_figure) - { - wm_iterator win; - if ((win = windows.find (fig_idx)) != windows.end ()) - { - if (menubar_is_figure) - win->second->show_menubar (); - else - win->second->hide_menubar (); - - win->second->redraw (); - } - } - - void do_mark_modified (int idx) - { - wm_iterator win; - if ((win = windows.find (idx)) != windows.end ()) - { - win->second->mark_modified (); - } - } - - void do_set_name (int idx) - { - wm_iterator win; - if ((win = windows.find (idx)) != windows.end ()) - { - win->second->set_name (); - } - } - - Matrix do_get_size (int idx) - { - Matrix sz (1, 2, 0.0); - - wm_iterator win; - if ((win = windows.find (idx)) != windows.end ()) - { - sz(0) = win->second->w (); - sz(1) = win->second->h (); - } - - return sz; - } - - void do_print (int idx, const int fid, const std::string& term) - { - wm_iterator win; - if ((win = windows.find (idx)) != windows.end ()) - { - win->second->print (fid, term); - } - } - - void do_uimenu_update (int idx, graphics_handle gh, int id) - { - wm_iterator win; - if ((win = windows.find (idx)) != windows.end ()) - { - win->second->uimenu_update (gh, id); - } - } - - void do_update_canvas (int idx, graphics_handle ca) - { - wm_iterator win; - if ((win = windows.find (idx)) != windows.end ()) - { - if (ca.ok ()) - win->second->show_canvas (); - else - win->second->hide_canvas (); - } - } - - - // FIXME -- default size should be configurable. - void default_size (int& x, int& y, int& w, int& h) - { - x = 0; - y = 0; - w = 640; - h = 480; - } - - static int str2idx (const caseless_str clstr) - { - int ind; - if (clstr.find (fltk_idx_header,0) == 0) - { - std::istringstream istr (clstr.substr (fltk_idx_header.size ())); - if (istr >> ind) - return ind; - } - error ("fltk_backend: could not recognize fltk index"); - return -1; - } - - void idx2figprops (int idx, figure::properties& fp) - { - std::ostringstream ind_str; - ind_str << fltk_idx_header << idx; - fp.set___plot_stream__ (ind_str.str ()); - } - - static int figprops2idx (const figure::properties& fp) - { - if (fp.get___backend__ () == FLTK_BACKEND_NAME) - { - octave_value ps = fp.get___plot_stream__ (); - if (ps.is_string ()) - return str2idx (ps.string_value ()); - else - return 0; - } - error ("fltk_backend:: figure is not fltk"); - return -1; - } - - static int hnd2idx (const double h) - { - graphics_object fobj = gh_manager::get_object (h); - if (fobj && fobj.isa ("figure")) - { - figure::properties& fp = - dynamic_cast<figure::properties&> (fobj.get_properties ()); - return figprops2idx (fp); - } - error ("fltk_backend:: H is not a figure"); - return -1; - } - - static int hnd2idx (const graphics_handle& fh) - { - return hnd2idx (fh.value ()); - } -}; - -figure_manager *figure_manager::instance = 0; - -std::string figure_manager::fltk_idx_header="fltk index="; -int figure_manager::curr_index = 1; - -static bool backend_registered = false; - -static int -__fltk_redraw__ (void) -{ - if (backend_registered) - { - // we scan all figures and add those which use FLTK as a backend - graphics_object obj = gh_manager::get_object (0); - if (obj && obj.isa ("root")) - { - base_properties& props = obj.get_properties (); - Matrix children = props.get_all_children (); - - for (octave_idx_type n = 0; n < children.numel (); n++) - { - graphics_object fobj = gh_manager::get_object (children (n)); - if (fobj && fobj.isa ("figure")) - { - figure::properties& fp = - dynamic_cast<figure::properties&> (fobj.get_properties ()); - if (fp.get___backend__ () == FLTK_BACKEND_NAME) - figure_manager::new_window (fp); - } - } - } - - // it seems that we have to call Fl::check twice to get everything drawn - Fl::check (); - Fl::check (); - } - - return 0; -} - -class fltk_backend : public base_graphics_backend -{ -public: - fltk_backend (void) - : base_graphics_backend (FLTK_BACKEND_NAME) { } - - ~fltk_backend (void) { } - - bool is_valid (void) const { return true; } - - void finalize (const graphics_object& go) - { - if (go.isa ("figure")) - { - octave_value ov = go.get (caseless_str ("__plot_stream__")); - - if (! ov.is_empty ()) - figure_manager::delete_window (ov.string_value ()); - } - } - - void uimenu_set_fltk_label(graphics_object uimenu_obj) - { - if (uimenu_obj.valid_object ()) - { - uimenu::properties& uimenup = - dynamic_cast<uimenu::properties&> (uimenu_obj.get_properties ()); - std::string fltk_label = uimenup.get_label (); - graphics_object go = gh_manager::get_object (uimenu_obj.get_parent ()); - if (go.isa ("uimenu")) - fltk_label = dynamic_cast<const uimenu::properties&> (go.get_properties ()).get_fltk_label () - + "/" - + fltk_label; - else if (go.isa ("figure")) - ; - else - error("unexpected parent object\n"); - - uimenup.set_fltk_label(fltk_label); - } - } - - void update (const graphics_object& go, int id) - { - if (go.isa ("figure")) - { - octave_value ov = go.get (caseless_str ("__plot_stream__")); - - if (! ov.is_empty ()) - { - const figure::properties& fp = - dynamic_cast<const figure::properties&> (go.get_properties ()); - - switch (id) - { - case base_properties::ID_VISIBLE: - figure_manager::toggle_window_visibility (ov.string_value (), fp.is_visible ()); - break; - case figure::properties::ID_MENUBAR: - figure_manager::toggle_menubar_visibility (ov.string_value (), fp.menubar_is("figure")); - break; - case figure::properties::ID_NAME: - case figure::properties::ID_CURRENTAXES: - figure_manager::update_canvas (go.get_handle (), fp.get_currentaxes ()); - break; - case figure::properties::ID_NUMBERTITLE: - figure_manager::set_name (ov.string_value ()); - break; - } - } - } - else if (go.isa ("uimenu")) - { - if (id == uimenu::properties::ID_LABEL) - uimenu_set_fltk_label (go); - - graphics_object fig = go.get_ancestor("figure"); - figure_manager::uimenu_update(fig.get_handle (), go.get_handle (), id); - } - } - - void redraw_figure (const graphics_object& go) const - { - figure_manager::mark_modified (go.get_handle ()); - - __fltk_redraw__ (); - } - - void print_figure (const graphics_object& go, - const std::string& term, - const std::string& file, bool /*mono*/, - const std::string& /*debug_file*/) const - { - int fid; - std::istringstream istr (file); - if (istr >> fid) - { - figure_manager::print (go.get_handle (), fid, term); - redraw_figure (go); - } - else - error ("fltk_backend: filename should be fid"); - } - - Matrix get_canvas_size (const graphics_handle& fh) const - { - return figure_manager::get_size (fh); - } - - double get_screen_resolution (void) const - { - // FLTK doesn't give this info. - return 72.0; - } - - Matrix get_screen_size (void) const - { - Matrix sz (1, 2, 0.0); - sz(0) = Fl::w (); - sz(1) = Fl::h (); - return sz; - } -}; - -DEFUN_DLD (__fltk_redraw__, , , "") -{ - __fltk_redraw__ (); - - return octave_value (); -} - -// Initialize the fltk backend. - -DEFUN_DLD (__init_fltk__, , , "") -{ - static bool remove_fltk_registered = false; - - if (! backend_registered) - { - mlock (); - - graphics_backend::register_backend (new fltk_backend); - backend_registered = true; - - octave_value_list args; - args(0) = "__fltk_redraw__"; - feval ("add_input_event_hook", args, 0); - - if (! remove_fltk_registered) - { - octave_add_atexit_function ("__remove_fltk__"); - - remove_fltk_registered = true; - } - } - - octave_value retval; - return retval; -} - - -// Delete the fltk backend. - -DEFUN_DLD (__remove_fltk__, , , "") -{ - if (backend_registered) - { - munlock ("__init_fltk__"); - - figure_manager::close_all (); - graphics_backend::unregister_backend (FLTK_BACKEND_NAME); - backend_registered = false; - - octave_value_list args; - args(0) = "__fltk_redraw__"; - feval ("remove_input_event_hook", args, 0); - - // FIXME ??? - Fl::wait (fltk_maxtime); - } - - octave_value retval; - return retval; -} - -DEFUN_DLD (__fltk_maxtime__, args, ,"") -{ - octave_value retval = fltk_maxtime; - - if (args.length () == 1) - { - if (args(0).is_real_scalar ()) - fltk_maxtime = args(0).double_value (); - else - error ("argument must be a real scalar"); - } - - return retval; -} - -DEFUN_DLD (fltk_mouse_wheel_zoom, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{speed} =} fltk_mouse_wheel_zoom ()\n\ -@deftypefnx {Built-in Function} {} fltk_mouse_wheel_zoom (@var{speed})\n\ -Query or set the mouse wheel zoom factor in the fltk backend.\n\ -@end deftypefn") -{ - octave_value retval = wheel_zoom_speed; - - if (args.length () == 1) - { - if (args(0).is_real_scalar ()) - wheel_zoom_speed = args(0).double_value (); - else - error ("fltk_mouse_wheel_zoom: SPEED must be a real scalar"); - } - - return retval; -} - -DEFUN_DLD (fltk_gui_mode, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{mode} =} fltk_gui_mode ()\n\ -@deftypefnx {Built-in Function} {} fltk_gui_mode (@var{mode})\n\ -Query or set the GUI mode for the fltk backend.\n\ -The @var{mode} argument can be one of the following strings:\n\ -@table @asis\n\ -@item '2d'\n\ -Allows panning and zooming of current axes.\n\ -\n\ -@item '3d'\n\ -Allows rotating and zooming of current axes.\n\ -\n\ -@item 'none'\n\ -Mouse inputs have no effect.\n\ -@end table\n\ -@end deftypefn") -{ - caseless_str mode_str; - - if (gui_mode == pan_zoom) - mode_str = "2d"; - else if (gui_mode == rotate_zoom) - mode_str = "3d"; - else - mode_str = "none"; - - - bool failed = false; - - if (args.length () == 1) - { - if (args(0).is_string ()) - { - mode_str = args(0).string_value (); - - if (mode_str.compare ("2d")) - gui_mode = pan_zoom; - else if (mode_str.compare ("3d")) - gui_mode = rotate_zoom; - else if (mode_str.compare ("none")) - gui_mode = none; - else - failed = true; - } - else - failed = true; - } - - if (failed) - error ("MODE must be one of the strings: ""2D"", ""3D"", or ""None""."); - - - return octave_value(mode_str); -} - -#include "file-ops.h" -DEFUN_DLD (__fltk_uigetfile__, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} __fltk_uigetfile__ (@dots{})\n\ -Undocumented internal function.\n\ -@end deftypefn") -{ - // This function should be called by uigetfile.m - // Error checking should be done in uigetfile.m! - // - // Expected argument list - // args(0) ... FileFilter in fltk format - // args(1) ... Title - // args(2) ... Default Filename - // args(3) ... PostionValue [x,y] - // args(4) ... SelectValue "on"/"off"/"dir"/"create" - - std::string file_filter, title, default_name, multi; - if (args(0).is_string ()) - file_filter = args(0).string_value(); - - if (args(1).is_string ()) - title = args(1).string_value(); - - if (args(2).is_string ()) - default_name = args(2).string_value(); - - if (args(3).is_real_matrix ()) - Matrix pos = args(3).matrix_value(); - - int multi_type = Fl_File_Chooser::SINGLE; - std::string flabel = "Filename:"; - if (args(4).is_string ()) - { - multi = args(4).string_value(); - if (multi == "on") - multi_type = Fl_File_Chooser::MULTI; - else if (multi == "dir") - { - multi_type = Fl_File_Chooser::DIRECTORY; - flabel = "Directory:"; - } - else if (multi == "create") - multi_type = Fl_File_Chooser::CREATE; - } - - Fl_File_Chooser::filename_label = flabel.c_str (); - Fl_File_Chooser *fc = new Fl_File_Chooser(default_name.c_str (), file_filter.c_str (), multi_type, title.c_str ()); - fc->preview(0); - - if (multi_type == Fl_File_Chooser::CREATE) - fc->ok_label("Save"); - - fc->show(); - while (fc->shown ()) - { Fl::wait (); } - - octave_value_list fargs, retval; - - retval(0) = octave_value(0); - retval(1) = octave_value(0); - retval(2) = octave_value(0); - - if (fc->value() != NULL) - { - int file_count = fc->count (); - std::string fname; - std::string sep = file_ops::dir_sep_str (); - std::size_t idx; - - if ((file_count == 1) && (multi_type != Fl_File_Chooser::DIRECTORY)) - { - fname = fc->value (); - idx = fname.find_last_of(sep); - retval(0) = fname.substr(idx + 1); - } - else - { - Cell file_cell = Cell(file_count, 1); - for (octave_idx_type n = 1; n <= file_count; n++) - { - fname = fc->value (n); - idx = fname.find_last_of(sep); - file_cell(n - 1) = fname.substr(idx + 1); - } - retval(0) = file_cell; - } - - if (multi_type == Fl_File_Chooser::DIRECTORY) - retval(0) = std::string(fc->value ()); - else - { - retval(1) = std::string(fc->directory ()); - retval(2) = fc->filter_value(); - } - } - - return retval; -} - -#endif
--- a/src/DLD-FUNCTIONS/module-files Wed Jan 19 21:16:13 2011 -0800 +++ b/src/DLD-FUNCTIONS/module-files Thu Jan 20 02:29:57 2011 -0500 @@ -3,6 +3,7 @@ __dispatch__.cc __dsearchn__.cc __glpk__.cc +__init_fltk__.cc __lin_interpn__.cc __magick_read__.cc __pchip_deriv__.cc @@ -24,9 +25,9 @@ dasrt.cc dassl.cc det.cc -dot.cc dlmread.cc dmperm.cc +dot.cc eig.cc eigs.cc fft.cc @@ -35,7 +36,6 @@ fftw.cc filter.cc find.cc -fltk_backend.cc gammainc.cc gcd.cc getgrent.cc
--- a/src/Makefile.am Wed Jan 19 21:16:13 2011 -0800 +++ b/src/Makefile.am Thu Jan 20 02:29:57 2011 -0500 @@ -618,7 +618,7 @@ lex.lo lex.o oct-parse.lo oct-parse.o: \ AM_CXXFLAGS := $(filter-out -Wold-style-cast, $(AM_CXXFLAGS)) -fltk_backend.lo fltk_backend.o: \ +__init_fltk__.lo __init_fltk__.o: \ AM_CXXFLAGS := $(filter-out $(DLL_CXXDEFS), $(AM_CXXFLAGS) $(GRAPHICS_CFLAGS)) # XERBLA = ../libcruft/blas-xtra/xerbla.o @@ -818,9 +818,9 @@ DLD_FUNCTIONS___glpk___la_CPPFLAGS = $(AM_CPPFLAGS) $(GLPK_CPPFLAGS) DLD_FUNCTIONS___glpk___la_LIBADD += $(GLPK_LDFLAGS) $(GLPK_LIBS) -DLD-FUNCTIONS/fltk_backend.df: CPPFLAGS += $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS) -DLD_FUNCTIONS_fltk_backend_la_CPPFLAGS = $(AM_CPPFLAGS) $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS) -DLD_FUNCTIONS_fltk_backend_la_LIBADD += $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) $(FT2_LDFLAGS) $(FT2_LIBS) +DLD-FUNCTIONS/__init_fltk__.df: CPPFLAGS += $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS) +DLD_FUNCTIONS___init_fltk___la_CPPFLAGS = $(AM_CPPFLAGS) $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS) +DLD_FUNCTIONS___init_fltk___la_LIBADD += $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) $(FT2_LDFLAGS) $(FT2_LIBS) DLD-FUNCTIONS/amd.df: CPPFLAGS += $(SPARSE_XCPPFLAGS) DLD_FUNCTIONS_amd_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
--- a/src/gl-render.cc Wed Jan 19 21:16:13 2011 -0800 +++ b/src/gl-render.cc Thu Jan 20 02:29:57 2011 -0500 @@ -564,7 +564,7 @@ void opengl_renderer::draw_figure (const figure::properties& props) { - backend = props.get_backend (); + toolkit = props.get_toolkit (); // Initialize OpenGL context @@ -3245,7 +3245,7 @@ return 0; unsigned int ID = glGenLists (1); - double sz = size * backend.get_screen_resolution () / 72.0; + double sz = size * toolkit.get_screen_resolution () / 72.0; // constants for the * marker const double sqrt2d4 = 0.35355339059327;
--- a/src/gl-render.h Wed Jan 19 21:16:13 2011 -0800 +++ b/src/gl-render.h Thu Jan 20 02:29:57 2011 -0500 @@ -137,8 +137,8 @@ bool filled) const; private: - // the backend associated with the figure being rendered - graphics_backend backend; + // The graphics toolkit associated with the figure being rendered. + graphics_toolkit toolkit; // axes transformation data graphics_xform xform;
--- a/src/graphics.cc Wed Jan 19 21:16:13 2011 -0800 +++ b/src/graphics.cc Thu Jan 20 02:29:57 2011 -0500 @@ -765,15 +765,15 @@ if (do_set (v)) { - // notify backend + // Notify graphics toolkit. if (id >= 0) { graphics_object go = gh_manager::get_object (parent); if (go) { - graphics_backend backend = go.get_backend(); - if (backend) - backend.update (go, id); + graphics_toolkit toolkit = go.get_toolkit (); + if (toolkit) + toolkit.update (go, id); } } @@ -1871,14 +1871,14 @@ bp.execute_deletefcn (); - // notify backend - graphics_backend backend = p->second.get_backend (); - if (backend) - backend.finalize (p->second); + // Notify graphics toolkit. + graphics_toolkit toolkit = p->second.get_toolkit (); + if (toolkit) + toolkit.finalize (p->second); // Note: this will be valid only for first explicitly // deleted object. All its children will then have an - // unknown backend. + // unknown graphics toolkit. // Graphics handles for non-figure objects are negative // integers plus some random fractional part. To avoid @@ -2051,7 +2051,7 @@ // --------------------------------------------------------------------- void -base_graphics_backend::update (const graphics_handle& h, int id) +base_graphics_toolkit::update (const graphics_handle& h, int id) { graphics_object go = gh_manager::get_object (h); @@ -2059,7 +2059,7 @@ } void -base_graphics_backend::initialize (const graphics_handle& h) +base_graphics_toolkit::initialize (const graphics_handle& h) { graphics_object go = gh_manager::get_object (h); @@ -2067,7 +2067,7 @@ } void -base_graphics_backend::finalize (const graphics_handle& h) +base_graphics_toolkit::finalize (const graphics_handle& h) { graphics_object go = gh_manager::get_object (h); @@ -2244,15 +2244,15 @@ obj.update_axis_limits (axis_type, h); } -graphics_backend -base_properties::get_backend (void) const +graphics_toolkit +base_properties::get_toolkit (void) const { graphics_object go = gh_manager::get_object (get_parent ()); if (go) - return go.get_backend (); + return go.get_toolkit (); else - return graphics_backend (); + return graphics_toolkit (); } void @@ -2291,13 +2291,13 @@ // --------------------------------------------------------------------- -class gnuplot_backend : public base_graphics_backend +class gnuplot_toolkit : public base_graphics_toolkit { public: - gnuplot_backend (void) - : base_graphics_backend ("gnuplot") { } - - ~gnuplot_backend (void) { } + gnuplot_toolkit (void) + : base_graphics_toolkit ("gnuplot") { } + + ~gnuplot_toolkit (void) { } bool is_valid (void) const { return true; } @@ -2402,16 +2402,16 @@ } }; -graphics_backend -graphics_backend::default_backend (void) -{ - if (available_backends.size () == 0) - register_backend (new gnuplot_backend ()); - - return available_backends["gnuplot"]; -} - -std::map<std::string, graphics_backend> graphics_backend::available_backends; +graphics_toolkit +graphics_toolkit::default_toolkit (void) +{ + if (available_toolkits.size () == 0) + register_toolkit (new gnuplot_toolkit ()); + + return available_toolkits["gnuplot"]; +} + +std::map<std::string, graphics_toolkit> graphics_toolkit::available_toolkits; // --------------------------------------------------------------------- @@ -3816,7 +3816,7 @@ // FIXME -- was this really needed? When compared to Matlab, it // does not seem to be required. Need investigation with concrete - // backend to see results visually. + // graphics toolkit to see results visually. if (false && dowarp) af = 1.0 / (xM > yM ? xM : yM); else @@ -5507,8 +5507,8 @@ { handle_map[0] = graphics_object (new root_figure ()); - // Make sure the default backend is registered. - graphics_backend::default_backend (); + // Make sure the default graphics toolkit is registered. + graphics_toolkit::default_toolkit (); } graphics_handle @@ -5529,10 +5529,10 @@ if (do_createfcn) go->get_properties ().execute_createfcn (); - // notify backend - graphics_backend backend = go->get_backend (); - if (backend) - backend.initialize (obj); + // Notify graphics toolkit. + graphics_toolkit toolkit = go->get_toolkit (); + if (toolkit) + toolkit.initialize (obj); } else error ("gh_manager::do_make_graphics_handle: invalid object type `%s'", @@ -5551,10 +5551,10 @@ handle_map[h] = obj; - // notify backend - graphics_backend backend = go->get_backend (); - if (backend) - backend.initialize (obj); + // Notify graphics toolkit. + graphics_toolkit toolkit = go->get_toolkit (); + if (toolkit) + toolkit.initialize (obj); return h; } @@ -6734,15 +6734,15 @@ return retval; } -DEFUN (available_backends, , , +DEFUN (available_graphics_toolkits, , , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} available_backends ()\n\ -Return a cell array of registered graphics backends.\n\ +@deftypefn {Built-in Function} {} available_graphiscs_toolkits ()\n\ +Return a cell array of registered graphics toolkits.\n\ @end deftypefn") { gh_manager::autolock guard; - return octave_value (graphics_backend::available_backends_list ()); + return octave_value (graphics_toolkit::available_toolkits_list ()); } DEFUN (drawnow, args, , @@ -6798,7 +6798,7 @@ { gh_manager::unlock (); - fprops.get_backend ().redraw_figure (go); + fprops.get_toolkit ().redraw_figure (go); gh_manager::lock (); } @@ -6879,7 +6879,7 @@ gh_manager::unlock (); - go.get_backend () + go.get_toolkit () .print_figure (go, term, file, mono, debug_file); gh_manager::lock ();
--- a/src/graphics.h.in Wed Jan 19 21:16:13 2011 -0800 +++ b/src/graphics.h.in Thu Jan 20 02:29:57 2011 -0500 @@ -348,7 +348,7 @@ void set_id (int d) { id = d; } - // Sets property value, notifies backend. + // Sets property value, notifies graphics toolkit. // If do_run is true, runs associated listeners. bool set (const octave_value& v, bool do_run = true); @@ -1764,19 +1764,19 @@ // --------------------------------------------------------------------- -class graphics_backend; +class graphics_toolkit; class graphics_object; -class base_graphics_backend +class base_graphics_toolkit { public: - friend class graphics_backend; + friend class graphics_toolkit; public: - base_graphics_backend (const std::string& nm) + base_graphics_toolkit (const std::string& nm) : name (nm), count (0) { } - virtual ~base_graphics_backend (void) { } + virtual ~base_graphics_toolkit (void) { } std::string get_name (void) const { return name; } @@ -1809,26 +1809,26 @@ } // Callback function executed when the given graphics object - // changes. This allows the grahpics backend to act on property + // changes. This allows the grahpics toolkit to act on property // changes if needed. virtual void update (const graphics_object&, int) - { gripe_invalid ("base_graphics_backend::update"); } + { gripe_invalid ("base_graphics_toolkit::update"); } void update (const graphics_handle&, int); // Callback function executed when the given graphics object is - // created. This allows the graphics backend to do backend-specific + // created. This allows the graphics toolkit to do toolkit-specific // initializations for a newly created object. virtual void initialize (const graphics_object&) - { gripe_invalid ("base_graphics_backend::initialize"); } + { gripe_invalid ("base_graphics_toolkit::initialize"); } void initialize (const graphics_handle&); // Callback function executed just prior to deleting the given - // graphics object. This allows the graphics backend to perform - // backend-specific cleanup operations before an object is deleted. + // graphics object. This allows the graphics toolkit to perform + // toolkit-specific cleanup operations before an object is deleted. virtual void finalize (const graphics_object&) - { gripe_invalid ("base_graphics_backend::finalize"); } + { gripe_invalid ("base_graphics_toolkit::finalize"); } void finalize (const graphics_handle&); @@ -1840,38 +1840,38 @@ void gripe_invalid (const std::string& fname) const { if (! is_valid ()) - error ("%s: invalid graphics backend", fname.c_str ()); + error ("%s: invalid graphics toolkit", fname.c_str ()); } }; -class graphics_backend +class graphics_toolkit { public: - graphics_backend (void) - : rep (new base_graphics_backend ("unknown")) + graphics_toolkit (void) + : rep (new base_graphics_toolkit ("unknown")) { rep->count++; } - graphics_backend (base_graphics_backend* b) + graphics_toolkit (base_graphics_toolkit* b) : rep (b) { rep->count++; } - graphics_backend (const graphics_backend& b) + graphics_toolkit (const graphics_toolkit& b) : rep (b.rep) { rep->count++; } - ~graphics_backend (void) + ~graphics_toolkit (void) { if (--rep->count == 0) delete rep; } - graphics_backend& operator = (const graphics_backend& b) + graphics_toolkit& operator = (const graphics_toolkit& b) { if (rep != b.rep) { @@ -1906,66 +1906,71 @@ Matrix get_screen_size (void) const { return rep->get_screen_size (); } - // Notifies backend that object't property has changed. + // Notifies graphics toolkit that object't property has changed. void update (const graphics_object& go, int id) { rep->update (go, id); } void update (const graphics_handle& h, int id) { rep->update (h, id); } - // Notifies backend that new object was created. + // Notifies graphics toolkit that new object was created. void initialize (const graphics_object& go) { rep->initialize (go); } void initialize (const graphics_handle& h) { rep->initialize (h); } - // Notifies backend that object was destroyed. + // Notifies graphics toolkit that object was destroyed. // This is called only for explicitly deleted object. Children are - // deleted implicitly and backend isn't notified. + // deleted implicitly and graphics toolkit isn't notified. void finalize (const graphics_object& go) { rep->finalize (go); } void finalize (const graphics_handle& h) { rep->finalize (h); } - OCTINTERP_API static graphics_backend default_backend (void); - - static void register_backend (const graphics_backend& b) - { available_backends[b.get_name ()] = b; } - - static void unregister_backend (const std::string& name) - { available_backends.erase (name); } - - static graphics_backend find_backend (const std::string& name) + OCTINTERP_API static graphics_toolkit default_toolkit (void); + + static void register_toolkit (const graphics_toolkit& b) + { available_toolkits[b.get_name ()] = b; } + + static void unregister_toolkit (const std::string& name) + { available_toolkits.erase (name); } + + static graphics_toolkit find_toolkit (const std::string& name) { - const_available_backends_iterator p = available_backends.find (name); - - if (p != available_backends.end ()) + const_available_toolkits_iterator p = available_toolkits.find (name); + + if (p != available_toolkits.end ()) return p->second; else - return default_backend (); + return default_toolkit (); } - static Cell available_backends_list (void) + static Cell available_toolkits_list (void) { - Cell m (1 , available_backends.size ()); - const_available_backends_iterator p; + Cell m (1 , available_toolkits.size ()); + const_available_toolkits_iterator p; int i; - for (i = 0,p = available_backends.begin (); p != available_backends.end (); p++,i++) + for (i = 0, p = available_toolkits.begin (); + p != available_toolkits.end (); p++, i++) m(i) = p->first; return m; } private: - base_graphics_backend *rep; - - static OCTINTERP_API std::map<std::string, graphics_backend> available_backends; - - typedef std::map<std::string, graphics_backend>::iterator available_backends_iterator; - typedef std::map<std::string, graphics_backend>::const_iterator const_available_backends_iterator; + base_graphics_toolkit *rep; + + static OCTINTERP_API std::map<std::string, graphics_toolkit> + available_toolkits; + + typedef std::map<std::string, graphics_toolkit>::iterator + available_toolkits_iterator; + + typedef std::map<std::string, graphics_toolkit>::const_iterator + const_available_toolkits_iterator; }; // --------------------------------------------------------------------- @@ -2037,7 +2042,7 @@ mark_modified (); } - virtual graphics_backend get_backend (void) const; + virtual graphics_toolkit get_toolkit (void) const; virtual Matrix get_boundingbox (bool /*internal*/ = false) const { return Matrix (1, 4, 0.0); } @@ -2355,14 +2360,14 @@ return type () == go_name; } - virtual graphics_backend get_backend (void) const + virtual graphics_toolkit get_toolkit (void) const { if (valid_object ()) - return get_properties ().get_backend (); + return get_properties ().get_toolkit (); else { - error ("base_graphics_object::get_backend: invalid graphics object"); - return graphics_backend (); + error ("base_graphics_object::get_toolkit: invalid graphics object"); + return graphics_toolkit (); } } @@ -2579,7 +2584,7 @@ bool is_handle_visible (void) const { return get_properties ().is_handle_visible (); } - graphics_backend get_backend (void) const { return rep->get_backend (); } + graphics_toolkit get_toolkit (void) const { return rep->get_toolkit (); } void add_property_listener (const std::string& nm, const octave_value& v, listener_mode mode = POSTSET) @@ -2753,44 +2758,44 @@ void set_visible (const octave_value& val); - graphics_backend get_backend (void) const + graphics_toolkit get_toolkit (void) const { - if (! backend) - backend = graphics_backend::default_backend (); - - return backend; + if (! toolkit) + toolkit = graphics_toolkit::default_toolkit (); + + return toolkit; } - void set_backend (const graphics_backend& b) + void set_toolkit (const graphics_toolkit& b) { - if (backend) - backend.finalize (__myhandle__); - backend = b; - __backend__ = b.get_name (); + if (toolkit) + toolkit.finalize (__myhandle__); + toolkit = b; + __graphics_toolkit__ = b.get_name (); __plot_stream__ = Matrix (); mark_modified (); } - void set___backend__ (const octave_value& val) + void set___graphics_toolkit__ (const octave_value& val) { if (! error_state) { if (val.is_string ()) { std::string nm = val.string_value (); - graphics_backend b = graphics_backend::find_backend (nm); + graphics_toolkit b = graphics_toolkit::find_toolkit (nm); if (b.get_name () != nm) { - error ("set___backend__: invalid backend"); + error ("set___graphics_toolkit__: invalid graphics toolkit"); } else { - set_backend (b); + set_toolkit (b); mark_modified (); } } else - error ("set___backend__ must be a string"); + error ("set___graphics_toolkit__ must be a string"); } } @@ -2858,7 +2863,7 @@ string_property xvisual , "" radio_property xvisualmode , "{auto}|manual" callback_property buttondownfcn , Matrix () - string_property __backend__ s , "gnuplot" + string_property __graphics_toolkit__ s , "gnuplot" END_PROPERTIES protected: @@ -2873,7 +2878,7 @@ } private: - mutable graphics_backend backend; + mutable graphics_toolkit toolkit; }; private: @@ -4453,13 +4458,13 @@ // created. std::list<graphics_handle> figure_list; - // The lock for accessing the graphics sytsem + // The lock for accessing the graphics sytsem. octave_mutex graphics_lock; - // The list of event queued by backends + // The list of events queued by graphics toolkits. std::list<graphics_event> event_queue; - // The stack of callback objects + // The stack of callback objects. std::list<graphics_object> callback_objects; graphics_handle get_handle (const std::string& go_name);