# HG changeset patch # User Pantxo Diribarne # Date 1429514773 -7200 # Mon Apr 20 09:26:13 2015 +0200 # Node ID d793aaf4e3e7aaf19a5bcd68d4bb2a0a42bb1220 # Parent 1f9ed81bd17311337c8b9940e3067ee265d313be Add uicontextmenu to annotation objects * Canvas.cc (Canvas::canvasMousePressEvent): Allow searching in axes that have hidden handles so that annotations objects can be picked by mouse events. * Canvas.cc (Canvas::canvasMousePressEvent): later disallow manipulating hidden axes in pan/zoomin/zoomout/rotate modes * annotation.m: add context menu to manipulate annotation properties * annotation.m: fix wrong position of textbox when position has negative width/height diff -r 1f9ed81bd173 -r d793aaf4e3e7 libgui/graphics/Canvas.cc --- a/libgui/graphics/Canvas.cc Sun Apr 19 06:53:30 2015 -0300 +++ b/libgui/graphics/Canvas.cc Mon Apr 20 09:26:13 2015 +0200 @@ -472,7 +472,7 @@ graphics_object currentObj, axesObj; QList axesList; - Matrix children = obj.get_properties ().get_children (); + Matrix children = obj.get_properties ().get_all_children (); octave_idx_type num_children = children.numel (); for (int i = 0; i < num_children; i++) @@ -518,7 +518,7 @@ axesObj = *it; } - if (axesObj) + if (axesObj && currentObj) break; } @@ -604,7 +604,7 @@ case RotateMode: case ZoomInMode: case ZoomOutMode: - if (axesObj) + if (axesObj && axesObj.get_properties ().handlevisibility_is ("on")) { bool redraw_figure = true; diff -r 1f9ed81bd173 -r d793aaf4e3e7 scripts/plot/appearance/annotation.m --- a/scripts/plot/appearance/annotation.m Sun Apr 19 06:53:30 2015 -0300 +++ b/scripts/plot/appearance/annotation.m Mon Apr 20 09:26:13 2015 +0200 @@ -306,6 +306,9 @@ ## Base hggroup h = hggroup ("parent", hax); + ## Base context menu + hui = uicontextmenu (get (hax, "parent")); + ## Add common properties if (strcmp (graphics_toolkit (), "gnuplot")) ## FIXME: this is a workaround for bug #39394 (gnuplot toolkit) @@ -318,6 +321,11 @@ addbaseprops (h, defprops); setappdata (h, "__former_units__", "normalized"); + ## Add common menus + prop = "units"; + vals = set (h, prop); + addbasemenu (hui, h, prop, vals, "Units"); + ## Common updaters listener = address@hidden, h, true}; @@ -357,12 +365,19 @@ "linestyle", get (h, "linestyle"), "linewidth", get (h, "linewidth")); + linemenu (hui, h); + set (hli, "uicontextmenu", hui); + ## create patch(s) and text if (strcmp (objtype, "arrow")) [x, y] = arrowcoordinates (h); hpa = patch (x, y, get (h, "color"), "parent", h, "edgecolor", get (h, "color")); update_arrow (h, {}, "position", hpa); + + arrowmenu (hui, h); + set (hpa, "uicontextmenu", hui); + elseif (strcmp (objtype, "doublearrow")) [x, y] = arrowcoordinates (h, 1); hpa = patch (x, y, get (h, "color"), "parent", h, @@ -373,6 +388,10 @@ "edgecolor", get (h, "color")); update_arrow (h, {}, "position", hpa); + + dblarrowmenu (hui, h); + set (hpa, "uicontextmenu", hui); + elseif (strcmp (objtype, "textarrow")) [x, y] = arrowcoordinates (h); hpa = patch (x, y, get (h, "color"), "parent", h, @@ -388,6 +407,12 @@ update_text (h, {}, propnames{ii}, hte); endfor update_text (h, {}, "position", hte); + + arrowmenu (hui, h); + textmenu (hui, h); + set (hpa, "uicontextmenu", hui); + set (hte, "uicontextmenu", hui); + endif ## updaters @@ -463,6 +488,9 @@ update_rect (h, {}, propnames{ii}, hr, objtype); endfor + rectmenu (hui, h); + set (hr, "uicontextmenu", hui); + ## Updaters addlistener (h, "position", address@hidden, "position", hr, objtype}); for ii = 1:numel (propnames) @@ -485,6 +513,10 @@ for ii = 1:numel (propnames) update_textbox (h, {}, propnames{ii}, [hte hpa]); endfor + + textboxmenu (hui, h); + set (hpa, "uicontextmenu", hui); + set (hte, "uicontextmenu", hui); ## Updaters addlistener (h, "position", address@hidden, "position", [hte hpa]}); @@ -502,6 +534,7 @@ endfunction function props = lineprops (varargin) + ## FIXME: Use "axesx(y)lim" instead of "linex(y)data" props = {"color", "color", [0 0 0], ... "linestyle", "linelinestyle", "-", ... "linewidth", "linelinewidth", 0.5, ... @@ -512,6 +545,28 @@ endif endfunction +function col = basecolors () + col = {"blue", "black", "cyan", "green", "magenta", "red", ... + "white", "yellow", "none"}; +endfunction + +function linemenu (hui, hpar) + hm = uimenu ("parent", hui, "label", "Line"); + + ## Color + vals = basecolors (); + addbasemenu (hm, hpar, "Color", vals); + + + ## Linestyle + vals = set (hpar, "linestyle"); + addbasemenu (hm, hpar, "Linestyle", vals); + + ## Linewidth + vals = [0.5 1 1.5 2]; + addbasemenu (hm, hpar, "Linewidth", vals); +endfunction + function props = arrowprops (varargin) props = {"headlength", "data", 10, ... "headstyle", "radio", "diamond|ellipse|none|plain|rectangle|vback1|{vback2}|vback3", ... @@ -521,6 +576,19 @@ endif endfunction +function arrowmenu (hui, hpar) + hm = uimenu ("parent", hui, "label", "Arrowhead"); + + ## Headlength/width + vals = 6:2:16; + addbasemenu (hm, hpar, "headlength", vals, "Length"); + addbasemenu (hm, hpar, "headwidth", vals, "Width"); + + ## Headstyle + vals = set (hpar, "headstyle"); + addbasemenu (hm, hpar, "Headstyle", vals); +endfunction + function props = dblarrowprops (varargin) props = {"head1length", "data", 10, ... "head1style", "radio", "diamond|ellipse|none|plain|rectangle|vback1|{vback2}|vback3", ... @@ -533,6 +601,23 @@ endif endfunction +function dblarrowmenu (hui, hpar) + hm1 = uimenu ("parent", hui, "label", "Arrowhead #1"); + hm2 = uimenu ("parent", hui, "label", "Arrowhead #2"); + + ## Headlength/width + vals = 6:2:16; + addbasemenu (hm1, hpar, "head1length", vals, "Length"); + addbasemenu (hm1, hpar, "head1width", vals, "Width"); + addbasemenu (hm2, hpar, "head2length", vals, "Length"); + addbasemenu (hm2, hpar, "head2width", vals, "Width"); + + ## Headstyle + vals = set (hpar, "head1style"); + addbasemenu (hm1, hpar, "head1style", vals, "Headstyle"); + addbasemenu (hm2, hpar, "head2style", vals, "Headstyle"); +endfunction + function props = textprops (varargin) props = {"fontangle", "textfontangle", "normal", ... "fontname", "textfontname", "Helvetica", ... @@ -554,6 +639,65 @@ endif endfunction +function stringdlg (hpar, prop) + def = get (hpar, prop); + if (iscell (def)) + prompt = arrayfun (@(n) sprintf ("Line #%d:", n), 1:numel (def), + "uniformoutput", false); + else + prompt = ""; + def = {def}; + endif + + cstr = inputdlg (prompt, prop, 1, def); + + if (! isempty (cstr)) + set (hpar, prop, cstr) + endif +endfunction + +function textmenu (hui, hpar) + hm = uimenu ("parent", hui, "label", "Text"); + + ## String; + prop = "String"; + fcn = @() stringdlg (hpar, prop); + uimenu (hm, "label", prop, "callback", fcn); + + ## Font properties + prop = "textcolor"; + vals = basecolors (); + addbasemenu (hm, hpar, prop, vals, "Color"); + prop = "fontsize"; + vals = 8:2:20; + addbasemenu (hm, hpar, prop, vals, "Size"); + prop = "fontangle"; + vals = set (hpar, prop); + addbasemenu (hm, hpar, prop, vals, "Angle"); + prop = "fontweight"; + vals = set (hpar, prop); + addbasemenu (hm, hpar, prop, vals, "Weight"); + prop = "textrotation"; + vals = 0:90:270; + addbasemenu (hm, hpar, prop, vals, "Rotation"); + + prop = "horizontalalignment"; + vals = set (hpar, prop); + addbasemenu (hm, hpar, prop, vals, "Horizontal Alignment", ... + "separator", "on"); + prop = "verticalalignment"; + vals = set (hpar, prop); + addbasemenu (hm, hpar, prop, vals, "Vertical Alignment"); + + ## FIXME: Add text background properties when they are supported + + prop = "interpreter"; + vals = set (hpar, prop); + addbasemenu (hm, hpar, prop, vals, "Interpreter", ... + "separator", "on"); + +endfunction + function props = textboxprops (varargin) props = {"backgroundcolor", "patchfacecolor", "none", ... "color", "textcolor", [0 0 0], ... @@ -577,6 +721,63 @@ endif endfunction +function textboxmenu (hui, hpar) + ## Text properties + hm1 = uimenu ("parent", hui, "label", "Text"); + + prop = "String"; + fcn = @() stringdlg (hpar, prop); + uimenu (hm1, "label", prop, "callback", fcn); + + prop = "Color"; + vals = basecolors (); + addbasemenu (hm1, hpar, prop, vals); + prop = "fontsize"; + vals = 8:2:20; + addbasemenu (hm1, hpar, prop, vals, "Size"); + prop = "fontangle"; + vals = set (hpar, prop); + addbasemenu (hm1, hpar, prop, vals, "Angle"); + prop = "fontweight"; + vals = set (hpar, prop); + addbasemenu (hm1, hpar, prop, vals, "Weight"); + + prop = "horizontalalignment"; + vals = set (hpar, prop); + addbasemenu (hm1, hpar, prop, vals, "Horizontal Alignment", ... + "separator", "on"); + prop = "verticalalignment"; + vals = set (hpar, prop); + addbasemenu (hm1, hpar, prop, vals, "Vertical Alignment"); + prop = "Margin"; + vals = 2:2:10; + addbasemenu (hm1, hpar, prop, vals); + + prop = "interpreter"; + vals = set (hpar, prop); + addbasemenu (hm1, hpar, prop, vals, "Interpreter", ... + "separator", "on"); + + ## Background properties + hm2 = uimenu ("parent", hui, "label", "Background"); + + prop = "fitboxtotext"; + vals = set (hpar, prop); + addbasemenu (hm2, hpar, prop, vals, "Fit box to text"); + prop = "backgroundcolor"; + vals = basecolors (); + addbasemenu (hm2, hpar, prop, vals, "Face Color"); + prop = "edgecolor"; + vals = basecolors (); + addbasemenu (hm2, hpar, prop, vals, "Edge Color"); + prop = "linestyle"; + vals = set (hpar, prop); + addbasemenu (hm2, hpar, prop, vals, "Line Style"); + prop = "linewidth"; + vals = 0.5:.5:2; + addbasemenu (hm2, hpar, prop, vals, "Line Width"); +endfunction + function props = rectprops (varargin) props = {"edgecolor", "patchedgecolor", "k", ... "facealpha", "patchfacealpha", 1, ... @@ -588,11 +789,63 @@ endif endfunction +function rectmenu (hui, hpar) + prop = "facecolor"; + vals = basecolors (); + addbasemenu (hui, hpar, prop, vals, "Face Color"); + prop = "edgecolor"; + vals = basecolors (); + addbasemenu (hui, hpar, prop, vals, "Edge Color"); + prop = "linestyle"; + vals = set (hpar, prop); + addbasemenu (hui, hpar, prop, vals, "Line Style"); + prop = "linewidth"; + vals = 0.5:.5:2; + addbasemenu (hui, hpar, prop, vals, "Line Width"); +endfunction + function addbaseprops (h, proptable) cellfun (@(pname, ptype, parg) addproperty (pname, h, ptype, parg), proptable(1:3:end), proptable(2:3:end), proptable(3:3:end)); endfunction +function addbasemenu (hm, hpar, pname, vals, mainlabel = "" ) + if (isempty (mainlabel)) + mainlabel = pname; + endif + + h = uimenu ("parent", hm, "label", mainlabel); + + is_numeric = ! iscell (vals); + nv = numel (vals); + htmp = zeros (1, nv); + for ii = 1:nv + if (! is_numeric) + val = label = vals{ii}; + else + val = vals(ii); + label = num2str (val); + endif + + fcn = @() set (hpar, pname, val); + htmp(ii) = uimenu (h, "label", label, "callback", fcn); + endfor + handle_check (hpar, {}, htmp, pname, is_numeric); + addlistener (hpar, pname, address@hidden, htmp, pname, is_numeric}) +endfunction + +function handle_check (h, dummy, hmenus, prop, is_numeric) + vals = get (hmenus, "label"); + current = get (h, prop); + if (is_numeric) + current = num2str (current); + endif + + idx = strcmp (vals, current); + set (hmenus(idx), "checked", "on"); + set (hmenus(! idx), "checked", "off"); +endfunction + function update_position (h1, dummy, h, force = false) if (! force) pos = convertposition (h, getappdata (h, "__former_units__"), @@ -799,7 +1052,7 @@ pos = getnormpos (h); if (strcmp (get (h, "fitboxtotext"), "on")) - pos(3:4) = get (hte, "extent")(3:4); + pos(3:4) = get (hte, "extent")(3:4) .* sign (pos(3:4)); endif [x, y] = pos2rect (pos); @@ -995,6 +1248,10 @@ ## annotation axes. %!demo %! clf; axes ('visible', 'off'); +%! annotation ('textbox', [.25 .9 .5 .09], 'string', ... +%! {'Right Click on annotation objects', ... +%! 'to customize their appearance'}, ... +%! 'horizontalalignment', 'center', 'fitboxtotext', 'off'); %! annotation ('ellipse', [.2 .2 .6 .6], 'linewidth', 4) %! ang = pi/2:-pi/2:-pi; %! lab = {'N', 'W', 'S', 'E'};