Code covered by the BSD License  

Highlights from
A figure with sliders

image thumbnail
from A figure with sliders by Emmanuel Farhi
Creates or adds sliders to a figure

f=figureslider(varargin)
function f=figureslider(varargin)
% FIGURESLIDER creates by itself a new figure with horizontal and vertical sliders
% and returns its handle. Sliders are hidden if all objects are shown in the figure.
% When the figure gets smaller than the enclosed object set, sliders may be used to 
% shift the figure view.
%
% FIGURESLIDER(H) adds sliders to an existing window.
%
% FIGURESLIDER works the same as FIGURE. You may use GET(H) to obtain properties 
% of the figure.
%
% Example: figureslider('Name','Figure with sliders', 'ToolBar','figure')
%
% See also: figure

% Author: E. Farhi <farhi@ill.fr>. Version $Revision: 1.4 $. Dec 15, 2008

  % create figure if none specified
  if isempty(varargin)
    hfig.handle=figure;
  else
    if nargin == 2 && strcmp(varargin{2}, 'resize')
      callback_resize(varargin{1}, [], []);
      return;
    else
      if isnumeric(varargin{1})
        hfig.handle=figure(varargin{1});
        set(hfig.handle,varargin{2:end});
      else
        hfig.handle=figure(varargin{:}); 
      end
    end
  end

  % check if there are already sliders and get their handles
  hfig.slider_h = findobj(hfig.handle,'Tag','Slider_h');
  hfig.slider_v = findobj(hfig.handle,'Tag','Slider_v');
  hfig.center   = findobj(hfig.handle,'Tag','Center');
  hfig.units    = get(hfig.handle, 'Units');
  hfig.sliderwidth=20;

  set(hfig.handle, 'Units','pixels');
  hfig.position  =get(hfig.handle,'Position');
  % horizontal slider
  if isempty(hfig.slider_h)
    hfig.slider_h = uicontrol(hfig.handle,'Style','slider',...
                 'Tag','Slider_h', ...
                 'Position', [1 1 ...
                    hfig.position(3)-hfig.sliderwidth hfig.sliderwidth], ...
                 'Max',100,'Min',0,'Value',50,...
                 'SliderStep',[0.05 0.2],...
                 'UserData',50, ...
                 'Callback',@callback_slider_h);
  end

  % vertical slider
  if isempty(hfig.slider_v)
    hfig.slider_v = uicontrol(hfig.handle,'Style','slider',...
                 'Tag','Slider_v', ...
                 'Position', ... 
                 [hfig.position(3)-hfig.sliderwidth hfig.sliderwidth ...
                   hfig.sliderwidth hfig.position(4)-hfig.sliderwidth], ...
                 'Max',100,'Min',0,'Value',50,...
                 'SliderStep',[0.05 0.2],...
                 'UserData',50, ...
                 'Callback',@callback_slider_v);
  end
  % add a button on lower right size, in between sliders for centering
  if isempty(hfig.center)
    hfig.center = uicontrol(hfig.handle,'Style','pushbutton',...
                 'Tag','Center', ...
                 'Position', ... 
                 [hfig.position(3)-hfig.sliderwidth 1 ...
                   hfig.sliderwidth hfig.sliderwidth], ....
                 'ToolTip','Click here to center figure contents', ...
                 'Callback',@callback_center);
  end

  % set resize callback so that sliders may be hidden/shown 
  % depending on size of inner objects to show
  resizeFcn = get(hfig.handle, 'ResizeFcn');
  if ~isempty(resizeFcn)
    if isempty(findstr(char(resizeFcn), 'figureslider(gcf, ''resize'');'))
      set(hfig.handle, 'ResizeFcn', [  'figureslider(gcf, ''resize''); ; ' char(resizeFcn) ';' ]);
    end
  else
    set(hfig.handle, 'ResizeFcn', 'figureslider(gcf, ''resize'');');
  end

  callback_resize(hfig.handle);  % setup sliders

  % restore initial figure Unit settings
  set(hfig.handle, 'Units', hfig.units);
  
  f=hfig.handle;

% ========== private functions ================================================
function callback_center(hObject, eventdata, handles)
% center figure on enclosing objects
  hfig.handle   = gcf;
  hfig.slider_h = findobj(hfig.handle,'Tag','Slider_h');
  hfig.slider_v = findobj(hfig.handle,'Tag','Slider_v');
  if ~isempty(hfig.slider_h), 
    set(hfig.slider_h, 'Value',50); 
    callback_slider_h(hfig.slider_h);
  end
  if ~isempty(hfig.slider_v), 
    set(hfig.slider_v, 'Value',50);
    callback_slider_v(hfig.slider_v);
  end
  
