function snu(action,categoryArg)
%
%   Vyukovy program pro predmet SOFTWARE NUMERICKYCH METOD 
%
%   Spusti se prikazem "snu" v prikazovem radku
%
%   Mozne argumenty jsou (staci jen cast nazvu)
%        ('nelinearni_rovnice'|...
%         'soustavy_linearnich_rovnic'|...
%         'vlastni_cisla'|...
%         'aproximace_funkci'|...
%         'derivace_funkce'|...
%         'urcity_integral'|...
%         'diferencialni_rovnice'),
%
%   SNU otevre snu s uvedenym tematem.
%
%   Josef Danek

datum='2025-10-06';

pomocny_adresar='nastaveni';

% if ~strcmp(feature('DefaultCharacterSet'),'UTF-8')
%   feature('DefaultCharacterSet','UTF8');
% end;    

if nargin<1,
   action = 'show';
   fSelectCategory = 0;
   fCmdLine = 1;
else
   action = lower(action);
end;

indent = '      ';


% add switch for show events
categoryNames = {'nelinearni_rovnice',...
                 'soustavy_linearnich_rovnic',...
                 'vlastni_cisla',...
                 'aproximace_funkci',...
                 'derivace_funkce',...
                 'urcity_integral',...
                 'diferencialni_rovnice'};

if (nargin > 0)
   fCmdLine = 0;
   % strmatch will also match partial strings
   catMatch = strmatch(action, categoryNames);
   % should only match one of these
   % but take only the first anyway
   if ~isempty(catMatch)
      action = ['show' categoryNames{catMatch(1)}];
      fCmdLine = 1;  
   end
   fSelectCategory = (nargin==2);
end

chooseMsg = 'Vyber téma pro nabídku příkladu';
clickMsg = 'Dvakrát klikni pro zobrazení tohoto tématu';

figHandles = allchild(0);
figH=findobj(figHandles, 'flat', 'Name', 'Software Numerických Metod', ...
   'Tag', 'snu');                         

if strcmp('rundemo',action)
   if isempty(figH)
      LocalRunDemo(findobj(figH,  'Type', 'uicontrol', 'Tag', 'test'));
   end;
