Code covered by the BSD License  

Highlights from
Precise Figure Placing

image thumbnail
from Precise Figure Placing by Markus Buehren
This contribution provides functions for precisely placing a figure to a given screen location.

computefiguresizeinfo(useDefaults)
function figureSizeInfo = computefiguresizeinfo(useDefaults)
%COMPUTEFIGURESIZEINFO  Compute figure size info.
%		FIGINFO = COMPUTEFIGURESIZEINFO(USEDEFAULTS) computes the figure size
%   info like menu bar height and task bar height. Default values are
%   returned if USEDEFAULTS is true.
%
%		Function COMPUTEFIGURESIZEINFO generates two figures and takes
%		screenshots to determine the mentioned values. As the code is not
%		absolutely error-safe, default values can be used.
%
%		Markus Buehren
%		Last modified: 20.04.2008
%
%		See also GETFIGURESIZEINFO, DELETEFIGURESIZEINFO.

if exist('useDefaults', 'var') && useDefaults
	% use default values
	disp(' ');
	disp(textwrap2([...
		'Default values are used for sizes like the menu bar height ', ...
		'of Matlab figures and the height of the task bar. Type']));
	disp(' ');
	disp('  deletefiguresizeinfo;');
	disp('  getfiguresizeinfo(0);');
	disp(' ');
	disp('to try the automatic retrieval of those values.');
	disp(' ');
	disp(textwrap2(['This message should only be displayed once on each ', ...
		'host and for each screen size.']));
	disp(' ');

	% get screen size
	figureSizeInfo.screenSize = getscreensizeinpixels;

	% set default values
	if ispc
		if strcmp(getplatform, 'Microsoft Windows 2000')
			% values obtained with Windows 2000
			figureSizeInfo.figureHeadHeight  = 23;
			figureSizeInfo.menuBarHeight     = 21;
			figureSizeInfo.toolBarHeight     = 27;
			figureSizeInfo.lowerBorderHeight = 4;
			figureSizeInfo.leftBorderWidth   = 4;
			figureSizeInfo.rightBorderWidth  = 4;
			figureSizeInfo.taskBarHeight     = 64;
		else
			% values obtained with Windows XP
			figureSizeInfo.figureHeadHeight  = 29;
			figureSizeInfo.menuBarHeight     = 21;
			figureSizeInfo.toolBarHeight     = 27;
			figureSizeInfo.lowerBorderHeight = 4;
			figureSizeInfo.leftBorderWidth   = 4;
			figureSizeInfo.rightBorderWidth  = 4;
			figureSizeInfo.taskBarHeight     = 60;
		end
	else
		% values obtained on some KDE system
		figureSizeInfo.figureHeadHeight  = 24;
		figureSizeInfo.menuBarHeight     = 27;
		figureSizeInfo.toolBarHeight     = 29;
		figureSizeInfo.lowerBorderHeight = 6;
		figureSizeInfo.leftBorderWidth   = 2;
		figureSizeInfo.rightBorderWidth  = 2;
		figureSizeInfo.taskBarHeight     = 31;
	end

	%versionInfo = ver('MATLAB');
	%if str2double(versionInfo.Version) >= 7.3;
	%	% no toolbar from version 7.3 on
	%	figureSizeInfo.toolBarHeight = 0;
	%end
	return
end

disp(' ');
disp(textwrap2(['Retrieval of the task bar height is now done. For this, ', ...
	'a figure with changing background color is displayed and screen shots are ', ...
	'taken. If this fails, a default value will be used.']));
disp(' ');
disp(textwrap2(['The retreived information is saved permanently. The procedure ', ...
	'should only be started once on each host and for each screen size.']));
disp(' ');
pause(2);

% make existing figures invisible
ch = get(0, 'Children');
figureHandles = ch(strcmp(get(ch, 'Type'), 'figure'));
figureVisible = get(figureHandles, 'Visible');
if ischar(figureVisible)
	figureVisible = {figureVisible};
end
set(figureHandles, 'Visible', 'off');

% get screen size
currentUnits = get(0, 'Units');
set(0, 'Units', 'pixels');
screenSize = getscreensizeinpixels;

% generate background figure
outerPosition = screenSize;
outerPosition = correctfigpos(outerPosition, 'set');
h1 = figure('Visible', 'off', 'NumberTitle', 'off', ...
	'Name', sprintf('Background figure generated by function %s.m', mfilename), ...
	'Pointer', 'custom', 'PointerShapeCdata', nan(16, 16), ...
	'OuterPosition', outerPosition);


