source: MML/trunk/machine/SOLEIL/common/toolbox/GUILayout/+uiextras/Grid.m @ 4

Last change on this file since 4 was 4, checked in by zhangj, 10 years ago

Initial import--MML version from SOLEIL@2013

File size: 13.8 KB
Line 
1classdef Grid < uiextras.Container
2    %Grid  Container with contents arranged in a grid
3    %
4    %   obj = uiextras.Grid() creates a new new grid layout with all
5    %   properties set to defaults. The number of rows and columns to use
6    %   is determined from the number of elements in the RowSizes and
7    %   ColumnSizes properties respectively. Child elements are arranged
8    %   down column one first, then column two etc. If there are
9    %   insufficient columns then a new one is added. The output is a new
10    %   layout object that can be used as the parent for other
11    %   user-interface components. The output is a new layout object that
12    %   can be used as the parent for other user-interface components.
13    %
14    %   obj = uiextras.Grid(param,value,...) also sets one or more
15    %   parameter values.
16    %
17    %   See the <a href="matlab:doc uiextras.Grid">documentation</a> for more detail and the list of properties.
18    %
19    %   Examples:
20    %   >> f = figure();
21    %   >> g = uiextras.Grid( 'Parent', f, 'Spacing', 5 );
22    %   >> uicontrol( 'Style', 'frame', 'Parent', g, 'Background', 'r' )
23    %   >> uicontrol( 'Style', 'frame', 'Parent', g, 'Background', 'b' )
24    %   >> uicontrol( 'Style', 'frame', 'Parent', g, 'Background', 'g' )
25    %   >> uiextras.Empty( 'Parent', g )
26    %   >> uicontrol( 'Style', 'frame', 'Parent', g, 'Background', 'c' )
27    %   >> uicontrol( 'Style', 'frame', 'Parent', g, 'Background', 'y' )
28    %   >> set( g, 'ColumnSizes', [-1 100 -2], 'RowSizes', [-1 100] );
29    %
30    %   See also: uiextras.GridFlex
31   
32    %   Copyright 2009-2010 The MathWorks, Inc.
33    %   1.1
34    %   2012/05/08 08:02:59
35   
36    properties( SetObservable )
37        Padding = 0 % padding around and between contents [pixels]
38        Spacing = 0 % spacing between contents [pixels]
39    end % public properties
40   
41    properties( Dependent )
42        RowSizes           % column vector of row sizes, with positive elements for absolute sizes (pixels) and negative elements for relative sizes
43        ColumnSizes        % column vector of column sizes, with positive elements for absolute sizes (pixels) and negative elements for relative sizes
44        MinimumRowSizes    % minimum size (in pixels) for each row
45        MinimumColumnSizes % minimum size (in pixels) for each column
46    end % dependent properties
47   
48    properties( Access=private )
49 
50       
51    end % private properties
52    properties( Access = private )
53        RowSizes_ = zeros( 0, 1 )           % private property for storing actual row sizes
54        ColumnSizes_ = zeros( 0, 1 )        % private property for storing actual column sizes
55        MinimumRowSizes_ = zeros( 0, 1 )    % private property for storing actual minimum row sizes
56        MinimumColumnSizes_ = zeros( 0, 1 ) % private property for storing actual minimum column sizes
57    end % private properties
58   
59    methods
60       
61        function obj = Grid( varargin )
62            %Grid  Create a container with contents in a grid.
63           
64            % First step is to create the parent class. We pass the
65            % arguments (if any) just incase the parent needs setting
66            obj@uiextras.Container( varargin{:} );
67
68            % Set some defaults
69            obj.setPropertyFromDefault( 'Padding' );
70            obj.setPropertyFromDefault( 'Spacing' );
71
72            % Set user-supplied property values (only if this is the leaf class)
73            if nargin>0 && isequal( class( obj ), 'uiextras.Grid' )
74                set( obj, varargin{:} );
75            end
76           
77        end % constructor
78       
79    end % public methods
80   
81    methods
82       
83        function set.RowSizes( obj, value )
84           
85            % Check
86            if ~isvector( value )
87                error( 'GUILayout:InvalidPropertyValue', ...
88                    'Property ''RowSizes'' must be a vector.' )
89            elseif ~isnumeric( value ) || ...
90                    any( ~isreal( value ) ) || any( isnan( value ) ) || any( ~isfinite( value ) )
91                error( 'GUILayout:InvalidPropertyValue', ...
92                    'Property ''RowSizes'' must consist of real, finite, numeric values.' )
93            end
94           
95            % Set
96            obj.RowSizes_ = value(:);
97           
98            % Make sure min row sizes is the same length
99            nMinSizes = length(obj.MinimumRowSizes_);
100            nSizes = length(obj.RowSizes_);
101            if nMinSizes > nSizes
102                obj.MinimumRowSizes_ = obj.MinimumRowSizes_(1:nSizes);
103            elseif nMinSizes < nSizes
104                obj.MinimumRowSizes_(end+1:nSizes,1) = 1;
105            end
106           
107            % Add/remove elements to/from ColumnSizes, if required
108            nColumns = ceil( numel( obj.Children ) / numel( obj.RowSizes_ ) );
109            if numel( obj.ColumnSizes_ ) > nColumns
110                obj.ColumnSizes_(nColumns+1:end,:) = [];
111                obj.MinimumColumnSizes_(nColumns+1:end,:) = [];
112            elseif numel( obj.ColumnSizes ) < nColumns
113                obj.ColumnSizes_(end+1:nColumns,1) = -1;
114                obj.MinimumColumnSizes_(end+1:nColumns,1) = 1;
115            end
116           
117            % Redraw
118            obj.redraw();
119           
120        end % set.RowSizes
121       
122        function value = get.RowSizes( obj )
123            value = obj.RowSizes_;
124        end % get.RowSizes
125       
126        function set.ColumnSizes( obj, value )
127            % Check
128            if ~isvector( value )
129                error( 'GUILayout:InvalidPropertyValue', ...
130                    'Property ''ColumnSizes'' must be a vector.' )
131            elseif ~isnumeric( value ) || ...
132                    any( ~isreal( value ) ) || any( isnan( value ) ) || any( ~isfinite( value ) )
133                error( 'GUILayout:InvalidPropertyValue', ...
134                    'Property ''ColumnSizes'' must consist of real, finite, numeric values.' )
135            end
136           
137            % Set
138            obj.ColumnSizes_ = value(:);
139           
140            % Make sure min row sizes is the same length
141            nMinSizes = length(obj.MinimumColumnSizes_);
142            nSizes = length(obj.ColumnSizes_);
143            if nMinSizes > nSizes
144                obj.MinimumColumnSizes_ = obj.MinimumColumnSizes_(1:nSizes);
145            elseif nMinSizes < nSizes
146                obj.MinimumColumnSizes_(end+1:nSizes,1) = 1;
147            end
148           
149            % Add/remove elements to/from RowSizes, if required
150            nRows = ceil( numel( obj.Children ) / numel( obj.ColumnSizes_ ) );
151            if numel( obj.RowSizes_ ) > nRows
152                obj.RowSizes_(nRows+1:end,:) = [];
153                obj.MinimumRowSizes_(nRows+1:end,:) = [];
154            elseif numel( obj.RowSizes ) < nRows
155                obj.RowSizes_(end+1:nRows,1) = -1;
156                obj.MinimumRowSizes_(end+1:nRows,1) = 1;
157            end
158           
159            % Redraw
160            obj.redraw();
161        end % set.ColumnSizes
162       
163        function value = get.ColumnSizes( obj )
164            value = obj.ColumnSizes_;
165        end % get.ColumnSizes       
166               
167        function set.MinimumRowSizes( obj, value )
168            % Check that this vector matches the size vector
169            if ~isequal( numel( obj.RowSizes ), numel( value ) )
170                error( 'GUILayout:InvalidPropertyValue', ...
171                    'Size of property ''MinimumRowSizes'' must match size of property ''RowSizes''.' )
172            elseif ~isnumeric( value ) || ...
173                    any( ~isreal( value ) ) || any( isnan( value ) ) || any( ~isfinite( value ) )
174                error( 'GUILayout:InvalidPropertyValue', ...
175                    'Property ''MinimumRowSizes'' must consist of real, finite, numeric values.' )
176            end
177           
178            % Set and redraw
179            obj.MinimumRowSizes_ = value(:)';
180            obj.redraw();
181        end % set.MinimumRowSizes
182       
183        function value = get.MinimumRowSizes( obj )
184            value = obj.MinimumRowSizes_;
185        end % get.MinimumRowSizes
186               
187        function set.MinimumColumnSizes( obj, value )
188            % Check that this vector matches the size vector
189            if ~isequal( numel( obj.ColumnSizes ), numel( value ) )
190                error( 'GUILayout:InvalidPropertyValue', ...
191                    'Size of property ''MinimumColumnSizes'' must match size of property ''RowSizes''.' )
192            elseif ~isnumeric( value ) || ...
193                    any( ~isreal( value ) ) || any( isnan( value ) ) || any( ~isfinite( value ) )
194                error( 'GUILayout:InvalidPropertyValue', ...
195                    'Property ''MinimumColumnSizes'' must consist of real, finite, numeric values.' )
196            end
197           
198            % Set and redraw
199            obj.MinimumColumnSizes_ = value(:)';
200            obj.redraw();
201        end % set.MinimumColumnSizes
202       
203        function value = get.MinimumColumnSizes( obj )
204            value = obj.MinimumColumnSizes_;
205        end % get.MinimumColumnSizes
206       
207        function set.Padding( obj, value )
208            % Check
209            if ~isnumeric( value ) || ~isscalar( value ) || ...
210                    ~isreal( value ) || isnan( value ) || ~isfinite( value ) || ...
211                    value < 0 || rem( value, 1 ) ~= 0
212                error( 'GUILayout:InvalidPropertyValue', ...
213                    'Property ''Padding'' must be a nonnegative integer.' )
214            end
215           
216            % Set
217            obj.Padding = value;
218           
219            % Redraw
220            obj.redraw();
221        end % set.Padding
222       
223        function set.Spacing( obj, value )
224            % Check
225            if ~isnumeric( value ) || ~isscalar( value ) || ...
226                    ~isreal( value ) || isnan( value ) || ~isfinite( value ) || ...
227                    value < 0 || rem( value, 1 ) ~= 0
228                error( 'GUILayout:InvalidPropertyValue', ...
229                    'Property ''Spacing'' must be a nonnegative integer.' )
230            end
231           
232            % Set
233            obj.Spacing = value;
234           
235            % Redraw
236            obj.redraw();
237        end % set.Spacing
238       
239    end % accessor methods
240   
241    methods( Access = protected )
242       
243        function [widths,heights] = redraw( obj )
244            %REDRAW  Redraw container contents.
245           
246            % Get container width and height
247            totalPosition = ceil( getpixelposition( obj.UIContainer ) );
248            totalWidth = totalPosition(3);
249            totalHeight = totalPosition(4);
250           
251            % Get children
252            children = obj.Children;
253            nChildren = numel( children );
254           
255            % Get padding, spacing, widths and heights
256            padding = obj.Padding;
257            spacing = obj.Spacing;
258            columnSizes = obj.ColumnSizes;
259            minColumnSizes = obj.MinimumColumnSizes;
260            rowSizes = obj.RowSizes;
261            minRowSizes = obj.MinimumRowSizes;
262            nColumns = numel( columnSizes );
263            nRows = numel( rowSizes );
264           
265            % Compute widths and heights
266            widths = uiextras.calculatePixelSizes( totalWidth, ...
267                columnSizes, minColumnSizes, ...
268                obj.Padding, obj.Spacing );
269            heights = uiextras.calculatePixelSizes( totalHeight, ...
270                rowSizes, minRowSizes, ...
271                obj.Padding, obj.Spacing );
272           
273            % Compute and set new positions in pixels
274            elementNumbers = reshape( 1:nRows*nColumns, [nRows, nColumns] );
275            rowNumbers = repmat( transpose( 1:nRows ), [1, nColumns] );
276            columnNumbers = repmat( 1:nColumns, [nRows, 1] );
277            for ii = 1:nChildren
278                child = children(ii);
279                jj = rowNumbers(elementNumbers==ii); % row index
280                kk = columnNumbers(elementNumbers==ii); % column index
281                x = sum( widths(1:kk-1) ) + padding + spacing * (kk-1) + 1;
282                y = totalHeight - sum( heights(1:jj) ) - padding - spacing*(jj-1) + 1;
283                newPosition = [x, y, widths(kk), heights(jj)];   
284                obj.repositionChild( child, newPosition );
285            end
286           
287        end % redraw
288       
289        function onChildAdded( obj, source, eventData ) %#ok<INUSD>
290            %onChildAdded: Callback that fires when a child is added to a container.
291            % Add element to RowSizes, if required
292            if numel( obj.RowSizes_ ) == 0
293                obj.RowSizes_ = -1;
294                obj.MinimumRowSizes_ = 1;
295            end
296           
297            % Add element to ColumnSizes, if required
298            nColumns = ceil( numel( obj.Children ) / numel( obj.RowSizes_ ) );
299            if numel( obj.ColumnSizes_ ) < nColumns
300                obj.ColumnSizes_(end+1:nColumns,:) = -1;
301                obj.MinimumColumnSizes_(end+1:nColumns,:) = 1;
302            end
303           
304            obj.redraw();
305           
306        end % onChildAdded
307       
308        function onChildRemoved( obj, source, eventData ) %#ok<INUSD>
309            %onChildAdded: Callback that fires when a container child is destroyed or reparented.
310            if numel( obj.Children ) == 0
311                % Remove elements from RowSizes and ColumnSizes
312                obj.RowSizes_ = zeros( 0, 1 );
313                obj.ColumnSizes_ = zeros( 0, 1 );
314                obj.MinimumRowSizes_ = zeros( 0, 1 );
315                obj.MinimumColumnSizes_ = zeros( 0, 1 );
316            else
317                % Remove elements from ColumnSizes, if required
318                nColumns = ceil( numel( obj.Children ) / numel( obj.RowSizes_ ) );
319                if numel( obj.ColumnSizes_ ) > nColumns
320                    obj.ColumnSizes_(nColumns+1:end,:) = [];
321                    obj.MinimumColumnSizes_(nColumns+1:end,:) = [];
322                end
323            end
324           
325            % Redraw
326            obj.redraw();
327        end % onChildRemoved
328       
329    end % protected methods
330   
331end % classdef
Note: See TracBrowser for help on using the repository browser.