Code covered by the BSD License  

Highlights from
Viewer3D

image thumbnail

Viewer3D

by

 

04 Nov 2008 (Updated )

MIP, Color, Slice and Shaded 3D (shearwarp) Volume Rendering, interactive 3D view/measurement GUI

menubar(varargin)
function menubar(varargin)
% This function MenuBar, allows the user to create menu's anywhere in a figure
% it replaces UIcontextmenu of UIpanels by real menu bars.
%
%   menubar(figure_handle)    or          menubar
%
% Mouse hover, and window-resize updates can be enabled by
%  
%   menubar('start',figure_handle)   or      menubar('start')
%
% Or alternatively by:
%
%   set(figure_handle,'ResizeFcn','menubar(''ResizeFcn'',gcf)');
%   set(figure_handle,'WindowButtonMotionFcn','menubar(''MotionFcn'',gcf)');
%
% Example,
%
%  % Creat figure with uipanel
%  figure,
%  uipanel1 = uipanel('Units','Pixels','Position',[10 200 400 200]);
%  
%  % Attach a contextmenu (right-mouse button menu)
%  menu_panel1=uicontextmenu;
%  set(uipanel1,'UIContextMenu',menu_panel1);
%
%  % Add menu-items to the context menu
%   hchild=uimenu(menu_panel1, 'Label', 'Random Pixels');
%   uimenu(hchild, 'Label', 'Red','Callback','disp(''Red callback'')');
%   uimenu(hchild, 'Label', 'Blue','Callback','disp(''Blue callback'')');
%
%  % Make form the context menu a real menubar
%   menubar
%   
%  % Add some other menu-buttons
%   hchild=uimenu(menu_panel1, 'Label', 'Clear','Callback','disp(''Clear'')');
%   hchild=uimenu(menu_panel1, 'Label', 'Help');
%   uimenu(hchild, 'Label', 'Info','Callback','disp(''Info callback'')');
%
%  % Update the menubar
%   menubar
%
%  % Enable the mouse over and resize effects
%   menubar('start');
%
% Function is written by D.Kroon University of Twente (December 2010)

% Get Figure Handle
figure_handle=gcf; 
if(nargin>0)
	if(isnumeric(varargin{1})), figure_handle=varargin{1}; end
    if(nargin==2), figure_handle=varargin{2}; end
    if(ischar(varargin{1}))
        switch lower(varargin{1})
            case 'resizefcn'
                menubar_ResizeFcn(figure_handle);
            case 'motionfcn'
                menubar_MotionFcn(figure_handle);
            case 'start'
                renewtimer(figure_handle);
        end
        return
    end
end

% There must be Motion Function otherwise the cursorpostion
% in the axis is not updated.
if(isempty(get(figure_handle,'WindowButtonMotionFcn')))
    set(figure_handle,'WindowButtonMotionFcn',@menubar_DummyFcn);
end

% Get the Children of the Figure which are UIpanels
C=get(figure_handle,'Children');
D=false(size(C));
for i=1:length(C), D(i)=strcmpi(get(C(i),'Type'),'uipanel'); end
C=C(D);

% Copy UIContextMenu of uipanels to real menubars
for i=1:length(C)
    % If the panel has a UIContextMenu it is processed    
    uimenuhandle=get(C(i),'UIContextMenu');
    if(isempty(uimenuhandle)||(~ishandle(uimenuhandle))), continue; end
    datahandle=C(i);
    UpdateMenu(datahandle,figure_handle);
end

figuredata.uipanels=C;
setMyData(figuredata,figure_handle)

function renewtimer(figure_handle)
figuredata=getMyData(figure_handle); if(isempty(figuredata)),return; end
if(isfield(figuredata,'timer'))
    stop(figuredata.timer); delete(figuredata.timer);
end
figuredata.timer = timer('TimerFcn',@(x,y)menubar_Timer(x,y,figure_handle), 'Period', 0.2,'ExecutionMode','fixedSpacing');

% Start the event-timer
start(figuredata.timer);
               
setMyData(figuredata,figure_handle);


