classdef BoxPanel < uix.Panel & uix.mixin.Panel
%uix.BoxPanel Box panel
%
% p = uix.BoxPanel(p1,v1,p2,v2,...) constructs a box panel and sets
% parameter p1 to value v1, etc.
%
% A box panel is a decorated container with a title box, border, and
% buttons to dock and undock, minimize, get help, and close. A box
% panel shows one of its contents and hides the others.
%
% See also: uix.Panel, uipanel, uix.CardPanel
% Copyright 2009-2016 The MathWorks, Inc.
% $Revision: 1599 $ $Date: 2018-04-07 07:15:03 +1000 (Sat, 07 Apr 2018) $
properties( Dependent )
TitleColor % title background color [RGB]
Minimized % minimized [true|false]
MinimizeFcn % minimize callback
Docked % docked [true|false]
DockFcn % dock callback
HelpFcn % help callback
CloseRequestFcn % close request callback
end
properties( Dependent, SetAccess = private )
TitleHeight % title panel height [pixels]
end
properties( Access = private )
TitleBox % title bar box
TitleText % title text label
EmptyTitle = '' % title when empty, [] otherwise
TitleAccess = 'public' % 'private' when getting or setting Title, 'public' otherwise
TitleHeight_ = -1 % cache of title text height (-1 denotes stale cache)
MinimizeButton % title button
DockButton % title button
HelpButton % title button
CloseButton % title button
Docked_ = true % backing for Docked
Minimized_ = false % backing for Minimized
end
properties( Constant, Access = private )
NullTitle = char.empty( [2 0] ) % an obscure empty string, the actual panel Title
BlankTitle = ' ' % a non-empty blank string, the empty uicontrol String
end
properties
MaximizeTooltipString = 'Expand this panel' % tooltip string
MinimizeTooltipString = 'Collapse this panel' % tooltip string
UndockTooltipString = 'Undock this panel' % tooltip string
DockTooltipString = 'Dock this panel' % tooltip string
HelpTooltipString = 'Get help on this panel' % tooltip string
CloseTooltipString = 'Close this panel' % tooltip string
end
methods
function obj = BoxPanel( varargin )
%uix.BoxPanel Box panel constructor
%
% p = uix.BoxPanel() constructs a box panel.
%
% p = uix.BoxPanel(p1,v1,p2,v2,...) sets parameter p1 to value
% v1, etc.
% Define default colors
foregroundColor = [1 1 1];
backgroundColor = [0.05 0.25 0.5];
% Set default colors
obj.ForegroundColor = foregroundColor;
% Create panels and decorations
titleBox = uix.HBox( 'Internal', true, 'Parent', obj, ...
'Units', 'pixels', 'BackgroundColor', backgroundColor );
titleText = uix.Text( 'Parent', titleBox, ...
'ForegroundColor', foregroundColor, ...
'BackgroundColor', backgroundColor, ...
'String', obj.BlankTitle, 'HorizontalAlignment', 'left' );
% Create buttons
minimizeButton = uix.Text( ...
'ForegroundColor', foregroundColor, ...
'BackgroundColor', backgroundColor, ...
'FontWeight', 'bold', 'Enable', 'on' );
dockButton = uix.Text( ...
'ForegroundColor', foregroundColor, ...
'BackgroundColor', backgroundColor, ...
'FontWeight', 'bold', 'Enable', 'on' );
helpButton = uix.Text( ...
'ForegroundColor', foregroundColor, ...
'BackgroundColor', backgroundColor, ...
'FontWeight', 'bold', 'String', '?', ...
'TooltipString', obj.HelpTooltipString, 'Enable', 'on' );
closeButton = uix.Text( ...
'ForegroundColor', foregroundColor, ...
'BackgroundColor', backgroundColor, ...
'FontWeight', 'bold', 'String', char( 215 ), ...
'TooltipString', obj.CloseTooltipString, 'Enable', 'on' );
% Store properties
obj.Title = obj.NullTitle;
obj.TitleBox = titleBox;
obj.TitleText = titleText;
obj.MinimizeButton = minimizeButton;
obj.DockButton = dockButton;
obj.HelpButton = helpButton;
obj.CloseButton = closeButton;
% Create listeners
addlistener( obj, 'BorderWidth', 'PostSet', ...
@obj.onBorderWidthChanged );
addlistener( obj, 'BorderType', 'PostSet', ...
@obj.onBorderTypeChanged );
addlistener( obj, 'FontAngle', 'PostSet', ...
@obj.onFontAngleChanged );
addlistener( obj, 'FontName', 'PostSet', ...
@obj.onFontNameChanged );
addlistener( obj, 'FontSize', 'PostSet', ...
@obj.onFontSizeChanged );
addlistener( obj, 'FontUnits', 'PostSet', ...
@obj.onFontUnitsChanged );
addlistener( obj, 'FontWeight', 'PostSet', ...
@obj.onFontWeightChanged );
addlistener( obj, 'ForegroundColor', 'PostSet', ...
@obj.onForegroundColorChanged );
addlistener( obj, 'Title', 'PreGet', ...
@obj.onTitleReturning );
addlistener( obj, 'Title', 'PostGet', ...
@obj.onTitleReturned );
addlistener( obj, 'Title', 'PostSet', ...
@obj.onTitleChanged );
% Draw buttons
obj.redrawButtons()
% Set properties
try
uix.set( obj, varargin{:} )
catch e
delete( obj )
e.throwAsCaller()
end
end % constructor
end % structors
methods
function value = get.TitleColor( obj )
value = obj.TitleBox.BackgroundColor;
end % get.TitleColor
function set.TitleColor( obj, value )
% Set
obj.TitleBox.BackgroundColor = value;
obj.TitleText.BackgroundColor = value;
obj.MinimizeButton.BackgroundColor = value;
obj.DockButton.BackgroundColor = value;
obj.HelpButton.BackgroundColor = value;
obj.CloseButton.BackgroundColor = value;
end % set.TitleColor
function value = get.CloseRequestFcn( obj )
value = obj.CloseButton.Callback;
end % get.CloseRequestFcn
function set.CloseRequestFcn( obj, value )
% Set
obj.CloseButton.Callback = value;
% Mark as dirty
obj.redrawButtons()
end % set.CloseRequestFcn
function value = get.DockFcn( obj )
value = obj.DockButton.Callback;
end % get.DockFcn
function set.DockFcn( obj, value )
% Set
obj.DockButton.Callback = value;
% Mark as dirty
obj.redrawButtons()
end % set.DockFcn
function value = get.HelpFcn( obj )
value = obj.HelpButton.Callback;
end % get.HelpFcn
function set.HelpFcn( obj, value )
% Set
obj.HelpButton.Callback = value;
% Mark as dirty
obj.redrawButtons()
end % set.HelpFcn
function value = get.MinimizeFcn( obj )
value = obj.MinimizeButton.Callback;
end % get.MinimizeFcn
function set.MinimizeFcn( obj, value )
% Set
obj.MinimizeButton.Callback = value;
obj.TitleText.Callback = value;
if isempty( value )
obj.TitleText.Enable = 'inactive';
else
obj.TitleText.Enable = 'on';
end
% Mark as dirty
obj.redrawButtons()
end % set.MinimizeFcn
function value = get.Docked( obj )
value = obj.Docked_;
end % get.Docked
function set.Docked( obj, value )
% Check
assert( islogical( value ) && isequal( size( value ), [1 1] ), ...
'uix:InvalidPropertyValue', ...
'Property ''Docked'' must be true or false.' )
% Set
obj.Docked_ = value;
% Mark as dirty
obj.redrawButtons()
end % set.Docked
function value = get.Minimized( obj )
value = obj.Minimized_;
end % get.Minimized
function set.Minimized( obj, value )
% Check
assert( islogical( value ) && isequal( size( value ), [1 1] ), ...
'uix:InvalidPropertyValue', ...
'Property ''Minimized'' must be true or false.' )
% Set
obj.Minimized_ = value;
% Show selected child
obj.showSelection()
% Mark as dirty
obj.Dirty = true;
end % set.Minimized
function value = get.TitleHeight( obj )
value = obj.TitleBox.Position(4);
end % get.TitleHeight
function set.MaximizeTooltipString( obj, value )
% Check
assert( ischar( value ), ...
'uix:InvalidPropertyValue', ...
'Property ''MaximizeTooltipString'' must be a string.' )
% Set
obj.MaximizeTooltipString = value;
% Mark as dirty
obj.redrawButtons()
end % set.MaximizeTooltipString
function set.MinimizeTooltipString( obj, value )
% Check
assert( ischar( value ), ...
'uix:InvalidPropertyValue', ...
'Property ''MinimizeTooltipString'' must be a string.' )
% Set
obj.MinimizeTooltipString = value;
% Mark as dirty
obj.redrawButtons()
end % set.MinimizeTooltipString
function set.UndockTooltipString( obj, value )
% Check
assert( ischar( value ), ...
'uix:InvalidPropertyValue', ...
'Property ''UndockTooltipString'' must be a string.' )
% Set
obj.UndockTooltipString = value;
% Mark as dirty
obj.redrawButtons()
end % set.UndockTooltipString
function set.DockTooltipString( obj, value )
% Check
assert( ischar( value ), ...
'uix:InvalidPropertyValue', ...
'Property ''DockTooltipString'' must be a string.' )
% Set
obj.DockTooltipString = value;
% Mark as dirty
obj.redrawButtons()
end % set.DockTooltipString
function set.HelpTooltipString( obj, value )
% Check
assert( ischar( value ), ...
'uix:InvalidPropertyValue', ...
'Property ''HelpTooltipString'' must be a string.' )
% Set
obj.HelpTooltipString = value;
% Mark as dirty
obj.redrawButtons()
end % set.HelpTooltipString
function set.CloseTooltipString( obj, value )
% assert that value is a char array
assert( ischar( value ), ...
'uix:InvalidPropertyValue', ...
'Property ''CloseTooltipString'' must be a string.' )
obj.CloseTooltipString = value;
% Mark as dirty
obj.redrawButtons()
end % set.CloseTooltipString
end % accessors
methods( Access = private )
function onBorderWidthChanged( obj, ~, ~ )
% Mark as dirty
obj.Dirty = true;
end % onBorderWidthChanged
function onBorderTypeChanged( obj, ~, ~ )
% Mark as dirty
obj.Dirty = true;
end % onBorderTypeChanged
function onFontAngleChanged( obj, ~, ~ )
obj.TitleText.FontAngle = obj.FontAngle;
end % onFontAngleChanged
function onFontNameChanged( obj, ~, ~ )
% Set
obj.TitleText.FontName = obj.FontName;
% Mark as dirty
obj.TitleHeight_ = -1;
obj.Dirty = true;
end % onFontNameChanged
function onFontSizeChanged( obj, ~, ~ )
% Set
fontSize = obj.FontSize;
obj.TitleText.FontSize = fontSize;
obj.HelpButton.FontSize = fontSize;
obj.CloseButton.FontSize = fontSize;
obj.DockButton.FontSize = fontSize;
obj.MinimizeButton.FontSize = fontSize;
% Mark as dirty
obj.TitleHeight_ = -1;
obj.Dirty = true;
end % onFontSizeChanged
function onFontUnitsChanged( obj, ~, ~ )
fontUnits = obj.FontUnits;
obj.TitleText.FontUnits = fontUnits;
obj.HelpButton.FontUnits = fontUnits;
obj.CloseButton.FontUnits = fontUnits;
obj.DockButton.FontUnits = fontUnits;
obj.MinimizeButton.FontUnits = fontUnits;
end % onFontUnitsChanged
function onFontWeightChanged( obj, ~, ~ )
obj.TitleText.FontWeight = obj.FontWeight;
end % onFontWeightChanged
function onForegroundColorChanged( obj, ~, ~ )
foregroundColor = obj.ForegroundColor;
obj.TitleText.ForegroundColor = foregroundColor;
obj.MinimizeButton.ForegroundColor = foregroundColor;
obj.DockButton.ForegroundColor = foregroundColor;
obj.HelpButton.ForegroundColor = foregroundColor;
obj.CloseButton.ForegroundColor = foregroundColor;
end % onForegroundColorChanged
function onTitleReturning( obj, ~, ~ )
if strcmp( obj.TitleAccess, 'public' )
obj.TitleAccess = 'private'; % start
if ischar( obj.EmptyTitle )
obj.Title = obj.EmptyTitle;
else
obj.Title = obj.TitleText.String;
end
end
end % onTitleReturning
function onTitleReturned( obj, ~, ~ )
obj.Title = obj.NullTitle; % unset Title
obj.TitleAccess = 'public'; % finish
end % onTitleReturned
function onTitleChanged( obj, ~, ~ )
if strcmp( obj.TitleAccess, 'public' )
% Set
obj.TitleAccess = 'private'; % start
title = obj.Title;
if isempty( title )
obj.EmptyTitle = title; % store
obj.TitleText.String = obj.BlankTitle; % set String to blank
else
obj.EmptyTitle = []; % not empty
obj.TitleText.String = title; % set String to title
end
obj.Title = obj.NullTitle; % unset Title
obj.TitleAccess = 'public'; % finish
% Mark as dirty
obj.TitleHeight_ = -1;
obj.Dirty = true;
end
end % onTitleChanged
end % property event handlers
methods( Access = protected )
function redraw( obj )
%redraw Redraw
%
% p.redraw() redraws the panel.
%
% See also: redrawButtons
% Compute positions
bounds = hgconvertunits( ancestor( obj, 'figure' ), ...
[0 0 1 1], 'normalized', 'pixels', obj );
tX = 1;
tW = max( bounds(3), 1 );
tH = obj.TitleHeight_; % title height
if tH == -1 % cache stale, refresh
tH = ceil( obj.TitleText.Extent(4) );
obj.TitleHeight_ = tH; % store
end
tY = 1 + bounds(4) - tH;
p = obj.Padding_;
cX = 1 + p;
cW = max( bounds(3) - 2 * p, 1 );
cH = max( bounds(4) - tH - 2 * p, 1 );
cY = tY - p - cH;
contentsPosition = [cX cY cW cH];
% Redraw contents
selection = obj.Selection_;
if selection ~= 0
uix.setPosition( obj.Contents_(selection), contentsPosition, 'pixels' )
end
obj.TitleBox.Position = [tX tY tW tH];
obj.redrawButtons()
end % redraw
function showSelection( obj )
%showSelection Show selected child, hide the others
%
% c.showSelection() shows the selected child of the container
% c, and hides the others.
% Call superclass method
showSelection@uix.mixin.Panel( obj )
% If minimized, hide selected contents too
selection = obj.Selection_;
if selection ~= 0 && obj.Minimized_
child = obj.Contents_(selection);
child.Visible = 'off';
if isa( child, 'matlab.graphics.axis.Axes' )
child.ContentsVisible = 'off';
end
% As a remedy for g1100294, move off-screen too
margin = 1000;
if isa( child, 'matlab.graphics.axis.Axes' ) ...
&& strcmp(child.ActivePositionProperty, 'outerposition' )
child.OuterPosition(1) = -child.OuterPosition(3)-margin;
else
child.Position(1) = -child.Position(3)-margin;
end
end
end % showSelection
end % template methods
methods( Access = private )
function redrawButtons( obj )
%redrawButtons Redraw buttons
%
% p.redrawButtons() redraws the titlebar buttons.
%
% Buttons use unicode arrow symbols:
% https://en.wikipedia.org/wiki/Arrow_%28symbol%29#Arrows_in_Unicode
% Retrieve button box and buttons
box = obj.TitleBox;
titleText = obj.TitleText;
minimizeButton = obj.MinimizeButton;
dockButton = obj.DockButton;
helpButton = obj.HelpButton;
closeButton = obj.CloseButton;
% Detach all buttons
titleText.Parent = [];
minimizeButton.Parent = [];
dockButton.Parent = [];
helpButton.Parent = [];
closeButton.Parent = [];
% Attach active buttons
titleText.Parent = box;
minimize = ~isempty( obj.MinimizeFcn );
if minimize
minimizeButton.Parent = box;
box.Widths(end) = minimizeButton.Extent(3);
end
dock = ~isempty( obj.DockFcn );
if dock
dockButton.Parent = box;
box.Widths(end) = dockButton.Extent(3);
end
help = ~isempty( obj.HelpFcn );
if help
helpButton.Parent = box;
helpButton.TooltipString = obj.HelpTooltipString;
box.Widths(end) = helpButton.Extent(3);
end
close = ~isempty( obj.CloseRequestFcn );
if close
closeButton.Parent = box;
closeButton.TooltipString = obj.CloseTooltipString;
box.Widths(end) = closeButton.Extent(3);
end
% Update icons
if obj.Minimized_
minimizeButton.String = char( 9662 );
minimizeButton.TooltipString = obj.MaximizeTooltipString;
else
minimizeButton.String = char( 9652 );
minimizeButton.TooltipString = obj.MinimizeTooltipString;
end
if obj.Docked_
dockButton.String = char( 8599 );
dockButton.TooltipString = obj.UndockTooltipString;
else
dockButton.String = char( 8600 );
dockButton.TooltipString = obj.DockTooltipString;
end
end % redrawButtons
end % helper methods
end % classdef