% ====================================
% Handle the SHOW events
elseif strmatch('show',action)
   
   if isempty(figH)
      snu initialize;
      figHandles = allchild(0);                 
      figH=findobj(figHandles, 'flat', 'Name', 'Software Numerických Metod', ...
         'Tag', 'snu');
      set(figH,'HandleVisibility','off');
   end;
   
   % raise the demo window if we're being invoked from the cmd line
   if(fCmdLine)
      figure(figH);
   end
   
   % because HandleVis is off, don't use gcf, use figH
   % get the global data
   param=get(figH,'UserData');
   
   % find ui controls
   % listboxes
   categoryListH = findobj(figH, ...
      'Type', 'uicontrol', 'Tag', 'CategoryListbox');
   index = get(categoryListH, 'UserData');
   demoListH = findobj(figH, 'Type','uicontrol','Tag','DemoListbox');
   aboutListH = findobj(figH,'Type','uicontrol','Tag','AboutListbox');
   aboutTopics = get(aboutListH, 'UserData');
   
   % buttons
   runBtn=findobj(figH, 'Type', 'uicontrol', 'Tag', 'test');
   pdfBtn=findobj(figH, 'Type', 'uicontrol', 'Tag', 'pdf');
   closeBtn=findobj(figH, 'Type', 'uicontrol', 'Tag','return');
   
   catValue = get(categoryListH, 'Value');
   
   theTopic = index.topic(catValue);
   theCategory = index.category(catValue);
   
   if fCmdLine
      clickType = 'none';
   else
      clickType = get(figH,'SelectionType');
   end
      
   % support direct calls to each topic area
   
   topicList = param.topicList;

   switch action
   case 'shownelinearni_rovnice',
      theTopic = LocalGetTopic(topicList, 'Nelineární rovnice', 1);
      incremListUpdate = 0;
   case 'showsoustavy_linearnich_rovnic',
      theTopic = LocalGetTopic(topicList,...
                     'Soustavy linearních algebraických rovnic', 1);
      incremListUpdate = 0;
   case 'showvlastni_cisla',
      theTopic = LocalGetTopic(topicList, 'Vlastní čísla', 1);
      incremListUpdate = 0;
   case 'showaproximace_funkci',
      theTopic = LocalGetTopic(topicList, 'Aproximace funkcí', 1);
      incremListUpdate = 0;
   case 'showderivace_funkce',
      theTopic = LocalGetTopic(topicList, 'Derivace funkce', 1);
      incremListUpdate = 0;
   case 'showurcity_integral',
      theTopic = LocalGetTopic(topicList, 'Urcitý integrál', 1);
      incremListUpdate = 0;
   case 'showdiferencialni_rovnice',
      theTopic = LocalGetTopic(topicList, 'Diferenciální rovnice', 1);
      incremListUpdate = 0;
   otherwise
      incremListUpdate = 1;
   end
   
   if (~incremListUpdate)   % rewrite the list from scratch
      
      index.expanded = zeros(1,length(topicList));
      index.expanded(theTopic) = 1;
      action = 'showlist';
      
      if (fSelectCategory)  % use the second argument
         theCategory = LocalGetTopic(...
            LocalCellLower({param.pageList{theTopic}.Name}),...
            [indent lower(categoryArg)],...
            0);
         newValue = theCategory+theTopic;
      else
         newValue = theTopic;
         theCategory = 0;
      end
      
      
      theCategoryList = {}; % initialize
      nTopics = length(param.topicList);
      index.topic = [];
      index.category = [];
      
      for iTopic = 1:nTopics,
         if (index.expanded(iTopic))
            prefix = '-';
         else
            prefix = '+';
         end
         theCategoryList = cat(2, theCategoryList, ...
            {[prefix param.topicList{iTopic}]});
         index.topic = cat(2, index.topic, [iTopic]);
         index.category = cat(2, index.category, [0]);
         if (index.expanded(iTopic)),
            nCategories = length({param.pageList{iTopic}.Name});
            theCategoryList = cat(2, theCategoryList, ...
               {param.pageList{iTopic}.Name});
            index.topic = cat(2, index.topic, iTopic*ones(1,nCategories));
            index.category = cat(2, index.category, [1:nCategories]);
         end % if (index.expanded(iTopic)),
      end % for iTopic = 1:nTopics,

      set(categoryListH, 'String', theCategoryList);
      set(categoryListH, 'Value', newValue);
      set(categoryListH, 'ListboxTop', newValue);
      set(categoryListH, 'UserData', index);
   end

   switch action
   case 'showlist',
      if (theCategory == 0) % this is a topic heading
         % RECOMPUTE CATEGORY LIST
         % recompute the list to be displayed in the category listbox
         % compute indices (Topic, Category) for each 'value' of the
         % category list

         if (strcmp(clickType,'open'))
            index.expanded(theTopic) = not(index.expanded(theTopic));
            theCategoryList = get(categoryListH, 'String');

            currentLength = length(theCategoryList);
            insertPt = 1;
            while index.topic(insertPt) ~= theTopic
               insertPt = insertPt + 1;
            end
            if (index.expanded(theTopic))
               prefix = '-';
            else
               prefix = '+';
            end
            theCategoryList(insertPt) = ...
               {[prefix param.topicList{theTopic}]};
            oldListboxTop = get(categoryListH,'ListboxTop');
            if index.expanded(theTopic)
               nCategories =length({param.pageList{theTopic}.Name});
               index.topic = LocalSplice(insertPt,...
                  theTopic*ones(1,nCategories), index.topic);
               index.category = LocalSplice(insertPt,...
                  [1:nCategories], index.category);
               
               for iCategory = 1:nCategories
                  theCategoryList = LocalSplice(insertPt,...
                     {param.pageList{theTopic}(iCategory).Name},...
                     theCategoryList);
                  insertPt = insertPt+1;
               end
               set(categoryListH, 'String', theCategoryList);
            else
               insertPt = insertPt + 1;
               while (index.topic(insertPt) == theTopic) 
                  index.topic(insertPt) = [];
                  index.category(insertPt) = [];
                  theCategoryList(insertPt) = [];                   
                  
                  if (insertPt > length(index.topic))
                     break;
                  end
               end
               set(categoryListH, 'String', theCategoryList);
            end
            set(categoryListH, 'UserData', index);
            set(categoryListH, 'ListboxTop', oldListboxTop)
         end   
         
         set(runBtn, 'String', 'Testuj', 'Enable', 'off');
        if (index.expanded(theTopic))
            helpMsg = chooseMsg;
         else
            helpMsg = clickMsg;
         end
         set(demoListH, 'String', helpMsg, ...
            'Max', 2, ...
            'Value', [], ...
            'Enable', 'inactive');
         set(aboutListH, 'String', aboutTopics{theTopic});
         set(aboutListH, 'Value', []);
         LocalSetPdfBtn(pdfBtn, theTopic);

      else % if (category ~= 0) i.e. we have chosen a category
         theCategoryName = param.pageList{theTopic}(theCategory).Name;
         demoLabel=[theCategoryName ' Demos']; 
         
         demoList=char(param.pageList{theTopic}(theCategory).DemoList);
         % set callback
         fcnList=char(param.pageList{theTopic}(theCategory).FcnList);

         theDemo = 1;
         demoFcn = fcnList(theDemo,:);
         
         set(demoListH, 'Enable', 'on', 'Max', 1, 'Value', 1);
         set(demoListH, 'String', demoList);
         LocalSetRunBtn(runBtn, demoList(1,:), demoFcn);
         LocalSetPdfBtn(pdfBtn, theTopic);

         % now set new text in the 'about' list
         % Help is a cell array of strings
         hlpStr=param.pageList{theTopic}(theCategory).Help;
         % Name is a string
         namestr=param.pageList{theTopic}(theCategory).Name;
         namestr(1:length(indent)) = [];  %strip pad
         
         % add a space
         if (theTopic == 1) % 
            spacestr = ' ';
         else
            spacestr = [];
         end
         % kludge: add some blanks to avoid colormap wierdness
         set(aboutListH, 'String', [{namestr}; {spacestr}; hlpStr; ...
               {' '}; {' '}]);
         set(aboutListH, 'Value', []);
      end % if (theCategory == 0), % this is a topic heading
      
      
   case 'showdemo',  % i.e. a click on the demo list
      
      theDemo = get(demoListH, 'Value');
      demoList=char(param.pageList{theTopic}(theCategory).DemoList);
      
      %set callback
      fcnList=char(param.pageList{theTopic}(theCategory).FcnList);
      demoFcn = fcnList(theDemo,:);
      
      LocalSetRunBtn(runBtn, demoList(theDemo,:), demoFcn); 
      LocalSetPdfBtn(pdfBtn, theTopic);
     
      if (strcmp(clickType,'open'))
          LocalRunDemo(runBtn);
      end
      
   end % switch
   
   
   %=====================================
   % Handle INITIALIZATION
