use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Display method snap.
/**
* Snap a Patch to the most overlapping Patch, if any.
* This method is a shallow wrap around AlignTask.snap, setting proper undo steps.
*/
public static final Bureaucrat snap(final Patch patch) {
final Set<Displayable> linked = patch.getLinkedGroup(null);
patch.getLayerSet().addTransformStep(linked);
final Bureaucrat burro = AlignTask.snap(patch, null, false);
burro.addPostTask(new Runnable() {
@Override
public void run() {
patch.getLayerSet().addTransformStep(linked);
}
});
return burro;
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Display method addAreaTreeAreasMenu.
private void addAreaTreeAreasMenu(final JPopupMenu popup, final AreaTree atree) {
final ActionListener listener = new ActionListener() {
private final Node<?> findNearestNode() {
final Layer la = getLayer();
final Point p = canvas.consumeLastPopupPoint();
final Node<?> lv = atree.getLastVisited();
boolean use_last_visited = false;
if (null != lv) {
final float[] xy = new float[] { lv.x, lv.y };
atree.getAffineTransform().transform(xy, 0, xy, 0, 1);
use_last_visited = lv.getLayer() == la && canvas.getSrcRect().contains((int) xy[0], (int) xy[1]);
}
// if no node lays near the clicked point.
return atree.findNodeNear(p.x, p.y, la, canvas, use_last_visited);
}
@Override
public void actionPerformed(final ActionEvent ae) {
final String command = ae.getActionCommand();
final LayerSet ls = atree.getLayerSet();
Bureaucrat.createAndStart(new Worker.Task(command) {
@Override
public void exec() {
final Node<?> nd = findNearestNode();
if (null == nd) {
Utils.log("No node found in the field of view!");
return;
}
if (command.equals("Copy area")) {
final Area area = (Area) nd.getData();
if (null == area)
return;
DisplayCanvas.setCopyBuffer(atree.getClass(), area.createTransformedArea(atree.getAffineTransform()));
} else if (command.equals("Paste area")) {
final Area wa = (Area) DisplayCanvas.getCopyBuffer(atree.getClass());
if (null == wa)
return;
try {
getLayerSet().addDataEditStep(atree);
atree.addWorldAreaTo(nd, wa);
atree.calculateBoundingBox(nd.getLayer());
getLayerSet().addDataEditStep(atree);
} catch (final Exception e) {
IJError.print(e);
getLayerSet().removeLastUndoStep();
}
} else if (command.equals("Interpolate gaps towards parent (node-centric)")) {
interpolate(nd, true);
} else if (command.equals("Interpolate gaps towards parent (absolute)")) {
interpolate(nd, false);
} else if (command.equals("Interpolate all gaps")) {
final GenericDialog gd = new GenericDialog("Interpolate");
final String[] a = new String[] { "node-centric", "absolute" };
gd.addChoice("Mode", a, a[0]);
gd.addCheckbox("Always use distance map", project.getBooleanProperty(AreaUtils.always_interpolate_areas_with_distance_map));
final String[] b = new String[] { "All selected AreaTrees", "Active AreaTree" };
gd.addChoice("Process", b, b[0]);
gd.showDialog();
if (gd.wasCanceled())
return;
final boolean node_centric = 0 == gd.getNextChoiceIndex();
final boolean use_distance_map = gd.getNextBoolean();
final boolean all = 0 == gd.getNextChoiceIndex();
final Set<Displayable> s = new HashSet<Displayable>();
if (all)
s.addAll(selection.get(AreaTree.class));
else
s.add(atree);
// Store current state for undo
ls.addDataEditStep(s);
try {
for (final Displayable d : s) {
((AreaTree) d).interpolateAllGaps(node_centric, use_distance_map);
}
ls.addDataEditStep(s);
} catch (final Exception e) {
IJError.print(e);
ls.undoOneStep();
}
Display.repaint();
}
}
private final void interpolate(final Node<?> nd, final boolean node_centric) {
if (null == nd.getDataCopy() || ((Area) nd.getData()).isEmpty()) {
Utils.log("Can't interpolate: node lacks an area!");
return;
}
ls.addDataEditStep(atree);
try {
if (atree.interpolateTowardsParent((AreaTree.AreaNode) nd, node_centric, project.getBooleanProperty(AreaUtils.always_interpolate_areas_with_distance_map))) {
ls.addDataEditStep(atree);
} else {
Utils.log("Nothing to interpolate: the parent node already has an area.");
ls.removeLastUndoStep();
}
} catch (final Exception e) {
IJError.print(e);
ls.undoOneStep();
}
Display.repaint();
}
}, atree.getProject());
}
};
final JMenu interpolate = new JMenu("Areas");
JMenuItem item = new JMenuItem("Interpolate gaps towards parent (node-centric)");
item.addActionListener(listener);
interpolate.add(item);
item = new JMenuItem("Interpolate gaps towards parent (absolute)");
item.addActionListener(listener);
interpolate.add(item);
item = new JMenuItem("Interpolate all gaps");
item.addActionListener(listener);
interpolate.add(item);
item = new JMenuItem("Area interpolation options...");
item.addActionListener(Display.this);
interpolate.add(item);
interpolate.addSeparator();
item = new JMenuItem("Copy area");
item.addActionListener(listener);
interpolate.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 0, true));
item = new JMenuItem("Paste area");
item.addActionListener(listener);
interpolate.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, 0, true));
item.setEnabled(null != DisplayCanvas.getCopyBuffer(active.getClass()));
popup.add(interpolate);
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Display method selectTab.
/**
* Select the proper tab, and also scroll it to show the given Displayable -unless it's a LayerSet, and unless the proper tab is already showing.
*/
private void selectTab(final Displayable displ) {
Method method = null;
try {
if (!(displ instanceof LayerSet)) {
method = Display.class.getDeclaredMethod("selectTab", new Class[] { displ.getClass() });
}
} catch (final Exception e) {
IJError.print(e);
}
if (null != method) {
final Method me = method;
dispatcher.exec(new Runnable() {
@Override
public void run() {
try {
me.setAccessible(true);
me.invoke(Display.this, new Object[] { displ });
} catch (final Exception e) {
IJError.print(e);
}
}
});
}
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Display method makeGUI.
private void makeGUI(final Layer layer, final Object[] props) {
// gather properties
final Point p;
double mag = 1.0D;
Rectangle srcRect = null;
if (null != props) {
p = (Point) props[0];
mag = ((Double) props[1]).doubleValue();
srcRect = (Rectangle) props[2];
} else {
p = null;
}
// transparency slider
this.transp_slider = new JSlider(javax.swing.SwingConstants.HORIZONTAL, 0, 100, 100);
this.transp_slider.setBackground(Color.white);
this.transp_slider.setMinimumSize(new Dimension(250, 20));
this.transp_slider.setMaximumSize(new Dimension(250, 20));
this.transp_slider.setPreferredSize(new Dimension(250, 20));
final TransparencySliderListener tsl = new TransparencySliderListener();
this.transp_slider.addChangeListener(tsl);
this.transp_slider.addMouseListener(tsl);
for (final KeyListener kl : this.transp_slider.getKeyListeners()) {
this.transp_slider.removeKeyListener(kl);
}
// Tabbed pane on the left
this.tabs = new JTabbedPane();
this.tabs.setMinimumSize(new Dimension(250, 300));
this.tabs.setBackground(Color.white);
this.tabs.addChangeListener(tabs_listener);
// Tab 1: Patches
this.panel_patches = new RollingPanel(this, Patch.class);
this.addTab("Patches", panel_patches);
// Tab 2: Profiles
this.panel_profiles = new RollingPanel(this, Profile.class);
this.addTab("Profiles", panel_profiles);
// Tab 3: ZDisplayables
this.panel_zdispl = new RollingPanel(this, ZDisplayable.class);
this.addTab("Z space", panel_zdispl);
// Tab 4: channels
this.panel_channels = makeTabPanel();
this.scroll_channels = makeScrollPane(panel_channels);
this.channels = new Channel[4];
this.channels[0] = new Channel(this, Channel.MONO);
this.channels[1] = new Channel(this, Channel.RED);
this.channels[2] = new Channel(this, Channel.GREEN);
this.channels[3] = new Channel(this, Channel.BLUE);
// this.panel_channels.add(this.channels[0]);
addGBRow(this.panel_channels, this.channels[1], null);
addGBRow(this.panel_channels, this.channels[2], this.channels[1]);
addGBRow(this.panel_channels, this.channels[3], this.channels[2]);
this.addTab("Opacity", scroll_channels);
// Tab 5: labels
this.panel_labels = new RollingPanel(this, DLabel.class);
this.addTab("Labels", panel_labels);
// Tab 6: layers
this.panel_layers = makeTabPanel();
this.scroll_layers = makeScrollPane(panel_layers);
recreateLayerPanels(layer);
this.scroll_layers.addMouseWheelListener(canvas);
this.addTab("Layers", scroll_layers);
// Tab 7: tool options
// empty
this.tool_options = new OptionPanel();
this.scroll_options = makeScrollPane(this.tool_options);
this.scroll_options.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.addTab("Tool options", this.scroll_options);
// Tab 8: annotations
this.annot_editor = new JEditorPane();
// by default, nothing is selected
this.annot_editor.setEnabled(false);
this.annot_editor.setMinimumSize(new Dimension(200, 50));
this.annot_label = new JLabel("(No selected object)");
this.annot_panel = makeAnnotationsPanel(this.annot_editor, this.annot_label);
this.addTab("Annotations", this.annot_panel);
// Tab 9: filter options
this.filter_options = createFilterOptionPanel();
this.scroll_filter_options = makeScrollPane(this.filter_options);
this.scroll_filter_options.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.addTab("Live filter", this.scroll_filter_options);
this.ht_tabs = new Hashtable<Class<?>, RollingPanel>();
this.ht_tabs.put(Patch.class, panel_patches);
this.ht_tabs.put(Profile.class, panel_profiles);
this.ht_tabs.put(ZDisplayable.class, panel_zdispl);
this.ht_tabs.put(AreaList.class, panel_zdispl);
this.ht_tabs.put(Pipe.class, panel_zdispl);
this.ht_tabs.put(Polyline.class, panel_zdispl);
this.ht_tabs.put(Treeline.class, panel_zdispl);
this.ht_tabs.put(AreaTree.class, panel_zdispl);
this.ht_tabs.put(Connector.class, panel_zdispl);
this.ht_tabs.put(Ball.class, panel_zdispl);
this.ht_tabs.put(Dissector.class, panel_zdispl);
this.ht_tabs.put(DLabel.class, panel_labels);
this.ht_tabs.put(Stack.class, panel_zdispl);
// channels not included
// layers not included
// tools not included
// annotations not included
// Navigator
this.navigator = new DisplayNavigator(this, layer.getLayerWidth(), layer.getLayerHeight());
// Layer scroller (to scroll slices)
int extent = (int) (250.0 / layer.getParent().size());
if (extent < 10)
extent = 10;
this.scroller = new JScrollBar(JScrollBar.HORIZONTAL);
this.scroller.setModel(new ScrollerModel(layer));
updateLayerScroller(layer);
this.scroller.addAdjustmentListener(scroller_listener);
// LAYOUT
final GridBagLayout layout = new GridBagLayout();
final GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.NONE;
c.weightx = 0;
c.weighty = 0;
c.gridx = 0;
c.gridy = 0;
c.ipadx = 0;
c.ipady = 0;
c.gridwidth = 1;
c.gridheight = 1;
Display.this.all = new JPanel();
all.setBackground(Color.white);
all.setLayout(layout);
c.insets = new Insets(0, 0, 0, 5);
// 1
// fixed dimensions
toolbar_panel = new ToolbarPanel();
layout.setConstraints(toolbar_panel, c);
all.add(toolbar_panel);
// 2
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
layout.setConstraints(transp_slider, c);
all.add(transp_slider);
// 3
c.gridy++;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
layout.setConstraints(tabs, c);
all.add(tabs);
// 4
c.gridy++;
c.weighty = 0;
c.fill = GridBagConstraints.NONE;
layout.setConstraints(navigator, c);
all.add(navigator);
// 5
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
layout.setConstraints(scroller, c);
all.add(scroller);
// Canvas
this.canvas = new DisplayCanvas(this, (int) Math.ceil(layer.getLayerWidth()), (int) Math.ceil(layer.getLayerHeight()));
c.insets = new Insets(0, 0, 0, 0);
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.NORTHWEST;
c.gridx = 1;
c.gridy = 0;
c.gridheight = GridBagConstraints.REMAINDER;
c.weightx = 1;
c.weighty = 1;
layout.setConstraints(Display.this.canvas, c);
all.add(canvas);
// prevent new Displays from screwing up if input is globally disabled
if (!project.isInputEnabled())
Display.this.canvas.setReceivesInput(false);
this.canvas.addComponentListener(canvas_size_listener);
this.navigator.addMouseWheelListener(canvas);
this.transp_slider.addKeyListener(canvas);
// JFrame to show the split pane
this.frame = ControlWindow.createJFrame(layer.toString());
this.frame.setBackground(Color.white);
this.frame.getContentPane().setBackground(Color.white);
if (IJ.isMacintosh() && IJ.getInstance() != null) {
// may be needed for Java 1.4 on OS X
IJ.wait(10);
this.frame.setMenuBar(ij.Menus.getMenuBar());
}
this.frame.addWindowListener(window_listener);
// this.frame.addComponentListener(display_frame_listener);
this.frame.getContentPane().add(all);
if (null != props) {
// restore canvas
canvas.setup(mag, srcRect);
// restore visibility of each channel
// aka c_alphas_state
final int cs = ((Integer) props[5]).intValue();
final int[] sel = new int[4];
sel[0] = ((cs & 0xff000000) >> 24);
sel[1] = ((cs & 0xff0000) >> 16);
sel[2] = ((cs & 0xff00) >> 8);
sel[3] = (cs & 0xff);
// restore channel alphas
Display.this.c_alphas = ((Integer) props[4]).intValue();
channels[0].setAlpha((float) ((c_alphas & 0xff000000) >> 24) / 255.0f, 0 != sel[0]);
channels[1].setAlpha((float) ((c_alphas & 0xff0000) >> 16) / 255.0f, 0 != sel[1]);
channels[2].setAlpha((float) ((c_alphas & 0xff00) >> 8) / 255.0f, 0 != sel[2]);
channels[3].setAlpha((float) (c_alphas & 0xff) / 255.0f, 0 != sel[3]);
// restore visibility in the working c_alphas
Display.this.c_alphas = ((0 != sel[0] ? (int) (255 * channels[0].getAlpha()) : 0) << 24) + ((0 != sel[1] ? (int) (255 * channels[1].getAlpha()) : 0) << 16) + ((0 != sel[2] ? (int) (255 * channels[2].getAlpha()) : 0) << 8) + (0 != sel[3] ? (int) (255 * channels[3].getAlpha()) : 0);
}
if (null != active && null != layer) {
final Rectangle r = active.getBoundingBox();
r.x -= r.width / 2;
r.y -= r.height / 2;
r.width += r.width;
r.height += r.height;
if (r.x < 0)
r.x = 0;
if (r.y < 0)
r.y = 0;
if (r.width > layer.getLayerWidth())
r.width = (int) layer.getLayerWidth();
if (r.height > layer.getLayerHeight())
r.height = (int) layer.getLayerHeight();
final double magn = layer.getLayerWidth() / (double) r.width;
canvas.setup(magn, r);
}
// add keyListener to the whole frame
this.tabs.addKeyListener(canvas);
this.frame.addKeyListener(canvas);
// create a drag and drop listener
dnd = new DNDInsertImage(Display.this);
Utils.invokeLater(new Runnable() {
@Override
public void run() {
Display.this.frame.pack();
ij.gui.GUI.center(Display.this.frame);
Display.this.frame.setVisible(true);
// doesn't get it through events
ProjectToolbar.setProjectToolbar();
final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
if (null != props) {
// fix positioning outside the screen (dual to single monitor)
if (p.x >= 0 && p.x < screen.width - 50 && p.y >= 0 && p.y <= screen.height - 50)
Display.this.frame.setLocation(p);
else
frame.setLocation(0, 0);
}
// fix excessive size
final Rectangle box = Display.this.frame.getBounds();
int x = box.x;
int y = box.y;
int width = box.width;
int height = box.height;
if (box.width > screen.width) {
x = 0;
width = screen.width;
}
if (box.height > screen.height) {
y = 0;
height = screen.height;
}
if (x != box.x || y != box.y) {
// added insets for bad window managers
Display.this.frame.setLocation(x, y + (0 == y ? 30 : 0));
}
if (width != box.width || height != box.height) {
// added insets for bad window managers
Display.this.frame.setSize(new Dimension(width - 10, height - 30));
}
if (null == props) {
// try to optimize canvas dimensions and magn
double magn = layer.getLayerHeight() / screen.height;
if (magn > 1.0)
magn = 1.0;
long size = 0;
// limit magnification if appropriate
for (final Displayable pa : layer.getDisplayables(Patch.class)) {
final Rectangle ba = pa.getBoundingBox();
size += (long) (ba.width * ba.height);
}
if (// 10 Mb
size > 10000000)
// 10 Mb
canvas.setInitialMagnification(0.25);
else {
Display.this.frame.setSize(new Dimension((int) (screen.width * 0.66), (int) (screen.height * 0.66)));
}
}
updateTab(panel_patches);
// re-layout:
tabs.validate();
// Set the calibration of the FakeImagePlus to that of the LayerSet
((FakeImagePlus) canvas.getFakeImagePlus()).setCalibrationSuper(layer.getParent().getCalibrationCopy());
updateFrameTitle(layer);
// Set the FakeImagePlus as the current image
setTempCurrentImage();
// start a repainting thread
if (null != props) {
// repaint() is unreliable
canvas.repaint(true);
}
ControlWindow.setLookAndFeel();
}
});
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class Display3D method show.
/**
* Scan the {@link ProjectThing} children and assign the renderable ones to an existing {@link Display3D} for their {@link LayerSet}, or open a new one. If {@code true == wait && -1 != resample}, then the method returns only when the mesh/es have been added.
*/
public static Future<Vector<Future<Content>>> show(final ProjectThing pt, final boolean wait, final int resample) {
if (null == pt)
return null;
final Future<Vector<Future<Content>>> fu = launchers.submit(new Callable<Vector<Future<Content>>>() {
@Override
public Vector<Future<Content>> call() {
// Scan the given ProjectThing for 3D-viewable items
// So: find arealist, pipe, ball, and profile_list types
final HashSet<ProjectThing> hs = pt.findBasicTypeChildren();
if (null == hs || 0 == hs.size()) {
Utils.logAll("Node " + pt + " does not contain any 3D-displayable children");
return null;
}
// Remove profile if it lives under a profile_list
for (final Iterator<ProjectThing> it = hs.iterator(); it.hasNext(); ) {
final ProjectThing pt = it.next();
if (null != pt.getObject() && pt.getObject().getClass() == Profile.class && pt.getParent().getType().equals("profile_list")) {
it.remove();
}
}
setWaitingCursor();
// Start new scheduler to publish/add meshes to the 3D Viewer every 5 seconds and when done.
final Hashtable<Display3D, Vector<Content>> contents = new Hashtable<Display3D, Vector<Content>>();
final ScheduledExecutorService updater = Executors.newScheduledThreadPool(1);
final AtomicInteger counter = new AtomicInteger();
updater.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
// Obtain a copy of the contents queue
final HashMap<Display3D, Vector<Content>> m = new HashMap<Display3D, Vector<Content>>();
synchronized (contents) {
m.putAll(contents);
contents.clear();
}
if (m.isEmpty())
return;
// Add all to the corresponding Display3D
for (final Map.Entry<Display3D, Vector<Content>> e : m.entrySet()) {
e.getKey().universe.addContentLater(e.getValue());
counter.getAndAdd(e.getValue().size());
}
Utils.showStatus(new StringBuilder("Rendered ").append(counter.get()).append('/').append(hs.size()).toString());
}
}, 100, 4000, TimeUnit.MILLISECONDS);
// A list of all generated Content objects
final Vector<Future<Content>> list = new Vector<Future<Content>>();
for (final Iterator<ProjectThing> it = hs.iterator(); it.hasNext(); ) {
// obtain the Displayable object under the node
final ProjectThing child = it.next();
final Object obc = child.getObject();
final Displayable displ = obc.getClass().equals(String.class) ? null : (Displayable) obc;
if (null != displ) {
if (displ.getClass().equals(Profile.class)) {
// handled by profile_list Thing
continue;
}
if (!displ.isVisible()) {
Utils.log("Skipping non-visible node " + displ);
continue;
}
}
// obtain the containing LayerSet
final Display3D d3d;
if (null != displ)
d3d = Display3D.get(displ.getLayerSet());
else if (child.getType().equals("profile_list")) {
final ArrayList<ProjectThing> al_children = child.getChildren();
if (null == al_children || 0 == al_children.size())
continue;
// else, get the first Profile and get its LayerSet
d3d = Display3D.get(((Displayable) ((ProjectThing) al_children.get(0)).getObject()).getLayerSet());
} else {
Utils.log("Don't know what to do with node " + child);
d3d = null;
}
if (null == d3d) {
Utils.log("Could not get a proper 3D display for node " + displ);
// java3D not installed most likely
return null;
}
boolean already;
synchronized (d3d.ht_pt_meshes) {
already = d3d.ht_pt_meshes.containsKey(child);
}
if (already) {
if (child.getObject() instanceof ZDisplayable) {
Utils.log("Updating 3D view of " + child.getObject());
} else {
Utils.log("Updating 3D view of " + child);
}
}
list.add(d3d.executors.submit(new Callable<Content>() {
@Override
public Content call() {
Content c = null;
try {
c = d3d.createMesh(child, displ, resample).call();
Vector<Content> vc;
synchronized (contents) {
vc = contents.get(d3d);
if (null == vc)
vc = new Vector<Content>();
contents.put(d3d, vc);
}
vc.add(c);
} catch (final Exception e) {
IJError.print(e);
}
return c;
}
}));
// If it's the last one:
if (!it.hasNext()) {
// Add the concluding task, that waits on all and shuts down the scheduler
d3d.executors.submit(new Runnable() {
@Override
public void run() {
// Wait until all are done
for (final Future<Content> c : list) {
try {
c.get();
} catch (final Throwable t) {
IJError.print(t);
}
}
try {
// Shutdown scheduler and execute remaining tasks
for (final Runnable r : updater.shutdownNow()) {
r.run();
}
} catch (final Throwable e) {
IJError.print(e);
}
// Reset cursor
doneWaiting();
Utils.showStatus(new StringBuilder("Done rendering ").append(counter.get()).append('/').append(hs.size()).toString());
}
});
}
}
return list;
}
});
if (wait && -1 != resample) {
try {
fu.get();
} catch (final Throwable t) {
IJError.print(t);
}
}
return fu;
}
Aggregations