use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.
the class TMLHandler method makeProjectThing.
private ProjectThing makeProjectThing(String type, final HashMap<String, String> ht_attributes) {
try {
type = type.toLowerCase();
// debug:
// Utils.log2("TMLHander.makeProjectThing for type=" + type);
long id = -1;
final String sid = ht_attributes.remove("id");
if (null != sid) {
id = Long.parseLong(sid);
}
long oid = -1;
final String soid = ht_attributes.remove("oid");
if (null != soid) {
oid = Long.parseLong(soid);
}
// default: collapsed
Boolean expanded = new Boolean(false);
Object eob = ht_attributes.remove("expanded");
if (null != eob) {
expanded = new Boolean((String) eob);
}
String title = ht_attributes.remove("title");
TemplateThing tt = this.project.getTemplateThing(type);
if (null == tt) {
Utils.log("No template for type " + type);
return null;
}
ProjectThing pt = new ProjectThing(tt, this.project, id, null == title ? type : title, null);
pt.addToDatabase();
ht_pt_expanded.put(pt, expanded);
// store the oid vs. pt relationship to fill in the object later.
if (-1 != oid) {
ht_oid_pt.put(new Long(oid), pt);
}
return pt;
} catch (Exception e) {
IJError.print(e);
}
// default:
return null;
}
use of ini.trakem2.tree.TemplateThing 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.tree.TemplateThing 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.tree.TemplateThing in project TrakEM2 by trakem2.
the class ProjectThing method createChild.
public ProjectThing createChild(String type) {
// create the Displayable
TemplateThing tt = template.getChildTemplate(type);
if (null == tt) {
Utils.log2("Can't create a child of type " + type);
return null;
}
Object ob = project.makeObject(tt);
Layer layer = null;
if (ob instanceof Displayable) {
// which layer to add it to? Get it from the front Display
layer = Display.getFrontLayer(this.project);
if (null == layer) {
Utils.showMessage("Open a display first!");
((DBObject) ob).removeFromDatabase();
return null;
}
}
// wrap it in a new ProjectThing
ProjectThing pt = null;
try {
pt = new ProjectThing(tt, project, ob);
} catch (Exception e) {
IJError.print(e);
return null;
}
// add it here as child
addChild(pt);
// finally, add it to the layer if appropriate
if (null != layer) {
if (ob instanceof ZDisplayable) {
layer.getParent().add((ZDisplayable) ob);
} else {
layer.add((Displayable) ob);
}
}
// finally, return it to be added to the ProjectTree as a new node
return pt;
}
use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.
the class ProjectTree method tryAddNewConnector.
/**
* If the parent node of {@code active} can accept a Connector or has a direct child
* node that can accept a {@link Connector}, add a new {@link Connector} and return it.
*
* @param d The {@link Displayable} that serves as reference, to decide which node to add the new {@link Connector}.
* @param selectNode Whether to select the new node containing the {@link Connector} in the ProjectTree.
*
* @return The newly created {@link Connector}.
*/
public Connector tryAddNewConnector(final Displayable d, final boolean selectNode) {
ProjectThing pt = project.findProjectThing(d);
ProjectThing parent = (ProjectThing) pt.getParent();
TemplateThing connectorType = project.getTemplateThing("connector");
boolean add = false;
if (parent.canHaveAsChild(connectorType)) {
// Add as a sibling of pt
add = true;
} else {
// Inspect if any of the sibling nodes can have it as child
for (final ProjectThing child : parent.getChildren()) {
if (child.canHaveAsChild(connectorType)) {
parent = child;
add = true;
break;
}
}
}
Connector c = null;
DefaultMutableTreeNode node = null;
if (add) {
// reuse same String instance
c = new Connector(project, connectorType.getType());
node = addChild(parent, connectorType.getType(), c);
}
if (null != node) {
d.getLayerSet().add(c);
if (selectNode)
setSelectionPath(new TreePath(node.getPath()));
return c;
}
Utils.logAll("Could not add a new Connector related to " + d);
return null;
}
Aggregations