elseif strcmp(action,'initialize'),
      
      % POSITION AND CREATE FIGURE
   
   figureColor=[0.6710 0.6500 0.5290];
   %figurePos=[30 15 90 35];
   figurePos=[20 10 130 45];
   
   figH=figure( ...
      'Name', 'Software Numerických Metod', ...
      'Units', 'characters', ...
      'NumberTitle','off', ...
      'Visible','off', ...
      'IntegerHandle','off', ...
      'Resize','on', ...
      'Color', figureColor, ...
      'Position',figurePos, ...
      'Pointer','watch', ...
      'MenuBar','none', ... 
      'Tag', 'snu');

   % banner graphic
%    oldRootUnits = get(0,'Units');
%    set(0, 'Units', 'points');
%    pixfactor = 72/get(0,'screenpixelsperinch')
%    set(0, 'Units', oldRootUnits);

   banner=imread('nastaveni/banner_SNU.jpg');
   oldUnits = get(figH,'Units');  
   set(figH, 'Units', 'points');
   Fig_Pos=get(figH,'Position');
   set(figH, 'Units', oldUnits);

   set(gca,'Units','points');
%   Ban_Pos=get(gca, 'Position')
   koefx=5;
   koefy=83.5;
   Ban_Pos(1)=koefx/100*Fig_Pos(3);
   Ban_Pos(2)=koefy/100*Fig_Pos(4);
   Ban_Pos(3)=(100-2*koefx)/100*Fig_Pos(3);
   Ban_Pos(4)=(100-koefy-koefx)/100*Fig_Pos(4);
   set(gca, 'Position', Ban_Pos);
   set(gca,'Units','normal');
   bannerH = image(banner);
   axis off;
   autor=text(30,327,[datum,'     Josef Daněk']);
