use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.
the class TMLHandler method getProjectData.
/**
* returns 4 objects packed in an array:
* <pre>
* [0] = root TemplateThing
* [1] = root ProjectThing (contains Project instance)
* [2] = root LayerThing (contains the top-level LayerSet)
* [3] = expanded states of all ProjectThing objects
* </pre>
* <p>
* Also, triggers the reconstruction of links and assignment of Displayable objects to their layer.
* </p>
*/
public Object[] getProjectData(final boolean open_displays) {
if (null == project)
return null;
this.open_displays = open_displays;
// Links exist between Displayable objects.
for (final Displayable d : ht_displayables.values()) {
String olinks = ht_links.get(d);
// not linked
if (null == olinks)
continue;
String[] links = olinks.split(",");
Long lid = null;
for (int i = 0; i < links.length; i++) {
try {
lid = new Long(links[i]);
} catch (NumberFormatException nfe) {
Utils.log2("Ignoring incorrectly formated link '" + links[i] + "' for ob " + d);
continue;
}
Displayable partner = ht_displayables.get(lid);
if (null != partner)
d.link(partner, false);
else
Utils.log("TMLHandler: can't find partner with id=" + links[i] + " for Displayable with id=" + d.getId());
}
}
// 1.2 - Reconstruct linked properties
for (final Map.Entry<Displayable, Map<Long, Map<String, String>>> lpe : all_linked_props.entrySet()) {
final Displayable origin = lpe.getKey();
for (final Map.Entry<Long, Map<String, String>> e : lpe.getValue().entrySet()) {
final Displayable target = ht_displayables.get(e.getKey());
if (null == target) {
Utils.log("Setting linked properties for origin " + origin.getId() + ":\n\t* Could not find target displayable #" + e.getKey());
continue;
}
origin.setLinkedProperties(target, e.getValue());
}
}
// 2 - Add Displayable objects to ProjectThing that can contain them
for (final Map.Entry<Long, ProjectThing> entry : ht_oid_pt.entrySet()) {
ProjectThing pt = entry.getValue();
Object od = ht_displayables.remove(entry.getKey());
// Utils.log("==== processing: Displayable [" + od + "] vs. ProjectThing [" + pt + "]");
if (null != od) {
pt.setObject(od);
} else {
Utils.log("#### Failed to find a Displayable for ProjectThing " + pt + " #####");
}
}
// 3 - Assign a layer pointer to ZDisplayable objects
for (final ZDisplayable zd : ht_zdispl.values()) {
// zd.setLayer((Layer)zd.getLayerSet().getLayers().get(0));
zd.setLayer(zd.getLayerSet().getLayer(0));
}
// 4 - Assign layers to Treeline nodes
for (final Layer la : al_layers) {
final List<Node<?>> list = node_layer_table.remove(la.getId());
if (null == list)
continue;
for (final Node<?> nd : list) nd.setLayer(la);
}
if (!node_layer_table.isEmpty()) {
Utils.log("ERROR: node_layer_table is not empty!");
}
// 5 - Assign root nodes to Treelines, now that all nodes have a layer
for (final Map.Entry<Tree<?>, Node<?>> e : tree_root_nodes.entrySet()) {
if (null == e.getValue()) {
// Utils.log2("Ignoring, applies to new Treeline format only.");
continue;
}
// Can't compile with <?>
// will generate node caches of each Treeline
e.getKey().setRoot((Node) e.getValue());
}
tree_root_nodes.clear();
// Assign colors to nodes
for (final Map.Entry<Color, Collection<Node<?>>> e : node_colors.entrySet()) {
for (final Node<?> nd : e.getValue()) {
nd.setColor(e.getKey());
}
}
node_colors.clear();
// 6 - Run legacy operations
for (final Runnable r : legacy) {
r.run();
}
try {
// Create a table with all layer ids vs layer instances:
final HashMap<Long, Layer> ht_lids = new HashMap<Long, Layer>();
for (final Layer layer : al_layers) {
ht_lids.put(new Long(layer.getId()), layer);
}
// Spawn threads to recreate buckets, starting from the subset of displays to open
int n = Runtime.getRuntime().availableProcessors();
switch(n) {
case 1:
break;
case 2:
case 3:
case 4:
n--;
break;
default:
n -= 2;
break;
}
final ExecutorService exec = Utils.newFixedThreadPool(n, "TMLHandler-recreateBuckets");
final Set<Long> dlids = new HashSet<Long>();
final LayerSet layer_set = (LayerSet) root_lt.getObject();
final List<Future<?>> fus = new ArrayList<Future<?>>();
final List<Future<?>> fus2 = new ArrayList<Future<?>>();
for (final HashMap<String, String> ht_attributes : al_displays) {
String ob = ht_attributes.get("layer_id");
if (null == ob)
continue;
final Long lid = new Long(ob);
dlids.add(lid);
final Layer la = ht_lids.get(lid);
if (null == la) {
ht_lids.remove(lid);
continue;
}
// to open later:
new Display(project, Long.parseLong(ht_attributes.get("id")), la, ht_attributes);
fus.add(exec.submit(new Runnable() {
public void run() {
la.recreateBuckets();
}
}));
}
fus.add(exec.submit(new Runnable() {
public void run() {
// only for ZDisplayable
layer_set.recreateBuckets(false);
}
}));
// Ensure launching:
if (dlids.isEmpty() && layer_set.size() > 0) {
dlids.add(layer_set.getLayer(0).getId());
}
final List<Layer> layers = layer_set.getLayers();
for (final Long lid : new HashSet<Long>(dlids)) {
fus.add(exec.submit(new Runnable() {
public void run() {
int start = layer_set.indexOf(layer_set.getLayer(lid.longValue()));
int next = start + 1;
int prev = start - 1;
while (next < layer_set.size() || prev > -1) {
if (prev > -1) {
final Layer lprev = layers.get(prev);
synchronized (dlids) {
if (dlids.add(lprev.getId())) {
// returns true if not there already
fus2.add(exec.submit(new Runnable() {
public void run() {
lprev.recreateBuckets();
}
}));
}
}
prev--;
}
if (next < layers.size()) {
final Layer lnext = layers.get(next);
synchronized (dlids) {
if (dlids.add(lnext.getId())) {
// returns true if not there already
fus2.add(exec.submit(new Runnable() {
public void run() {
lnext.recreateBuckets();
}
}));
}
}
next++;
}
}
Utils.log2("done recreateBuckets chunk");
}
}));
}
Utils.wait(fus);
exec.submit(new Runnable() {
public void run() {
Utils.log2("waiting for TMLHandler fus...");
Utils.wait(fus2);
Utils.log2("done waiting TMLHandler fus.");
exec.shutdown();
}
});
} catch (Throwable t) {
IJError.print(t);
}
return new Object[] { root_tt, root_pt, root_lt, ht_pt_expanded };
}
use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.
the class DefaultTreeTransferHandler method canPerformAction.
public boolean canPerformAction(DNDTree target, DefaultMutableTreeNode dragged_node, int action, Point location) {
// prevent drags from non-tree components
if (null == dragged_node)
return false;
// Can't drop onto a TemplateTree
if (target instanceof TemplateTree) {
return false;
}
// Can't drag a node that contains a Project!
if (dragged_node.getUserObject() instanceof ProjectThing && ((ProjectThing) dragged_node.getUserObject()).getObject() instanceof Project) {
return false;
}
// Can't drag basic object nodes from a template tree RECONSIDERED, I like it even if it looks inconsistent (but types are types!)
/*
if (dragged_node.getUserObject() instanceof TemplateThing && project.isBasicType(((Thing)dragged_node.getUserObject()).getType())) {
return false;
}
*/
// else, the target has to be not null
TreePath pathTarget = target.getPathForLocation(location.x, location.y);
if (pathTarget == null) {
target.setSelectionPath(null);
return false;
}
/* // debug
if (action == DnDConstants.ACTION_COPY) {
Utils.log("can drop: Action copy");
} else if (action == DnDConstants.ACTION_MOVE) {
Utils.log("can drop: Action move");
} else {
Utils.log("can drop: Unexpected action: " + action);
}
*/
target.setSelectionPath(pathTarget);
DefaultMutableTreeNode parent_node = (DefaultMutableTreeNode) pathTarget.getLastPathComponent();
// can be a Thing or an Attribute
Object parent_ob = parent_node.getUserObject();
Thing child_thing = (Thing) dragged_node.getUserObject();
if (DnDConstants.ACTION_MOVE == action || DnDConstants.ACTION_COPY == action) {
if (parent_ob instanceof ProjectThing) {
ProjectThing parent_thing = (ProjectThing) parent_ob;
// check if it's allowed to give to this parent such a child:
if (!parent_thing.uniquePathExists(child_thing.getType()) && !parent_thing.canHaveAsChild(child_thing)) {
// Utils.log("Not possible.");
return false;
}
// - the leaf that is going to be dropped into itself or any of its descendants.
if (parent_node == dragged_node.getParent() || dragged_node.isNodeDescendant(parent_node)) {
// Utils.log("preventing dragging onto itself or any of the self children.");
return false;
} else {
return true;
}
}
}
// default:
return false;
}
use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.
the class ProjectTree method keyPressed.
@Override
public void keyPressed(final KeyEvent ke) {
super.keyPressed(ke);
if (ke.isConsumed())
return;
if (!ke.getSource().equals(ProjectTree.this) || !project.isInputEnabled()) {
return;
}
// get the first selected node only
TreePath path = getSelectionPath();
if (null == path)
return;
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
if (null == node)
return;
final ProjectThing pt = (ProjectThing) node.getUserObject();
if (null == pt)
return;
//
final int flags = ke.getModifiers();
switch(ke.getKeyCode()) {
case KeyEvent.VK_PAGE_UP:
move(node, -1);
// in any case
ke.consume();
break;
case KeyEvent.VK_PAGE_DOWN:
move(node, 1);
// in any case
ke.consume();
break;
case KeyEvent.VK_F2:
rename(pt);
ke.consume();
break;
case KeyEvent.VK_H:
if (0 == (flags ^ Event.ALT_MASK)) {
pt.setVisible(true);
ke.consume();
} else if (0 == flags) {
pt.setVisible(false);
ke.consume();
}
break;
case KeyEvent.VK_A:
if (0 == flags || (0 == (flags ^ Event.SHIFT_MASK))) {
selectInDisplay(pt, 0 == (flags ^ Event.SHIFT_MASK));
ke.consume();
}
break;
case KeyEvent.VK_3:
if (0 == flags) {
ini.trakem2.display.Display3D.showAndResetView(pt);
ke.consume();
break;
}
// else, flow:
case KeyEvent.VK_1:
case KeyEvent.VK_2:
case KeyEvent.VK_4:
case KeyEvent.VK_5:
case KeyEvent.VK_6:
case KeyEvent.VK_7:
case KeyEvent.VK_8:
case KeyEvent.VK_9:
// run a plugin, if any
if (pt.getObject() instanceof Displayable && null != Utils.launchTPlugIn(ke, "Project Tree", project, (Displayable) pt.getObject())) {
ke.consume();
}
break;
}
ke.consume();
}
use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.
the class Merger method compare.
/**
* Take two projects and find out what is different among them,
* independent of id.
*/
public static final void compare(final Project p1, final Project p2) {
Utils.log("Be warned: only Treeline, AreaTree and Connector are considered at the moment.");
final LayerSet ls1 = p1.getRootLayerSet(), ls2 = p2.getRootLayerSet();
final Collection<ZDisplayable> zds1 = ls1.getZDisplayables(), zds2 = ls2.getZDisplayables();
final HashSet<Class<?>> accepted = new HashSet<Class<?>>();
accepted.add(Treeline.class);
accepted.add(AreaTree.class);
accepted.add(Connector.class);
final HashMap<Displayable, List<Change>> matched = new HashMap<Displayable, List<Change>>();
final HashSet<ZDisplayable> empty1 = new HashSet<ZDisplayable>(), empty2 = new HashSet<ZDisplayable>();
final HashSet<ZDisplayable> unmatched1 = new HashSet<ZDisplayable>(), unmatched2 = new HashSet<ZDisplayable>(zds2);
// Remove instances of classes not accepted
for (final Iterator<ZDisplayable> it = unmatched2.iterator(); it.hasNext(); ) {
ZDisplayable zd = it.next();
if (!accepted.contains(zd.getClass())) {
it.remove();
continue;
}
if (zd.isDeletable()) {
it.remove();
empty2.add(zd);
}
}
zds2.removeAll(empty2);
final AtomicInteger counter = new AtomicInteger(0);
// or at least one or more that are similar in that they have some nodes in common.
try {
ini.trakem2.parallel.Process.unbound(zds1, new TaskFactory<ZDisplayable, Object>() {
@Override
public Object process(final ZDisplayable zd1) {
Utils.showProgress(counter.getAndIncrement() / (float) zds1.size());
if (!accepted.contains(zd1.getClass())) {
Utils.log("Ignoring: [A] " + zd1);
return null;
}
if (zd1.isDeletable()) {
synchronized (empty1) {
empty1.add(zd1);
}
return null;
}
final List<Change> cs = new ArrayList<Change>();
for (final ZDisplayable zd2 : zds2) {
// Same class?
if (zd1.getClass() != zd2.getClass())
continue;
if (zd1 instanceof Tree<?> && zd2 instanceof Tree<?>) {
Change c = compareTrees(zd1, zd2);
if (c.hasSimilarNodes()) {
cs.add(c);
if (1 == cs.size()) {
synchronized (matched) {
matched.put(zd1, cs);
}
}
synchronized (unmatched2) {
unmatched2.remove(zd2);
}
}
// debug
if (zd1.getId() == zd2.getId()) {
Utils.log("zd1 #" + zd1.getId() + " is similar to #" + zd2.getId() + ": " + c.hasSimilarNodes());
}
}
}
if (cs.isEmpty()) {
synchronized (unmatched1) {
unmatched1.add(zd1);
}
}
return null;
}
});
} catch (Exception e) {
IJError.print(e);
}
// reset
Utils.showProgress(1);
Utils.log("matched.size(): " + matched.size());
makeGUI(p1, p2, empty1, empty2, matched, unmatched1, unmatched2);
}
use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.
the class TemplateTree method renameType.
/**
* Rename a TemplateThing type from @param old_name to @param new_name.
* If such a new_name already exists, the renaming will not occur and returns false.
*/
public boolean renameType(final String old_name, String new_name) {
// to lower case!
new_name = new_name.toLowerCase();
Project project = root.getProject();
if (new_name.equals(old_name)) {
return true;
} else if (project.typeExists(new_name)) {
Utils.logAll("Type '" + new_name + "' exists already!");
return false;
}
// process name change in all TemplateThing instances that have it
ArrayList<TemplateThing> al = root.collectAllChildren(new ArrayList<TemplateThing>());
al.add(root);
for (final TemplateThing tet : al) {
// Utils.log("\tchecking " + tet.getType() + " " + tet.getId());
if (tet.getType().equals(old_name))
tet.rename(new_name);
}
// and update the ProjectThing objects in the tree and its dependant Displayable objects in the open Displays
project.getRootProjectThing().updateType(new_name, old_name);
// tell the project about it
project.updateTypeName(old_name, new_name);
// repaint both trees (will update the type names)
updateUILater();
project.getProjectTree().updateUILater();
return true;
}
Aggregations