function callback_slider(hObject, eventdata, handles, type)
  % move enclosing objects if not in units=nomalized 
  hfig.handle   = gcf;
  hfig.children = get(hfig.handle, 'Children');
  hfig.units    = get(hfig.handle, 'Units');
  hfig.slider_h = findobj(hfig.handle,'Tag','Slider_h');
  hfig.slider_v = findobj(hfig.handle,'Tag','Slider_v');
  hfig.center   = findobj(hfig.handle,'Tag','Center');
  set(hfig.handle, 'Units','pixels');
  extension = callback_getchildrenextension(hfig.handle);
  
  for index=1:length(hfig.children)
    this.handle = hfig.children(index);
    try
      this.pos    = get(hfig.children(index), 'Position');
    catch
      continue; % object has no Position
    end
    try
      this.units  = get(hfig.children(index), 'Units');
    catch
      continue;
    end
    % skip sliders
    if isempty(this.units) | length(this.pos) < 4 | this.handle == hfig.slider_h | this.handle == hfig.slider_v | this.handle == hfig.center
      continue; 
    end
    if strcmp(this.units,'normalized') | strcmp(get(this.handle, 'Tag'), 'Slider_h') | strcmp(get(this.handle, 'Tag'), 'Slider_v') | strcmp(get(this.handle, 'Tag'), 'Center') 
      continue; 
    else set(hfig.children(index), 'Units', 'pixels');
    end
    if type == 'h'
      step = [ extension(3)*(get(hObject,'Value')-get(hObject,'UserData'))/100 0 0 0 ];
    elseif type == 'v'
      step = [ 0 extension(4)*(get(hObject,'Value')-get(hObject,'UserData'))/100 0 0 ];
    end
    set(hfig.children(index), 'Position', this.pos-step);
    set(hfig.children(index), 'Units', this.units);
  end % for
  set(hObject,'UserData', get(hObject,'Value'));
  
  set(hfig.handle, 'Units', hfig.units);

function callback_slider_h(varargin)
  varargin{4} = 'h';
  callback_slider(varargin{:});

function callback_slider_v(varargin)
  varargin{4} = 'v';
  callback_slider(varargin{:});

function callback_resize(hObject, eventdata, handles)
  hfig.handle   = hObject;
  hfig.units    = get(hfig.handle, 'Units');
  set(hfig.handle, 'Units','pixels');
  hfig.position = get(hfig.handle,'Position');
  hfig.slider_h = findobj(hfig.handle,'Tag','Slider_h');
  hfig.slider_v = findobj(hfig.handle,'Tag','Slider_v');
  hfig.center   = findobj(hfig.handle,'Tag','Center');

  hfig.sliderwidth=20;

  % move sliders at figure edges
  if ~isempty(hfig.slider_h), 
    set(hfig.slider_h, 'Position', ...
      [1 1 ...
       hfig.position(3)-hfig.sliderwidth hfig.sliderwidth]);
  end
  if ~isempty(hfig.slider_v), 
    set(hfig.slider_v, 'Position', ... 
      [hfig.position(3)-hfig.sliderwidth hfig.sliderwidth ...
       hfig.sliderwidth hfig.position(4)-hfig.sliderwidth]);
  end
  set(hfig.center, 'Position', ... 
    [hfig.position(3)-hfig.sliderwidth 1 ...
     hfig.sliderwidth hfig.sliderwidth]);

  % hide or show sliders, depending on size of uipanel vs. figure
  extension = callback_getchildrenextension(hfig.handle);

  if ~isempty(hfig.slider_h), 
    if extension(3) <= hfig.position(3)
      set(hfig.slider_h, 'Visible','off');
    else
      set(hfig.slider_h, 'Visible','on');
    end
  end

  if ~isempty(hfig.slider_v), 
    if extension(4) <= hfig.position(4)
      set(hfig.slider_v, 'Visible','off');
    else
      set(hfig.slider_v, 'Visible','on');
    end
  end
  
  if extension(3) <= hfig.position(3) & extension(4) <= hfig.position(4)
    set(hfig.center, 'Visible','off');
  else
    set(hfig.center, 'Visible','on');
  end

  set(hfig.handle, 'Units', hfig.units);

function extension=callback_getchildrenextension(hObject, eventdata, handles)
% compute the total extension on enclosed objects
  hfig.handle   = hObject;
  hfig.units    = get(hfig.handle, 'Units');
  set(hfig.handle, 'Units','pixels');
  hfig.children = get(hfig.handle, 'Children');
  hfig.slider_h = findobj(hfig.handle,'Tag','Slider_h');
  hfig.slider_v = findobj(hfig.handle,'Tag','Slider_v');
  hfig.center   = findobj(hfig.handle,'Tag','Center');

  min_x=Inf; d_x=-Inf; min_y=Inf; d_y=-Inf;
  for index=1:length(hfig.children)
    this.handle = hfig.children(index);
    try
      this.pos    = get(hfig.children(index), 'Position');
    catch
      continue; % object has no Position
    end
    try
        this.units  = get(hfig.children(index), 'Units');
    catch
        this.units  = [];
    end
    % skip sliders
    if isempty(this.units) | this.handle == hfig.slider_h | this.handle == hfig.slider_v | this.handle == hfig.center
      continue; 
    end
    if strcmp(this.units, 'normalized'), continue;
    else set(hfig.children(index), 'Units', 'pixels');
    end
    % get extension of children
    min_x = min(this.pos(1), min_x);        % origin of object
    min_y = min(this.pos(2), min_y);
    d_x   = max(this.pos(1)+this.pos(3), d_x);  % maximum extension of object
    d_y   = max(this.pos(2)+this.pos(4), d_y);
    set(hfig.children(index), 'Units', this.units);
  end

  extension = [ min_x min_y d_x-min_x d_y-min_y ];

  set(hfig.handle, 'Units', hfig.units);

Contact us at files@mathworks.com