%   set(autor,'FontWeight','bold');
   set(autor,'Color',[0.386 0.275 0.058],'FontWeight','bold');

   % Initialize  buttons and listboxes
   boxesNButtons = Localbuildpage(figH, chooseMsg);
   
   % when this precedes the Localbuildpage invocation,
   % the rest of the graphic disappears on UNIX (not PC)
   % make the figure visible
   set(figH, 'Visible', 'on','Pointer','watch');
   
   drawnow;
   % watchon here:
   % otherwise, watchon before drawnow puts up an I beam
   % with it around here, it's an arrow.
   
   % INITIALIZE CONTENT STRUCTURES
   
   cd(pomocny_adresar);
   nrList = nrinfo;
   slarList = slarinfo;
   vcList = vcinfo;   
   afList = afinfo;   
   derList = derinfo;   
   intList = intinfo;   
   difList = difinfo;   
   cd ..;
   
   nTopics=1;
   topicList{1}='Nelineární rovnice';
   pageList{1} = nrList;
   
   if ~isempty(slarList)
      nTopics=nTopics+1;       
      topicList{nTopics}='Soustavy lineárních algebraických rovnic';
      pageList{nTopics} = slarList;
   end

   if ~isempty(vcList)
      nTopics=nTopics+1;       
      topicList{nTopics}='Vlastní čísla';
      pageList{nTopics} = vcList;
   end

   if ~isempty(afList)
      nTopics=nTopics+1;       
      topicList{nTopics}='Aproximace funkcí';
      pageList{nTopics} = afList;
   end

   if ~isempty(derList)
      nTopics=nTopics+1;       
      topicList{nTopics}='Derivace funkce';
      pageList{nTopics} = derList;
   end

   if ~isempty(intList)
      nTopics=nTopics+1;       
      topicList{nTopics}='Určitý integrál';
      pageList{nTopics} = intList;
   end

   if ~isempty(difList)
      nTopics=nTopics+1;       
      topicList{nTopics}='Diferenciální rovnice';
      pageList{nTopics} = difList;
   end

   param.pageList  = pageList;
   param.topicList = topicList;  
   
   for iTopic = 1:nTopics
      nCategories = length({param.pageList{iTopic}.Name});
      topicList{iTopic} = ['+' topicList{iTopic}];
      for iCategory = 1:nCategories
         param.pageList{iTopic}(iCategory).Name ...
            = [indent param.pageList{iTopic}(iCategory).Name];
      end
   end
   
   % save this global data into the figure info
   set(figH,'UserData',param);
   
   categoryListH = findobj(figH, ...
      'Type', 'uicontrol', 'Tag', 'CategoryListbox');
   
   % make an index for the entries visible in the category list box    
   index.topic = [1:nTopics];
   index.category = zeros(1,nTopics);
   index.expanded = zeros(1,nTopics);

   set(categoryListH, ...
      'UserData', index, ...
      'String', topicList, ...
      'Value', 1);
   
   % allow resizing
   set(boxesNButtons, 'Units', 'normalized');
   
   % Initialization is now complete.
%   set(waitH, 'Visible', 'off');

   set(boxesNButtons, 'Visible', 'on');
   drawnow;
   refresh;
   set(figH,'Pointer','arrow');


elseif strcmp('pdfview',action)
   if exist('figH')
      Localview(findobj(figH,'Type', 'uicontrol', 'Tag', 'pdf'))
   end;
end;  %

%====================================
function handleArray = Localbuildpage(figH, chooseMsg)
%  build buttons and listboxes for each page

figureColor = get(figH, 'Color');

%====================================
% pull out the geometry information

