diff --git a/GUIs/GuiNa.mlapp b/GUIs/GuiNa.mlapp index c5dd836..d622b06 100644 Binary files a/GUIs/GuiNa.mlapp and b/GUIs/GuiNa.mlapp differ diff --git a/GUIs/GuiScope.mlapp b/GUIs/GuiScope.mlapp index f345e28..ff1659b 100644 Binary files a/GUIs/GuiScope.mlapp and b/GUIs/GuiScope.mlapp differ diff --git a/GUIs/GuiTlb.mlapp b/GUIs/GuiTlb.mlapp index 3dd195e..907e153 100644 Binary files a/GUIs/GuiTlb.mlapp and b/GUIs/GuiTlb.mlapp differ diff --git a/Utility functions/App utilities/linkGuiElement.m b/Utility functions/App utilities/linkGuiElement.m index 3ec175d..6b2ecfe 100644 --- a/Utility functions/App utilities/linkGuiElement.m +++ b/Utility functions/App utilities/linkGuiElement.m @@ -1,132 +1,135 @@ % By using app.linked_elem_list, create a correspondence between a property % of MyInstrument class (named prop_tag) and an element of the app gui function linkGuiElement(app, elem, prop_tag, varargin) p=inputParser(); % GUI control element addRequired(p,'elem'); % Instrument command to be linked to the GUI element addRequired(p,'prop_tag',@ischar); % If input_presc is given, the value assigned to the instrument propery % is related to the value x displayed in GUI as x/input_presc. addParameter(p,'input_presc',1,@isnumeric); % Add an arbitrary function for processing the value, read from the % device before outputting it. addParameter(p,'out_proc_fcn',@(x)x,@(f)isa(f,'function_handle')); addParameter(p,'create_callback',true,@islogical); % For drop-down menues initializes entries automatically based on the % list of values. Ignored for all the other control elements. addParameter(p,'init_val_list',false,@islogical); parse(p,elem,prop_tag,varargin{:}); % Check if the property is present in the app, otherwise disable the % gui element tmpval = app; tag_split=regexp(prop_tag,'\.','split'); for j=1:length(tag_split) try tmpval=tmpval.(tag_split{j}); catch + disp(['Property corresponding to tag ',prop_tag,... + ' is not accesible, element is not linked.']) elem.Enable='off'; return end end - - % The property-control link is established by assigning the tag - % and adding the control to the list of linked elements - elem.Tag = prop_tag; - app.linked_elem_list = [app.linked_elem_list, elem]; % If the create_callback is true, assign genericValueChanged as % callback if p.Results.create_callback assert(ismethod(app,'createGenericCallback'), ['App needs to ',... 'contain public createGenericCallback method to automatically'... 'assign callbacks. Use ''create_callback'',false in order to '... 'disable automatic callback']); elem.ValueChangedFcn = createGenericCallback(app); % Make callbacks non-interruptible for other callbacks % (but are still interruptible for timers) try elem.Interruptible = 'off'; elem.BusyAction = 'cancel'; catch warning('Could not make callback for %s non-interruptible',... prop_tag); end end % If prescaler is given, add it to the element as a new property if p.Results.input_presc ~= 1 if isprop(elem, 'InputPrescaler') warning(['The InputPrescaler property already exists',... ' in the control element']); else addprop(elem,'InputPrescaler'); end elem.InputPrescaler = p.Results.input_presc; end % Add an arbitrary function for output processing if ~ismember('out_proc_fcn',p.UsingDefaults) if isprop(elem, 'OutputProcessingFcn') warning(['The OutputProcessingFcn property already exists',... ' in the control element']); else addprop(elem,'OutputProcessingFcn'); end elem.OutputProcessingFcn = p.Results.out_proc_fcn; end %% Code below is applicable when linking to commands of MyScpiInstrument - if strcmp(tag_split{1},'Instr') + if strcmp(tag_split{1},'Instr')&&... + ismember(tag_split{2},app.Instr.command_names) cmd=tag_split{2}; % If supplied command does not have read permission, issue warning. if ~contains(app.Instr.CommandList.(cmd).access,'r') fprintf(['Instrument command ''%s'' does not have read permission,\n',... 'corresponding gui element will not be automatically ',... 'syncronized\n'],cmd); % Try switching color of the gui element to orange warning_color = [0.93, 0.69, 0.13]; try elem.BackgroundColor = warning_color; catch try elem.FontColor = warning_color; catch end end end % Auto initialization of entries, for dropdown menus only if p.Results.init_val_list && isequal(elem.Type, 'uidropdown') try cmd_val_list = app.Instr.CommandList.(cmd).val_list; if all(cellfun(@ischar, cmd_val_list)) % If the command has only string values, get the list of % values ignoring abbreviations cmd_val_list = stdValueList(app.Instr, cmd); elem.Items = lower(cmd_val_list); elem.ItemsData = cmd_val_list; else % Items in a dropdown should be strings, so convert if % necessary str_list=cell(length(cmd_val_list), 1); for i=1:length(cmd_val_list) if ~ischar(cmd_val_list{i}) str_list{i}=num2str(cmd_val_list{i}); end end elem.Items = str_list; % Put raw values in ItemsData elem.ItemsData = cmd_val_list; end catch warning(['Could not automatically assign values',... ' when linking ',cmd,' property']); end end end + + % The property-control link is established by assigning the tag + % and adding the control to the list of linked elements + elem.Tag = prop_tag; + app.linked_elem_list = [app.linked_elem_list, elem]; end diff --git a/Utility functions/App utilities/updateLinkedGuiElements.m b/Utility functions/App utilities/updateLinkedGuiElements.m index 94a6089..4be4ed3 100644 --- a/Utility functions/App utilities/updateLinkedGuiElements.m +++ b/Utility functions/App utilities/updateLinkedGuiElements.m @@ -1,33 +1,39 @@ % Set values for all the gui elements listed in app.linked_elem_list % according to the properties of an object % Instrument property corresponds to the control element having the same % tag as property name, may be a filed of structure or a property of class % If specified within the control element OutputProcessingFcn or % InputPrescaler is applied to the property value first -function updateLinkedGuiElements(app) +function updateLinkedGuiElements(app) + % Record indices at which errors occurred + broken_ind=[]; for i=1:length(app.linked_elem_list) tmpelem = app.linked_elem_list(i); try % update the element value based on app.(tag), % where tag can contain a reference to sub-objects tmpval = app; % regexp is faster at splitting than strsplit prop_list=regexp(tmpelem.Tag,'\.','split'); for j=1:length(prop_list) tmpval=tmpval.(prop_list{j}); end % scale the value if the control element has a prescaler if isprop(tmpelem, 'OutputProcessingFcn') tmpval = tmpelem.OutputProcessingFcn(tmpval); elseif isprop(tmpelem, 'InputPrescaler') tmpval = tmpval*tmpelem.InputPrescaler; end tmpelem.Value = tmpval; catch - warning(['Could not update the value of element ',... - 'with tag ''%s'' and value:'],tmpelem.Tag); - disp(tmpval) + warning(['Could not update the value of element with tag ''%s'' ',... + 'and value ''%s''. The element will be disabled.'],... + tmpelem.Tag,var2str(tmpval)); + tmpelem.Enable='off'; + broken_ind=[broken_ind,i]; end end + % Delete the element from list + app.linked_elem_list(broken_ind)=[]; end