www.gusucode.com > mbcguitools 工具箱 matlab 源码程序 > mbcguitools/+mbcgui/+container/layoutpanel.m

    function P = layoutpanel(varargin)
%LAYOUTPANEL Construct a panel that has an associated layout.
%
%  P = LAYOUTPANEL(VARARGIN) constructs a uipanel that has additional
%  properties added to it.  All arguments to this function are passed on to
%  the panel constructor.
%
%  The additional properties will be:
%
%    LayoutComponent  : A component handle that will be resized so that its
%                       position matches the size of the panel.  This
%                       property may be set to either a component handle
%                       or to a single-element cell array that contains the
%                       component handle.  This second form allows Matlab
%                       to correctly dispatch the "set" to the uipanel
%                       property instead of the component set method.
%    LayoutBorder     : Border in pixels to apply between the
%                       LayoutComponent and the panel.  The border is
%                       specified as a 4-element vector that contains the
%                       [W S E N] border.
%
%  The panel will also have the following properties set to non-standard
%  values unless overridden by new values in the input list:
%
%    Units            : Set to 'pixels'
%    Position         : Set to [0 0 1 1]
%    BorderType       : Set to 'none'
%    HitTest          : Set to 'off'
%
%   Example:
%      pnl = mbcgui.container.layoutpanel(...
%                'Position', [20 20 300 200], ...
%                'BorderType', 'beveledin', ...
%                'LayoutBorder', [20 10 20 30]);
%      hEdit = uicontrol('Parent', pnl, ...
%                'Style', 'edit', ...
%                'String', 'Edit box');
%      hButton = uicontrol('Parent', pnl, ...
%                'Style', 'pushbutton', ...
%                'String', 'Button');
%      L = xreggridbaglayout(pnl, ...
%                'dimension', [1 2], ...
%                'colsizes', [-1 65], ...
%                'elements', {hEdit, hButton});
%      set(pnl, 'LayoutComponent', {L});

%   Copyright 2008-2013 The MathWorks, Inc.

% Pull out LayoutComponent/LayoutBorder from property list and set them
% later
LC = [];
LB = [0 0 0 0];
LCidx = find(strcmpi('LayoutComponent',varargin),1,'last');
if ~isempty(LCidx)
    LC = varargin{LCidx+1};
    varargin([LCidx LCidx+1]) = [];
end

LBidx = find(strcmpi('LayoutBorder',varargin),1,'last');
if ~isempty(LBidx)
    LB = varargin{LBidx+1};
    varargin([LBidx LBidx+1]) = [];
end

P = uipanel(...
    'Units', 'pixels', ...
    'Position', [0 0 1 1], ...
    'BorderType', 'none', ...
    'HitTest', 'off', ...
    varargin{:});

fHandles = manageLayoutPanel(P);
% Component that is resized with the layout
mbcgui.hgclassesutil.addprop(P, 'LayoutComponent','SetMethod',fHandles.setLayout);

% Border to apply between the panel edge and the component.  This is a
% vector of pixel widths to apply to the [top, right, bottom, left] edges.
mbcgui.hgclassesutil.addprop(P, 'LayoutBorder','SetMethod',fHandles.setBorder);

mbcgui.hgclassesutil.addprop(P, 'MotionManagerStore', 'Hidden', true);
mbcgui.hgclassesutil.addprop(P, 'ControlHook', 'Hidden', true);


% Set the component and border if they have been provided
if ~isempty(LB)
    set(P, 'LayoutBorder', LB);
end
if ~isempty(LC)
    set(P, 'LayoutComponent', {LC});
end

% Add a listener to the panel resize to update the layout
addlistener(P, 'SizeChanged', fHandles.setPosition);

% Add a destruction listener to destroy the contained layout
addlistener(P, 'ObjectBeingDestroyed', fHandles.deleteLayout);

addlistener(P, 'Visible', 'PostSet', fHandles.setVisible);


end


function fHandles = manageLayoutPanel(Panel)
%manageLayoutPanel nested function to manage positionin,visibility and border of inner layout 
LayoutComponent = [];
LayoutBorder = [];

fHandles.setLayout = @iSetLayout;
fHandles.setPosition = @iSetLayoutPosition;
fHandles.setBorder = @iSetBorder;
fHandles.deleteLayout = @iDestroyLayout;
fHandles.setVisible = @iSetVisible;

    function iSetLayout(P, Layout)
    % Layout must be an object or empty
    
    % Also accept a cell array - this insulates us from set-dispatch problems
    if iscell(Layout)
        Layout = Layout{1};
    end
    
    if ~(mbcgui.util.isComponentHandle(Layout) || isempty(Layout))
        error(message('mbc:mbcgui:container:layoutpanel:InvalidPropertyValue'))
    end
    P.LayoutComponent = Layout;
    LayoutComponent = Layout;
    iSetLayoutPosition(P);
    end


    function iSetBorder(~, Border)
    % Border must be a 1x4 vector or empty
    BorderOK = isempty(Border) ...
        || (isnumeric(Border) && ismatrix(Border) && all(size(Border)==[1 4]) && all(Border>=0));
    
    if ~BorderOK
        error(message('mbc:mbcgui:container:layoutpanel:InvalidPropertyValue1'))
    end
    if ~isequal(Border, LayoutBorder)
        Panel.LayoutBorder = Border;
        LayoutBorder = Border;
        iSetLayoutPosition(Panel);
    end
    end


    function iSetLayoutPosition(~, ~)
    L = LayoutComponent;
    if ~isempty(L)
        if ~strcmp(Panel.Units,'pixels')
            pos = getpixelposition(Panel);
        else
            pos= Panel.Position;
        end
        panelpos = pos;
        pos(1:2) = 1;
        
        % Adjust for the pixels lost due to the border decoration and title
        [W, titleW] = mbcgui.util.getPanelBorderWidth(Panel);
        pos(3:4) = pos(3:4)-2*W;
        pos(4) = pos(4) - titleW;
        
        B = LayoutBorder;
        if ~isempty(B)
            pos = pos + [B(1) B(2) -(B(1)+B(3)) -(B(2)+B(4))];
        end
        
        pos = mbcgui.util.clipRect(pos, [1 1 panelpos(3:4)]);
        set(L, 'Position', pos);
    end
    
    end


    function iDestroyLayout(~, ~)
    L = LayoutComponent;
    if mbcgui.util.isComponentHandle(L) && ~isgraphics(L)
        delete(L);
    end
    end

%--------------------------------------------------------------------------
%  Functions that help patch up visible setting for java
    function iSetVisible(~, ~)
    component = LayoutComponent;
    VisVal = Panel.Visible;
    if ~isempty(component)
        set(component, 'Visible',VisVal);
    end
    
    end

end