waiting for current folder viewer to expand

13 views (last 30 days)
I'm writing some code to expand the current folder viewer and I've found that expanding the folders, equivalent to clicking on the plus buttons, is a non-blocking call. The children of the folder are not valid until the folder has expanded. I'd like to put in some call that waits until the expansion is done but I'm not exactly sure how to proceed. Below is some code that will create a testing folder structure. The second part of code makes the expansion requests and indicates the failure point.
%create lots of folders in a folder called 'test_root' in the current directory
root = cd;
mkdir(cd,'test_root')
cd test_root
for i = 1:50
root2 = cd;
name = sprintf('test%d',i);
mkdir(cd,name);
cd(name)
for j = 1:20
root3 = cd;
name = sprintf('test%d',j);
mkdir(cd,name);
cd(name)
for k = 1:5
root4 = cd;
name = sprintf('test%d',k);
mkdir(cd,name);
end
cd(root3)
end
cd(root2)
end
cd(root)
cd test_root
%-------------------------------------------------------
%Now for expansion testing
h = com.mathworks.mde.explorer.Explorer.getInstance;
table = h.getTable;
table.collapseAll;
pause(1)
r = table.getRowAt(0);
%n1 will be at 1 for non-expanded folders
n1 = r.getChildrenCount;
r.setExpanded(true);
%'x' says true, even though r2 will be null
%suggests that the property value does not wait until expansion finishes
x = r.isExpanded;
%Setting the pause value longer allows the expansion to occur
%and for r2 to be valid
pause(0.001);
%r2 = [] if we ask for it before rendering has completed
%I'm not sure if r2 is valid after the first folder has been rendered, or if all folders need to be rendered before r2 is valid
%in the latter case r2 could be used to signal that expansion is done
r2 = r.getChildAt(1);
%If we go too quickly, n2 will still be at 1
n2 = r.getChildrenCount;
I can probably put together a hack based on getting the directory listing (e.g. dir) and waiting until the # of children equals the returned value, but I was hoping someone with more Java experience might have some insight into how to look for events that would notify the user that rendering has completed (or even better, if someone has actually has knowledge of this interface and could comment accordingly).

Accepted Answer

Jim Hokanson
Jim Hokanson about 2 hours ago
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

More Answers (0)

Categories

Find more on Filename Construction in Help Center and File Exchange

Products


Release

R2018b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!