aboutListPos = [52.5 24 72 10.4];
demoListPos = [52.5 5.5 72 17];
catListPos =[5 5.5 44 29];
closeBtnPos = [18.5  1.5  16.5000 2.2500] ;
runBtnPos = [96 1.5  16.5000 2.2500] ;
pdfBtnPos = [65 1.5 16.5000 2.2500] ;
% aboutListPos = [35 16.5 50 10];
% demoListPos = [35 5.5 50 10];
% catListPos =[5 5.5 27 21.2];
% closeBtnPos = [10  1.5  16.5000 2.2500] ;
% runBtnPos = [63 1.5  16.5000 2.2500] ;
% pdfBtnPos = [41 1.5 16.5000 2.2500] ;

% build demo listbox
demoListH = uicontrol( ...
   'Style', 'list', ...
   'HorizontalAlignment','left', ...
   'Units', 'character', ...
   'Visible', 'off',...
   'BackgroundColor', [0.968 0.941 0.798], ...
   'ForegroundColor', [0.386 0.275 0.058], ...
   'Max', 2, ...
   'Value', [], ...
   'Enable', 'inactive', ...
   'Position', demoListPos, ...
   'Callback', 'snu showdemo', ...
   'String', chooseMsg, ...
   'Tag', 'DemoListbox', ...
   'FontSize',12);

% Set up category listbox
tbxListH = uicontrol( ...
   'Style', 'list', ...
   'HorizontalAlignment','left', ...
   'Units','character', ...
   'Visible','off',...
   'BackgroundColor', [0.968 0.941 0.798], ...
   'ForegroundColor', [0.386 0.275 0.058], ...
   'Max', 1, ...
   'Value', 1, ...
   'Enable', 'on', ...
   'Position', catListPos, ...
   'Callback', 'snu showlist', ...
   'String', ' ', ...
   'Tag', 'CategoryListbox', ...
   'FontSize',12);

uvodni_rec={...
    ' Právě jste spustili výukový program  snu.m,'
    ' který slouží k demonstraci základních      '
    ' algoritmů numerické matematiky.            '
    '                                            '
    ' Nejprve si zvolte téma v levém menu. Dvojím'
    ' kliknutím jej otevřete nebo zavřete.       '
    ' Dále si zvolte podtéma, které Vás zajímá.  '
    ' Pro zvolené podtéma se v pravém dolním menu'
    ' zobrazí seznam demo příkladů, které lze    '
    ' spustit dvojím kliknutím nebo použitím     '
    ' tlačítka "Testuj".                         '
    '                                            '
    ' Ke každému hlavnímu tématu je k dispozici  '
    ' doprovodný text v PDF formátu, který lze   '
    ' zobrazit použitím tlačítka "Zobraz PDF".   '
    '                                            '
    ' -------------------------------------------'
    ' Autor :    Josef Daněk                     '
    ' -------------------------------------------'
    '                                            '
    };

% create a listbox for displaying the 'about' information
aboutListH = uicontrol( ...
   'Style', 'list', ...
   'HorizontalAlignment','left', ...
   'Units','character', ...
   'Visible','off',...
   'BackgroundColor', figureColor, ...
   'Min', 0, ...
   'Max', 2, ...
   'Value', [], ...
   'Enable', 'on', ...
   'Position', aboutListPos, ...
   'Callback', '', ...
   'String', uvodni_rec, ...
   'Tag', 'AboutListbox', ...
   'UserData', LocalLoadTopics, ...
   'FontSize',12);


% The close button
backH = uicontrol( ...
   'Style', 'pushbutton', ...
   'Units', 'character', ...
   'Position', closeBtnPos, ...
   'BackgroundColor', [0.814 0.629 0.492], ...
   'String', 'KONEC', ...
   'Visible', 'off', ...
   'Tag', 'return', ...
   'Callback', 'close(gcbf)', ...
   'FontSize',12); 

% The run button    
runH = uicontrol( ...
   'Style', 'pushbutton', ...
   'Units', 'characters', ...
   'Position', runBtnPos, ...
   'BackgroundColor', [0.8090 0.8460 0.7460], ...
   'String', 'Testuj', ...
   'Visible', 'off', ...
   'Enable', 'off', ...
   'Tag', 'test', ...
   'Callback', 'snu rundemo', ...
   'FontSize',12); 

% The pdf button    
pdfH = uicontrol( ...
   'Style', 'pushbutton', ...
   'Units', 'characters', ...
   'Position', pdfBtnPos, ...
   'BackgroundColor', [0.8090 0.8460 0.7460], ...
   'String', 'Zobraz PDF', ...
   'Visible', 'on', ...
   'Enable', 'off', ...   
   'Tag', 'pdf', ...
   'Callback', 'snu pdfview', ...
   'FontSize',12); 