function m=AddChildren(h,Properties)
% This function will create a Matlab Structure from the UICContextMenu
%
% The structure looks like :
% m(1).Label='File';
% m(1).Children(1).Label='New';
% m(1).Children(1).Children(1).Label='Script';
% m(1).Children(1).Children(2).Label='Function';
% m(1).Children(1).Children(2).Separator='on';
% m(1).Children(1).Children(3).Label='Class';
% m(1).Children(1).Children(3).Callback='disp(''callback'')';
% m(1).Children(2).Label='Open';
% m(1).Children(3).Label='Close';
% m(2).Label='Edit';
% m(2).Callback='disp(''callback'')';
% m(3).Label='View';
% m(4).Label='Insert';
%
m=struct;
% Get all children (menu-items) of the handle
hc=get(h,'Children');
% Sort the children by their tag position (menu-items)
p=zeros(1,length(hc)); 
for i=1:length(hc), p(i)=get(hc(i),'Position'); end; 
[t,i]=sort(p);
% Add the menu-item to the structure
hc=hc(i);
for i=1:length(hc)
    for j=1:length(Properties)
    m(i).(Properties{j})=get(hc(i),Properties{j});
    end
    % If the menu-item has also children (sub-menus), then use the current
    % function recursivly to get all sub-(sub)-(sub)-menus.
    C=get(hc(i),'Children');
    if(~isempty(C)), m(i).Children=AddChildren(hc(i),Properties); end
end

function CreatMenuBar(uimenuhandle,datahandle,Pos,figure_handle)
% Properties (Writeable) of a menu-item
Properties={'Label','Callback','Separator','Checked','Enable','ForegroundColor','Position','ButtonDownFcn','Selected','SelectionHighlight','Visible','UserData'};

% This will create a Matlab Structure from the UICContextMenu
data.menuitems=AddChildren(uimenuhandle,Properties);

% This variable will store the selected-menu button
data.sel=[];

% Store the handle to the current figure
data.figure_handle=figure_handle;

% This variable will store the menu button beneath the mouse 
% used for hover-animation
data.hov=[];

% Store position of uipanel
data.Pos=Pos;

% This Calculates the length and position of each menu-button
% related to the string-lenght of the label
tstr=zeros(length(data.menuitems),1);
for i=1:length(data.menuitems)
    tstr(i)=length(data.menuitems(i).Label)*7+16;
end
% Pos(1) and Pos(2), are the location of the UIpanel in the figure
xpositions=[0;cumsum(tstr)]+Pos(1)+1;
data.xpositions=xpositions;
data.yposition=Pos(2)+Pos(4)-26;

% Instead of .png files with the images, we store the pixels to make
% menubuttons inside the function loadbarimages
[data.IN,data.IS,data.IH]=loadbarimages();

% This function will paint all menu-buttons in the figure
for i=1:length(data.menuitems);
    w=tstr(i); 
    h=25;
    x=xpositions(i);
    [barimage,barimagehover,barimageselect]=getbarimage(w,data);
    data.menuitems(i).Handle=axes('Units','Pixels','Position',[x data.yposition w h],'Parent',figure_handle);
    data.menuitems(i).HandleImshow=imshow(barimage,'Parent',data.menuitems(i).Handle);
    set(data.menuitems(i).HandleImshow,'ButtonDownFcn',@(x,y)menubar_ButtonDownFcn(x,y,datahandle));
    if(strcmpi(data.menuitems(i).Enable,'on'))
        hc=text(8,25/2,data.menuitems(i).Label,'Parent',data.menuitems(i).Handle);
        set(hc,'ButtonDownFcn',@(x,y)menubar_ButtonDownFcn(x,y,datahandle));
    else
        hc=text(8,25/2,data.menuitems(i).Label,'Parent',data.menuitems(i).Handle);
        data.menuitems(i).Children=[];
        set(hc,'Color',[0.5 0.5 0.5]);
    end
    data.menuitems(i).barimage=barimage;
    data.menuitems(i).barimagehover=barimagehover;
    data.menuitems(i).barimageselect=barimageselect;
end

i=length(data.menuitems)+1;
w=round(Pos(3))-sum(tstr(1:end))-3; w(w<1)=1;
x=xpositions(i);
barimage=getbarimage(w,data);
data.menuitems(i).Handle=axes('Units','Pixels','Position',[x data.yposition w h],'Parent',figure_handle);
data.menuitems(i).HandleImshow=imshow(barimage,'Parent',data.menuitems(i).Handle);

