use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.
the class ProjectThing method getPopupItems.
public JMenuItem[] getPopupItems(final ActionListener listener) {
JMenuItem item = null;
ArrayList<JMenuItem> al_items = new ArrayList<JMenuItem>();
JMenu menu = new JMenu("Add...");
// call the project unique type
final ArrayList<TemplateThing> tc = project.getTemplateThing(template.getType()).getChildren();
if (null != tc) {
for (final TemplateThing tt : tc) {
item = new JMenuItem("new " + tt.getType());
item.addActionListener(listener);
menu.add(item);
}
item = new JMenuItem("many...");
item.addActionListener(listener);
menu.add(item);
}
if (0 != menu.getItemCount()) {
if (template.getType().equals("profile_list") && null != al_children && al_children.size() > 0) {
// can't add a new profile unless linked to another one.
item.setEnabled(false);
}
al_items.add(menu);
}
// generic for all:
// a 'Show' command on a non-basic type is a render preview.
addPopupItem("Unhide", listener, al_items).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.ALT_MASK, true));
addPopupItem("Hide", listener, al_items).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, 0, true));
addPopupItem("Info", listener, al_items);
addPopupItem("Rename...", listener, al_items).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0, true));
// enable duplicating for basic types only
if (Project.isBasicType(getType())) {
addPopupItem("Duplicate", listener, al_items);
}
addPopupItem("Select in display", listener, al_items).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true));
if (null != object && object instanceof Displayable) {
addPopupItem("Show centered in Display", listener, al_items);
}
if (null != object && object instanceof Tree<?>) {
addPopupItem("Show tabular view", listener, al_items);
}
// plugins
JMenuItem plugin_menu = Utils.addPlugIns("Project Tree", project, new Callable<Displayable>() {
public Displayable call() {
if (object instanceof Displayable)
return (Displayable) object;
return null;
}
});
if (null != plugin_menu)
al_items.add(plugin_menu);
addPopupItem("Measure", listener, al_items);
addPopupItem("Show in 3D", listener, al_items).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, 0, true));
addPopupItem("Remove from 3D view", listener, al_items);
if (template.getType().equals("project")) {
if (project.getLoader() instanceof DBLoader) {
addPopupItem("Export project...", listener, al_items);
} else if (project.getLoader() instanceof FSLoader) {
addPopupItem("Save", listener, al_items).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true));
addPopupItem("Save as...", listener, al_items);
}
}
if (!(template.getType().equals("project") && project.getLoader() instanceof FSLoader)) {
addPopupItem("Delete...", listener, al_items);
}
JMenuItem[] items = new JMenuItem[al_items.size()];
al_items.toArray(items);
return items;
}
use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.
the class ProjectTree method insertSegmentations.
/* // makes no sense, because there may be multiple projects open and thus the viewport and position may interfere with each other across multiple projects. Saving the collapsed node state suffices.
public void exportXML(final StringBuffer sb_body, String indent, JScrollPane jsp) {
Point p = jsp.getViewport().getViewPosition();
Dimension d = jsp.getSize(null);
sb_body.append(indent).append("<t2_tree")
.append(" width=\"").append(d.width).append('\"')
.append(" height=\"").append(d.height).append('\"')
.append(" viewport_x=\"").append(p.e).append('\"')
.append(" viewport_y=\"").append(p.y).append('\"')
;
sb_body.append("\n").append(indent).append("</t2_tree>\n");
}
*/
/**
* Creates a new node of basic type for each AreaList, Ball, Pipe or Polyline present in the ArrayList. Other elements are ignored.
*/
public void insertSegmentations(final Collection<? extends Displayable> al) {
final TemplateThing tt_root = (TemplateThing) project.getTemplateTree().getRoot().getUserObject();
// create a new abstract node called "imported_segmentations", if not there
final String imported_labels = "imported_labels";
if (!project.typeExists(imported_labels)) {
// create it
// yes I know I should check for the project of each Displayable in the ArrayList
TemplateThing tet = new TemplateThing(imported_labels, project);
project.addUniqueType(tet);
DefaultMutableTreeNode root = project.getTemplateTree().getRoot();
tt_root.addChild(tet);
DefaultMutableTreeNode child_node = addChild(tet, root);
DNDTree.expandNode(project.getTemplateTree(), child_node);
// JTree is serious pain
}
// it's the same as 'tet' above, unless it existed
TemplateThing tt_is = project.getTemplateThing(imported_labels);
// create a project node from "imported_segmentations" template under a new top node
final DefaultMutableTreeNode project_node = project.getProjectTree().getRoot();
ProjectThing project_pt = (ProjectThing) project_node.getUserObject();
final ProjectThing ct = project_pt.createChild(tt_root.getType());
ProjectThing pt_is = ct.createChild(imported_labels);
// addChild(pt_is, ctn);
final DefaultMutableTreeNode node_pt_is = new DefaultMutableTreeNode(pt_is);
final HashMap<Class<?>, String> types = new HashMap<Class<?>, String>();
types.put(AreaList.class, "area_list");
types.put(Pipe.class, "pipe");
types.put(Polyline.class, "polyline");
types.put(Ball.class, "ball");
types.put(Treeline.class, "treeline");
types.put(AreaTree.class, "areatree");
types.put(Connector.class, "connector");
// now, insert a new ProjectThing if of type AreaList, Ball and/or Pipe under node_child
for (final Displayable d : al) {
final String type = types.get(d.getClass());
if (null == type) {
Utils.log("insertSegmentations: ignoring " + d);
continue;
}
try {
final TemplateThing tt = getOrCreateChildTemplateThing(tt_is, type);
ProjectThing one = new ProjectThing(tt, project, d);
pt_is.addChild(one);
// addChild(one, node_pt_is);
// at the end
node_pt_is.add(new DefaultMutableTreeNode(one));
// Utils.log2("one parent : " + one.getParent());
} catch (Exception e) {
IJError.print(e);
}
}
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
DefaultMutableTreeNode ctn = addChild(ct, project_node);
ctn.add(node_pt_is);
try {
ProjectTree.this.scrollPathToVisible(new TreePath(node_pt_is.getPath()));
} catch (Exception e) {
e.printStackTrace();
}
}
});
DNDTree.expandNode(this, node_pt_is);
}
use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.
the class ProjectTree method actionPerformed.
public void actionPerformed(final ActionEvent ae) {
if (!project.isInputEnabled())
return;
super.dispatcher.exec(new Runnable() {
public void run() {
try {
if (null == selected_node)
return;
final Object ob = selected_node.getUserObject();
if (!(ob instanceof ProjectThing))
return;
final ProjectThing thing = (ProjectThing) ob;
int i_position = 0;
String command = ae.getActionCommand();
final Object obd = thing.getObject();
if (command.startsWith("new ") || command.equals("Duplicate")) {
ProjectThing new_thing = null;
if (command.startsWith("new ")) {
// if it's a Displayable, it will be added to whatever layer is in the front Display
new_thing = thing.createChild(command.substring(4));
} else if (command.equals("Duplicate")) {
// just to keep myself from screwing in the future
if (Project.isBasicType(thing.getType()) && null != thing.getParent()) {
new_thing = ((ProjectThing) thing.getParent()).createClonedChild(thing);
}
// adjust parent
selected_node = (DefaultMutableTreeNode) selected_node.getParent();
}
// add it to the tree
if (null != new_thing) {
DefaultMutableTreeNode new_node = new DefaultMutableTreeNode(new_thing);
((DefaultTreeModel) ProjectTree.this.getModel()).insertNodeInto(new_node, selected_node, i_position);
TreePath treePath = new TreePath(new_node.getPath());
ProjectTree.this.scrollPathToVisible(treePath);
ProjectTree.this.setSelectionPath(treePath);
}
// bring the display to front
if (new_thing.getObject() instanceof Displayable) {
Display.getFront().getFrame().toFront();
}
} else if (command.equals("many...")) {
ArrayList<TemplateThing> children = thing.getTemplate().getChildren();
if (null == children || 0 == children.size())
return;
String[] cn = new String[children.size()];
int i = 0;
for (final TemplateThing child : children) {
cn[i] = child.getType();
i++;
}
GenericDialog gd = new GenericDialog("Add many children");
gd.addNumericField("Amount: ", 1, 0);
gd.addChoice("New child: ", cn, cn[0]);
gd.addCheckbox("Recursive", true);
gd.showDialog();
if (gd.wasCanceled())
return;
int amount = (int) gd.getNextNumber();
if (amount < 1) {
Utils.showMessage("Makes no sense to create less than 1 child!");
return;
}
project.getRootLayerSet().addChangeTreesStep();
final ArrayList<ProjectThing> nc = thing.createChildren(cn[gd.getNextChoiceIndex()], amount, gd.getNextBoolean());
addLeafs(nc, new Runnable() {
public void run() {
project.getRootLayerSet().addChangeTreesStep();
}
});
} else if (command.equals("Unhide")) {
thing.setVisible(true);
} else if (command.equals("Select in display")) {
boolean shift_down = 0 != (ae.getModifiers() & ActionEvent.SHIFT_MASK);
selectInDisplay(thing, shift_down);
} else if (command.equals("Show centered in Display")) {
if (obd instanceof Displayable) {
Displayable displ = (Displayable) obd;
Display.showCentered(displ.getLayer(), displ, true, 0 != (ae.getModifiers() & ActionEvent.SHIFT_MASK));
}
} else if (command.equals("Show tabular view")) {
((Tree<?>) obd).createMultiTableView();
} else if (command.equals("Show in 3D")) {
Display3D.showAndResetView(thing);
} else if (command.equals("Remove from 3D view")) {
Display3D.removeFrom3D(thing);
} else if (command.equals("Hide")) {
// find all Thing objects in this subtree starting at Thing and hide their Displayable objects.
thing.setVisible(false);
} else if (command.equals("Delete...")) {
// store old state
project.getRootLayerSet().addChangeTreesStep();
remove(true, thing, selected_node);
// store new state
project.getRootLayerSet().addChangeTreesStep();
return;
} else if (command.equals("Rename...")) {
// if (!Project.isBasicType(thing.getType())) {
rename(thing);
// }
} else if (command.equals("Measure")) {
// block displays while measuring
Bureaucrat.createAndStart(new Worker("Measuring") {
public void run() {
startedWorking();
try {
thing.measure();
} catch (Throwable e) {
IJError.print(e);
} finally {
finishedWorking();
}
}
}, thing.getProject());
} else /* else if (command.equals("Export 3D...")) {
GenericDialog gd = ControlWindow.makeGenericDialog("Export 3D");
String[] choice = new String[]{".svg [preserves links and hierarchical grouping]", ".shapes [limited to one profile per layer per profile_list]"};
gd.addChoice("Export to: ", choice, choice[0]);
gd.addNumericField("Z scaling: ", 1, 2);
gd.showDialog();
if (gd.wasCanceled()) return;
double z_scale = gd.getNextNumber();
switch (gd.getNextChoiceIndex()) {
case 0:
Render.exportSVG(thing, z_scale);
break;
case 1:
new Render(thing).save(z_scale);
break;
}
}*/
if (command.equals("Export project...") || command.equals("Save as...")) {
// "Save as..." is for a FS project
Utils.log2("Calling export project at " + System.currentTimeMillis());
thing.getProject().getLoader().saveTask(thing.getProject(), "Save as...");
} else if (command.equals("Save")) {
// overwrite the xml file of a FSProject
// Just do the same as in "Save as..." but without saving the images and overwritting the XML file without asking.
thing.getProject().getLoader().saveTask(thing.getProject(), "Save");
} else if (command.equals("Info")) {
showInfo(thing);
return;
} else if (command.equals("Move up")) {
move(selected_node, -1);
} else if (command.equals("Move down")) {
move(selected_node, 1);
} else if (command.equals("Collapse nodes of children nodes")) {
if (null == selected_node)
return;
Enumeration<?> c = selected_node.children();
while (c.hasMoreElements()) {
DefaultMutableTreeNode child = (DefaultMutableTreeNode) c.nextElement();
if (child.isLeaf())
continue;
collapsePath(new TreePath(child.getPath()));
}
} else if (command.equals("Sibling project")) {
sendToSiblingProjectTask(selected_node);
} else {
Utils.log("ProjectTree.actionPerformed: don't know what to do with the command: " + command);
return;
}
} catch (Exception e) {
IJError.print(e);
}
}
});
}
use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.
the class ProjectTree method sendToSiblingProject.
/**
* When two or more people work on the same XML file, images may be the same but segmentations and the transformations of the images may diverge.
* This function provides the means to send VectorData instances, wrapped in tree nodes, from one project to another,
* transforming the VectorData as appropriate to fall onto the same locations on the images.
* The ids of the copied objects will be new and unique for the target project.
* A dialog opens asking for options.
*/
@SuppressWarnings("unchecked")
public boolean sendToSiblingProject(final DefaultMutableTreeNode node) {
ArrayList<Project> ps = Project.getProjects();
if (1 == ps.size()) {
Utils.log("There aren't any other projects open!");
return false;
}
final ProjectThing pt = (ProjectThing) node.getUserObject();
if (pt.getTemplate().getType().equals("project")) {
Utils.log("Cannot transfer the project node.");
return false;
}
final ArrayList<Project> psother = new ArrayList<Project>(ps);
psother.remove(this.project);
ps = null;
// Find all potential landing nodes for this node: those with a TemplateThing type like the parent of node:
final String parent_type = ((ProjectThing) pt.getParent()).getTemplate().getType();
final List<ProjectThing> landing_pt = new ArrayList<ProjectThing>(psother.get(0).getRootProjectThing().findChildrenOfTypeR(parent_type));
final Comparator<ProjectThing> comparator = new Comparator<ProjectThing>() {
public int compare(ProjectThing t1, ProjectThing t2) {
return t1.toString().compareTo(t2.toString());
}
public boolean equals(Object o) {
return this == o;
}
};
Collections.sort(landing_pt, comparator);
String[] landing = new String[landing_pt.size()];
int next = 0;
if (landing_pt.isEmpty()) {
landing = new String[] { "-- NONE --" };
} else
for (ProjectThing t : landing_pt) landing[next++] = t.toString();
// Suggest the first potential landing node that has the same title
String parentTitle = pt.getParent().toString();
int k = 0;
boolean matched = false;
// First search for exact match
for (final String candidate : landing) {
if (candidate.equals(parentTitle)) {
matched = true;
break;
}
k += 1;
}
// If not matched, find one that contains the string
if (!matched) {
k = 0;
for (final String candidate : landing) {
if (-1 != candidate.indexOf(parentTitle)) {
matched = true;
break;
}
k += 1;
}
}
if (!matched) {
k = 0;
}
// Ask:
GenericDialog gd = new GenericDialog("Send to sibling project");
gd.addMessage("Transfering node: " + pt);
final String[] trmode = new String[] { "As is", "Transformed as the images" };
gd.addChoice("Transfer:", trmode, trmode[0]);
String[] ptitles = new String[psother.size()];
for (int i = 0; i < ptitles.length; i++) ptitles[i] = psother.get(i).toString();
gd.addChoice("Target project:", ptitles, ptitles[0]);
gd.addChoice("Landing node:", landing, landing[k]);
final Vector<Choice> vc = (Vector<Choice>) gd.getChoices();
final Choice choice_project = vc.get(vc.size() - 2);
final Choice choice_landing = vc.get(vc.size() - 1);
choice_project.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ie) {
landing_pt.clear();
landing_pt.addAll(psother.get(choice_project.getSelectedIndex()).getRootProjectThing().findChildrenOfTypeR(parent_type));
Collections.sort(landing_pt, comparator);
choice_landing.removeAll();
if (landing_pt.isEmpty()) {
choice_landing.add("-- NONE --");
} else
for (ProjectThing t : landing_pt) choice_landing.add(t.toString());
}
});
gd.showDialog();
if (gd.wasCanceled())
return false;
if (choice_landing.getSelectedItem().equals("-- NONE --")) {
Utils.log("No valid landing nodes!");
return false;
}
final int transfer_mode = gd.getNextChoiceIndex();
final Project target_project = psother.get(gd.getNextChoiceIndex());
final ProjectThing landing_parent = landing_pt.get(gd.getNextChoiceIndex());
return rawSendToSiblingProject(pt, transfer_mode, target_project, landing_parent);
}
use of ini.trakem2.tree.TemplateThing in project TrakEM2 by trakem2.
the class ProjectTree method rawSendToSiblingProject.
/**
* Assumes that both projects have the same TemplateThing structure,
* and assumes that the parent of the ({@code source_pt} and the {@code landing_parent}
* instances are of the same type.
*
* @param source_pt The {@link ProjectThing} to be cloned.
* @param transfer_mode Either 0 ("As is") or 1 ("Transformed with the images").
* @param target_project The sibling project into which insert a clone of the {@code source_pt}.
* @param landing_parent The ProjectThing in the sibling project that receives the cloned {@code source_pt}.
*/
public boolean rawSendToSiblingProject(// the source ProjectThing to copy to the target project
final ProjectThing source_pt, final int transfer_mode, final Project target_project, final ProjectThing landing_parent) {
try {
// Check that all the Layers used by the objects to transfer also exist in the target project!
// 1 - Cheap way: check if all layers in the target project exist in the source project, by id
HashSet<Long> lids = new HashSet<Long>();
for (final Layer layer : this.project.getRootLayerSet().getLayers()) {
lids.add(layer.getId());
}
HashSet<Long> tgt_lids = new HashSet<Long>(lids);
for (final Layer layer : target_project.getRootLayerSet().getLayers()) {
lids.remove(layer.getId());
tgt_lids.add(layer.getId());
}
List<Displayable> original_vdata = null;
final Set<Long> lids_to_operate = new HashSet<Long>();
if (0 != lids.size()) {
original_vdata = new ArrayList<Displayable>();
// All their layers MUST be in the target project.
for (final ProjectThing child : source_pt.findChildrenOfTypeR(Displayable.class)) {
final Displayable d = (Displayable) child.getObject();
if (!tgt_lids.containsAll(d.getLayerIds())) {
Utils.log("CANNOT transfer: not all required layers are present in the target project!\n First object that couldn't be transfered: \n " + d);
return false;
}
if (d instanceof VectorData) {
original_vdata.add(d);
lids_to_operate.addAll(d.getLayerIds());
}
}
}
// Deep cloning of the ProjectThing to transfer, then added to the landing_parent in the other tree.
ProjectThing copy;
try {
// new ids, taken from target_project
copy = source_pt.deepClone(target_project, false);
} catch (Exception ee) {
Utils.logAll("Can't send: " + ee.getMessage());
IJError.print(ee);
return false;
}
if (null == landing_parent.getChildTemplate(copy.getTemplate().getType())) {
// ensure a copy is there
landing_parent.getTemplate().addChild(copy.getTemplate().shallowCopy());
}
if (!landing_parent.addChild(copy)) {
Utils.log("Could NOT transfer the node!");
return false;
}
// Get the list of Profile instances in the source Project, in the same order
// that they will be in the target project:
final List<Profile> srcProfiles = new ArrayList<Profile>();
for (final ProjectThing profile_pt : source_pt.findChildrenOfTypeR(Profile.class)) {
srcProfiles.add((Profile) profile_pt.getObject());
}
final List<ProjectThing> copies = copy.findChildrenOfTypeR(Displayable.class);
final List<Profile> newProfiles = new ArrayList<Profile>();
// Utils.log2("copies size: " + copies.size());
final List<Displayable> vdata = new ArrayList<Displayable>();
final List<ZDisplayable> zd = new ArrayList<ZDisplayable>();
for (final ProjectThing t : copies) {
final Displayable d = (Displayable) t.getObject();
// all should be, this is just future-proof code.
if (d instanceof VectorData)
vdata.add(d);
if (d instanceof ZDisplayable) {
zd.add((ZDisplayable) d);
} else {
// profile: always special
newProfiles.add((Profile) d);
}
}
// Fix Profile instances: exploit that the order as been conserved when copying.
int profileIndex = 0;
for (final Profile newProfile : newProfiles) {
// Corresponding Profile:
final Profile srcProfile = srcProfiles.get(profileIndex++);
// Corresponding layer: layers have the same IDs by definition of what a sibling Project is.
final Layer newLayer = target_project.getRootLayerSet().getLayer(srcProfile.getLayer().getId());
newLayer.add(newProfile);
// Corresponding links
for (final Displayable srcLinkedProfile : srcProfile.getLinked(Profile.class)) {
newProfile.link(newProfiles.get(srcProfiles.indexOf(srcLinkedProfile)));
}
}
// add them all in one shot
target_project.getRootLayerSet().addAll(zd);
// could have changed
target_project.getTemplateTree().rebuild();
// When trying to rebuild just the landing_parent, it doesn't always work. Needs checking TODO
target_project.getProjectTree().rebuild();
// Open up the path to the landing parent node
final TreePath tp = new TreePath(DNDTree.findNode(landing_parent, target_project.getProjectTree()).getPath());
Utils.invokeLater(new Runnable() {
public void run() {
target_project.getProjectTree().scrollPathToVisible(tp);
target_project.getProjectTree().setSelectionPath(tp);
}
});
if (1 == transfer_mode) {
// Collect original vdata
if (null == original_vdata) {
original_vdata = new ArrayList<Displayable>();
for (final ProjectThing child : source_pt.findChildrenOfTypeR(Displayable.class)) {
final Displayable d = (Displayable) child.getObject();
if (d instanceof VectorData) {
original_vdata.add(d);
lids_to_operate.addAll(d.getLayerIds());
}
}
}
// Utils.log2("original vdata:", original_vdata);
// Utils.log2("vdata:", vdata);
// Transform with images
AlignTask.transformVectorData(AlignTask.createTransformPropertiesTable(original_vdata, vdata, lids_to_operate), vdata, target_project.getRootLayerSet());
}
return true;
} catch (Exception e) {
IJError.print(e);
}
return false;
}
Aggregations