handleArray = [runH pdfH backH aboutListH tbxListH demoListH];


% =====================================
function aboutTopicArray = LocalLoadTopics

about1 = {...
   ' Řešení nelineárních rovnic '
   ' '
   ' Je dána funkce f: <a,b> -> R.  '
   ' Hledáme číslo x z intervalu <a,b>, pro které platí f(x)=0.'
   ' '
   ' Popisované metody jsou založeny na iteračním principu,'
   ' tj. konstruujeme posloupnost aproximací řešení tak, aby'
   ' konvergovala k přesnému řešení.'
   };
about2 = {...
   ' Řešení soustav lineárních algebraických rovnic '
   ' '
   ' Je dána regulární čtvercová matice A řádu n a' 
   ' sloupcový vektor b o n prvcích.'
   ' Hledáme sloupcový vektor x, pro který platí Ax=b.'
   ' '
   };

about3 = {...
   ' Nalezení vlastních čísel a vlastních vektorů'
   ' '
   ' Vlastní čísla lambda čtvercové matice A jsou taková čísla,'
   ' pro která existuje nenulové řešení homogenní soustavy'
   '                            A.v = lambda.v '
   ' (v je vlastní vektor odpovidající vlastnímu číslu lambda).'
   ' '
   };

about4 = {...
   ' Určení aproximace funkce'
   ' '
   ' Pro danou reálnou funkci f(x) hledáme vhodnou aproximaci '
   ' phi(x), která vhodným způsobem popisuje chovaní funkce.'
   ' '
   ' Funkci phi(x) hledáme jako lineárni kombinaci bázových '
   ' funkcí phi_i(x), tj.'
   ' phi(x) = c_0 phi_0(x) + c_1 phi_1(x) + ... + c_n phi_n(x).'
   };

about5 = {...
   ' Výpočet derivace funkce'
   ' '
   ' Pro danou reálnou funkci f(x) a zadaný bod alfa'
   ' hledáme přibližnou hodnotu derivace funkce f v bodě alfa'
   ' (obecně hledáme derivaci n-tého řádu). '
   };

about6 ={...
   ' Výpočet hodnoty určitého integrálu'
   ' '
   ' Pro danou reálnou funkci f(x) a zadaný interval <a,b>'
   ' hledáme přibližnou hodnotu určitého integrálu '
   ' z funkce f(x) na intervalu <a,b>.'
   };

about7 ={...
   ' Řešení počáteční úlohy pro obyčejnou diferenciální rovnici'
   ' 1. řádu'
   '  '
   ' Hledáme reálnou funkci y=y(x), která splňuje '
   ' diferenciální rovnici  '
   '                                        y`(x)=f(x,y(x))'
   ' a počáteční podmínku '
   '                                        y(x0)=y0.'
   };

about8 =...
   {'Pomoc'
   };

aboutTopicArray = {about1 about2 about3 about4 about5 about6 about7 about8};

%=====================================
% insert into string, array or cell array of dim 1xn or nx1
function together = LocalSplice(insertPt, piece, target)

[sizeOne sizeTwo] = size(target);
% splice along the big dimension
if sizeOne > 1
   dim = 1;
   nItems = sizeOne;
   if sizeTwo > 1
      % then this is ambiguous...
   end
else % sizeTwo > 1
   dim = 2;
   nItems = sizeTwo;
end

if (insertPt<1)
   together =  cat(dim, piece, target);
elseif (insertPt>nItems)
   together =  cat(dim, target, piece);
else
   together = cat(dim, target(1:insertPt), ...
      piece,...
      target(insertPt+1:nItems));
end

% =====================================
function theTopic = LocalGetTopic(topicList, targetString, noHitTopic)

hits = strmatch(targetString, topicList);
if (hits)
   theTopic = hits(1);
else
   theTopic = noHitTopic;  % default if we don't find it
end

% =====================================
function LocalSetRunBtn(runBtn, labelStr, demoFcn)

nMax = 8;

if isempty(labelStr)
    labelStr='';
