-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtilefigs.m
265 lines (249 loc) · 10.3 KB
/
tilefigs.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
function tilefigs(handles,resize,nRows,nCols,leftRightSpacing,topBottomSpacing,...
border,monitor,monitorLocation,monitorSize)
% TILEFIGS Tile figures (spread them out). Tile figs has a number of
% arguments, which may either be specified, or entered as [] to use the
% default
% TILEFIGS(handles,resize,nRows,nCols,leftRightSpacing,...
% topBottomSpacing,border,monitor,monitorLocation,monitorSize)
% TILEFIGS , by itself, resizes and tiles all open figures on to the primary monitor
% TILEFIGS(handles) Resizes and tiles the figures specified in handles,
% with the first handle in the upper left corner
% TILEFIGS(...,resize) If resize is set to false, the figures will be
% moved but not resized. Effort has been made to have minimal overlap,
% but some may still occur.
% TILEFIGS(...,nRows) Specifies a number of rows for the tile grid
% TILEFIGS(...,nCols) Specifies a number of column for the tile grid.
% Note that the figures are still included row by row, so if one has 8
% open figures and tilefigs([],[],[],5) is called, the figures will be
% put into a 4 x 2 grid with space left for a 5th column.
% TILEFIGS(...,leftRightSpacing) leaves a horizontal space between the
% figures. Spacing is specified in pixels. This may have no effect if
% resize is set to false.
% TILEFIGS(...,topBottomSpacing) Same as above, except for vertical
% spacing
% TILEFIGS(...,border) Leaves a border around the tiling of figures.
% border is a 1 x 4 matrix, which is [leftSpace bottomSpace rightSpace
% topSpace]. If the primary monitor is used, the default is [0 35 0 0]
% which is approximately the size of the taskbar in Windows 7. If a
% secondary monitor is used, the default is [0 0 0 0]
% TILEFIGS(...,monitor , monitorLocation,monitorSize) Specifies a monitor to use,
% which is the row of the call get(0,'MonitorPositions'). MATLAB does not
% officially support dual monitors. The author has found that the
% MonitorPositions call correctly gets the size of the monitor (in
% pixels), but not the location of the monitor. monitorLocation and
% monitorSize overrides the location and size of the monitor.
% Written by Brendan Tracey October 11th, 2012.
% Inspirational credit to:
%Charles Plum Nichols Research Corp.
%<[email protected]> 70 Westview Street
%Tel: (781) 862-9400 Kilnbrook IV
%Fax: (781) 862-9485 Lexington, MA 02173
% Nomenclature -- first number is width, second is length
% x is left to right, y is up and down
if ~exist('topBottomSpacing','var') || isempty(topBottomSpacing)
topBottomSpacing = 0;
end
if ~exist('leftRightSpacing','var') || isempty(leftRightSpacing)
leftRightSpacing = 0;
end
%% Select the monitor and get the location and size of the monitor
monitorPositions = get(0,'MonitorPositions');
matlabMonitorLocation = monitorPositions(:,1:2);
matlabMonitorSize = monitorPositions(:,3:4) - monitorPositions(:,1:2) + 1;
if ~exist('monitor','var') || isempty(monitor)
% No monitor specified, use the primary
monitor = 1;
end
if ~exist('monitorSize','var') || isempty(monitorSize)
% No monitor size specified, use what Matlab says
monitorSize = matlabMonitorSize(monitor,:);
end
if ~exist('monitorLocation','var') || isempty(monitorLocation)
% No monitor location specified, use what Matlab says
monitorLocation = matlabMonitorLocation(monitor,1:2);
end
% Set the default border if none is specified [left, bottom, right, top]
if monitor > 1
if ~exist('border','var') || isempty(border)
border = [0 0 0 0];
end
else
if ~exist('border','var') || isempty(border)
border = [0 30 0 0];
end
end
% Modify the monitor size and location to account for the border
monitorLocation = monitorLocation + border(1:2);
monitorSize(1) = monitorSize(1) - border(1) - border(3);
monitorSize(2) = monitorSize(2) - border(2) - border(4);
%% Select figures to use
if ~exist('handles','var') || isempty(handles)
% No figure handles specified, select all figures
handles = get (0,'Children'); % locate all open figure handles
handles = handles(end:-1:1); % Re-order so that first created is in upper left
end
nFigures = length(handles);
% Put all of the figures in pixel units
units = get(handles, 'units');
set(handles,'units','pixels');
%% Determine the grid for figures
if (~exist('nRows','var') || isempty(nRows)) && (~exist('nCols','var') || isempty(nCols))
% No grid specified, choose the grid which roughly matches the monitor
% aspect ratio
monitorAspectRatio = monitorSize(1) / monitorSize(2);
if monitorAspectRatio < 1
nCols = round(sqrt(nFigures));
nRows = ceil(nFigures/nCols);
else
nRows = round(sqrt(nFigures));
nCols = ceil(nFigures/nRows);
end
elseif (exist('nRows','var') && ~isempty(nRows)) && (~exist('nCols','var') || isempty(nCols))
nCols = ceil(nFigures/nRows);
elseif (~exist('nRows','var') || isempty(nRows)) && (exist('nCols','var') && ~isempty(nCols))
nRows = ceil(nFigures/nCols);
elseif (exist('nRows','var') && ~isempty(nRows)) && (exist('nCols','var') && ~isempty(nCols))
if nRows*nCols < nFigures
error('Grid size not big enough')
end
else
error('Should not be here')
end
%% Calculate the grid sizing
if ~exist('resize','var') || isempty(resize)
% Resize not set, default is to resize
resize = 1;
end
if resize
width = (monitorSize(1) - leftRightSpacing*(nCols - 1))/nCols;
height = (monitorSize(2) - topBottomSpacing*(nRows - 1))/nRows;
else
% Make the spacing equal with the constraint that the figures do not go
% off the edge of the screen.
figureWidths = zeros(nFigures,1);
figureHeights = zeros(nFigures,1);
for ii = 1:nFigures
figSize = get(handles(ii),'OuterPosition');
figureWidths(ii) = figSize(3);
figureHeights(ii) = figSize(4);
end
widthEndInds = nCols:nCols:nFigures;
heightEndInds = 1:nCols;
maxWidth = max(figureWidths(widthEndInds));
maxHeight = max(figureHeights(heightEndInds));
width = (monitorSize(1) - maxWidth)/max(nCols-1,1);
if nRows ==1
height = 0;
else
height = (monitorSize(2) - maxHeight)/(nRows-1);
end
end
%% Move and resize the figures
if resize
pnum = 0;
for row = 1:nRows
for col = 1:nCols
pnum = pnum+1;
if (pnum>nFigures)
break
end
xLocation = monitorLocation(1) + (col - 1)*width + (col - 1)*leftRightSpacing;
yLocation = monitorLocation(2) + monitorSize(2) - row*height ...
- (row - 1)*topBottomSpacing;
figure(handles(pnum))
set(handles(pnum),'OuterPosition',[xLocation yLocation width height]);
end
end
else
% Not resizing, set initial locations
xLocations = inf*ones(nRows,nCols);
yLocations = inf*ones(nRows,nCols);
widthMat = zeros(nRows,nCols);
heightMat = zeros(nRows,nCols);
pnum = 0;
for row = 1:nRows
for col = 1:nCols
pnum = pnum+1;
if (pnum>nFigures)
break
end
widthMat(row,col) = figureWidths(pnum);
heightMat(row,col) = figureHeights(pnum);
end
end
pnum = 0;
for row = 1:nRows
for col = 1:nCols
pnum = pnum+1;
if (pnum>nFigures)
break
end
xLocation = (col - 1)*width;
yLocation = monitorSize(2) - (row - 1)*height - heightMat(row,col);
xLocations(row,col) = xLocation;
yLocations(row,col) = yLocation;
end
end
% Modify the positions to make it look nicer.
% First, if the figures are too big to not overlap, spread the rows and
% columns out to use up all of the space at the border to minimize
% overlap. The subtraction of the width if there are no figures is to
% avoid the issue of both the column and the row being moved into the
% empty spot
if (sum(sum(widthMat,2) > monitorSize(1)) > 0)
for row = 1:nRows
lastNonemptyCol = find(xLocations(row,:) < inf,1,'Last');
whitespace = monitorSize(1) - xLocations(row,lastNonemptyCol) - widthMat(row,lastNonemptyCol) - width*(nCols-lastNonemptyCol);
if lastNonemptyCol>1
for col = 1:lastNonemptyCol
xLocations(row,col) = xLocations(row,col) + (col-1)/(lastNonemptyCol-1) * whitespace;
end
end
end
end
if sum(sum(heightMat,1) > monitorSize(2)) > 0
for col = 1:nCols
lastNonemptyRow = find(xLocations(:,col) < inf,1,'Last');
whitespace = yLocations(lastNonemptyRow,col) - 1 - height*(nRows - lastNonemptyRow);
if lastNonemptyRow>1
for row = 1:lastNonemptyRow
yLocations(row,col) = yLocations(row,col) - ((row-1)/(nRows-1)) * whitespace;
end
end
end
end
% If the figures can be condensed, slide the rows and columns in.
for col = 1:nCols - 1
lastNonemptyRow = find(xLocations(:,col) < inf,1,'Last');
endOfPlot = xLocations(1:lastNonemptyRow,col) + widthMat(1:lastNonemptyRow,col) + leftRightSpacing;
beginningOfNextPlot = xLocations(1:lastNonemptyRow,col + 1);
gap = beginningOfNextPlot - endOfPlot;
minGap = max(min(gap),0);
xLocations(1:lastNonemptyRow,col+1) = xLocations(1:lastNonemptyRow,col+1) - minGap;
end
for row = 2:nRows
lastNonemptyCol = find(xLocations(row,:) < inf,1,'Last');
bottomOfUpperRow = yLocations(row-1,1:lastNonemptyCol) - topBottomSpacing;
topOfThisRow = yLocations(row,1:lastNonemptyCol) + heightMat(row,1:lastNonemptyCol);
gap = bottomOfUpperRow - topOfThisRow;
minGap = max(min(gap),0);
yLocations(row,1:lastNonemptyCol) = yLocations(row,1:lastNonemptyCol) + minGap;
end
% Finally, actually move and replot the figures.
pnum = 0;
for row = 1:nRows
for col = 1:nCols
pnum = pnum+1;
if (pnum>nFigures)
break
end
figure(handles(pnum))
xloc = xLocations(row,col);
yloc = yLocations(row,col);
set(handles(pnum),'OuterPosition',[monitorLocation(1)+xloc monitorLocation(2) + yloc figureWidths(pnum) figureHeights(pnum)]);
end
end
end
for ii = 1:nFigures
set(handles(ii),'units',units{ii});
end