function supersizeme(varargin)
% supersizeme(h,gainFactor)
% Given a figure or axis handle(s), scale the font sizes of all text elements to make the figure
% more presentable before you email it to your boss or throw it into a powerpoint for your
% presentation that starts in 5 minutes. This code has also been adapted to work with TeX markup.
% OPTIONAL INPUTS
% h: a handle to a figure or a vector of axes or object handles; if the handle is to a figure, the
% code will search for all text within the figure. If h is missing, the code uses gcf().
% gainFactor: a non-zero number that is multiplied to the current font size of each individual text
% object. If missing, a default value is used (1.1). The value '1' will result in no
% change. To double the size of all text, enter 2. To halve the size of all text, enter
% either 0.5 or -2 (negative values are treated as 1/abs(gainFactor)). Alternatively,
% use the characters '-' or '+' to decrease/increase by the default value.
% INTERACTIVE MODE
% supersizeme('interactive') will open a simple GUI that uses a sliding scale to adjust all
% font sizes on the current figure, axis, or object (depending which is selected in the GUI).
%
% EXAMPLES
% %Create Plot
% fh = figure;
% s1=subplot(2,1,1); plot(rand(1,20), '-o'); title('RandomDots'); xlabel('x axis'); ylabel('y axis');
% text(10,.9,'Text goes here', 'fontsize', 8)
% s2=subplot(2,1,2); plot(rand(1,200), '-o'); title('RandomDots2'); xlabel('x axis'); ylabel('y axis');
% suptitle('Example plot'); legend('fake data')
% %SUPERSIZE OPTIONS
% supersizeme()
% supersizeme('-') %reverses previous line
% supersizeme(s1) %only affects subplot 1
% supersizeme([s1,s2]) %only affects subplots (not legend)
% supersizeme(fh, '+') %affects everything in figure
% supersizeme(2.5)
% supersizeme(-2.5) %same as supersizeme(1/2.5)
% supersizeme(1.5, fh) %order doesn't matter
% supersizeme('interactive') % for interactive mode.
%
% Requires matlab 2016b or later.
% Danz 180522
% Source: https://www.mathworks.com/matlabcentral/fileexchange/67644-supersizeme-varargin-
% Copyright (c) 2018, Adam Danz All rights reserved
% Please report bugs to adam.danz at gmail
% change history
% 180906 fixed error when allFontSz is not a cell array.
% 190710 * check for property "string" to avoid error with objects from xline() yline()
% * Added interactive mode
%% input validity
% If user entered interactive mode, create the GUI then quit.
if nargin>0 && strcmpi(varargin{1},'interactive')
sliderRange = [0,4];
GUI.fig = figure('Name',[mfilename,' interactive'],'MenuBar','none','ToolBar','None','WindowStyle','normal',...
'DockControls','off', 'Color',[0.41016 0.41016 0.41016],'Units','Normalize','Resize','off','HandleVisibility','off',...
'NumberTitle','off'); %dimgray
GUI.fig.Position([3,4]) = [.34,.25];
GUI.slider=uicontrol('Parent',GUI.fig,'Style','slider','Units','Normalize','Position',[.1,.32,.8,.18],... %slider
'value',1.0,'min',sliderRange(1),'max',sliderRange(2),'BackgroundColor',[0.66016 0.66016 0.66016],...
'SliderStep',[.1/range(sliderRange), .25/range(sliderRange)]); %darkgray
GUI.ax = axes(GUI.fig,'Units','Normalize','Position',[.15,.28,.695,.00],'FontSize',12,'XLim',sliderRange,'XTick',... %ticks
sliderRange(1):sliderRange(2), 'YTick',[],'XMinorTick','on','XColor',[1 0.64453 0],'Color',...
[0.41016 0.41016 0.41016],'TickLength',[.02,.035]); %orange
xlabel(GUI.ax,'Fontsize gain')
GUI.popup = uicontrol('Parent',GUI.fig,'Style','Popupmenu','Units','Normalize','Position',[.6,.55,.3,.18],... %popup menu
'Value',1,'String',{'Current figure','Current axis','Current object'},'FontSize',12,... %NOTE:If String is ever change, adjust callback fcn!
'BackgroundColor', [0.66016 0.66016 0.66016],'ForegroundColor',[0.41016 0.41016 0.41016]);
GUI.header = uicontrol('Parent',GUI.fig,'Style','Text','Units','Normalize','Position',[.1,.82,.8,.13], ... %header text
'String','Supersizeme interactive mode','Fontsize', 14,'BackgroundColor',[0.41016 0.41016 0.41016], ...
'ForegroundColor',[1 0.64453 0],'FontWeight','Bold');
GUI.instructions = uicontrol('Parent',GUI.fig,'Style','Text','Units','Normalize','Position',[.2,.56,.3,.18], ... %instructions
'String','Select target and scale font sizes.','Fontsize', 10,'BackgroundColor',[0.41016 0.41016 0.41016], ...
'ForegroundColor',[1 0.64453 0]);
GUI.undo = uicontrol('Parent',GUI.fig,'Style','pushbutton','Units','Normalize','Position',[.82,.02,.08,.09], ... %undo button
'String','undo','Fontsize', 8,'BackgroundColor',[0.41016 0.41016 0.41016], ...
'ForegroundColor',[1 0.64453 0]);
GUI.listenerBox = uicontrol('Parent',GUI.fig,'Style','Text','Units','Normalize','Position',[.1,.02,.08,.10], ... %active slider value
'String','1.00','Fontsize', 10,'BackgroundColor',[0.41016 0.41016 0.41016], ...
'ForegroundColor',[1 0.64453 0],'FontName','Consolas','Tag','ListenerBox');
GUI.listener = addlistener(GUI.slider,'ContinuousValueChange',@(hObj,event)sliderContinuousValCallbackFcn(hObj,event,GUI));
GUI.slider.Callback = {@interactiveSupersizeFcn, GUI};
GUI.undo.Callback = {@undoSupersizeFcn, GUI};
guidata(GUI.fig,GUI)
return
end
% ishandle() will return 'true' if the gainFactor is an integer that corresponds with a figure number (douh!)
% isnumeric(), however, distinguishes between object handles and numbers (whew!)
gainIdx = cellfun(@isnumeric, varargin) | cellfun(@ischar, varargin);
% any inputs that aren't ID'd by gainIdx must be fig/axis handles.
handIdx = ~gainIdx;
% If user didn't enter handle, get curr fig
if ~any(handIdx)
h = gcf;
else
h = varargin{handIdx};
end
% If user didn't enter gainFactor, set default value
defaultGain = 1.1;
if ~any(gainIdx)
gainFactor = defaultGain;
else
gainFactor = varargin{gainIdx};
end
% If user entered a string for the gain, replace with value
if ischar(gainFactor) && strcmp(gainFactor, '+')
gainFactor = defaultGain;
elseif ischar(gainFactor) && strcmp(gainFactor, '-')
gainFactor = 1/defaultGain;
end
% If user entered gain of 0, throw error
if gainFactor == 0
error('A gainfactor of zero would set fontsize to zero which is not allowed.')
end
% If user entered a negative gainFactor, replace with reciprocal
if gainFactor < 0
gainFactor = 1/abs(gainFactor);
end
%% Supersize me
% Loop through all handles and identify anything that has a 'fontsize' param
for i = 1:length(h)
textHand = findall(h(i), '-property','FontSize');
if isempty(textHand); continue; end
% Get fontsize of all text
allFontSz = get(textHand, 'FontSize');
if ~iscell(allFontSz)
allFontSz = {allFontSz};
end
% FontSizes
for j = 1:length(textHand)
textHand(j).FontSize = gainFactor * allFontSz{j};
% if text uses TeX markup and "\fontsize{xx}" is in string, change the fontsize from within the string
if isprop(textHand(j), 'Interpreter') && strcmp(textHand(j).Interpreter, 'tex') && isprop(textHand(j), 'String') && any(contains(cellstr(textHand(j).String), '\fontsize{')) %see [1]
for k = 1:length(textHand(j).String)
currFontCommand = regexp(textHand(j).String{k}, '\\fontsize{\d+\.?\d*}', 'match'); %search allows for possible decimals
currFontSize = regexp(currFontCommand{:}, '\d+\.?\d*', 'match'); %{str}
textHand(j).String(k) = strrep(textHand(j).String{k}, currFontCommand, ['\fontsize{',num2str(str2double(currFontSize{:})*gainFactor),'}']);
end
end
end
end
%% GUI callback function
function interactiveSupersizeFcn(hObj, ~, GUI)
% This function is evoked by the interactive gui when the slider is changed and affects either the current
% figure, axis, or object depending on popup selection.
switch GUI.popup.Value
case 1
currHand = gcf();
case 2
currHand = gca();
case 3
currHand = gco();
end
if hObj.Value==0
hObj.Value = 0.01;
end
if ~isempty(currHand) && isvalid(currHand)
hObj.UserData = {currHand,hObj.Value}; %store the most recent change so it can be reverted by 'undo'.
supersizeme(currHand,hObj.Value)
end
hObj.Value = 1; %return to 1
GUI.listenerBox.String = '1.00';
function undoSupersizeFcn(~, ~, GUI)
% This function is evoked by the interactive gui when the undo button is pressed. It reverts the most recent
% fontsize change.
if ~isempty(GUI.slider.UserData) && isvalid(GUI.slider.UserData{1})
supersizeme(GUI.slider.UserData{1},-GUI.slider.UserData{2})
GUI.slider.UserData{2} = -GUI.slider.UserData{2};
end
function sliderContinuousValCallbackFcn(hObj,~,GUI)
GUI.listenerBox.String = sprintf('%.2f',hObj.Value);
%% Notes
%[1] The contains() function is necessary because regexp doesn't work since '.String' can be char or cell.
% Furthermore, cellstr() is necessary because .String can be a cell array which will break (cellstr added 180802)
% contains() was released in r2016b.