else
  % remove trailing and leading blanks
  [r,c] = find(labelStr ~= ' ' & labelStr ~= 0);
  if isempty(c)
    labelStr = '';
  else
    labelStr = labelStr(:,min(c):max(c));
  end
end

demoData.demoFcn = deblank(demoFcn);
demoData.demoName = labelStr;

% first, clip
if (length(labelStr)>nMax)
   labelStr = labelStr(1:nMax);

   % find the last space before the nMax'th character
   spaces = findstr(' ', labelStr);

   if (isempty(spaces))
      labelStr = [labelStr '...'];
   else
      % truncate to last complete word before nMax
      lastSpace = spaces(length(spaces));
      labelStr = [labelStr(1:lastSpace) '...'];
   end
end
if isempty(demoData.demoFcn)
   runString='Testuj';
   btnEnable='off';
else
   %runString=['Testuj ' labelStr];
   runString=['Testuj'];
   btnEnable='on';
end

set(runBtn, ...
   'String', runString , ...
   'Enable', btnEnable, ...
   'UserData', demoData);

% =====================================
function warningStr = LocalSetWarningStr(demoFcn, demoName)
warningStr = ...
   ['Error running "' demoName '" demo (' ...
         demoFcn '):' ];

% =====================================
% protect against demos clearing the workspace
function errorStatus = LocalSafeEval(tryStr, warningStr)

   % allow single quotes in the name of the demo
   warningStr = LocalDoubleQuote(warningStr);
   catchStr = ...
       ['errordlg([''' warningStr ''' sprintf(''\n'') lasterr],'...
          '''Demo Error'', ''replace''); errorCaught=1;'];
   errorStatus = LocalOneLevelDeeper(tryStr, catchStr);

% =====================================
function errorCaught = LocalOneLevelDeeper(tryStr, catchStr)
   errorCaught = 0;
   evalin('caller',tryStr, catchStr);
   % errorStatus bound in catchStr if there is an error

% =====================================
% view PDF file
function Localview(pdfBtn)

if exist('pdfBtn')
  adresar_snu=cd;
  clc;
  cd('pdf_soubory');
  out=is_acroread;
  if (out==1)|(out==2)|(out==4)
    soubor2=[];
    pdfData = get(pdfBtn,'UserData');
    switch pdfData
      case 1,
        soubor='nelinearni_rovnice.pdf';
        soubor2='soustavy_nelinearnich_rovnic.pdf';
      case 2,
        soubor='soustavy_linearnich_rovnic.pdf';
      case 3,
        soubor='vlastni_cisla.pdf';
      case 4,
        soubor='aproximace_funkci.pdf';
      case 5,
        soubor='derivace.pdf';
      case 6,
        soubor='integrace.pdf';
      case 7,
        soubor='diferencialni_rovnice.pdf';
    end;
    disp(' ');
    disp(sprintf(' Zobrazuji soubor:   %s',soubor));
    disp(' ');
    if ~isempty(soubor2) 
      disp(sprintf(' Zobrazuji soubor:   %s',soubor2));
      disp(' ');
    end;
  end;
  if out==1
    switch pdfData
      case 1,
        unix 'acroread nelinearni_rovnice.pdf &';
        pause(1);
        unix 'acroread soustavy_nelinearnich_rovnic.pdf &';
      case 2,
        unix 'acroread soustavy_linearnich_rovnic.pdf &';
      case 3,
        unix 'acroread vlastni_cisla.pdf &';
      case 4,
        unix 'acroread aproximace_funkci.pdf &';
      case 5,
        unix 'acroread derivace.pdf &';
      case 6,
        unix 'acroread integrace.pdf &';
      case 7,
        unix 'acroread diferencialni_rovnice.pdf &';
    end;
  end;
  if out==2
    switch pdfData
      case 1,
        unix 'xpdf nelinearni_rovnice.pdf &';
        pause(1);
        unix 'xpdf soustavy_nelinearnich_rovnic.pdf &';
      case 2,
        unix 'xpdf soustavy_linearnich_rovnic.pdf &';
      case 3,
        unix 'xpdf vlastni_cisla.pdf &';
      case 4,
        unix 'xpdf aproximace_funkci.pdf &';
      case 5,
        unix 'xpdf derivace_integrace.pdf &';
      case 6,
        unix 'xpdf derivace_integrace.pdf &';
      case 7,
        unix 'xpdf diferencialni_rovnice.pdf &';
    end;
  end;
  if out==3
    disp('Nemohu zobrazit PDF soubory ... Neni k dispozici Acroread ani Xpdf');
  end;
  if out==4
      dos(sprintf('Reader\\Reader\\AcroRd32 %s &',soubor));
      if ~isempty(soubor2) 
        dos(sprintf('Reader\\Reader\\AcroRd32 %s &',soubor2));
      end;
  end;
  cd(adresar_snu);