% with tool bar and menu bar
set(h1, 'ToolBar', 'figure', 'MenuBar', 'figure'); drawnow;
innerPosition = get(h1, 'Position');
innerPosition = correctfigpos(innerPosition, 'get');
height1           = screenSize(4)    - innerPosition(2) - innerPosition(4);
leftBorderWidth   = innerPosition(1) - screenSize   (1);
lowerBorderHeight = innerPosition(2) - screenSize   (2);
rightBorderWidth  = screenSize   (3) - innerPosition(3) - innerPosition(1) + 1;

% without tool bar
set(h1, 'ToolBar', 'none'); drawnow;
innerPosition = get(h1, 'Position');
innerPosition = correctfigpos(innerPosition, 'get');
height2 = screenSize(4) - innerPosition(2) - innerPosition(4);

% without menu bar
set(h1, 'MenuBar', 'none'); drawnow;
innerPosition = get(h1, 'Position');
innerPosition = correctfigpos(innerPosition, 'get');
figureHeadHeight = screenSize(4) - innerPosition(2) - innerPosition(4);

% get task bar height
bgColorMatrix = [
	1 1 0; % yellow
	1 0 0; % red
	0 1 0; % green
	];

nOfColors = size(bgColorMatrix, 1);
screenShotCell = cell(nOfColors, 1);
for bgColorNr = 1:nOfColors
	set(h1, 'Visible', 'on', 'Color', bgColorMatrix(bgColorNr,:)); drawnow;

	% get frame
	frame = getframe(h1, screenSize);

	% sample screenshot to reduce computational effort and memory
	screenShotCell{bgColorNr} = frame.cdata(:, 10:20:screenSize(3)-10,:);

	pause(0.2);
end
delete(h1);

bgColorMatrix = bgColorMatrix * 255;
bgIndex = 1;
for bgColorNr = 1:nOfColors
	% get screenshot
	screenShot = screenShotCell{bgColorNr};

	% compute most frequent color in each row
	screenShotMode = mode(double(screenShot), 2);

	% update background index
	bgColor = bgColorMatrix(bgColorNr,:);
	bgIndex = bgIndex & ...
		screenShotMode(:,1,1) == bgColor(1) & ...
		screenShotMode(:,1,2) == bgColor(2) & ...
		screenShotMode(:,1,3) == bgColor(3);
end

chIndex = find(diff(bgIndex) ~= 0);

if length(chIndex) == 2
	% expected result
	taskBarHeight = screenSize(4) - chIndex(2);
elseif length(chIndex) == 1 && chIndex < screenSize(4)*0.3
	% probably the task bar was set to automatically disapper
	taskBarHeight = 0;
else
	
	versionInfo = evalc('ver'); %#ok
	fileName = [mfilename, '_crashdump.mat'];
	save(fileName, 'screenShotCell', 'screenSize', 'chIndex', 'versionInfo');
	disp(textwrap2(sprintf(['Unexpected result during screen shot processing!!\n', ...
		'Please send the files %s and %s to mb_matlab', char(double('@')), ...
		'g', char('f'+2*sum(eig(eye(3)))+1), 'x.d', 'e for inspection. Maybe ', ...
		'I can solve the problem for you.\n', ...
		'Regards, Markus Buehren.\n'], which(fileName), which(mfilename))));

	if length(chIndex) > 2
		% changing background color contained in figure head or task bar
		[ignore, index] = max(diff(chIndex)); %#ok
		taskBarHeight = screenSize(4) - chIndex(index+1);
	elseif length(chIndex) == 1
		% figure head not visible
		taskBarHeight = screenSize(4) - chIndex(1);
	else
		disp('Background color not found in screenshot. Unable to retrieve task bar height (set to 100).');
		taskBarHeight = 100;
	end
end

% restore visibility status of other figures
for k=1:length(figureHandles);
	set(figureHandles(k), 'Visible', figureVisible{k});
end

% reset units
set(0, 'Units', currentUnits);

% put results into a structure
figureSizeInfo.screenSize        = screenSize;
figureSizeInfo.figureHeadHeight  = figureHeadHeight;
figureSizeInfo.menuBarHeight     = height2 - figureHeadHeight;
figureSizeInfo.toolBarHeight     = height1 - figureHeadHeight - figureSizeInfo.menuBarHeight;
figureSizeInfo.lowerBorderHeight = lowerBorderHeight;
figureSizeInfo.leftBorderWidth   = leftBorderWidth;
figureSizeInfo.rightBorderWidth  = rightBorderWidth;
figureSizeInfo.taskBarHeight     = taskBarHeight;

Contact us