% This function builds the sub-menus which will appear beneath the menubar 
% in the figure
z=data.menuitems;
for i=1:length(z)
    data.cMenu(i) = uicontextmenu('Parent',figure_handle);
    addMenuChilds(z(i),data.cMenu(i),Properties)
end

% Store all data (this structure is attached to the uipanel-handle
setMyData(data,datahandle);


function addMenuChilds(z,h,Properties)
% This function builds the sub-menus of the menubar 
% (adding sub-sub-menus recursively)
if(isfield(z,'Children')&&~isempty(z.Children))
    for i=1:length(z.Children)
        z2=z.Children(i);
        hchild=uimenu(h, 'Label', z2.Label);
        for j=1:length(Properties)
            Pr=Properties{j};
            if(isfield(z2,Pr))
                val=z2.(Pr);
                if(~isempty(val)), set(hchild ,Pr,val); end
            end
        end
        addMenuChilds(z2,hchild,Properties)
    end
end

function [barimage,barimagehover,barimageselect]=getbarimage(w,data)
% This function builds the whole menu-buttons from the few pixel-lines stored
% in loadbarimages
barimage=zeros(size(data.IN,1),w,'uint8');
barimage(:,:,1)=repmat(data.IN(:,1),1,w);
barimage(:,:,2)=repmat(data.IN(:,2),1,w);
barimage(:,:,3)=repmat(data.IN(:,3),1,w);
barimagehover=zeros(size(data.IN,1),w,'uint8');
barimagehover(:,:,1)=repmat(data.IH(:,4,1),1,w);
barimagehover(:,:,2)=repmat(data.IH(:,4,2),1,w);
barimagehover(:,:,3)=repmat(data.IH(:,4,3),1,w);
barimagehover(:,1:3,1)=data.IH(:,1:3,1);
barimagehover(:,1:3,2)=data.IH(:,1:3,2);
barimagehover(:,1:3,3)=data.IH(:,1:3,3);
barimagehover(:,end-2:end,1)=data.IH(:,5:7,1);
barimagehover(:,end-2:end,2)=data.IH(:,5:7,2);
barimagehover(:,end-2:end,3)=data.IH(:,5:7,3);
barimageselect=zeros(size(data.IN,1),w,'uint8');
barimageselect(:,:,1)=repmat(data.IS(:,4,1),1,w);
barimageselect(:,:,2)=repmat(data.IS(:,4,2),1,w);
barimageselect(:,:,3)=repmat(data.IS(:,4,3),1,w);
barimageselect(:,1:3,1)=data.IS(:,1:3,1);
barimageselect(:,1:3,2)=data.IS(:,1:3,2);
barimageselect(:,1:3,3)=data.IS(:,1:3,3);
barimageselect(:,end-2:end,1)=data.IS(:,5:7,1);
barimageselect(:,end-2:end,2)=data.IS(:,5:7,2);
barimageselect(:,end-2:end,3)=data.IS(:,5:7,3);

function menubar_ButtonDownFcn(hObject, eventdata,datahandle)
data=getMyData(datahandle); if(isempty(data)), return; end
% Get the handle of the axes, (which is a parant of the clicked image or text).
hp=hObject;
switch get(hp,'Type');
    case 'text', hp=get(hObject,'Parent');
    case 'image', hp=get(hObject,'Parent');
end

% Detect the number of the clicked button
sel=find([data.menuitems.Handle]==hp);

% If another button was selected, reset the image to normal
if(~isempty(data.sel))
    I=data.menuitems(data.sel).barimage;
    set(data.menuitems(data.sel).HandleImshow,'CData',I);
end

% Set the selected-button image to selected, and display menu if present
data.sel=sel;
setSelect(data);

% If this main menu-item has a callback executes it.
dm=data.menuitems(data.sel);
if(isfield(dm,'Callback')&&(~isempty(dm.Callback)))
     if(isa(dm.Callback,'function_handle'))
         feval(dm.Callback);
     else
         eval(dm.Callback);
     end
end

% Store the Data
setMyData(data,datahandle);

function setSelect(data)
% Set the selected-button image to selected, and display menu if present
cMenu=data.cMenu(data.sel);
I=data.menuitems(data.sel).barimageselect;
set(data.menuitems(data.sel).HandleImshow,'CData',I);
set(cMenu,'Visible','off');
u=get(data.menuitems(data.sel).Handle,'Units');
set(data.menuitems(data.sel).Handle,'Units','pixels');
pos=get(data.menuitems(data.sel).Handle,'Position');
set(data.menuitems(data.sel).Handle,'Units',u);
set(cMenu,'Position',[pos(1) pos(2)])
set(cMenu,'Visible','on'); drawnow

function menubar_DummyFcn(hObject, eventdata)



function menubar_MotionFcn(figurehandle)
figuredata=getMyData(figurehandle); if(isempty(figuredata)), return; end
arrayfun(@(x)ProcessMotion(x),figuredata.uipanels)

function menubar_ResizeFcn(figurehandle)
figuredata=getMyData(figurehandle); if(isempty(figuredata)), return; end
arrayfun(@(x)ProcessResize(x),figuredata.uipanels)

function menubar_Timer(hObject, eventdata,figurehandle)
% This function acts like a MotionFcn, (Used to animated hover effect
% on menu buttons)
if(ishandle(figurehandle))
    figuredata=getMyData(figurehandle); if(isempty(figuredata)), return; end
    arrayfun(@(x)ProcessResize(x),figuredata.uipanels)
    arrayfun(@(x)ProcessMotion(x),figuredata.uipanels)
else
    stop(hObject); delete(hObject);
end

function ProcessResize(datahandle)
% This function is responsible for the hover-effect of the menu-buttons.
data=getMyData(datahandle); if(isempty(data)), return; end

% Get Position of Panel in Pixels
U=get(datahandle,'Units'); set(datahandle,'Units','Pixels'); Pos=get(datahandle,'Position'); set(datahandle,'Units',U);

% Replace the menu-bar by a new one, if window resized.
if(any(abs(Pos-data.Pos)>1e-3))
    UpdateMenu(datahandle,data.figure_handle)
end

function UpdateMenu(datahandle,figure_handle)
% Get Position of Panel in Pixels
U=get(datahandle,'Units'); set(datahandle,'Units','Pixels'); Pos=get(datahandle,'Position'); set(datahandle,'Units',U);

% Remove old existing menubars of the panel
removeOldMenuBar(datahandle);
uimenuhandle=get(datahandle,'UIContextMenu');
% Create a real-menubar from the panel UICContextMenu
if(~isempty( get(uimenuhandle,'Children')))
    CreatMenuBar(uimenuhandle,datahandle,Pos,figure_handle)
end
drawnow('expose');
    
function ProcessMotion(datahandle)
% This function is responsible for the hover-effect of the menu-buttons.
data=getMyData(datahandle); if(isempty(data)), return; end
    
hover=false;
for i=1:length(data.menuitems),
    if(~ishandle(data.menuitems(i).Handle)), return; end
    % Detect mouseposition relative to axis coordinates
    p = get(data.menuitems(i).Handle, 'CurrentPoint');
    y= p(1,2); x= p(1,1);
    % The position must be inside the axis it self
    if(y<0||y>25||x<0), break; end
    if(x>0&&x<size( data.menuitems(i).barimage,2))
        % The Mouse is hovering over a menu-button
        hover=true;
        if(~isempty(data.hov)&&(data.hov~=i))
            % If another button is already in hover-modes, set
            % that button to normal-look
            I=data.menuitems( data.hov).barimage;
            set(data.menuitems( data.hov).HandleImshow,'CData',I);
        end
        data.hov=i;
        if(isempty(data.sel))
            % Set current button to hover look
            I=data.menuitems( data.hov).barimagehover;
            set(data.menuitems( data.hov).HandleImshow,'CData',I);
        else
            % If another button is selected, set that button
            % to normal look
            if(data.hov~=data.sel)
                I=data.menuitems( data.hov).barimagehover;
                set(data.menuitems( data.hov).HandleImshow,'CData',I);
            end
        end
        % If another button was already selected, disable the menu
        % beneath the button, enable the menu of the hover-button,
        % and set it to selected modus.
        if(~isempty(data.sel)&&(data.sel~=data.hov))
            cMenu=data.cMenu(data.sel);
            set(cMenu,'Visible','off');
            data.sel=data.hov;
            setSelect(data)
        end
        drawnow('expose');
        break;
    end
end
if(hover)
    setMyData(data,datahandle);
else
    % If the mouse isn't above a button reset any past hover-button to
    % normal
    if(~isempty(data.hov))
        I=data.menuitems( data.hov).barimage;
        set(data.menuitems( data.hov).HandleImshow,'CData',I);
        data.hov=[];
        setMyData(data,datahandle);
        drawnow('expose');
    end
end
% If there is an menubar in selected modus, but his sub-menu already
% disappeared, because the user clicked elsewhere in the figure
% reset also the button in the menubar.
if(~isempty(data.sel))
    cMenu=data.cMenu(data.sel);
    p=get(cMenu,'Visible');
    if(strcmpi(p,'off'))
        I=data.menuitems(data.sel).barimage;
        set(data.menuitems(data.sel).HandleImshow,'CData',I);
        data.sel=[];
        setMyData(data,datahandle);
        drawnow('expose');
    end
end

function [IN,IS,IH]=loadbarimages()
IN(:,:,1) = [254 252 249 246 242 239 235 232 229 211 211 211 212 212 213 214 215 217 218 219 220 222 223 224 225;
    254 253 250 248 245 242 239 236 234 218 218 218 219 219 220 221 222 223 224 225 226 227 228 229 230;
    255 254 253 252 250 249 248 246 245 237 237 237 237 238 238 239 240 240 241 242 243 243 244 245 245]';
IS(:,:,1) = [254  252  175  106   84   83   82   81   80   74   74   74   74   74   74   75   75   76   76   76   77   77   96  157  225;
    254  179   92  145  202  200  206  207  205  193  196  196  200  197  198  199  200  202  202  204  204  207  213  109  156;
    254  111  146  187  206  203  206  207  205  193  196  196  200  197  198  199  200  202  202  204  204  207  213  196   96;
    254   88  161  185  202  200  205  207  205  193  196  196  200  196  197  199  202  203  206  209  210  212  213  212   79;
    254  111  146  169  186  183  191  194  191  181  184  184  188  184  185  187  189  191  193  195  196  198  200  181   96;
    254  179  102  147  163  161  166  168  166  158  160  160  163  161  162  162  165  166  167  170  171  172  162  100  156;
    254  252  175  106   84   83   82   81   80   74   74   74   74   74   74   75   75   76   76   76   77   77   96  157  225]';
IS(:,:,2) = [254  253  175  107   86   84   83   82   82   76   76   76   76   76   77   77   77   78   78   79   79   79   98  161  230;
    254  180   92  146  205  202  209  211  209  199  203  203  206  204  204  205  206  207  207  209  210  212  217  111  160;
    254  111  147  189  208  206  210  211  209  199  203  203  206  204  204  205  206  207  207  209  210  212  217  200   98;
    254   88  161  186  205  202  208  211  209  199  203  203  206  203  204  205  208  209  212  214  215  216  218  217   80;
    254  111  147  171  188  186  195  197  195  187  190  190  194  190  191  193  195  196  198  200  201  202  204  185   98;
    254  180  102  148  164  163  168  170  169  162  165  165  167  166  166  167  169  170  171  174  175  175  165  102  160;
    254  253  175  107   86   84   83   82   82   76   76   76   76   76   77   77   77   78   78   79   79   79   98  161  230]';
IS(:,:,3) = [255  254  178  109   87   87   87   86   86   83   83   83   83   83   83   83   84   84   84   84   85   85  105  172  245;
    255  180   93  148  209  208  217  220  219  217  220  220  223  221  221  222  223  223  223  225  226  227  233  119  170;
    255  112  148  192  213  212  218  220  219  217  220  220  223  221  221  222  223  223  223  225  226  227  233  214  105;
    255   89  163  189  209  208  216  220  219  217  220  220  223  220  220  222  225  225  228  231  232  232  233  232   86;
    255  112  148  173  191  191  202  205  204  202  206  206  209  206  206  208  210  210  212  215  216  216  218  197  105;
    255  180  103  150  167  167  174  176  176  174  177  177  179  178  178  179  181  181  183  185  186  186  175  109  170;
    255  254  178  109   87   87   87   86   86   83   83   83   83   83   83   83   84   84   84   84   85   85  105  172  245]';
IH(:,:,1) = [254  252  215  181  169  167  164  162  160  147  147  147  148  148  149  149  150  151  152  153  154  155  164  193  225;
    254  218  192  242  251  250  248  246  244  235  234  234  233  210  211  214  218  219  223  229  229  233  226  176  193;
    254  187  242  252  244  242  237  231  229  214  211  211  209  193  194  197  201  203  208  213  214  219  233  228  165;
    254  176  252  248  244  242  237  231  229  214  211  211  209  193  194  197  201  203  208  213  214  219  223  238  157;
    254  187  242  252  244  242  237  231  229  214  211  211  209  193  194  197  201  203  208  213  214  219  233  228  165;
    254  218  192  242  251  250  248  246  244  235  234  234  233  210  211  214  218  219  223  229  229  233  226  176  193;
    254  252  215  181  169  167  164  162  160  147  147  147  148  148  149  149  150  151  152  153  154  155  164  193  225]';
IH(:,:,2) = [254  253  216  183  171  169  167  165  163  152  152  152  153  153  154  154  155  156  156  157  158  158  168  198  230;
    254  219  193  243  252  251  249  247  246  238  237  237  237  214  214  217  222  222  226  232  232  235  229  179  198;
    254  188  242  253  245  244  239  234  233  219  216  216  215  199  200  203  207  208  213  219  220  224  236  231  169;
    254  177  253  249  245  244  239  234  233  219  216  216  215  199  200  203  207  208  213  219  220  224  227  241  161;
    254  188  242  253  245  244  239  234  233  219  216  216  215  199  200  203  207  208  213  219  220  224  236  231  169;
    254  219  193  243  252  251  249  247  246  238  237  237  237  214  214  217  222  222  226  232  232  235  229  179  198;
    254  253  216  183  171  169  167  165  163  152  152  152  153  153  154  154  155  156  156  157  158  158  168  198  230]';
IH(:,:,3) = [255  254  218  186  175  174  173  172  171  165  165  165  165  166  166  167  168  168  168  169  170  170  180  211  245;
    255  220  195  244  253  253  252  251  251  247  246  246  246  222  222  226  230  230  234  240  240  243  237  189  210;
    255  188  243  254  248  248  245  241  240  233  231  231  229  215  215  218  222  222  228  234  234  238  246  240  180;
    255  177  253  251  248  248  245  241  240  233  231  231  229  215  215  218  222  222  228  234  234  238  242  249  171;
    255  188  243  254  248  248  245  241  240  233  231  231  229  215  215  218  222  222  228  234  234  238  246  240  180;
    255  220  195  244  253  253  252  251  251  247  246  246  246  222  222  226  230  230  234  240  240  243  237  189  210;
    255  254  218  186  175  174  173  172  171  165  165  165  165  166  166  167  168  168  168  169  170  170  180  211  245]';
IN=uint8(IN);
IH=uint8(IH);
IS=uint8(IS);

function w=removeOldMenuBar(datahandle)
% This function detects if the uipanel is replaced in the past by 
% a menubar, and removes the menubar in the figure, and the stored-data.
data=getMyData(datahandle); if(isempty(data)),return; end
for i=1:length(data.menuitems)
    if(ishandle(data.menuitems(i).Handle))
        delete(data.menuitems(i).Handle);
    end
    if(ishandle(data.cMenu(i)))
        delete(data.cMenu(i));
    end
end
remMyData(datahandle);
w=true;

function remMyData(datahandle)
% Get data struct stored in figure
rmappdata(datahandle,'menubar');
 
function setMyData(data,datahandle)
% Store data struct in figure
setappdata(datahandle,'menubar',data);

function data=getMyData(datahandle)
% Get data struct stored in figure
data=getappdata(datahandle,'menubar');

Contact us