end

% =====================================
% run from the run button or from double click
function LocalRunDemo(runBtn)

grt=get(runBtn,'Tag');
if grt=='test'

   adresar_snu=cd;
   figH = gcbf;
   demoData = get(runBtn,'UserData');

   %======================================
   % Check for product dependencies and make sure all products
   % are present.  Only start demo if all is OK.  Else, show
   % an error dialog.

   dn=demoData.demoName;

   % only check if there are parens in the demo name
   if ~isempty(dn) & sum(dn=='(')
      % pull out whatever is between the parens
      depends=dn(find(dn=='(')+1:find(dn==')')-1);
      % cut out any spaces
      depends(find(depends==' '))='';
      prodList={};
      depends=[',' depends];
      csMarker=cumsum(depends==',');
      % loop over the number of commas
      for i=1:csMarker(end);
         nextOne=depends(csMarker==i);
         % chop off comma
         nextOne(1)='';
         % stuff string into cell array
         prodList{1,i}=nextOne;
      end;
   end;
   ProductMissing='';

   % End of product checking code.
   %======================================


   % If there's a product missing, pop up the dialogue...
   if ~isempty(ProductMissing)
      ContactUs='Contact The MathWorks for more information.';
      msgbox({ProductMissing;ContactUs},'Product Missing','modal')

      % else fire off the demo.
   else
      set(figH,'Pointer','watch');  % watchon
      oldFigs = allchild(0)';       % work with row vectors

      warningStr = LocalSetWarningStr(demoData.demoFcn, ...
         demoData.demoName);
      lasterr('');
      errorCaughtInDemo = LocalSafeEval(demoData.demoFcn, warningStr);

      set(figH,'Pointer','arrow');  % watchoff

      % flush the HG event queue so we get the right stacking order
      drawnow;

      currentFigs = allchild(0)';
      currentVisFigs = currentFigs(find(LocalIsVisible(currentFigs)));

      if errorCaughtInDemo
         % then close all new windows (including invisible figures
         % and systems) except the error dialog

         % we have used errordlg with Replace='replace', so there should not
         % ever be more than one errorfig with this name
         errorFig = findobj(currentFigs,'Name', 'Demo Error');

         % some of the figures (scopes) may already be closed
         currentFigs = allchild(0)';
         close(setdiff(setdiff(currentFigs,oldFigs),[errorFig]));
         % bring error dialog to front
         figure(errorFig);
         lasterr('');
      else
         % bring new windows to front;
         % setdiff sorts its result:
         % so use ismember to preserve ordering of new figs

         newVisFigs = ...
            currentVisFigs(find(~ismember(currentVisFigs,oldFigs)));
                 for f = fliplr(newVisFigs)
                        % f may contain Java frames in addition to figure.
                        % Make sure f is a figure
                        if strcmp(get(f,'Type'),'figure'),
                           figure(f);
                        end
                 end
          end
   end
  cd(adresar_snu);
end

% =====================================
function resultV = LocalIsVisible(aFigHandleVector)
resultV = strcmp('on', get(aFigHandleVector,'Visible'))';
% returns a row vector


% =====================================
function lowerArray = LocalCellLower(theCellArray)

   i = 1;
   for anElement = theCellArray
      lowerArray{i} = lower(anElement{1});
      i = i+1;
   end

%==================================================
function outStr=LocalDoubleQuote(inStr)
% add double quote to quoted string
    outStr=inStr(sort([1:length(inStr) find(inStr=='''')]));



%==================================================
function LocalSetPdfBtn(pdfBtn,theTopic)
set(pdfBtn, 'UserData', theTopic);
set(pdfBtn, 'Enable', 'on');














