function getfigure68 % This function adds a new menu option to copy the contents of a figure (axes, % lines, or even the whole figure) into the current figure % % first call adds the menu, second call deletes it % E. Clotet & J. Palacín % http://robotica.udl.cat % TO-DO: Check why undo is not working when setting a bitmap as background Version = 6.81; % May-2024 hmenu = findobj(gcf,'Tag','getfigure'); if (isempty(hmenu)) % Initialize menu options h_get = uimenu(gcf,'label','Getfigure','Tag','getfigure'); uimenu(h_get,'Label','Select a Figure and replicate figure size, Axis position, and Font format','TAG','GET','enable','on','callback',{@resizeFigureAndContent, 'all'}); uimenu(h_get,'Label','Select a Figure and replicate Text format','TAG','GET','enable','on','callback',{@resizeFigureAndContent, 'fonts'}); uimenu(h_get,'Label','Select a Figure and replicate Axis position (relative in the figure)','TAG','GET','enable','on','callback',{@resizeFigureAndContent, 'axes'}); uimenu(h_get,'label','Get a copy of a Figure','callback',{@copy, 'Figure', 'Original'},'TAG','GET','separator','on'); uimenu(h_get,'label','Get a copy of a Figure (replicating Figure size)','callback',{@copy, 'Figure', 'Exact'},'TAG','GET'); uimenu(h_get,'label','Get a copy of a specific Axis','callback',{@copy, 'Axes', 'Resize'},'TAG','GET','separator','on'); uimenu(h_get,'label','Get a copy of a specific Axis and adjust figure size','callback',{@copy, 'Axes', 'Tighten'},'TAG','GET'); uimenu(h_get,'label','Get a copy of a specific Axis (replicating Axis size)','callback',{@copy, 'Axes', 'Original'},'TAG','GET'); uimenu(h_get,'label','Copy all the content of a specific Axis','separator','on','callback',{@merge,'NoResize'},'TAG','GET'); uimenu(h_get,'label','Copy all the content of a specific Axis (replicating Figure and Axis size)','callback',{@merge,'ResizeFigAndAx'},'TAG','GET'); uimenu(h_get,'label','Copy one bitmap as Axis background','separator','on','callback',{@copybitmap, 1},'TAG','GET'); uimenu(h_get,'label','Copy one bitmap as Axis background (scale image)','callback',{@copybitmap, 0},'TAG','GET'); uimenu(h_get,'label','Copy one Line','separator','on','callback',{@copy, 'Line','Original'},'TAG','GET'); uimenu(h_get,'label','Copy one Line (subsampled)','callback',{@copy, 'Line','Subsampled'},'TAG','GET'); uimenu(h_get,'label','Copy one Line (oversampled)','callback',{@copy, 'Line','Oversampled'},'TAG','GET'); %uimenu(h_get,'Label','Copy all objects with the same ''Tag''','TAG','GET','enable','on','Callback',{@copy,'Tag','original'}); %uimenu(h_get,'Label','Copy all objects in axes with the same ''Tag''','TAG','GET','enable','on','Callback',{@copy,'TagInAxes','original'}); uimenu(h_get,'Label','Copy all objects in axes with the same ''Tag''','TAG','GET','enable','on','Callback',{@copy,'SelectedTagInAxes','original'}); undoButton = uimenu(h_get,'label','Undo last Get','callback',@undo_copy,'separator','on','enable','off','TAG','GET'); draggMenu = uimenu(h_get,'label','Add draggable objects...','TAG','GET','separator','on'); uimenu(draggMenu,'label','Add a draggable distance tool','callback','gca;imdistline;'); uimenu(draggMenu,'label','Add a draggable point','callback','gca;impoint;','separator','on'); uimenu(draggMenu,'label','Add a draggable line','callback','gca;imline;'); uimenu(draggMenu,'label','Add a draggable rectangle','callback','gca;imrect;'); uimenu(draggMenu,'label','Add a draggable ellipse','callback','gca;imellipse;'); uimenu(draggMenu,'label','Add a draggable polygon region','callback','gca;impoly;'); uimenu(draggMenu,'label','Add a draggable freehand region','callback','gca;imfreehand;'); uimenu(draggMenu,'label','Delete all draggable distance tools and lines','callback','delete(findobj(gca,''Tag'',''imline''));','separator','on'); uimenu(draggMenu,'label','Delete all draggable points','callback','delete(findobj(gca,''Tag'',''impoint''));'); uimenu(draggMenu,'label','Delete all draggable rectangles and ellipses','callback','delete(findobj(gca,''Tag'',''imrect''));'); uimenu(draggMenu,'label','Delete all draggable polygons','callback','delete(findobj(gca,''Tag'',''impoly''));'); uimenu(draggMenu,'label','Delete all draggable freehands','callback','delete(findobj(gca,''Tag'',''imfreehand''));'); uimenu(draggMenu,'label','Delete all draggable objects','callback','delete(findobj(gca,''Type'',''hggroup''));','separator','on'); axisMenu = uimenu(h_get,'label','Axis Position, Orientation and Visibility...','TAG','GET','separator','on'); uimenu(axisMenu,'Label','Toggle manual edition of the Axis position','Callback','plotedit(gcf);'); uimenu(axisMenu,'Label','Normal Y-X view of the Axis: view(0,90)','Callback','view(0,90);','separator','on'); uimenu(axisMenu,'Label','90º rotated X-Y view of the Axis: view(-90,90)','Callback','view(-90,90);'); uimenu(axisMenu,'Label','Toggle Axis visible/invisible','Callback',{@axisView,'Axis','Visibility','Toggle'},'separator','on'); uimenu(axisMenu,'Label','Set Axis Position to full window','Callback',{@axisView,'Axis','Position','FullWindow'},'separator','on'); uimenu(axisMenu,'Label','Set Axis Position to its default position','Callback',{@axisView,'Axis','Position','default'}); uimenu(axisMenu,'Label','Set MINIMUM Axis Position spacing','Callback',{@axisView,'Axis','Spacing','Minimum'}); uimenu(axisMenu,'Label','Set MINIMUM no label Axis Position spacing','Callback',{@axisView,'Axis','Spacing','None'}); uimenu(axisMenu,'Label','Set Figure Height to small','Callback',{@axisView,'Figure', 'Height', 1/2},'separator','on'); uimenu(axisMenu,'Label','Set Figure Height to medium','Callback',{@axisView,'Figure', 'Height', 2/3}); uimenu(axisMenu,'Label','Set Figure Height to normal','Callback',{@axisView,'Figure', 'Height', []}); % Empty for default height uimenu(axisMenu,'Label','Reset Figure size','Callback',{@axisView,'Figure','Size',[]},'separator','on'); axisEsc = uimenu(h_get,'label','Axis Scale. Limits and Width...','TAG','GET'); uimenu(axisEsc,'Label','Y Axis scaled as the X','Callback',@escalarY); uimenu(axisEsc,'Label','X Axis scaled as the Y','Callback',@escalarX) uimenu(axisEsc,'Label','Y Axis Limits: add 5% Upper and Lower margin','Callback',@escalarYY,'separator','on'); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 1.0','Callback',{@scaleFigure, 1},'separator','on'); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 1.5','Callback',{@scaleFigure, 1.5}); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 1.618','Callback',{@scaleFigure, 1.618}); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 2.0','Callback',{@scaleFigure, 2}); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 2.5','Callback',{@scaleFigure, 2.5}); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 3.0','Callback',{@scaleFigure, 3}); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 3.5','Callback',{@scaleFigure, 3.5}); uimenu(axisEsc,'Label','X Axis Width as the Y Axis x 4.0','Callback',{@scaleFigure, 4}); axisMenu = uimenu(h_get,'label','Axis visual appearance...','TAG','GET'); uimenu(axisMenu,'Label','zoom on click ( [ESC] to finish)','Callback',@zoomonclic); uimenu(axisMenu,'Label','toggle: zoom','Callback','zoom;','separator','on'); uimenu(axisMenu,'Label','toggle: pan','Callback','pan;'); uimenu(axisMenu,'Label','toggle: box','Callback','box;','separator','on'); uimenu(axisMenu,'Label','toggle: grid','Callback','grid;'); uimenu(axisMenu,'Label','toggle: grid(''minor'')','Callback','grid(''minor'');'); axisMenu2 = uimenu(axisMenu,'label','MenuBar...','separator','on'); uimenu(axisMenu2,'Label','not shown: ''none''','Callback',@quitMenuBar); uimenu(axisMenu2,'Label','with only Getfigure shown','Callback','set(gcf,''MenuBar'',''none'');'); uimenu(axisMenu2,'Label','normally shown: ''figure''','Callback',@addMenuBar); axisMenu2 = uimenu(axisMenu,'label','ToolBar...'); uimenu(axisMenu2,'Label','not shown: ''none''','Callback','set(gcf,''ToolBar'',''none'');'); uimenu(axisMenu2,'Label','normally shown: ''figure''','Callback','set(gcf,''ToolBar'',''figure'');'); uimenu(h_get,'Label','Delete objects outside the current Axis (to reduce .fig size)','Callback',@hideoutside,'separator','on','TAG','GET'); uimenu(h_get,'Label','Toggle the manual edition of objects','Callback','plotedit(gcf);','separator','on','TAG','GET'); moveToMenu = uimenu(h_get,'label','Select one object an reorder its visual stacking...','TAG','GET'); uimenu(moveToMenu,'label','Send to front','callback',{@changeLayer, 'top'}); uimenu(moveToMenu,'label','Send to back','callback',{@changeLayer, 'bottom'}); uimenu(moveToMenu,'label','Move forward','callback',{@changeLayer, 'up'}); uimenu(moveToMenu,'label','Move backwards','callback',{@changeLayer, 'donw'}); uimenu(h_get,'label','Select one object and call inspect(gco)','callback',@openInspect,'TAG','GET'); uimenu(h_get,'label',['Remove Getfigure (V' num2str(Version) ') from the menu'],'callback','delete(findobj(gcf,''Tag'',''getfigure''));','TAG','GET','separator','on'); uimenu(h_get,'label','Cancel','callback',@cancelCopy,'separator','on','Visible','off','Tag','UNDO'); %**************** % UNDO STRUCTURE %**************** % numActions: Number of actions listed % currentAction: ID of the last action % actionsList: List of objects involved in each action undoStructure.numActions = 0; undoStructure.currentAction = 0; undoStructure.actionsList = {}; undoButton.UserData = undoStructure; disp(['''Getfigure'' (V' num2str(Version) ') has been added to the menu']); % Set foccus on figure figure(gcf); else delete(hmenu); disp(['''Getfigure'' (V' num2str(Version) ') has been removed from the menu']); end end function escalarX(~,~) % get the axis hca = get(gcf,'CurrentAxes'); if ~isempty(hca) % avois axis square axis(gca,'normal'); old_units = get(hca,'Units'); set(hca,'Units','pixels'); YLim = get(hca,'YLim'); XLim = get(hca,'XLim'); YTick = get(hca,'YTick'); XTick = get(hca,'XTick'); if (length(YTick) == 1) && (length(XTick) == 1) YTickDif = (YLim(2)- YLim(1))/4; elseif (length(YTick) == 1) YTickDif = XTick(2) - XTick(1); else YTickDif = YTick(2) - YTick(1); end % width of the axis Position = get(hca,'Position'); AmpladaY = Position(4); AmpladaX = Position(3); Ytot = YLim(2) - YLim(1); % Ycentre = (YLim(2) + YLim(1))/2; Xtot = XLim(2) - XLim(1); Xcentre = (XLim(2) + XLim(1))/2; XXtot = Ytot * AmpladaX / AmpladaY; % proportional XLim XXLim1 = ((XLim(1)-Xcentre)/Xtot) * XXtot + Xcentre; XXLim2 = ((XLim(2)-Xcentre)/Xtot) * XXtot + Xcentre; set(hca,'XLim',[XXLim1 XXLim2]); zoom(hca,'reset'); % set YTick: requires 0 to be in visible in the axis set(hca,'XTick',-floor(-XXLim1/YTickDif)*YTickDif:YTickDif:floor(XXLim2/YTickDif)*YTickDif); set(hca,'XTickMode','auto'); set(hca,'Units',old_units); end end function escalarY(~,~) % get the axis hca = get(gcf,'CurrentAxes'); if ~isempty(hca) % avois axis square axis(gca,'normal'); old_units = get(hca,'Units'); set(hca,'Units','pixels'); YLim = get(hca,'YLim'); XLim = get(hca,'XLim'); YTick = get(hca,'YTick'); XTick = get(hca,'XTick'); if (length(XTick) == 1) && (length(YTick) == 1) XTickDif = (XLim(2)- XLim(1))/4; elseif (length(XTick) == 1) XTickDif = YTick(2) - YTick(1); else XTickDif = XTick(2) - XTick(1); end % width of axis Position = get(hca,'Position'); AmpladaY = Position(4); AmpladaX = Position(3); Ytot = YLim(2) - YLim(1); Ycentre = (YLim(2) + YLim(1))/2; Xtot = XLim(2) - XLim(1); % Xcentre = (XLim(2) + XLim(1))/2; YYtot = Xtot * AmpladaY / AmpladaX; % proportional YLim YYLim1 = ((YLim(1)-Ycentre)/Ytot) * YYtot + Ycentre; YYLim2 = ((YLim(2)-Ycentre)/Ytot) * YYtot + Ycentre; set(hca,'YLim',[YYLim1 YYLim2]); zoom(hca,'reset'); % set YTick: requires 0 to be visible in the axis set(hca,'YTick',-floor(-YYLim1/XTickDif)*XTickDif:XTickDif:floor(YYLim2/XTickDif)*XTickDif); set(hca,'YTickMode','auto'); set(hca,'Units',old_units); end end function escalarYY(~, ~) % get the axis hca = get(gcf,'CurrentAxes'); if ~isempty(hca) % avois axis square axis(gca,'normal'); YLim = hca.YLim; Ymargin = YLim(2)-YLim(1); % add 5% margin hca.YLim = [(YLim(1)-0.05*Ymargin) (YLim(2)+0.05*Ymargin)]; end end function axisView(~, ~, target, feature, value) axID = gca; % avois axis square axis(axID,'normal'); switch lower(target) % Target is a figure case 'figure' % Get the Matlab default figure position/size defaultFigureSize = get(0,'defaultfigureposition'); % Get the current figure and set Units to pixels figID = gcf(); originalUnits = figID.Units; figID.Units = 'Pixels'; switch lower(feature) case 'size' figID.Position = defaultFigureSize; case 'height' if isempty(value) % empty value means reset hegith figID.Position(4) = defaultFigureSize(4); else figID.Position(4) = defaultFigureSize(4)*value; end end % Restore original units figID.Units = originalUnits; % Target is an axis case 'axis' % Get the Matlab default axes position/size defaultAxesPosition = get(groot, 'defaultAxesPosition'); originalUnits = axID.Units; axID.Units = 'Normalized'; switch lower(feature) case 'position' switch lower(value) case 'default' axID.Position = defaultAxesPosition; case 'fullwindow' axID.Position = [0, 0, 1, 1]; end case 'spacing' axesList = {axID.XLabel, axID.YLabel, axID.ZLabel}; switch lower(value) case 'none' % Disable visibility of labels to adjust % tightinset for axIterator = 1:length(axesList) axesList{axIterator}.Visible = 'off'; end case 'minimum' % Enable visibility of labels and, if empty, % add some blank text to force recalculating % the tightinset variable for axIterator = 1:length(axesList) if isempty(axesList{axIterator}.String) axesList{axIterator}.String = ' '; end axesList{axIterator}.Visible = 'on'; end end % Adjust the position of the axis in the figure axID.OuterPosition = [0,0,1,1]; axID.Position(1:2) = axID.TightInset(1:2); axID.Position(3)= 1-axID.TightInset(3)-axID.TightInset(1)-0.01; axID.Position(4)= 1-axID.TightInset(4)-axID.TightInset(2)-0.01; case 'visibility' if strcmp(axID.Visible,'on') axID.Visible = 'off'; else axID.Visible = 'on'; end end % Restore original axes units axID.Units = originalUnits; end end function quitMenuBar(~,~) % remove getfigure eval(mfilename); set(gcf,'MenuBar','none'); end function addMenuBar(~,~) % remove getfigure eval(mfilename); set(gcf,'MenuBar','figure'); % add getfigure at the end eval(mfilename); end function zoomonclic(~,~) % zoom en la posició del cursor hca = gca; % entrada repetida amb el mouse set(findobj(gcf,'Tag','getfigure'),'Enable','off'); while 1 [x, y, button] = ginput(1); if (button ~= 1) && (button ~= 3) % fin % activar botons set(findobj(gcf,'Tag','getfigure'),'Enable','on'); return; end % debug %disp(['x = ' num2str(x) ', y = ' num2str(y)]); c = axis(hca); c_i = c(1); c_f = c(2); f_i = c(3); f_f = c(4); % trobar les distancies d_c_i = x - c_i; d_c_f = c_f - x; d_f_i = y - f_i; d_f_f = f_f - y; if (button == 1) % Zoom (+) escalat on es fa el clic-esquerra' d_c_i = d_c_i * 0.75; d_c_f = d_c_f * 0.75; d_f_i = d_f_i * 0.75; d_f_f = d_f_f * 0.75; elseif (button == 3) % decrementar el zoom d_c_i = d_c_i / 0.75; d_c_f = d_c_f / 0.75; d_f_i = d_f_i / 0.75; d_f_f = d_f_f / 0.75; end % aplicar el zoom c_i = x - d_c_i; c_f = d_c_f + x; f_i = y - d_f_i; f_f = d_f_f + y; axis(hca,[c_i c_f f_i f_f]); end end function hideoutside(~,~) hca = gca; YLim = get(hca,'YLim'); XLim = get(hca,'XLim'); achild = hca.Children; for i = 1:1:length(achild) % inicialitzar xmin = XLim(1); xmax = XLim(2); ymin = YLim(1); ymax = YLim(2); try switch get(achild(i),'Type') case 'text' pp = achild(i).Extent; xmin = pp(1); xmax = pp(1) + pp(3); ymin = pp(2); ymax = pp(2) + pp(4); case 'line' xmin = min(achild(i).XData); xmax = max(achild(i).XData); ymin = min(achild(i).YData); ymax = max(achild(i).YData); otherwise % ????? end catch % probablement es un GraphPlot (no té propietat type) xmin = min(achild(i).XData); xmax = max(achild(i).XData); ymin = min(achild(i).YData); ymax = max(achild(i).YData); end % verificar que estigui dintre de l'axis if ((ymax < YLim(1)) || (ymin > YLim(2)) || (xmax < XLim(1)) || (xmin > XLim(2))) % està fora delete(achild(i)); end end end function scaleFigure(~, ~, zoomFactor) % Scale figure without modifying the initial axis position % Get axis handle axisID = gca; % Avoid square axis axis(axisID, 'normal'); % Get the original axis size in pixels oldUnits = axisID.Units; axisID.Units = 'pixels'; % obtenir l'amplada Y en pixels originalWidth = axisID.Position(3); originalHeight = axisID.Position(4); % Size ratio to be applied % Compute the new width of the axis newWidth = originalHeight * zoomFactor; % Compuite the width difference widthDiff = newWidth - originalWidth; % Modify axis width axisID.Position(3) = newWidth; % Set the new figure width figID = gcf(); figID.Position(3) = figID.Position(3)+widthDiff; % Restore axis units axisID.Units = oldUnits; end function changeLayer(~, ~, direction) ginput(1); uistack(gco, direction); end function openInspect(~,~) if isempty(findobj(gcf,'Type','axes')) inspect(gcf); else ginput(1); inspect(gco); end end function cancelCopy(src, ~) src.Visible = 'off'; end function copy(src, ~, target, targetSize) persistent offsetinicialp numerop offsetfinalp rnoise if isempty(offsetinicialp) % initialize persistent subsampling values offsetinicialp = 1; numerop = 10; offsetfinalp = 0; rnoise = 0; end % Special flag for copying the elements of an axis with matching tag tagMode = 0; % Do not use tag if strcmpi(target, 'tagInAxes') target = 'Axes'; tagMode = 1; % Prompt for tag elseif strcmpi(target, 'SelectedTagInAxes') target = 'Object'; tagMode = 2; % Get tag from selected object end [dstFigure, source] = detectSrcAndDst(src, target); if dstFigure == -1 return; end % If target is a figure, remove previous content; if strcmpi(target,'figure') achild = dstFigure.Children; for i=1:1:length(achild) switch achild(i).Type case 'axes' delete(achild(i)); end end end % Initialize a variable to store the original units of the figure dstFigureUnits = []; % Check the figure units in dstFigure matches the figure units in src if strcmpi(target, 'figure') if ~strcmp(source.Units, dstFigure.Units) % The two figures have diferent units. % Store the current dstFigure units dstFigureUnits = dstFigure.Units; % Change the units of the dstFigure to match the src units dstFigure.Units = source.Units; end end % Get the list of elements to copy and the number of elements on that % list [cpyElmsList, numCpyItems] = getTargetElms(source, tagMode); % Initialize list of newly added objects newlyAddedObjects = {}; % Copy elements on cpyElmsList for i = 1:numCpyItems switch class(cpyElmsList{i}) case 'matlab.graphics.illustration.Legend' la = copyobj([cpyElmsList{i}, cpyElmsList{i}.Axes], dstFigure); case 'matlab.graphics.axis.Axes' la = copyobj(cpyElmsList{i}, dstFigure); case 'matlab.graphics.chart.primitive.Line' dstChildsList = dstFigure.Children; numChilds = length(dstChildsList); targetChild = []; for childID = 1:numChilds if isa(dstChildsList(childID), 'matlab.graphics.axis.Axes') targetChild = dstChildsList(childID); break; end end if isempty(targetChild) figure(dstFigure); targetChild = axes(); end la = copyobj(cpyElmsList{i}, targetChild); numElms = length(la.XData); if strcmpi(targetSize,'subsampled') if numerop > numElms numerop = numElms; % limit end answer=inputdlg({'Index of the initial point of the line (1..)',['Number of points after the sampling (1..' num2str(numElms) ')'],'Offset to the index of the end point (0,-1,-2,...)','Add random noise to YData with amplitude...'},'Subsampling',1,{num2str(offsetinicialp),num2str(numerop),num2str(offsetfinalp),num2str(rnoise)}); drawnow; if(isempty(answer)) delete(la) return; end offsetinicialp = str2double(char(answer(1))); numerop = str2double(char(answer(2))); offsetfinalp = str2double(char(answer(3))); rnoise = str2double(char(answer(4))); if numerop > numElms numerop = numElms; % limit again end if offsetfinalp > 0 offsetfinalp = -offsetfinalp; end p = round(linspace(offsetinicialp,numElms+offsetfinalp,numerop)); la.XData = la.XData(p); la.YData = la.YData(p) + (rand(1,length(p))-0.5)*2*rnoise; if ~isempty(la.ZData) la.ZData = la.ZData(p); end elseif strcmpi(targetSize,'oversampled') answer=inputdlg({'Index of the initial point of the line (1..)',['Number of points after spline oversampling ( ..' num2str(numElms) '.. )'],'Offset to the index of the end point (0,-1,-2,...)','Add random noise to YData with amplitude...'},'Oversampling',1,{num2str(offsetinicialp),num2str(numerop),num2str(offsetfinalp),num2str(rnoise)}); drawnow; if(isempty(answer)) delete(la) return; end offsetinicialp = str2double(char(answer(1))); numerop = str2double(char(answer(2))); offsetfinalp = str2double(char(answer(3))); rnoise = str2double(char(answer(4))); if numerop < 1 numerop = 1; % limit end if offsetfinalp > 0 offsetfinalp = -offsetfinalp; end p = linspace(offsetinicialp,numElms+offsetfinalp,numerop); % oversampling using splines la.XData = spline(1:1:numElms,la.XData,p); la.YData = spline(1:1:numElms,la.YData,p) + (rand(1,length(p))-0.5)*2*rnoise; if ~isempty(la.ZData) la.ZData = spline(1:1:numElms,la.ZData,p); end end otherwise try la = copyobj(cpyElmsList{i}, dstFigure); catch E disp(['Warning: an element could not be copied. ',E.message]); end end if length(la) == 1 newlyAddedObjects{end+1} = la; %#ok Total number of elements is unknown else numAddedElems = length(la); for elemID = 1:numAddedElems newlyAddedObjects{end+1} = la(elemID); %#ok Total number of elements is unknown end end end if strcmp(targetSize, 'Resize') la.Position = [0.1300 0.1100 0.7750 0.8150]; end if strcmp(targetSize,'Tighten') % Get original figure size and units parentFigID = source.Parent; % Get original dst figure units originalUnits = dstFigure.Units; % Change dstFigureUnits to match the source dstFigure.Units = parentFigID.Units; dstFigure.Position(3:4) = parentFigID.Position(3:4); la.Units = 'Pixels'; la.OuterPosition(2) = 0; la.XLim = source.XLim; la.YLim = source.YLim; %dstFigure.Position = [originalFigCornerPos, la.OuterPosition(3:4)]; dstFigure.Position(4) = la.OuterPosition(4); % Restore dst figure units and axis units dstFigure.Units = originalUnits; la.Units = source.Units; end if strcmp(target,'Figure') && strcmp(targetSize,'Exact') dstFigure.Position(3:4) = source.Position(3:4); % Restore the dstFigureUnits if needed if ~isempty(dstFigureUnits) dstFigure.Units = dstFigureUnits; end end if strcmp(target,'Axes') && strcmp(targetSize,'OriginalFigure') dstFigure.Position(3:4) = currentElm.Parent.Position(3:4); end % Retrieve undo actions list btnID = getButtonID(src.Parent,'Undo last Get'); if isempty(btnID) disp('Button not found'); end undoButton = src.Parent.Children(btnID); undoButton.Enable = 'on'; % Update undo actions list undoStructure = undoButton.UserData; undoStructure.numActions = undoStructure.numActions + 1; undoStructure.currentAction = undoStructure.currentAction + 1; undoStructure.actionsList{undoStructure.currentAction} = newlyAddedObjects; undoButton.UserData = undoStructure; end function [dstFigure, currentElm] = detectSrcAndDst(src, target) % Enable cancel button % Retrieve undo actions list btnID = getButtonID(src.Parent,'Cancel'); if isempty(btnID) disp('Cancel button not found'); dstFigure = -1; currentElm = -1; return; end % Hide other options hcf = gcf; set(findobj(hcf,'TAG','GET'),'Visible','off'); cancelBtn = src.Parent.Children(btnID); cancelBtn.Visible = 'on'; % Get destination figure dstFigure = gcf; % Get the current type of element initialObject = gco; % Set targetDectected flag to 0 targetDetected = 0; switch target case 'Axes' expectedSelectionClass = 'matlab.graphics.axis.Axes'; initialObject = get(dstFigure,'CurrentAxes'); case 'Figure' expectedSelectionClass = 'matlab.ui.Figure'; initialObject = gcf; case 'Line' expectedSelectionClass = 'matlab.graphics.chart.primitive.Line'; initialObject = gco; case 'Image' expectedSelectionClass = 'matlab.graphics.primitive.Image'; case 'Object' % We dont know the target class, we just know its not an axes nor a figure initialObject = gco; expectedSelectionClass = []; end % Wait untill the user selects an object that matches the target class while ~targetDetected && strcmp(cancelBtn.Visible,'on') if strcmp(target,'Figure') currentElm = gcf; elseif strcmp(target,'Axes') currentElm = get(gcf,'CurrentAxes'); else currentElm = gco; end % Check if the user selected an object matching the target class % and its different from the initial object if ~isempty(expectedSelectionClass) if isa(currentElm, expectedSelectionClass) && ~isequal(initialObject, currentElm) targetDetected = 1; end else if ~isequal(initialObject, currentElm) targetDetected = 1; end end refresh(); drawnow(); end % Show the other menus set(findobj(hcf,'TAG','GET'),'Visible','on'); % Check if user cancelled the action if strcmp(cancelBtn.Visible,'off') disp('Copy action canceled'); dstFigure = -1; currentElm = -1; end cancelBtn.Visible = 'off'; end function resizeFigureAndContent(src, ~, resizeTarget) fontsPropsList = {'FontUnits','FontSize','FontName','FontAngle','FontSmoothing','FontWeight'}; [dstFigure, currentElm] = detectSrcAndDst(src, 'Figure'); if dstFigure == -1 || currentElm == -1 return; end % start resizing matching elements if strcmpi(resizeTarget, 'all') dstFigure.Units = currentElm.Units; dstFigure.Position(3:4) = currentElm.Position(3:4); end % Adjust sizes of common elements: numDstFigureElems = length(dstFigure.Children); % Adjust sizes of common elements: numSrcFigureElems = length(currentElm.Children); for dstChildID = 1:numDstFigureElems % Get the handle of the child we want to resize dstChild = dstFigure.Children(dstChildID); if isa(dstChild, 'matlab.ui.container.Menu') continue; end targetClass = class(dstChild); for srcChildID =1:numSrcFigureElems if strcmp(targetClass, class(currentElm.Children(srcChildID))) srcElm = currentElm.Children(srcChildID); if strcmpi(resizeTarget, 'all') || strcmpi(resizeTarget, 'axes') dstChild.Units = srcElm.Units; dstChild.Position = srcElm.Position; end if strcmpi(resizeTarget, 'all') || strcmpi(resizeTarget, 'fonts') for fontPropID = 1:length(fontsPropsList) % Check if the target Font property exists whithin the % object if isprop(dstChild,fontsPropsList{fontPropID}) dstChild.(fontsPropsList{fontPropID}) = srcElm.(fontsPropsList{fontPropID}); dstChild.(fontsPropsList{fontPropID}) = srcElm.(fontsPropsList{fontPropID}); end end end break; end end end end function copybitmap(src, ~, keepLimits) [dstFigure, currentElm] = detectSrcAndDst(src, 'Image'); if dstFigure == -1 || currentElm == -1 return; end % Bring dst figure to front figure(dstFigure); % Get the current axes of the figure. If none detected, create new one axID = gca(); % Check if the hold flag is On isHoldActive = ishold(axID); % Temporarilly enable hold to draw image if ~isHoldActive hold(axID, 'on'); end % Copy bitmap to axis and send it to the bottom hi = copyobj(currentElm, axID); uistack(hi, 'bottom'); if ~keepLimits hi.XData = axID.XLim; hi.YData = axID.YLim; end % If hold was not enabled, disable it again. if ~isHoldActive hold(axID, 'off'); end % Retrieve undo actions list btnID = getButtonID(src.Parent,'Undo last Get'); if isempty(btnID) disp('Button not found'); end undoButton = src.Parent.Children(btnID); undoButton.Enable = 'on'; % Update undo actions list undoStructure = undoButton.UserData; undoStructure.numActions = undoStructure.numActions + 1; undoStructure.currentAction = undoStructure.currentAction + 1; undoStructure.actionsList{undoStructure.currentAction} = {hi}; % TO-DO: Check why undo is not working undoButton.UserData = undoStructure; end function btnID = getButtonID(parentID,targetName) childsList = parentID.Children; numChilds = length(childsList); btnID = []; for childID = 1:numChilds currentChild = childsList(childID); if strcmpi(currentChild.Label,targetName) btnID = childID; end end if isempty(btnID) return; end end function merge(src, ~, targetSize) [dstFigure, currentElm] = detectSrcAndDst(src, 'Axes'); [cpyElmsList, numCpyItems] = getTargetElms(currentElm, 0); newlyAddedObjects = {}; % get destination axes (creates an axes if no axes in the figure) figure(dstFigure); dstAx = gca; for i = 1:numCpyItems switch class(cpyElmsList{i}) case 'matlab.graphics.illustration.Legend' axesObj = cpyElmsList{i}.Axes; case 'matlab.graphics.axis.Axes' axesObj = cpyElmsList{i}; end childList = axesObj.Children; numChildren = length(childList); for childID = numChildren:-1:1 newlyAddedObjects{end+1} = copyobj(childList(childID), dstAx); %#ok unknown total number of elms uistack(newlyAddedObjects{end},'top'); % copy figure colormap in case of Image if isprop(childList(childID),'Type') if strcmp(get(childList(childID),'Type'),'image') cc = get(currentFig,'colormap'); set(hcf,'colormap',cc) end end end end if strcmp(targetSize,'ResizeFigAndAx') dstAx.Position = currentElm.Position; dstAx.Parent.Position(3:4) = currentElm.Parent.Position(3:4); % Revise axis limits of the destination c = axis(dstAx); c2 = axis(currentElm); if (c(1) ~= c2(1)) c(1) = c2(1); end if (c(2) ~= c2(2)) c(2) = c2(2); end if (c(3) ~= c2(3)) c(3) = c2(3); end if (c(4) ~= c2(4)) c(4) = c2(4); end if length(c2) > 4 % 3D if (length(c2) > length(c)) c(5) = c2(5); c(6) = c2(6); else if (c(5) ~= c2(5)) c(5) = c2(5); end if (c(6) ~= c2(6)) c(6) = c2(6); end end end % set the new limits axis(dstAx,c); zoom(dstAx,'reset'); end % Retrieve undo actions list btnID = getButtonID(src.Parent,'Undo last Get'); if isempty(btnID) disp('Button not found'); end undoButton = src.Parent.Children(btnID); undoButton.Enable = 'on'; % Update undo actions list undoStructure = undoButton.UserData; undoStructure.numActions = undoStructure.numActions + 1; undoStructure.currentAction = undoStructure.currentAction + 1; undoStructure.actionsList{undoStructure.currentAction} = newlyAddedObjects; undoButton.UserData = undoStructure; end function [axesList, lastAxesID] = getTargetElms(srcElm, tagMode) if tagMode ~= 0 switch tagMode case 1 % Get elements with the user-specified tag % Ask for target tag answer = inputdlg('Tag of the objects to be copied','Copy by tag'); % Look for all objects with this tag childList = findobj(srcElm, 'Tag',answer{1}); numChildren = length(childList); axesList = cell(1, numChildren); if childList == 1 axesList{1} = childList; else for childID = 1:numChildren axesList{childID} = childList(childID); end end lastAxesID = numChildren; return; case 2 % List all elements with the same tag than the selected object % Get the tag from the selected object tagName = srcElm.Tag; % Look for all objects with this tag childList = findobj(srcElm.Parent, 'Tag', tagName); numChildren = length(childList); axesList = cell(1, numChildren); if childList == 1 axesList{1} = childList; else for childID = 1:numChildren axesList{childID} = childList(childID); end end lastAxesID = numChildren; return; end end switch class(srcElm) case 'matlab.graphics.chart.primitive.Line' axesList{1} = srcElm; lastAxesID = 1; case 'matlab.graphics.axis.Axes' childList = srcElm.Children; numChildren = length(childList); axesList = cell(1, 1); % Check if this axis is linked to a Legend object for childID = 1:numChildren if isa(childList(childID),'matlab.graphics.illustration.Legend') if isequal(childList(childID).Axes) % Axes linked to a legend, just return the legend axesList{1} = childList(childID); lastAxesID = 1; return; end end end % No legend was linked to this axes, return the axes object axesList{1} = srcElm; lastAxesID = 1; % % childList = srcElm.Children; % % numChildren = length(childList); % % axesList = cell(1, 1); % % % Check if this axis is linked to a Legend object % for childID = 1:numChildren % if isa(childList(childID),'matlab.graphics.illustration.Legend') % if isequal(childList(childID).Axes) % % Axes linked to a legend, just return the legend % axesList{1} = childList(childID); % lastAxesID = 1; % return; % end % end % end % % % No legend was linked to this axes, return the axes object % axesList{1} = srcElm; % lastAxesID = 1; case 'matlab.ui.Figure' childList = srcElm.Children; numChildren = length(childList); legendsList = cell(1, numChildren); lastLegendID = 0; axesList = cell(1, numChildren); for childID = 1:numChildren if isa(childList(childID),'matlab.graphics.illustration.Legend') lastLegendID = lastLegendID + 1; legendsList{lastLegendID} = childList(childID); axesList{lastLegendID} = legendsList{lastLegendID}.Axes; end end legendsList = legendsList(1:lastLegendID); lastAxesID = lastLegendID; for childID = 1:numChildren if isa(childList(childID),'matlab.graphics.axis.Axes') found = 0; % check if this axes has already been detected as part of legend for legendID = 1:lastLegendID if isequal(childList(childID), axesList{legendID}) found = 1; end end if ~found lastAxesID = lastAxesID + 1; axesList{lastAxesID} = childList(childID); end end end axesList = axesList(1:lastAxesID); axesList(1:lastLegendID) = legendsList; case 'matlab.graphics.primitive.Data' % This is for tag objects list % Count the number of elements listed in srcElm lastAxesID = length(srcElm); % Create a cell array to store them axesList = cell(1, length(srcElm)); % Store the handles of the objects to be copied in axesList for taggedObjID = 1:lastAxesID axesList{taggedObjID} = srcElm(taggedObjID); end end end function undo_copy(source,~) % UNDO function undoStructure = source.UserData; undoID = undoStructure.currentAction; deleteElems = undoStructure.actionsList{undoID}; % remove one item at a time for elemID = 1:length(deleteElems) if ishandle(deleteElems{elemID}) % Try-catch block as some elements may have been deleted % manually by the user try delete(deleteElems{elemID}); catch end end end % Update UNDO structure undoStructure.actionsList(undoID) = []; undoStructure.currentAction = undoStructure.currentAction - 1; undoStructure.numActions = undoStructure.numActions -1; source.UserData = undoStructure; % Disable undo option if undoStructure.numActions == 0 source.Enable = 'off'; end end