imod_struct_jd

PURPOSE ^

SYNOPSIS ^

function [s,mod] = imod_struct_jd(s,sname,d_opt,opt_gui,sextra,style)

DESCRIPTION ^

 This function interactively modifies the fields of structure s

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [s,mod] = imod_struct_jd(s,sname,d_opt,opt_gui,sextra,style)
0002     %
0003     % This function interactively modifies the fields of structure s
0004     %
0005     if nargin < 6,
0006         style = struct;
0007     end
0008     if nargin < 5,
0009         sextra = struct;
0010     end
0011     if nargin < 4,
0012         opt_gui = false;
0013     end
0014     if nargin < 3,
0015         d_opt = 1;
0016     end
0017     if nargin < 2,
0018         sname = '';
0019     end
0020     %
0021     if length(s) ~= 1,
0022         error('This function applies only to (1,1) structures')
0023     end
0024     %
0025     if ~isfield(style,'fontname')
0026         style.fontname = 'fixedwidth';
0027     end
0028     %
0029     if ~isfield(style,'fontsize')
0030         style.fontsize = 10;
0031     end
0032     %
0033     if ~isfield(style,'titlefontsize')
0034         style.titlefontsize = 2*style.fontsize;
0035     end
0036     %
0037     fexcept = {'info','expert','values'};
0038     %
0039     for ifield = 1:length(fexcept),
0040         if isfield(s,fexcept{ifield}),
0041             s = rmfield(s,fexcept{ifield});
0042         end
0043     end
0044     %
0045     numlim = 10;%maximum number of elements for horizontal vectors
0046     ftsize = 10;%font size
0047     if islogical(opt_gui) || ~ishandle(opt_gui) || opt_gui == 0,
0048         scsz = get(0,'screensize');
0049     else
0050         scsz = get(opt_gui,'position');
0051     end
0052     
0053     margin = 50;%marge
0054     nspaces = 1.5;%number of spaces between fields and pushbuttons
0055     lfactor = 1.0;%factor between fontsize and width
0056     lmaxmin = 18;%
0057     %
0058     fnames_all = fieldnames(s);
0059     nf_all = length(fnames_all);
0060     %
0061     s = putinfo_yp(s,sname,fexcept);
0062     %
0063     s = conc_struct_jd(s,sextra);
0064     %
0065     expert = zeros(1,nf_all);
0066     for iname = 1:nf_all,
0067         expert(iname) = s.expert.(fnames_all{iname});
0068     end
0069     %
0070     nexplist = find(~expert);
0071     fnames_nexp = fnames_all(nexplist);
0072     %
0073     isel = NaN;
0074     mod = zeros(1,nf_all);
0075     expmode = 0;
0076     %
0077     sinit = s;
0078     sinitvalues = '';
0079     sinitstrings = '';
0080     %
0081     while isel ~= 0,
0082         %
0083         if expmode == 0,
0084             fnames = fnames_nexp;
0085             switchstr = 'Enter expert mode (more parameters).';
0086             guistr = 'expert fields';
0087         else
0088             fnames = fnames_all;
0089             switchstr = 'Leave expert mode (main parameters).';
0090             guistr = 'main fields';
0091         end
0092         %
0093         buttonstr = {guistr,['reset ',sname],['return ',sname]};
0094         isellist = [-2,-4,0];
0095         %
0096         nf = length(fnames);
0097         %
0098         lmax = lmaxmin;
0099         %
0100         for iname = 1:nf,
0101             lmax = max([lmax,length(fnames{iname})]);
0102         end  
0103         emptstr = repmat(' ',[1,lmax]);
0104         %
0105         nmax = length(num2str(nf))+1;
0106         emptnstr = repmat(' ',[1,nmax]);
0107         %
0108         if ~opt_gui,
0109             %
0110             disp(' ');
0111             disp(['====> Fields of the structure ',sname]);
0112             disp(' ')
0113             %
0114         else
0115             %
0116             cwidth = 5*margin + 2*lfactor*lmax*ftsize;% column width
0117             nfh = fix((scsz(4) - 2*margin)/(3*ftsize) - nspaces);% maximum number of fields per column
0118             ncl = ceil(max([nf,1])/nfh);% number of columns
0119             width = cwidth*ncl;%figure width
0120             %
0121             if width > (scsz(3) - 2*margin),
0122                 error('Too many fields... improve GUI!')
0123             end
0124             %
0125             nfh = ceil(nf/ncl);% number of fields per column
0126             height = (nfh+nspaces)*3*ftsize;
0127             %
0128             cguipos = [(scsz(3) - width)/2,(scsz(4) - height)/2,width,height];
0129             %
0130             if islogical(opt_gui) || ~ishandle(opt_gui),
0131                 cgui = figure('visible','on','name',sname,'Position',cguipos,'menubar','none','numbertitle','off','resize','off');
0132             else
0133                 cguipos(4) = cguipos(4) + 2*ftsize + style.titlefontsize;
0134                 cgui = uipanel('Parent',opt_gui,'Title',sname,'units','pixels','Position',cguipos,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.titlefontsize);
0135             end
0136             %
0137             cguis = zeros(1,nf);
0138             cguic = zeros(1,nf);
0139             cguir = zeros(1,nf+3);
0140             %
0141         end
0142         %
0143         stype = zeros(1,nf);
0144         rev = zeros(1,nf);
0145         %
0146         for iname = 1:nf,
0147             fname = fnames{iname};
0148             fval = s.(fname);
0149             values = s.values.(fname);
0150             %
0151             if islogical(fval) || (iscell(values) && length(values) == 2 && islogical(values{1})),
0152                 stype(iname) = 0;
0153                 if fval,
0154                     sval = 'true';
0155                 else
0156                     sval = 'false';
0157                 end
0158                 if isempty(values),
0159                     values = {true,false};
0160                 end
0161             elseif ischar(fval),
0162                 stype(iname) = 1;
0163                 sval = fval;
0164             elseif isnumeric(fval),
0165                 %
0166                 valsize = size(fval);
0167                 stype(iname) = 6;
0168                 %
0169                 if length(valsize) > 2 || min(valsize) > 1,
0170                     sval = ['< ',num2str(length(valsize)),'-D array >'];
0171                 elseif numel(fval) > numlim
0172                     sval = ['< ',num2str(numel(fval)),' elements vector>'];  
0173                 else
0174                     if valsize(1) > 1,
0175                         rev(iname) = 1;
0176                         fval = fval(:).';
0177                     end
0178                     stype(iname) = 2;                
0179                     sval = num2str(fval);
0180                     if isempty(values),
0181                         values = [-Inf;Inf];
0182                     end
0183                 end
0184                 %
0185             elseif isstruct(fval),
0186                 stype(iname) = 3;
0187                 sval = '< fields structure >';
0188             elseif iscell(fval),
0189                 stype(iname) = 4;
0190                 sval = '< cell array >';
0191             else
0192                 stype(iname) = 5;
0193                 sval = '< unidentified type >';
0194             end
0195             %
0196             istr = num2str(iname);
0197             %
0198             if ~opt_gui,
0199                 %
0200                 disp(['[',istr,']',emptnstr(1:nmax-length(istr)),' : ',fname,emptstr(1:lmax - length(fname)),' : ',sval]);
0201                 %
0202             else
0203                 %
0204                 lref = cwidth*fix((iname - 1)/nfh);%left reference position for column
0205                 bref = (((nfh - rem(iname - 1,nfh) - 1)+nspaces)*3 + 0.5)*ftsize;%bottom reference position
0206                 %
0207                 sposition = [lref + margin,bref,cwidth/2  - 2.5*margin,2*ftsize];
0208                 cposition = [lref + cwidth/2  - 0.5*margin,bref,cwidth/2  - 2.5*margin,2*ftsize];
0209                 rposition = [lref + cwidth - 2*margin,bref,margin,2*ftsize];
0210                 %
0211                 cguis(iname) = uicontrol(cgui,'style','text','string',fname,'position',sposition,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'tooltipstring',sprintf(s.info.(fname)));
0212                 %
0213                 if stype(iname) == 0,%logical
0214                     cguic(iname) = uicontrol(cgui,'style','checkbox','string','','value',fval,'position',cposition,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'callback',@field_cbf);
0215                 elseif stype(iname) == 1,%string
0216                     if iscell(values),
0217                         for ielem = 1:length(values),
0218                             if strcmp(fval,values{ielem}),
0219                                 break
0220                             end
0221                         end
0222                         %
0223                         cguic(iname) = uicontrol(cgui,'style','popupmenu','string',values,'value',ielem,'position',cposition,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'callback',@field_cbf);
0224                     else
0225                         cguic(iname) = uicontrol(cgui,'style','edit','string',sval,'position',cposition,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'callback',@field_cbf);
0226                     end                
0227                 elseif stype(iname) == 2,%scalar or small vector
0228                     if iscell(values) || size(values,1) == 1,
0229                         if iscell(values),
0230                             for ielem = 1:length(values),
0231                                 if fval == values{ielem},
0232                                     break
0233                                 end
0234                             end
0235                         else
0236                             ielem = find(fval == values,1,'first');
0237                         end
0238                         %
0239                         cguic(iname) = uicontrol(cgui,'style','popupmenu','string',values,'value',ielem,'position',cposition,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'callback',@field_cbf);
0240                     elseif size(values,1) == 2,
0241                         cguic(iname) = uicontrol(cgui,'style','edit','string',sval,'position',cposition,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'callback',@field_cbf);
0242                     else
0243                         error('GUI error');
0244                     end                
0245                 elseif any(stype(iname) == [3:6]),%structure, cell, or large vector or 2D+ array
0246                     cguic(iname) = uicontrol(cgui,'style','pushbutton','string',sval,'position',cposition,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'callback',@field_cbf);
0247                     if d_opt == 0,
0248                         set(cguic(iname),'enable','off');
0249                     end
0250                 else                       
0251                     error('GUI error');
0252                 end
0253                 %
0254                 if ~isfield(sinitvalues,fname),
0255                     sinitvalues.(fname) = get(cguic(iname),'value');
0256                 end
0257                 if ~isfield(sinitstrings,fname),
0258                     sinitstrings.(fname) = get(cguic(iname),'string');
0259                 end
0260                 %
0261                 cguir(iname) = uicontrol(cgui,'style','pushbutton','string','reset','position',rposition,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'tooltipstring','Reset field to original value','callback',@pushbutton_cbf);
0262                 %
0263             end
0264             %
0265         end
0266         %
0267         if ~opt_gui,
0268             %
0269             disp(' ')
0270             %
0271             disp(['[-4]',emptnstr(1:nmax-2),' : Reset structure'])
0272             disp(['[-3]',emptnstr(1:nmax-2),' : Reset one field'])
0273             disp(['[-2]',emptnstr(1:nmax-2),' : ',switchstr])
0274             disp(['[-1]',emptnstr(1:nmax-2),' : Get fields info'])
0275             disp(['[0]',emptnstr(1:nmax-1),' : Return structure'])
0276             disp(' ')
0277             %
0278             isel = input_dke_yp('',0,-6:nf);
0279             disp(' ');
0280             %
0281         else
0282             %
0283             pwidth = min([lfactor*ftsize*(7 + length(sname)),width/3]); 
0284             %
0285             rposition1 = [width/6 - pwidth/2,0.5*ftsize,pwidth,2*ftsize];
0286             rposition2 = [width/2 - pwidth/2,0.5*ftsize,pwidth,2*ftsize];
0287             rposition3 = [5*width/6 - pwidth/2,0.5*ftsize,pwidth,2*ftsize];
0288             %
0289             cguir(nf+1) = uicontrol(cgui,'style','pushbutton','string',buttonstr{1},'position',rposition1,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'callback',@pushbutton_cbf);
0290             cguir(nf+2) = uicontrol(cgui,'style','pushbutton','string',buttonstr{2},'position',rposition2,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'tooltipstring','Reset all fields to original value','callback',@pushbutton_cbf);
0291             cguir(nf+3) = uicontrol(cgui,'style','pushbutton','string',buttonstr{3},'position',rposition3,'FontName',style.fontname,'FontUnits','pixels','FontSize',style.fontsize,'tooltipstring','Press to continue when done modifying the structure','callback',@pushbutton_cbf,'BackgroundColor',[0 0.75 0]);
0292             %
0293         end
0294         %
0295         if opt_gui,
0296             uiwait;%(cgui)
0297             delete(cgui);
0298         end
0299         %
0300         if isel == -4,
0301             s = sinit;
0302             mod = zeros(1,nf_all);
0303         end
0304         %
0305         if isel == -3,
0306             locisel = input_dke_yp('Number of the field to reset (enter 0 to cancel)',0,0:nf);
0307             if locisel > 0,
0308                 s.(fnames{locisel}) = sinit.(fnames{locisel});
0309                 if expmode,
0310                     mod(locisel) = 0;
0311                 else
0312                     mod(nexplist(locisel)) = 0;
0313                 end
0314             end
0315         end
0316         %
0317         if isel == -2,
0318             expmode = ~expmode;
0319         end
0320         %
0321         if isel == -1,
0322             %
0323             for iname = 1:nf,
0324                 %
0325                 fname = fnames{iname};
0326                 disp(['- ',fname,emptstr(1:lmax - length(fname)),' : ',getfieldinfo_jd(s,fname)]);
0327                 %
0328             end
0329         end
0330         %
0331         if isel > 0,
0332             %
0333             fname = fnames{isel};
0334             fval = s.(fname);
0335             values = s.values.(fname);
0336             locmod = 0;
0337             %
0338             if stype(isel) <= 2,
0339                 %
0340                 disp(['Field : ',fname,' : ',getfieldinfo_jd(s,fname)]);
0341                 [fval,locmod] = input_dke_yp(['New value for field : ',fname,' '],fval,values);
0342                 %
0343                 if stype(isel) == 0,
0344                     %
0345                     s.(fname) = logical(fval);
0346                     %
0347                 elseif stype(isel) == 1 || rev(isel) == 0,
0348                     %
0349                     s.(fname) = fval;
0350                     %
0351                 else % rev = 1
0352                     s.(fname) = fval(:);
0353                 end
0354                 %
0355             elseif stype(isel) == 3,
0356                 %
0357                 if d_opt == 1
0358                     %
0359                     [fval,locmod] = imod_struct_jd(fval,fname,1,opt_gui,struct,style);
0360                     s.(fname) = fval;
0361                     %
0362                 else
0363                     %
0364                     disp(['The substructure ',fname,' cannot be modified.'])
0365                     %
0366                 end
0367                 %
0368             elseif stype(isel) == 4,
0369                 %
0370                 if d_opt == 1
0371                     %
0372                     [fval,locmod] = imod_cell_jd(fval,fname,1,opt_gui);
0373                     s.(fname) = fval;
0374                     %
0375                 else
0376                     %
0377                     disp(['The subcell ',fname,' cannot be modified.'])
0378                     %
0379                 end
0380                 %
0381             elseif stype(isel) == 5,
0382                 %
0383                 disp(['The type of field ',fname,' cannot be identified.'])
0384                 %
0385             elseif stype(isel) == 6,
0386                 %
0387                 disp(['Field ',fname,' can be changed on command line only.'])
0388                 %
0389             end
0390             %
0391             if locmod == 1,
0392                 if expmode,
0393                     mod(isel) = 1;
0394                 else
0395                     mod(nexplist(isel)) = 1;
0396                 end
0397             end
0398             %
0399         end
0400         %
0401     end
0402     %
0403     mod = any(mod);
0404     s = rminfo(s,fexcept);
0405     %
0406     function pushbutton_cbf(hObject,eventdata)
0407         %
0408         iname = find(hObject == cguir);
0409         %
0410         if iname > nf,
0411             %
0412             isel = isellist(iname - nf);
0413             uiresume
0414             %
0415         else
0416             %
0417             fname = fnames{iname};
0418             s.(fname) = sinit.(fname);
0419             set(cguic(iname),'value',sinitvalues.(fname));
0420             set(cguic(iname),'string',sinitstrings.(fname));
0421             if expmode,
0422                 mod(iname) = 0;
0423             else
0424                 mod(nexplist(iname)) = 0;
0425             end
0426             %
0427         end
0428         %
0429     end
0430     %
0431     function field_cbf(hObject,eventdata)
0432         %
0433         iname = find(hObject == cguic);
0434         fname = fnames{iname};
0435         values = s.values.(fname);
0436         if expmode,
0437             imod = iname;
0438         else
0439             imod = (nexplist(iname));
0440         end
0441         %
0442         if stype(iname) == 0,%logical
0443             s.(fname) = get(hObject,'value');
0444             %
0445             if s.(fname) ~= sinit.(fname),
0446                 mod(imod) = 1;
0447             end
0448         elseif stype(iname) == 1,%string
0449             if iscell(values),
0450                 s.(fname) = values{get(hObject,'value')};
0451             else
0452                 s.(fname) = get(hObject,'string');
0453             end
0454             %
0455             if ~strcmp(s.(fname),sinit.(fname)),
0456                 mod(imod) = 1;
0457             end
0458         elseif stype(iname) == 2,%scalar or small vector
0459             %
0460             if iscell(values),
0461                 s.(fname) = values{get(hObject,'value')};
0462             elseif size(values,1) == 1,
0463                 s.(fname) = values(get(hObject,'value'));
0464             else
0465                 s.(fname) = str2num(get(hObject,'string'));
0466             end
0467             %
0468             if rev(iname) == 1,
0469                 s.(fname) = s.(fname).';
0470             end
0471             %
0472             if any(size(s.(fname)) ~= size(sinit.(fname))) || any(s.(fname) ~= sinit.(fname)),
0473                 mod(imod) = 1;
0474             end            
0475             %
0476         elseif stype(iname) == 3,%structure
0477             set(cgui,'Visible','off');
0478             [s.(fname),mod(imod)] = imod_struct_jd(s.(fname),fname,d_opt,opt_gui,struct,style);
0479             set(cgui,'Visible','on');
0480         elseif stype(iname) == 4,%cell
0481             [s.(fname),mod(imod)] = imod_cell_jd(s.(fname),fname,d_opt,opt_gui);
0482         elseif stype(iname) == 5,%unidentified type
0483             disp(['   ---> you can change the field ',fname,' manually. It is stored in the variable ''field''. Press ''return'' to validate.'])
0484             field = s.(fname);
0485             keyboard
0486             s.(fname) = field;
0487             mod(imod) = 1;
0488         elseif stype(iname) == 6,%large vector or 2D+ array
0489             disp(['   ---> you can change the array ',fname,' manually. It is stored in the variable ''field''. Press ''return'' to validate.'])
0490             field = s.(fname);
0491             keyboard
0492             s.(fname) = field;
0493             if any(size(s.(fname)) ~= size(sinit.(fname))) || any(s.(fname)(:) ~= sinit.(fname)(:)),
0494                 mod(imod) = 1;
0495             end                        
0496         else
0497             error('GUI error');
0498         end
0499         %
0500     end
0501     %
0502 end
0503 %
0504 function s = rminfo(s,fexcept)   
0505     for ifield = 1:length(fexcept),
0506         if isfield(s,fexcept{ifield}),
0507             s = rmfield(s,fexcept{ifield});
0508         end
0509     end    
0510     %s = rmfield(s,fexcept);
0511     fnames = fieldnames(s);
0512     for iname = 1:length(fnames);
0513         if isstruct(s.(fnames{iname})),
0514             s.(fnames{iname}) = rminfo(s.(fnames{iname}),fexcept);
0515         end
0516     end
0517 end

Community support and wiki are available on Redmine. Last update: 18-Apr-2019.