I ended up going with the hack, sort of.
Two things of importance:
1) I iterate through using the absolute row. Before expansion I check if expanded. If expanded, there is nothing to do. If not expanded, I get the total row count and then wait for the expansion to occur. Note, this currently assumes expansion is possible (which in my case it is).
2) When expanded, the first child is now the previous row number + 1 (by definition).
Here's some code that will expand the current directory to a file or folder that is a subdirectory of the current directory:
function expandToPath(target_path)
% EXPANDTOPATH Expands the Current Folder browser to show the specified path
%
% Usage:
% expandToPath('D:\repos\matlab\laborie_uds_matlab\+laborie\+utils')
TIMEOUT_SECONDS = 5;
POLL_INTERVAL = 0.05; % 50ms between checks
% Get the file browser tree component
%---------------------------------------------------------
%
% MAGIC
%
% Not sure where I got this bit from. When writing this function
% I pulled this from this older post of mine:
% https://www.mathworks.com/matlabcentral/answers/479982-waiting-for-current-folder-viewer-to-expand
h = com.mathworks.mde.explorer.Explorer.getInstance();
tree = h.getTable;
child = tree.getRowAt(0); %0 is first row in table/box
% Normalize the target path (remove trailing filesep if present)
target_path = fullfile(target_path); % Normalize
if endsWith(target_path, filesep)
target_path = target_path(1:end-1);
end
current_root = cd();
% Ensure currentRoot is part of targetPath
if ~startsWith(target_path, current_root, 'IgnoreCase', true)
error('expandToPath:InvalidPath', ...
'Target path "%s" is not under current folder "%s"', ...
target_path, current_root);
end
%Note file is OK for files or folders
if ~exist(target_path,'file')
error('The requested path does not exist\nmissing:%s',target_path)
end
% Get the relative path from current root
relative_path = target_path(length(current_root)+1:end);
if startsWith(relative_path, filesep)
relative_path = relative_path(2:end);
end
% If we're already at the target, nothing to do
if isempty(relative_path)
fprintf('Already at target path: %s\n', target_path);
return;
end
% Split relative path into parts
path_parts = strsplit(relative_path, filesep);
% Start from row 0 (root level)
row_number = 0;
%4 pathParts - 4th is m file or target
%
%1 -> end of running gets you to 1st element
%2 -> get to 2
n_parts_traverse = length(path_parts);
for depth_idx = 1:n_parts_traverse
fprintf('Depth: %d ------------------\n',depth_idx)
% searchName = pathParts{depthIdx};
% searchFullPath = fullfile(currentRoot, pathParts{1:depthIdx});
%
%We start inside a folder at the first element. On the first
%loop that folder is result of cd()
child_item = child.getItem();
item_location = char(child_item.getLocation());
fprintf('Current parent: %s\n',item_location)
%Within a folder, find the relevant sub-folder or final item
%-----------------------------------------------------------
child_found = false;
% fprintf('Row before search: %d\n',row_number)
while ~child_found
child_item = child.getItem();
item_location = char(child_item.getLocation());
fprintf('Going to: %s\n',item_location)
if startsWith(target_path,item_location)
fprintf('Matched: %s\n',item_location)
child_found = true;
else
%For now we can only specify rows, not siblings
%- there is a nextSibling function but I can't get it to
% work
%- This increments rows until we get back to the same
%level of the current object. This is an issue when the
%item is expanded, such that the next row is not the next
%sibling but rather is a child of the folder we don't care
%about
[child,row_number] = h__getNextSibling(child,tree,row_number);
%Note, techically child can be empty, but I don't think
%that happens IF we know that the target is a child
%of the current folder
end
end
% fprintf('Next sibling row: %d\n',row_number)
child_item = child.getItem();
item_location = char(child_item.getLocation());
%Are we at the final location
if depth_idx == n_parts_traverse
continue
end
if child.isExpanded
fprintf('Is expanded: %s\n',item_location)
row_number = row_number+1;
child = tree.getRowAt(row_number);
continue
end
fprintf('Expanding: %s\n',item_location)
start_row_count = tree.getRowCount();
child.setExpanded(true);
successful_expansion = false;
h_tic = tic();
while toc(h_tic) < TIMEOUT_SECONDS
pause(POLL_INTERVAL);
row_count = tree.getRowCount();
if row_count ~= start_row_count
successful_expansion = true;
break
end
end
if ~successful_expansion
error('Expansion failed')
else
row_number = row_number+1;
child = tree.getRowAt(row_number);
end
end
end
function [sibling,row_number] = h__getNextSibling(row,tree,row_number)
current_level = row.getLevel();
done = false;
while ~done
row_number = row_number + 1;
row2 = tree.getRowAt(row_number);
done = isempty(row2) || row2.getLevel() == current_level;
end
sibling = row2;
end