/**
TrakEM2 plugin for ImageJ(C).
Copyright (C) 2005-2009 Albert Cardona and Rodney Douglas.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation (http://www.gnu.org/licenses/gpl.txt )
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
You may contact Albert Cardona at acardona at ini.phys.ethz.ch
Institute of Neuroinformatics, University of Zurich / ETH, Switzerland.
**/
package ini.trakem2.display;
import ini.trakem2.utils.Utils;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public final class LayerPanel extends JPanel implements MouseListener {
private static final long serialVersionUID = 1L;
private final JLabel title;
protected final JSlider slider = new JSlider(javax.swing.SwingConstants.HORIZONTAL, 0, 100, 0);
private Color color = Color.white;
private float alpha = 0.0f; // for overlays
private final Display display;
protected final Layer layer;
public LayerPanel(final Display display, final Layer layer) {
this.display = display;
this.layer = layer;
this.slider.addChangeListener(new ChangeListener() {
public void stateChanged(final ChangeEvent ce) {
final float a = slider.getValue() / 100.0f;
setAlpha(a);
display.storeLayerAlpha(LayerPanel.this, a);
display.getCanvas().repaint(true);
}
});
// Insert this mouse listener before the slider's
/* // BIZARRE autoscrolling of the slider when popup is up. And cannot be fixed with if (popup), neither within the ChangeEvent (which doesn't register)
final MouseListener[] mls = slider.getMouseListeners();
for (final MouseListener ml : mls) slider.removeMouseListener(ml); // works because getMouseListeners returns an immutable array.
slider.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
doMousePressed(me);
me.consume();
}
});
for (final MouseListener ml : mls) slider.addMouseListener(ml);
*/
this.title = new JLabel(makeTitle());
this.title.addMouseListener(this);
GridBagLayout gb = new GridBagLayout();
setLayout(gb);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.weighty = 0;
gb.setConstraints(title, c);
add(title);
JPanel empty = new JPanel();
c.gridy += 1;
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
gb.setConstraints(empty, c);
c.gridy += 1;
c.weighty = 0;
c.fill = GridBagConstraints.HORIZONTAL;
gb.setConstraints(slider, c);
add(slider);
setMinimumSize(new Dimension(0, DisplayablePanel.HEIGHT));
setPreferredSize(new Dimension(250, DisplayablePanel.HEIGHT));
addMouseListener(this);
setBackground(this.color);
setBorder(BorderFactory.createLineBorder(Color.black));
}
private final String makeTitle() {
return new StringBuilder().append(layer.getParent().indexOf(layer) + 1).append(':').append(' ').append(layer.getTitle()).toString();
}
public final void setColor(final Color color) {
this.color = color;
setBackground(color);
slider.setBackground(color);
if (Color.white == color) {
title.setForeground(Color.black);
} else {
title.setForeground(Color.white);
}
repaint();
}
public final Color getColor() { return color; }
public final void setAlpha(final float alpha) {
if (alpha < 0 || alpha > 1) return;
this.alpha = alpha;
slider.setValue((int)(alpha * 100));
}
public final float getAlpha() { return alpha; }
public final void paint(final Graphics g) {
title.setText(makeTitle());
if (display.getLayer() == layer) {
setBackground(Color.green);
slider.setBackground(Color.green);
} else {
setBackground(color);
slider.setBackground(color);
}
super.paint(g);
}
private class ColorActionListener implements ActionListener {
final Color c;
ColorActionListener(final Color c) { this.c = c; }
public void actionPerformed(final ActionEvent ae) {
setColor(c);
display.setColorChannel(layer, c);
}
}
public void mousePressed(final MouseEvent me) {
doMousePressed(me);
}
private void doMousePressed(final MouseEvent me) {
if (Utils.isPopupTrigger(me)) {
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem("Set as red channel"); popup.add(item);
if (Color.red == this.color) item.setEnabled(false);
else item.addActionListener(new ColorActionListener(Color.red));
item = new JMenuItem("Set as blue channel"); popup.add(item);
if (Color.blue == this.color) item.setEnabled(false);
else item.addActionListener(new ColorActionListener(Color.blue));
item = new JMenuItem("Reset"); popup.add(item);
if (Color.white == this.color) item.setEnabled(false);
else item.addActionListener(new ColorActionListener(Color.white));
JCheckBoxMenuItem citem = new JCheckBoxMenuItem("Invert"); popup.add(citem);
citem.setState(display.invert_colors);
citem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
display.invert_colors = !display.invert_colors;
display.getCanvas().repaint(true);
}
});
JMenu transp_menu = new JMenu("Overlay items"); popup.add(transp_menu);
final JCheckBoxMenuItem cbI = new JCheckBoxMenuItem("Images", display.transp_overlay_images);
final JCheckBoxMenuItem cbA = new JCheckBoxMenuItem("Areas", display.transp_overlay_areas);
final JCheckBoxMenuItem cbL = new JCheckBoxMenuItem("Text labels", display.transp_overlay_text_labels);
ActionListener lis = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Object src = ae.getSource();
if (src == cbI) display.setTranspOverlayImages(cbI.getState());
else if (src == cbA) display.setTranspOverlayAreas(cbA.getState());
else if (src == cbL) display.setTranspOverlayTextLabels(cbL.getState());
}
};
for (JCheckBoxMenuItem rb : new JCheckBoxMenuItem[]{cbI, cbA, cbL}) {
transp_menu.add(rb);
rb.addActionListener(lis);
}
popup.addSeparator();
JMenu composites = new JMenu("Composite mode");
ButtonGroup group = new ButtonGroup();
byte compositeMode = display.getLayerCompositeMode(layer);
for (int i=0; i<Displayable.compositeModes.length; i++) {
JRadioButton rb = new JRadioButton(Displayable.compositeModes[i], compositeMode == i);
rb.setActionCommand(Displayable.compositeModes[i]);
final byte cm = (byte) i;
rb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
display.setLayerCompositeMode(layer, cm);
}
});
composites.add(rb);
group.add(rb);
}
popup.add(composites);
popup.addSeparator();
item = new JMenuItem("Reset all layer coloring"); popup.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
display.resetLayerColors();
}
});
item = new JMenuItem("Reset all layer alphas"); popup.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
display.resetLayerAlphas();
}
});
item = new JMenuItem("Reset all layer composites"); popup.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
display.resetLayerComposites();
}
});
popup.show(this, me.getX(), me.getY());
me.consume();
return;
}
final int mod = me.getModifiers();
Utils.log2("mouse pressed : " + mod);
if (0 == (mod & Event.ALT_MASK) && 0 == (mod & Event.SHIFT_MASK)) {
// Would mess up translation of red/blue colors when scrolling
// So just do nothing.
/*
display.toLayer(this.layer);
setColor(Color.white);
display.setColorChannel(this.layer, this.color);
repaint();
*/
} else if (display.getLayer() == this.layer) {
// do nothing
} else if (0 != (mod & Event.ALT_MASK)) {
if (this.color == Color.blue) {
// unset
setColor(Color.white);
} else {
// set as blue channel
setColor(Color.blue);
}
display.setColorChannel(this.layer, this.color);
me.consume();
} else if (0 != (mod & Event.SHIFT_MASK)) {
if (this.color == Color.red) {
// unset
setColor(Color.white);
} else {
// set as red channel
setColor(Color.red);
}
display.setColorChannel(this.layer, this.color);
me.consume();
}
}
public void mouseReleased(MouseEvent me) {}
public void mouseEntered(MouseEvent me) {}
public void mouseExited (MouseEvent me) {}
public void mouseClicked(MouseEvent me) {}
public final String toString() {
return "Layer panel for " + layer.getTitle();
}
}