сделано подключение сурсов по конфигу, но надо бы как-то структуризировать

This commit is contained in:
Razvalyaev 2025-06-15 23:39:34 +03:00
parent 982d29560f
commit 5a92e0bec0

View File

@ -54,9 +54,11 @@ classdef periphConfig
end end
end end
periphConfig.create_all_code_storage_params(blockPath, config); periphConfig.create_all_code_storage_params(blockPath, config);
periphConfig.cleanup_obsolete_code_params(blockPath, config); % periphConfig.cleanup_obsolete_code_params(blockPath, config);
periphConfig.update_all();
% Восстанавливаем таблицы % Восстанавлиperiph = allTabNamesваем таблицы
customtable.restore_all_tables(tableNames, columns_backup); customtable.restore_all_tables(tableNames, columns_backup);
catch catch
% Восстанавливаем таблицы % Восстанавливаем таблицы
@ -157,65 +159,149 @@ classdef periphConfig
fclose(fid); fclose(fid);
end end
function update_callback() function update_all()
blockPath = gcb; blockPath = gcb;
mask = Simulink.Mask.get(blockPath); mask = Simulink.Mask.get(blockPath);
config = periphConfig.read_config(blockPath); config = periphConfig.read_config(blockPath);
periphs = fieldnames(config);
for i = 1:numel(periphs)
periph = periphs{i};
% Сохраняем код, если он есть
periphConfig.store_single_periph_code(mask, periph, config.(periph));
end
containerName = 'configTabAll'; containerName = 'configTabAll';
container = mask.getDialogControl(containerName); container = mask.getDialogControl(containerName);
paramsAll = mcuMask.collect_all_parameters(container); paramsAll = mcuMask.collect_all_parameters(container);
% Цикл по параметрам % Получаем все имена в кладок из container (у вас должен быть container)
for i = 1:length(paramsAll) allTabs = container.DialogControls;
name = paramsAll{i}; allTabNames = arrayfun(@(t) t.Name, allTabs, 'UniformOutput', false);
% Ищем параметры вида Tab_<Periph>_Enable fieldsConfig = fieldnames(config);
expr = '^Tab_(\w+)_Enable$'; % Цикл по всем вкладкам в контейнере
tokens = regexp(name, expr, 'tokens'); for i = 1:length(allTabNames)
periph = fieldsConfig{i};
if ~isempty(tokens)
periph = tokens{1}{1}; % Извлекаем имя вкладки % Попытка найти параметр чекбокса Tab_<Periph>_Enable
paramObj = mask.getParameter(name); checkboxName = ['Tab_' periph '_Enable'];
if ismember(checkboxName, paramsAll)
% Чекбокс есть - проверяем его состояние
paramObj = mask.getParameter(checkboxName);
val = paramObj.Value; val = paramObj.Value;
if strcmpi(val, 'off') try
% Найдём вкладку по имени tab = container.getDialogControl(periph);
try if strcmpi(val, 'off')
tab = container.getDialogControl(periph);
tab.Enabled = 'off'; tab.Enabled = 'off';
periphConfig.clear_single_periph_code_param(mask, periph); % Рекурсивно очищаем связанные скрытые параметры
catch periphConfig.clear_tab_params(mask, config.(periph), periph);
warning('Вкладка с именем "%s" не найдена.', periph); else
end
else
% Найдём вкладку по имени
try
tab = container.getDialogControl(periph);
tab.Enabled = 'on'; tab.Enabled = 'on';
periphConfig.store_single_periph_code(mask, periph, config.(periph)); periphConfig.sync_tab_params(mask, config.(periph), periph);
catch
warning('Вкладка с именем "%s" не найдена.', periph);
end end
catch
warning('Вкладка с именем "%s" не найдена.', periph);
end end
else
% Чекбокса нет просто пытаемся включить вкладку, если она есть
try
tab = container.getDialogControl(periph);
tab.Enabled = 'on';
% Опционально можно синхронизировать параметры, если есть config поле
if isfield(config, periph)
periphConfig.sync_tab_params(mask, config.(periph), periph);
end
catch
% Можно не выводить предупреждение вкладка может быть необязательной
% warning('Вкладка с именем "%s" не найдена.', periph);
end
end end
end end
periphConfig.getWrapperCode(); periphConfig.getWrapperCode();
end end
function update_callback(paramName)
blockPath = gcb;
mask = Simulink.Mask.get(blockPath);
hObj = mask.getParameter(paramName);
config = periphConfig.read_config(blockPath);
container = mask.getDialogControl('configTabAll');
% === Проверка на Tab_<Periph>_Enable ===
exprTab = '^Tab_(\w+)_Enable$';
tokensTab = regexp(paramName, exprTab, 'tokens');
if ~isempty(tokensTab)
periph = tokensTab{1}{1};
try
tab = container.getDialogControl(periph);
paramVal = hObj.Value;
if strcmpi(paramVal, 'off')
tab.Enabled = 'off';
if isfield(config, periph)
periphConfig.clear_tab_params(mask, config.(periph), periph);
end
else
tab.Enabled = 'on';
if isfield(config, periph)
periphConfig.sync_tab_params(mask, config.(periph), periph);
end
end
catch
warning('Ошибка обработки вкладки "%s".', periph);
end
periphConfig.getWrapperCode();
return;
end
% === Проверка на параметр, связанный с Sources/Includes ===
% Проверка: это параметр, у которого есть соответствующий Hidden_<Name>_Sources или Hidden_<Name>_Includes
nameBase = paramName;
paramNames = string({mask.Parameters.Name});
hasSources = any(paramNames == "Hidden_" + nameBase + "_Sources");
hasIncludes = any(paramNames == "Hidden_" + nameBase + "_Includes");
if hasSources || hasIncludes
useVal = hObj.Value;
% Получаем содержимое config по nameBase возможно, вложенное
try
valueStruct = periphConfig.get_field(config, nameBase);
catch
warning('Не удалось найти путь %s в config.', nameBase);
return;
end
if strcmpi(useVal, 'on')
try
periphConfig.store_single_periph_code(mask, nameBase, valueStruct);
catch
warning('Не удалось сохранить параметры для %s.', nameBase);
end
else
periphConfig.clear_single_periph_code_param(mask, nameBase);
end
periphConfig.getWrapperCode();
return;
end
% === Если не подошло ни под одно из условий ===
warning('Объект "%s" не поддерживается универсальным коллбеком.', paramName);
end
function getWrapperCode() function getWrapperCode()
blockPath = gcb; blockPath = gcb;
CodeStruct = periphConfig.restore_periph_code_from_mask(blockPath); CodeStruct = periphConfig.restore_periph_code_from_mask(blockPath);
@ -231,53 +317,162 @@ classdef periphConfig
methods(Static, Access=private) methods(Static, Access=private)
function create_all_code_storage_params(blockPath, config) function clear_tab_params(mask, configStruct, prefix, depth)
mask = Simulink.Mask.get(blockPath); if nargin < 4
existingParams = arrayfun(@(p) p.Name, mask.Parameters, 'UniformOutput', false); depth = 0;
end
maxDepth = 3; % Максимальная глубина рекурсии
fields = fieldnames(configStruct);
periphs = fieldnames(config); for i = 1:numel(fields)
for i = 1:numel(periphs) key = fields{i};
periph = periphs{i}; value = configStruct.(key);
paramName = [prefix '_' key];
% Проверяем, нужно ли создавать параметры if isstruct(value)
hasSources = isfield(config.(periph), 'Sources'); if depth < maxDepth
hasIncludes = isfield(config.(periph), 'Includes'); % Рекурсивный вызов для вложенных структур с увеличением глубины
periphConfig.clear_tab_params(mask, value, paramName, depth + 1);
if ~hasSources && ~hasIncludes
continue;
end
% Добавляем параметр для Sources
if hasSources
srcParamName = ['Hidden_' periph '_Sources'];
if ~ismember(srcParamName, existingParams)
mask.addParameter( ...
'Name', srcParamName, ...
'Type', 'edit', ...
'Prompt', '', ...
'Value', '', ...
'Visible', 'off' ...
);
fprintf('Создан скрытый параметр: %s\n', srcParamName);
end end
end else
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
% Добавляем параметр для Includes baseName = periphConfig.get_final_name_from_prefix(prefix);
if hasIncludes periphConfig.clear_single_periph_code_param(mask, baseName);
incParamName = ['Hidden_' periph '_Includes'];
if ~ismember(incParamName, existingParams)
mask.addParameter( ...
'Name', incParamName, ...
'Type', 'edit', ...
'Prompt', '', ...
'Value', '', ...
'Visible', 'off' ...
);
fprintf('Создан скрытый параметр: %s\n', incParamName);
end end
end end
end end
end end
function sync_tab_params(mask, configStruct, prefix, depth)
if nargin < 4
depth = 0;
end
maxDepth = 3; % Максимальная глубина рекурсии
fields = fieldnames(configStruct);
for i = 1:numel(fields)
key = fields{i};
value = configStruct.(key);
paramName = [prefix '_' key];
if isstruct(value)
if depth < maxDepth
% Рекурсивный вызов для вложенных структур с увеличением глубины
periphConfig.sync_tab_params(mask, value, paramName, depth + 1);
end
else
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
baseName = periphConfig.get_final_name_from_prefix(prefix);
periphConfig.store_single_periph_code(mask, baseName, configStruct);
end
end
end
end
function short = get_final_name_from_prefix(prefix)
% Берёт последнее имя после "_" (читаемое имя)
parts = strsplit(prefix, '_');
short = parts{end};
end
function value = get_field(configStruct, targetConfig)
value = [];
fields = fieldnames(configStruct);
for i = 1:numel(fields)
key = fields{i};
if strcmp(key, targetConfig)
value = configStruct.(key);
return; % нашли и возвращаем
elseif isstruct(configStruct.(key))
value = periphConfig.get_field(configStruct.(key), targetConfig);
if ~isempty(value)
return; % нашли во вложенной структуре
end
end
end
% Если не нашли, можно выбросить ошибку или вернуть пустое
if isempty(value)
% error('Поле "%s" не найдено в структуре.', targetConfig);
end
end
function create_all_code_storage_params(blockPath, config)
mask = Simulink.Mask.get(blockPath);
containerName = 'configTabAll';
container = mask.getDialogControl(containerName);
existingParams = mcuMask.collect_all_parameters(container);
% Убедимся, что контейнер существует
tabName = 'hiddenCodeTab';
tab = mask.getDialogControl(tabName);
if isempty(tab)
tab = container.addDialogControl('tab', tabName);
tab.Prompt = 'Hidden Code Settings';
tab.Visible = 'off';
else
tab.Visible = 'off';
end
% Запуск рекурсивного обхода
periphConfig.process_struct_recursive(mask, tabName, config, {}, existingParams);
end
function process_struct_recursive(mask, tabName, currentStruct, nameStack, existingParams)
fields = fieldnames(currentStruct);
for i = 1:numel(fields)
fieldName = fields{i};
value = currentStruct.(fieldName);
newStack = [nameStack, fieldName]; % Добавляем уровень к имени
% Если value структура, обходим дальше
if isstruct(value)
% Проверяем: это структура с Sources/Includes или просто промежуточный узел?
hasSources = isfield(value, 'Sources');
hasIncludes = isfield(value, 'Includes');
if hasSources
periphConfig.addHiddenParam(mask, tabName, fieldName, 'Sources', existingParams);
end
if hasIncludes
periphConfig.addHiddenParam(mask, tabName, fieldName, 'Includes', existingParams);
end
% Рекурсивно продолжаем обход
periphConfig.process_struct_recursive(mask, tabName, value, newStack, existingParams);
end
end
end
function addHiddenParam(mask, containerName, nameBase, kind, existingParams)
% Преобразуем к красивому имени
prettyName = strrep(nameBase, '_', ' ');
paramName = ['Hidden_' nameBase '_' kind];
if ismember(paramName, existingParams)
return;
end
mask.addParameter( ...
'Name', paramName, ...
'Type', 'edit', ...
'Prompt', ['Hidden ' prettyName ' ' kind], ...
'Value', '', ...
'Visible', 'off', ...
'Container', containerName ...
);
fprintf('Создан скрытый параметр: %s\n', paramName);
end
function cleanup_obsolete_code_params(blockPath, config) function cleanup_obsolete_code_params(blockPath, config)
mask = Simulink.Mask.get(blockPath); mask = Simulink.Mask.get(blockPath);
@ -357,8 +552,6 @@ classdef periphConfig
codeStruct.Includes = allIncludes; codeStruct.Includes = allIncludes;
end end
function clear_single_periph_code_param(mask, periph) function clear_single_periph_code_param(mask, periph)
% Формируем имена параметров % Формируем имена параметров
paramNames = { paramNames = {
@ -380,7 +573,7 @@ classdef periphConfig
function store_single_periph_code(mask, periph, code) function store_single_periph_code(mask, periph, code)
% Сохраняем Sources, если они есть % Сохраняем Sources, если они есть
if isfield(code, 'Sources') if isfield(code, 'Sources')
paramName = ['Hidden_' periph '_Sources']; paramName = ['Hidden_' char(periph) '_Sources'];
try try
param = mask.getParameter(paramName); param = mask.getParameter(paramName);
param.Value = periphConfig.convert_code_value(code.Sources); param.Value = periphConfig.convert_code_value(code.Sources);
@ -411,7 +604,7 @@ classdef periphConfig
elseif iscell(codeField) elseif iscell(codeField)
value = strjoin(codeField, newline); value = strjoin(codeField, newline);
else else
warning('Неподдерживаемый тип данных: сохранено как пустая строка'); % warning('Неподдерживаемый тип данных: сохранено как пустая строка');
value = ''; value = '';
end end
end end
@ -598,7 +791,8 @@ classdef periphConfig
end end
end end
param.Callback = 'periphConfig.update_callback();'; callback = sprintf('periphConfig.update_callback("%s");', paramName);
param.Callback = callback;
end end