# HG changeset patch # Parent 26c861b0abe38a2ee40b504a902ddb6180ce97cd # User Jesse Glick #206556: asynch ChildFactory has poor support for incremental display. diff --git a/hudson/nbproject/project.xml b/hudson/nbproject/project.xml --- a/hudson/nbproject/project.xml +++ b/hudson/nbproject/project.xml @@ -179,7 +179,7 @@ - 7.9 + 7.27 diff --git a/hudson/src/org/netbeans/modules/hudson/ui/nodes/HudsonJobNode.java b/hudson/src/org/netbeans/modules/hudson/ui/nodes/HudsonJobNode.java --- a/hudson/src/org/netbeans/modules/hudson/ui/nodes/HudsonJobNode.java +++ b/hudson/src/org/netbeans/modules/hudson/ui/nodes/HudsonJobNode.java @@ -46,7 +46,6 @@ import java.io.CharConversionException; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import javax.swing.Action; import org.netbeans.modules.hudson.api.HudsonJob; @@ -94,24 +93,15 @@ } return Children.create(new ChildFactory() { final Object WORKSPACE = new Object(); - LinkedList builds; protected @Override boolean createKeys(List toPopulate) { - if (Thread.interrupted()) { - return true; - } else if (builds == null) { - // XXX would be nicer to avoid adding this in case there is no remote workspace... - toPopulate.add(WORKSPACE); - builds = new LinkedList(job.getBuilds()); - return false; - } else if (builds.isEmpty()) { - return true; - } else { + // XXX would be nicer to avoid adding this in case there is no remote workspace... + toPopulate.add(WORKSPACE); + for (HudsonJobBuild b : job.getBuilds()) { // Processing one build at a time, make sure its result is known (blocking call). - HudsonJobBuild b = builds.removeFirst(); b.getResult(); toPopulate.add(b); - return false; } + return true; } protected @Override Node createNodeForKey(Object key) { if (key == WORKSPACE) { diff --git a/maven/nbproject/project.xml b/maven/nbproject/project.xml --- a/maven/nbproject/project.xml +++ b/maven/nbproject/project.xml @@ -349,7 +349,7 @@ - 7.5 + 7.27 diff --git a/maven/src/org/netbeans/modules/maven/nodes/ModulesNode.java b/maven/src/org/netbeans/modules/maven/nodes/ModulesNode.java --- a/maven/src/org/netbeans/modules/maven/nodes/ModulesNode.java +++ b/maven/src/org/netbeans/modules/maven/nodes/ModulesNode.java @@ -155,12 +155,7 @@ @Override protected boolean createKeys(final List modules) { - List all = project.getOriginalMavenProject().getModules(); - int alreadyAdded = modules.size(); - if (alreadyAdded >= all.size()) { - return true; - } - String module = all.get(alreadyAdded); + for (String module : project.getOriginalMavenProject().getModules()) { File base = project.getOriginalMavenProject().getBasedir(); File projDir = FileUtil.normalizeFile(new File(base, module)); FileObject fo = FileUtil.toFileObject(projDir); @@ -174,7 +169,6 @@ wr.isAggregator = NbMavenProject.TYPE_POM.equals(mp.getPackaging()) && !mp.getModules().isEmpty(); wr.provider = prj.getLookup().lookup(LogicalViewProvider.class); modules.add(wr); - return false; } } catch (IllegalArgumentException ex) { ex.printStackTrace();//TODO log ? @@ -184,15 +178,12 @@ } else { //TODO broken module reference.. show as such.. } - modules.add(new Wrapper()); // broken submodule ref - return false; + } + return true; } @Override protected Node createNodeForKey(Wrapper wr) { - if (wr.proj == null) { - return null; - } return new ProjectFilterNode(project, wr.proj, wr.provider.createLogicalView(), wr.isAggregator); } diff --git a/openide.nodes/apichanges.xml b/openide.nodes/apichanges.xml --- a/openide.nodes/apichanges.xml +++ b/openide.nodes/apichanges.xml @@ -49,6 +49,29 @@ Nodes API + + + ChildFactory.createKeys better supports incremental display + + + + +

+ Existing factories which returned false from createKeys + may continue to do so with the same behavior, but should consider + just producing all keys within the body of the loop instead. +

+
+ +

+ An implementation of ChildFactory.createKeys may now + use List.add a number of times and return true at the + end, while still displaying keys incrementally. +

+
+ + +
A way to show a custom editor dialog for a property diff --git a/openide.nodes/manifest.mf b/openide.nodes/manifest.mf --- a/openide.nodes/manifest.mf +++ b/openide.nodes/manifest.mf @@ -2,5 +2,5 @@ OpenIDE-Module: org.openide.nodes OpenIDE-Module-Localizing-Bundle: org/openide/nodes/Bundle.properties AutoUpdate-Essential-Module: true -OpenIDE-Module-Specification-Version: 7.26 +OpenIDE-Module-Specification-Version: 7.27 diff --git a/openide.nodes/src/org/openide/nodes/AsynchChildren.java b/openide.nodes/src/org/openide/nodes/AsynchChildren.java --- a/openide.nodes/src/org/openide/nodes/AsynchChildren.java +++ b/openide.nodes/src/org/openide/nodes/AsynchChildren.java @@ -164,6 +164,7 @@ volatile boolean cancelled = false; volatile boolean notified; private final Object notifyLock = new Object(); + private static final class Stop extends RuntimeException {} public void run() { boolean fail = cancelled || Thread.interrupted(); logger.log (Level.FINE, "Running background children creation on " + //NOI18N @@ -172,7 +173,21 @@ setKeys (Collections.emptyList()); return; } - List keys = new LinkedList (); + List keys = new LinkedList () { + @Override public boolean add(T e) { + if (cancelled || Thread.interrupted()) { + throw new Stop(); + } + super.add(e); + LinkedList newKeys = new LinkedList(this); + Node n = factory.getWaitNode(); + if (n != null) { + newKeys.add(n); + } + setKeys(newKeys); + return true; + } + }; boolean done; do { synchronized (notifyLock) { @@ -185,12 +200,23 @@ setKeys (Collections.emptyList()); return; } - done = factory.createKeys (keys); + try { + done = factory.createKeys(keys); + } catch (Stop stop) { + done = true; + } if (cancelled || Thread.interrupted()) { setKeys (Collections.emptyList()); return; } - setKeys (new LinkedList (keys)); + LinkedList newKeys = new LinkedList(keys); + if (!done) { + Node n = factory.getWaitNode(); + if (n != null) { + newKeys.add(n); + } + } + setKeys (newKeys); } while (!done && !Thread.interrupted() && !cancelled); initialized = done; } diff --git a/openide.nodes/src/org/openide/nodes/ChildFactory.java b/openide.nodes/src/org/openide/nodes/ChildFactory.java --- a/openide.nodes/src/org/openide/nodes/ChildFactory.java +++ b/openide.nodes/src/org/openide/nodes/ChildFactory.java @@ -131,7 +131,11 @@ * Children.create() with the asynchronous parameter * set to true. If not, then no guarantees are made as to what * the calling thread is. - * + *

Returning false is tricky since there is no way to tell whether + * the loop has been restarted except by examining what is already in + * the list. As of 7.27 it is generally unnecessary since calls to + * {@link List#add(Object)} will immediately display the new element + * as well as checking for interruption. * @param toPopulate A list to add key objects to * @return true if the list of keys has been completely populated, * false if the list has only been partially populated and diff --git a/projectui/nbproject/project.xml b/projectui/nbproject/project.xml --- a/projectui/nbproject/project.xml +++ b/projectui/nbproject/project.xml @@ -190,7 +190,7 @@ - 6.2 + 7.27 diff --git a/projectui/src/org/netbeans/modules/project/ui/TemplateChooserPanelGUI.java b/projectui/src/org/netbeans/modules/project/ui/TemplateChooserPanelGUI.java --- a/projectui/src/org/netbeans/modules/project/ui/TemplateChooserPanelGUI.java +++ b/projectui/src/org/netbeans/modules/project/ui/TemplateChooserPanelGUI.java @@ -269,19 +269,18 @@ // private static final Comparator NATURAL_NAME_SORT = Collator.getInstance(); - private enum Visibility {HIDE, LEAF, CATEGORY} private final class TemplateKey { final DataObject d; - final Visibility visibility; - TemplateKey(DataObject d, Visibility visibility) { + final boolean leaf; + TemplateKey(DataObject d, boolean leaf) { this.d = d; - this.visibility = visibility; + this.leaf = leaf; } @Override public boolean equals(Object o) { if (!(o instanceof TemplateKey)) { return false; } - return d == ((TemplateKey) o).d && visibility == ((TemplateKey) o).visibility; + return d == ((TemplateKey) o).d && leaf == ((TemplateKey) o).leaf; } @Override public int hashCode() { return d.hashCode(); @@ -304,37 +303,23 @@ } @Override protected boolean createKeys(List keys) { - DataObject[] kids = folder.getChildren(); - int alreadyAdded = keys.size(); - if (alreadyAdded >= kids.length) { - return true; + for (DataObject d : folder.getChildren()) { + if (isFolderOfTemplates(d)) { + boolean leaf = true; + for (DataObject child : ((DataFolder) d).getChildren()) { + if (isFolderOfTemplates(child)) { + leaf = false; + break; + } + } + keys.add(new TemplateKey(d, leaf)); + } } - DataObject d = kids[alreadyAdded]; - Visibility v; - if (isFolderOfTemplates(d)) { - v = Visibility.LEAF; - for (DataObject child : ((DataFolder) d).getChildren()) { - if (isFolderOfTemplates(child)) { - v = Visibility.CATEGORY; - break; - } - } - } else { - v = Visibility.HIDE; - } - keys.add(new TemplateKey(d, v)); - return false; + return true; } @Override protected Node createNodeForKey(TemplateKey k) { - switch (k.visibility) { - case CATEGORY: - return new FilterNode(k.d.getNodeDelegate(), Children.create(new TemplateChildren((DataFolder) k.d), true)); - case LEAF: - return new FilterNode(k.d.getNodeDelegate(), Children.LEAF); - default: - return null; - } + return new FilterNode(k.d.getNodeDelegate(), k.leaf ? Children.LEAF : Children.create(new TemplateChildren((DataFolder) k.d), true)); } @Override public void actionPerformed (ActionEvent event) { @@ -361,24 +346,7 @@ } - private final class FileKey { - final DataObject d; - final boolean visible; - FileKey(DataObject d, boolean visible) { - this.d = d; - this.visible = visible; - } - @Override public boolean equals(Object o) { - if (!(o instanceof FileKey)) { - return false; - } - return d == ((FileKey) o).d && visible == ((FileKey) o).visible; - } - @Override public int hashCode() { - return d.hashCode(); - } - } - private final class FileChildren extends ChildFactory { + private final class FileChildren extends ChildFactory { private DataFolder root; @@ -387,26 +355,20 @@ assert this.root != null : "Root can not be null"; //NOI18N } - @Override protected boolean createKeys(List keys) { - DataObject[] kids = root.getChildren(); - int alreadyAdded = keys.size(); - if (alreadyAdded >= kids.length) { - return true; + @Override protected boolean createKeys(List keys) { + for (DataObject dobj : root.getChildren()) { + if (isTemplate(dobj) && OpenProjectList.isRecommended(projectRecommendedTypes, dobj.getPrimaryFile())) { + if (dobj instanceof DataShadow) { + dobj = ((DataShadow) dobj).getOriginal(); + } + keys.add(dobj); + } } - DataObject dobj = kids[alreadyAdded]; - if (isTemplate(dobj) && OpenProjectList.isRecommended(projectRecommendedTypes, dobj.getPrimaryFile())) { - if (dobj instanceof DataShadow) { - dobj = ((DataShadow) dobj).getOriginal(); - } - keys.add(new FileKey(dobj, true)); - } else { - keys.add(new FileKey(dobj, false)); - } - return false; + return true; } - @Override protected Node createNodeForKey(FileKey key) { - return key.visible ? new FilterNode(key.d.getNodeDelegate(), Children.LEAF) : null; + @Override protected Node createNodeForKey(DataObject d) { + return new FilterNode(d.getNodeDelegate(), Children.LEAF); } }