/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package de.cismet.tools.gui.jbands;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.RepaintManager;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import de.cismet.tools.gui.jbands.interfaces.Band;
import de.cismet.tools.gui.jbands.interfaces.BandAbsoluteHeightProvider;
import de.cismet.tools.gui.jbands.interfaces.BandMember;
import de.cismet.tools.gui.jbands.interfaces.BandMemberActionProvider;
import de.cismet.tools.gui.jbands.interfaces.BandMemberMouseListeningComponent;
import de.cismet.tools.gui.jbands.interfaces.BandMemberSelectable;
import de.cismet.tools.gui.jbands.interfaces.BandModel;
import de.cismet.tools.gui.jbands.interfaces.BandModelListener;
import de.cismet.tools.gui.jbands.interfaces.BandModificationProvider;
import de.cismet.tools.gui.jbands.interfaces.BandPostfixProvider;
import de.cismet.tools.gui.jbands.interfaces.BandPrefixProvider;
import de.cismet.tools.gui.jbands.interfaces.BandSnappingPointProvider;
import de.cismet.tools.gui.jbands.interfaces.BandWeightProvider;
import de.cismet.tools.gui.jbands.interfaces.DisposableBand;
import de.cismet.tools.gui.jbands.interfaces.Section;
import de.cismet.tools.gui.jbands.interfaces.Spot;
import de.cismet.tools.gui.jbands.interfaces.StationaryBandMemberMouseListeningComponent;
import de.cismet.tools.gui.log4jquickconfig.Log4JQuickConfig;
/**
* DOCUMENT ME!
*
* @author thorsten
* @version $Revision$, $Date$
*/
public class JBand extends JPanel implements ActionListener,
MouseListener,
MouseMotionListener,
BandModelListener,
KeyListener {
//~ Static fields/initializers ---------------------------------------------
public static final Dimension MINDIM = new Dimension(0, 0);
//~ Enums ------------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
public static enum SelectionMode {
//~ Enum constants -----------------------------------------------------
SINGLE_SELECTION, MULTIPLE_INTERVAL_SELECTION
}
//~ Instance fields --------------------------------------------------------
HashMap<JComponent, BandMember> bandMembersViaComponents = new HashMap<JComponent, BandMember>();
HashMap<BandMember, JComponent> componentsViaBandMembers = new HashMap<BandMember, JComponent>();
JBandsPanel bandsPanel = new JBandsPanel();
JLegendPanel legendPanel = new JLegendPanel();
JLegendPanel postfixPanel = new JLegendPanel();
ArrayList<ActionListener> actionListeners = new ArrayList<ActionListener>();
List<BandMemberSelectable> selectedBandMember = new ArrayList<BandMemberSelectable>();
int count = 0;
private int maxPreferredPrefixWidth = 0;
private int maxPreferredPostfixWidth = 0;
private final transient org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(this.getClass());
private BandModel model;
private double zoomFactor = 1.0;
private JScrollPane scrollPane = new JScrollPane(bandsPanel);
private float[] heightWeights;
private double minValue = Double.MAX_VALUE;
private double maxValue = Double.MIN_VALUE;
private double additionalZoomFactor = 1;
private float heightsWeightSum = 0f;
private double realWidth = 0;
private List<JBandYDimension> bandPosY = new ArrayList<JBandYDimension>();
private Map<Band, ArrayList<ArrayList<BandMember>>> subBandMap =
new HashMap<Band, ArrayList<ArrayList<BandMember>>>();
private List<SnappingPoint> snappingPoints = new ArrayList<SnappingPoint>();
private boolean readOnly = false;
private boolean refreshAvoided = false;
private Component lastPressedComponent = null;
private boolean dragged = false;
private SelectionMode selectionMode = SelectionMode.SINGLE_SELECTION;
private boolean hideEmptyPrePostfix = false;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new JBand object.
*/
public JBand() {
this(false);
}
/**
* Creates a new JBand object.
*
* @param readOnly DOCUMENT ME!
*/
public JBand(final boolean readOnly) {
this.readOnly = readOnly;
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
setOpaque(false);
bandsPanel.setOpaque(false);
bandsPanel.addMouseMotionListener(this);
bandsPanel.addMouseListener(this);
setFocusable(true);
bandsPanel.setFocusable(true);
legendPanel.setFocusable(true);
postfixPanel.setFocusable(true);
// this.addKeyListener(this);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));
setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
}
/**
* Creates a new JBand object.
*
* @param model DOCUMENT ME!
*/
public JBand(final BandModel model) {
this();
setModel(model);
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return the hideEmptyPrePostfix
*/
public boolean isHideEmptyPrePostfix() {
return hideEmptyPrePostfix;
}
/**
* DOCUMENT ME!
*
* @param hideEmptyPrePostfix the hideEmptyPrePostfix to set
*/
public void setHideEmptyPrePostfix(final boolean hideEmptyPrePostfix) {
this.hideEmptyPrePostfix = hideEmptyPrePostfix;
if (model != null) {
init();
}
}
/**
* DOCUMENT ME!
*
* @return the selectionMode
*/
public SelectionMode getSelectionMode() {
return selectionMode;
}
/**
* DOCUMENT ME!
*
* @param selectionMode the selectionMode to set
*/
public void setSelectionMode(final SelectionMode selectionMode) {
this.selectionMode = selectionMode;
}
@Override
public void keyTyped(final KeyEvent e) {
if (((e.getModifiers() & KeyEvent.CTRL_DOWN_MASK) != 0) && (e.getKeyChar() == 'a')) {
for (int bandIndex = 0; bandIndex < model.getNumberOfBands(); ++bandIndex) {
final Band b = model.getBand(bandIndex);
for (int memberIndex = 0; memberIndex < b.getNumberOfMembers(); ++memberIndex) {
final BandMember member = b.getMember(memberIndex);
if (member instanceof BandMemberSelectable) {
final BandMemberSelectable bms = (BandMemberSelectable)member;
if (!selectedBandMember.contains(bms)) {
bms.setSelected(true);
selectedBandMember.add(bms);
}
}
}
}
}
repaint();
}
@Override
public void keyPressed(final KeyEvent e) {
}
@Override
public void keyReleased(final KeyEvent e) {
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public BandMember getSelectedBandMember() {
if (selectedBandMember.size() > 0) {
return selectedBandMember.get(0).getBandMember();
} else {
return null;
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public List<BandMemberSelectable> getSelectedBandMemberList() {
return selectedBandMember;
}
/**
* DOCUMENT ME!
*
* @param horizontalScrollBarPolicy DOCUMENT ME!
*/
public void setHorizontalScrollBarPolicy(final int horizontalScrollBarPolicy) {
scrollPane.setHorizontalScrollBarPolicy(horizontalScrollBarPolicy);
}
/**
* DOCUMENT ME!
*
* @param model DOCUMENT ME!
*/
public void setModel(final BandModel model) {
if (this.model != null) {
this.model.removeBandModelListener(this);
}
this.model = model;
model.addBandModelListener(this);
init();
}
/**
* DOCUMENT ME!
*
* @param readOnly DOCUMENT ME!
*/
public void setReadOnly(final boolean readOnly) {
this.readOnly = readOnly;
}
/**
* DOCUMENT ME!
*/
private void init() {
final double prefWidth = legendPanel.getPreferredSize().getWidth();
minValue = Double.MAX_VALUE;
maxValue = Double.MIN_VALUE;
bandsPanel.removeAll();
legendPanel.removeAll();
for (int row = 0; row < model.getNumberOfBands(); ++row) {
final int cols = model.getBand(row).getNumberOfMembers();
final Band rowBand = model.getBand(row);
JComponent prefix = null;
if (rowBand instanceof BandPrefixProvider) {
prefix = ((BandPrefixProvider)rowBand).getPrefixComponent();
legendPanel.add(prefix);
maxPreferredPrefixWidth = (maxPreferredPrefixWidth < prefix.getPreferredSize().width)
? prefix.getPreferredSize().width : maxPreferredPrefixWidth;
}
for (int col = 0; col < cols; ++col) {
final BandMember member = rowBand.getMember(col);
final JComponent comp = member.getBandMemberComponent();
if (member instanceof BandMemberActionProvider) {
((BandMemberActionProvider)member).addActionListener(this);
}
bandsPanel.add(comp);
bandMembersViaComponents.put(comp, member);
componentsViaBandMembers.put(member, comp);
if (!Arrays.asList(comp.getMouseListeners()).contains(this)) {
comp.addMouseListener(this);
}
if (!Arrays.asList(comp.getMouseMotionListeners()).contains(this)) {
comp.addMouseMotionListener(this);
}
}
if (rowBand instanceof BandPostfixProvider) {
final JComponent postfix = ((BandPostfixProvider)rowBand).getPostfixComponent();
postfixPanel.add(postfix);
final int pWidth = postfix.getPreferredSize().width;
if (maxPreferredPostfixWidth < pWidth) {
maxPreferredPostfixWidth = pWidth;
}
}
}
heightWeights = new float[model.getNumberOfBands()];
for (int zeile = 0; zeile < model.getNumberOfBands(); ++zeile) {
final Band b = model.getBand(zeile);
if (b instanceof BandWeightProvider) {
heightWeights[zeile] = ((BandWeightProvider)b).getBandWeight();
} else if (b instanceof BandAbsoluteHeightProvider) {
heightWeights[zeile] = 0f;
} else {
heightWeights[zeile] = 1f;
}
if (b.getMax() > getMaxValue()) {
setMaxValue(b.getMax());
}
if (b.getMin() < getMinValue()) {
setMinValue(b.getMin());
}
}
if (isHideEmptyPrePostfix()) {
if (!Arrays.asList(getComponents()).contains(legendPanel) && (legendPanel.getComponentCount() > 0)) {
add(legendPanel, BorderLayout.LINE_START);
} else if (Arrays.asList(getComponents()).contains(legendPanel) && (legendPanel.getComponentCount() == 0)) {
remove(legendPanel);
}
if (!Arrays.asList(getComponents()).contains(postfixPanel) && (postfixPanel.getComponentCount() > 0)) {
add(postfixPanel, BorderLayout.LINE_END);
} else if (Arrays.asList(getComponents()).contains(postfixPanel)
&& (postfixPanel.getComponentCount() == 0)) {
remove(postfixPanel);
}
} else {
if (!Arrays.asList(getComponents()).contains(legendPanel)) {
add(legendPanel, BorderLayout.LINE_START);
}
if (!Arrays.asList(getComponents()).contains(postfixPanel)) {
add(postfixPanel, BorderLayout.LINE_END);
}
}
realWidth = getMaxValue() - getMinValue();
layoutBandMemberComponents();
if (legendPanel.getPreferredSize().getWidth() != prefWidth) {
updateUI();
}
}
/**
* DOCUMENT ME!
*/
private void layoutBandMemberComponents() {
heightsWeightSum = 0;
bandPosY.clear();
snappingPoints.clear();
if ((model == null) || (model.getNumberOfBands() == 0) || (bandsPanel.getWidth() <= 0)) {
return;
}
int remainingBandsPanelHeight = bandsPanel.getHeight();
for (int zeile = 0; zeile < model.getNumberOfBands(); ++zeile) {
final Band rowBand = model.getBand(zeile);
if (rowBand.isEnabled()) {
heightsWeightSum += heightWeights[zeile];
if (rowBand instanceof BandAbsoluteHeightProvider) {
remainingBandsPanelHeight -= ((BandAbsoluteHeightProvider)rowBand).getAbsoluteHeight();
}
// save snapping points
if (rowBand instanceof BandSnappingPointProvider) {
for (int i = 0; i < rowBand.getNumberOfMembers(); ++i) {
final BandMember m = rowBand.getMember(i);
snappingPoints.add(new SnappingPoint(m.getMin(), m.getBandMemberComponent()));
snappingPoints.add(new SnappingPoint(m.getMax(), m.getBandMemberComponent()));
}
}
if (remainingBandsPanelHeight < 0) {
// TODO
}
}
}
// prefixes
int posy = 0;
for (int zeile = 0; zeile < model.getNumberOfBands(); ++zeile) {
final Band rowBand = model.getBand(zeile);
int memberHeight;
if (!rowBand.isEnabled()) {
memberHeight = 0;
} else if ((heightWeights[zeile] == 0) && (rowBand instanceof BandAbsoluteHeightProvider)) {
memberHeight = ((BandAbsoluteHeightProvider)rowBand).getAbsoluteHeight();
final int subCount = getSubbandCount(rowBand);
if (memberHeight < subCount) {
memberHeight = subCount;
}
} else {
memberHeight = (int)(((double)remainingBandsPanelHeight) * heightWeights[zeile] / heightsWeightSum);
final int subCount = getSubbandCount(rowBand);
if (memberHeight < subCount) {
memberHeight = subCount;
}
}
if (rowBand instanceof BandPrefixProvider) {
final JComponent prefix = ((BandPrefixProvider)rowBand).getPrefixComponent();
prefix.setBounds(0, posy, maxPreferredPrefixWidth, memberHeight);
}
if (memberHeight > 0) {
bandPosY.add(new JBandYDimension(rowBand, posy, posy + memberHeight - 1));
}
posy += memberHeight;
}
// BandMember
posy = 0;
for (int zeile = 0; zeile < model.getNumberOfBands(); ++zeile) {
final Band rowBand = model.getBand(zeile);
int memberHeight;
if (!rowBand.isEnabled()) {
memberHeight = 0;
for (int i = 0; i < rowBand.getNumberOfMembers(); ++i) {
rowBand.getMember(i).getBandMemberComponent().setBounds(new Rectangle(0, 0, 0, 0));
}
continue;
} else if ((heightWeights[zeile] == 0) && (rowBand instanceof BandAbsoluteHeightProvider)) {
memberHeight = ((BandAbsoluteHeightProvider)rowBand).getAbsoluteHeight();
final int subCount = getSubbandCount(rowBand);
if (memberHeight < subCount) {
memberHeight = subCount;
}
} else {
memberHeight = (int)(((double)remainingBandsPanelHeight) * heightWeights[zeile] / heightsWeightSum);
final int subCount = getSubbandCount(rowBand);
if (memberHeight < subCount) {
memberHeight = subCount;
}
}
final ArrayList<ArrayList<BandMember>> subBands = new ArrayList<ArrayList<BandMember>>();
final ArrayList<BandMember> masterBand = new ArrayList<BandMember>();
for (int i = 0; i < rowBand.getNumberOfMembers(); ++i) {
masterBand.add(rowBand.getMember(i));
}
for (int i = 0; i < rowBand.getNumberOfMembers(); ++i) {
for (int j = i; j < rowBand.getNumberOfMembers(); ++j) {
final BandMember bi = rowBand.getMember(i);
final BandMember bj = rowBand.getMember(j);
if ((i != j) && masterBand.contains(bi) && masterBand.contains(bj)) {
if (isColliding(bi, bj)) {
masterBand.remove(bj);
boolean added = false;
for (final ArrayList<BandMember> subBand : subBands) {
if (!hasCollisions(subBand, bj)) {
subBand.add(bj);
added = true;
break;
}
}
if (!added) {
final ArrayList<BandMember> newSubBand = new ArrayList<BandMember>();
newSubBand.add(bj);
subBands.add(newSubBand);
}
}
}
}
}
double roundingDifference = 0.0;
if (subBands.size() > 0) {
roundingDifference = ((double)memberHeight / (1.0 + (double)subBands.size()));
memberHeight = (int)(memberHeight / (1 + subBands.size()));
roundingDifference = roundingDifference - (double)memberHeight;
}
for (final BandMember bm : masterBand) {
bm.getBandMemberComponent().setBounds(getBoundsOfComponent(bm, memberHeight, posy));
}
posy += memberHeight;
for (final ArrayList<BandMember> subBand : subBands) {
for (final BandMember bm : subBand) {
bm.getBandMemberComponent().setBounds(getBoundsOfComponent(bm, memberHeight, posy));
}
posy += memberHeight;
}
posy += roundingDifference * (1 + subBands.size());
subBands.add(masterBand);
subBandMap.put(rowBand, subBands);
}
// postfix
posy = 0;
for (int row = 0; row < model.getNumberOfBands(); ++row) {
final Band rowBand = model.getBand(row);
int memberHeight;
if (!rowBand.isEnabled()) {
memberHeight = 0;
} else if ((heightWeights[row] == 0) && (rowBand instanceof BandAbsoluteHeightProvider)) {
memberHeight = ((BandAbsoluteHeightProvider)rowBand).getAbsoluteHeight();
final int subCount = getSubbandCount(rowBand);
if (memberHeight < subCount) {
memberHeight = subCount;
}
} else {
memberHeight = (int)(((double)remainingBandsPanelHeight) * heightWeights[row] / heightsWeightSum);
final int subCount = getSubbandCount(rowBand);
if (memberHeight < subCount) {
memberHeight = subCount;
}
}
if (rowBand instanceof BandPostfixProvider) {
final JComponent prefix = ((BandPostfixProvider)rowBand).getPostfixComponent();
prefix.setBounds(0, posy, maxPreferredPostfixWidth, memberHeight);
}
if (memberHeight > 0) {
bandPosY.add(new JBandYDimension(rowBand, posy, posy + memberHeight - 1));
}
posy += memberHeight;
}
}
/**
* DOCUMENT ME!
*
* @param members DOCUMENT ME!
* @param candidate DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private boolean hasCollisions(final ArrayList<BandMember> members, final BandMember candidate) {
for (final BandMember bm : members) {
if (isColliding(bm, candidate)) {
return true;
}
}
return false;
}
/**
* Calculates the count of subbands for the given band.
*
* @param band DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private int getSubbandCount(final Band band) {
final ArrayList<ArrayList<BandMember>> subBands = new ArrayList<ArrayList<BandMember>>();
final ArrayList<BandMember> masterBand = new ArrayList<BandMember>();
for (int i = 0; i < band.getNumberOfMembers(); ++i) {
masterBand.add(band.getMember(i));
}
for (int i = 0; i < band.getNumberOfMembers(); ++i) {
for (int j = i; j < band.getNumberOfMembers(); ++j) {
final BandMember bi = band.getMember(i);
final BandMember bj = band.getMember(j);
if ((i != j) && masterBand.contains(bi) && masterBand.contains(bj)) {
if (isColliding(bi, bj)) {
masterBand.remove(bj);
boolean added = false;
for (final ArrayList<BandMember> subBand : subBands) {
if (!hasCollisions(subBand, bj)) {
subBand.add(bj);
added = true;
break;
}
}
if (!added) {
final ArrayList<BandMember> newSubBand = new ArrayList<BandMember>();
newSubBand.add(bj);
subBands.add(newSubBand);
}
}
}
}
}
return subBands.size() + 1;
}
/**
* DOCUMENT ME!
*
* @param a DOCUMENT ME!
* @param b DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
private boolean isColliding(final BandMember a, final BandMember b) {
if ((a instanceof Section) && (b instanceof Section)) {
return (!((a.getMax() <= b.getMin()) || (a.getMin() >= b.getMax())));
} else if ((a instanceof Spot) || (b instanceof Spot)) {
// dummy werte
final int memberHeight = 10;
final int posy = 10;
final Rectangle ri = getBoundsOfComponent(a, memberHeight, posy);
final Rectangle rj = getBoundsOfComponent(b, memberHeight, posy);
final int rimax = ri.x + ri.width;
final int rimin = ri.x;
final int rjmax = rj.x + rj.width;
final int rjmin = rj.x;
return (!((rimax <= rjmin) || (rimin >= rjmax)));
}
throw new IllegalArgumentException("Possible Combinations are Section,Section and Spot,Spot");
}
/**
* DOCUMENT ME!
*
* @param member DOCUMENT ME!
* @param memberHeight DOCUMENT ME!
* @param posy DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private Rectangle getBoundsOfComponent(final BandMember member,
final int memberHeight,
final int posy) {
final JComponent comp = member.getBandMemberComponent();
final double widthFactor = ((double)bandsPanel.getWidth()) / realWidth;
if (member instanceof Section) {
final int posx = (int)(((member.getMin() - minValue) * widthFactor) + 0.5d);
final int lastPosX = (int)(((member.getMax() - minValue) * widthFactor) + 0.5d);
final int memberWidth = Math.max(lastPosX - posx, 1);
return new Rectangle(posx, posy, memberWidth, memberHeight);
} else if (member instanceof Spot) {
final int memberWidth = comp.getPreferredSize().width;
final int posx = (int)(((member.getMin() - minValue) * widthFactor) + 0.5d - (memberWidth / 2d));
return new Rectangle(posx, posy, memberWidth, memberHeight);
}
return null;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public double getZoomFactor() {
return zoomFactor / additionalZoomFactor;
}
/**
* DOCUMENT ME!
*
* @param zoomFactor DOCUMENT ME!
*/
public void setZoomFactor(double zoomFactor) {
zoomFactor = zoomFactor * additionalZoomFactor;
final double myZoomFactor = zoomFactor / this.zoomFactor;
this.zoomFactor = zoomFactor;
setRefreshAvoided(true);
final RepaintManager rm = RepaintManager.currentManager(bandsPanel);
rm.markCompletelyClean(bandsPanel);
scrollPane.getViewport().revalidate();
if (!selectedBandMember.isEmpty()) {
final double relTargetPosition = ((selectedBandMember.get(0).getBandMember().getMin() - minValue)
/ (maxValue - minValue));
final double newJBandWidth = scrollPane.getWidth() * 0.9 * zoomFactor; //
final double absTargetPosition = newJBandWidth / myZoomFactor * relTargetPosition;
final double currentXOffset = scrollPane.getViewport().getViewPosition().getX();
final double currentAbsTargetViewPosition = absTargetPosition - currentXOffset;
final double newOffset = ((currentAbsTargetViewPosition + currentXOffset) * myZoomFactor)
- currentAbsTargetViewPosition;
final Rectangle r = scrollPane.getViewportBorderBounds();
final Point newPosition = new Point((int)(newOffset), (int)r.getY());
scrollPane.getViewport().setViewPosition(newPosition);
}
setRefreshAvoided(false);
scrollPane.getViewport().revalidate();
}
/**
* DOCUMENT ME!
*/
public void fireActionPerformed() {
final ActionEvent e = new ActionEvent(this, 1, "selectionChanged");
log.info("BandMemberAction Performed");
for (final ActionListener al : actionListeners) {
al.actionPerformed(e);
}
}
/**
* DOCUMENT ME!
*
* @param listener DOCUMENT ME!
*/
public void addActionListener(final ActionListener listener) {
actionListeners.add(listener);
}
/**
* DOCUMENT ME!
*
* @param listener DOCUMENT ME!
*/
public void removeActionListener(final ActionListener listener) {
actionListeners.remove(listener);
}
@Override
public void mouseClicked(final MouseEvent e) {
if (!readOnly && (e.getClickCount() == 2)) {
if (e.getComponent() == bandsPanel) {
final int y = e.getY();
int startY = 0;
int bandHeight = 0;
Band targetBand = null;
for (final JBandYDimension tmp : bandPosY) {
if ((y >= tmp.getyMin()) && (y <= tmp.getyMax())) {
targetBand = tmp.getBand();
startY = tmp.getyMin();
bandHeight = tmp.getyMax() - tmp.getyMin();
break;
}
}
if (targetBand != null) {
if (targetBand instanceof BandModificationProvider) {
final double station = getSationForXValue(e.getX());
final ArrayList<ArrayList<BandMember>> subBands = subBandMap.get(targetBand);
int n = (y - startY) / (bandHeight / subBands.size());
--n;
// the first band is a the end of the list
if (n == -1) {
n = subBands.size() - 1;
}
((BandModificationProvider)targetBand).addMember(
station,
null,
getMinValue(),
getMaxValue(),
subBands.get(n));
}
}
}
} else {
if (e.getComponent() instanceof BandMemberSelectable) {
final BandMemberSelectable selecteable = (BandMemberSelectable)e.getComponent();
JBandCursorManager.getInstance().setCursor(this);
if (e.getClickCount() == 1) {
if (!e.isPopupTrigger()) {
if ((selectionMode == SelectionMode.MULTIPLE_INTERVAL_SELECTION)
&& !(e.isShiftDown() || e.isControlDown())
&& (selectedBandMember.size() > 1)) {
deselectAllBandMember();
}
if (selecteable.isSelectable() && !selecteable.isSelected()
&& !selectedBandMember.contains(selecteable)) {
// select band member
if (!selectedBandMember.isEmpty()
&& !((selectionMode == SelectionMode.MULTIPLE_INTERVAL_SELECTION)
&& (e.isShiftDown() || e.isControlDown()))) {
deselectAllBandMember();
}
selecteable.setSelected(true);
if ((selectionMode == SelectionMode.MULTIPLE_INTERVAL_SELECTION) && e.isShiftDown()
&& !selectedBandMember.isEmpty()) {
final Band targetBand = getBandForYCoordinate(e.getY());
final BandMember bm = selectedBandMember.get(selectedBandMember.size() - 1)
.getBandMember();
final double min = Math.min(bm.getMin(), selecteable.getBandMember().getMin());
final double max = Math.max(bm.getMax(), selecteable.getBandMember().getMax());
final List<BandMember> members = getAllBandMembersBetween(targetBand, min, max);
selectedBandMember.add(selecteable);
Collections.sort(members, new BandMemberComparator());
for (final BandMember member : members) {
if (member instanceof BandMemberSelectable) {
final BandMemberSelectable bms = (BandMemberSelectable)member;
if (!selectedBandMember.contains(bms)) {
bms.setSelected(true);
selectedBandMember.add(bms);
}
}
}
repaint();
} else {
selectedBandMember.add(selecteable);
}
} else {
// deselect band member
if (!selectedBandMember.isEmpty()
&& !((selectionMode == SelectionMode.MULTIPLE_INTERVAL_SELECTION)
&& (e.isShiftDown() || e.isControlDown()))) {
deselectAllBandMember();
}
if (selecteable.isSelected()) {
selecteable.setSelected(false);
}
selectedBandMember.remove(selecteable);
repaint();
}
if (model instanceof SimpleBandModel) {
final SimpleBandModel sbm = ((SimpleBandModel)model);
final BandModelEvent event = new BandModelEvent();
event.setSelectionLost(!(e.isShiftDown() || e.isControlDown()));
sbm.fireBandModelSelectionChanged(event);
}
} else {
// Popup
}
}
}
}
if ((e.getComponent() instanceof BandMemberMouseListeningComponent)) {
((BandMemberMouseListeningComponent)e.getComponent()).mouseClicked(e);
}
}
/**
* Deselects all selected band member.
*/
private void deselectAllBandMember() {
for (final BandMemberSelectable tmp : selectedBandMember) {
tmp.setSelected(false);
}
selectedBandMember.clear();
repaint();
}
/**
* Determies the band that conains the given y coordinate.
*
* @param y DOCUMENT ME!
*
* @return the band at the position of the given y coordinate
*/
private Band getBandForYCoordinate(final int y) {
Band targetBand = null;
for (final JBandYDimension tmp : bandPosY) {
if ((y >= tmp.getyMin()) && (y <= tmp.getyMax())) {
targetBand = tmp.getBand();
break;
}
}
return targetBand;
}
/**
* Determines all band members, which intersects the given x value range.
*
* @param band the band that should check its members
* @param startX the start of the x range
* @param endX the end of the x range
*
* @return all band members, which intersects the given x value range.
*/
private List<BandMember> getAllBandMembersBetween(final Band band, final double startX, final double endX) {
final List<BandMember> bandMembers = new ArrayList<BandMember>();
for (int i = 0; i < band.getNumberOfMembers(); ++i) {
final BandMember member = band.getMember(i);
if (((startX < member.getMin()) && (member.getMin() < endX))
|| ((startX < member.getMax()) && (member.getMax() < endX))) {
bandMembers.add(member);
}
}
return bandMembers;
}
/**
* Select the given band member.
*
* @param selecteable The band member to select
*/
public void setSelectedMember(final BandMemberSelectable selecteable) {
final List<BandMemberSelectable> l = new ArrayList<BandMemberSelectable>();
if (selecteable != null) {
l.add(selecteable);
}
setSelectedMember(l);
}
/**
* Select the given band member. Even if the selection mode is SINGLE_SELECTION, it is possible to select more than
* one band member with this method.
*
* @param selecteable The band member to select
*/
public void setSelectedMember(final List<BandMemberSelectable> selecteable) {
List<BandMemberSelectable> newSelection = selecteable;
if (selecteable == null) {
newSelection = new ArrayList<BandMemberSelectable>();
}
for (final BandMemberSelectable tmp : new ArrayList<BandMemberSelectable>(selectedBandMember)) {
if (!newSelection.contains(tmp)) {
tmp.setSelected(false);
selectedBandMember.remove(tmp);
}
}
for (final BandMemberSelectable tmp : newSelection) {
if (tmp.isSelectable() && !tmp.isSelected() && !selectedBandMember.contains(tmp)) {
tmp.setSelected(true);
selectedBandMember.add(tmp);
}
}
repaint();
if (model instanceof SimpleBandModel) {
final SimpleBandModel sbm = ((SimpleBandModel)model);
final BandModelEvent e = new BandModelEvent();
e.setSelectionLost(true);
sbm.fireBandModelSelectionChanged(e);
}
}
/**
* DOCUMENT ME!
*/
public void dispose() {
if (model != null) {
for (int i = 0; i < model.getNumberOfBands(); ++i) {
final Band band = model.getBand(i);
if (band instanceof DisposableBand) {
((DisposableBand)band).dispose();
}
for (int mi = 0; mi < band.getNumberOfMembers(); ++mi) {
band.getMember(mi).getBandMemberComponent().removeMouseListener(this);
band.getMember(mi).getBandMemberComponent().removeMouseMotionListener(this);
}
}
}
}
@Override
public void setSize(final int width, final int height) {
super.setSize(width, height);
scrollPane.setSize(width, height);
bandsPanel.setSize(width, height);
}
@Override
public void bandModelSelectionChanged(final BandModelEvent e) {
}
@Override
public void mouseEntered(final MouseEvent e) {
if (e.getComponent() instanceof BandMemberMouseListeningComponent) {
((BandMemberMouseListeningComponent)e.getComponent()).mouseEntered(e);
}
}
@Override
public void mouseExited(final MouseEvent e) {
if (e.getComponent() instanceof BandMemberMouseListeningComponent) {
((BandMemberMouseListeningComponent)e.getComponent()).mouseExited(e);
}
}
@Override
public void mousePressed(final MouseEvent e) {
if (!readOnly && (e.getComponent() instanceof BandMemberMouseListeningComponent)) {
lastPressedComponent = e.getComponent();
((BandMemberMouseListeningComponent)e.getComponent()).mousePressed(e);
}
}
@Override
public void mouseReleased(final MouseEvent e) {
dragged = false;
if (!readOnly && (e.getComponent() instanceof BandMemberMouseListeningComponent)) {
((BandMemberMouseListeningComponent)e.getComponent()).mouseReleased(e);
}
}
@Override
public void mouseDragged(final MouseEvent e) {
if (JBandCursorManager.getInstance().isLocked()) {
JBandCursorManager.getInstance().setCursor(this);
}
dragged = true;
if (!readOnly && (e.getComponent() instanceof BandMemberMouseListeningComponent)) {
((BandMemberMouseListeningComponent)e.getComponent()).mouseDragged(e);
}
if (!readOnly && (e.getComponent() instanceof StationaryBandMemberMouseListeningComponent)) {
int x = 0;
if (e.getSource() == bandsPanel) {
x = e.getX();
} else {
x = (int)((Component)e.getSource()).getBounds().getX() + e.getX();
}
double station = getSationForXValue(x);
if (station < getMinValue()) {
station = getMinValue();
} else if (station > getMaxValue()) {
station = getMaxValue();
}
station = considerSnapping(station, e.getComponent());
((StationaryBandMemberMouseListeningComponent)e.getComponent()).mouseDragged(e, station);
}
}
/**
* DOCUMENT ME!
*
* @param station DOCUMENT ME!
* @param c DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private double considerSnapping(final double station, final Component c) {
int dist = (int)((maxValue - minValue) / (100 * ((zoomFactor == 0) ? 1 : zoomFactor)));
if (dist < 1) {
dist = 1;
}
for (final SnappingPoint tmp : snappingPoints) {
if ((Math.abs(tmp.value - station) < (dist)) && (tmp.c != c)) {
return tmp.value;
}
}
return station;
}
@Override
public void mouseMoved(final MouseEvent e) {
if (e.isAltDown()) {
final Component source = e.getComponent();
int x = 0;
if (source == bandsPanel) {
x = e.getX();
} else {
x = (int)source.getBounds().getX()
+ e.getX();
}
if (!bandsPanel.isMeasurementEnabled()) {
bandsPanel.setMeasurementEnabled(true);
}
bandsPanel.setMeasurementx(x);
// System.out.println("x"+first.getBounds());
} else {
if (bandsPanel.isMeasurementEnabled()) {
bandsPanel.setMeasurementEnabled(false);
}
}
if (JBandCursorManager.getInstance().isLocked()) {
JBandCursorManager.getInstance().setCursor(this);
} else {
JBandCursorManager.getInstance().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JBandCursorManager.getInstance().setCursor(this);
}
if ((e.getComponent() instanceof BandMemberMouseListeningComponent)) {
((BandMemberMouseListeningComponent)e.getComponent()).mouseMoved(e);
}
}
@Override
public void actionPerformed(final ActionEvent e) {
// reagieren auf ActionEvents von BandMembern
}
@Override
public void bandModelChanged(final BandModelEvent e) {
if (!refreshAvoided) {
init();
if ((e != null) && e.isSelectionLost()) {
selectedBandMember.clear();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
bandsPanel.repaint();
}
});
}
}
@Override
public void bandModelValuesChanged(final BandModelEvent e) {
if (!refreshAvoided) {
if ((e != null) && e.isSelectionLost()) {
selectedBandMember.clear();
}
layoutBandMemberComponents();
repaint();
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public BandModel getModel() {
return model;
}
/**
* DOCUMENT ME!
*
* @param args DOCUMENT ME!
*/
public static void main(final String[] args) {
Log4JQuickConfig.configure4LumbermillOnLocalhost();
final JFrame jf = new JFrame("Test");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.getContentPane().setLayout(new BorderLayout());
final JBand jbdTest = new JBand();
final MinimumHeightBand sb0 = new MinimumHeightBand();
sb0.addMember(new SimpleTextSection("OTOL-800", 0, 300, true, false));
sb0.addMember(new SimpleTextSection("OTOL-8700", 300, 500, false, false));
sb0.addMember(new SimpleTextSection("OTOL-900", 500, 1000, false, true));
final DefaultBand sb1 = new DefaultBand("Selektierbar");
sb1.addMember(new SelectableSectionPanel(250, 1000));
final SimpleBand sb2 = new SimpleBand();
sb2.addMember(new SimpleSection(0, 10));
sb2.addMember(new SimpleSection(10, 20));
sb2.addMember(new SimpleSection(20, 80));
sb2.addMember(new SimpleSection(80, 100));
final SimpleBand sb3 = new SimpleBand();
sb3.addMember(new SimpleSection(0, 50));
sb3.addMember(new SimpleSection(50, 300));
sb3.addMember(new SimpleSection(300, 1000));
final SimpleBand sb4 = new SimpleBand("Punkte .......");
sb4.addMember(new SimpleSpot(100));
sb4.addMember(new SimpleSpot(200));
sb4.addMember(new SimpleSpot(300));
sb4.addMember(new SimpleSpot(400));
sb4.addMember(new SimpleSpot(500));
final SimpleBand sb4a = new SimpleBand("auch");
sb4a.addMember(new SimpleSection(100, 100));
sb4a.addMember(new SimpleSection(110, 110));
sb4a.addMember(new SimpleSection(300, 300));
sb4a.addMember(new SimpleSection(400, 400));
sb4a.addMember(new SimpleSection(500, 500));
final SimpleBandModel sbm = new SimpleBandModel();
sbm.addBand(sb0);
sbm.addBand(sb1);
// sbm.addBand(new EmptyWeightedBand(2f));
sbm.addBand(new EmptyAbsoluteHeightedBand(1));
sbm.addBand(sb2);
sbm.addBand(new EmptyAbsoluteHeightedBand(1));
final SimpleModifiableBand sb6 = new SimpleModifiableBand("Band");
sb6.addMember(new SimpleModifiableBandMember(sb6, false, 0, 100));
sb6.addMember(new SimpleModifiableBandMember(sb6, false, 200, 500));
sb6.addMember(new SimpleModifiableBandMember(sb6, false, 600, 1000));
sbm.addBand(sb3);
sbm.addBand(sb4);
sbm.addBand(sb4a);
sbm.addBand(sb6);
final SimpleBand sb5 = new SimpleBand();
sb5.addMember(new SimpleSection(0, 1100));
sb5.addMember(new SimpleSection(50, 500));
sb5.addMember(new SimpleSection(400, 600));
sbm.addBand(sb5);
jbdTest.setModel(sbm);
// jbdTest.setZoomFactor(2);
// jf.getContentPane().setBackground(Color.red);
jbdTest.setBorder(new EmptyBorder(10, 10, 10, 10));
jf.getContentPane().add(jbdTest, BorderLayout.CENTER);
final JSlider jsl = new JSlider(0, 100);
jsl.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(final ChangeEvent ce) {
final double zfAdd = jsl.getValue() / 10.0;
jbdTest.setZoomFactor(1 + zfAdd);
}
});
final JCheckBox checker = new JCheckBox("test");
checker.setSelected(true);
checker.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
sb1.setEnabled(!sb1.isEnabled());
((SimpleBandModel)(jbdTest.getModel())).fireBandModelValuesChanged();
}
});
final JButton cmd2 = new JButton("2.0");
cmd2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
jbdTest.setZoomFactor(2d);
}
});
// jf.getContentPane().add(checker, BorderLayout.NORTH);
jf.getContentPane().add(cmd2, BorderLayout.NORTH);
jsl.setValue(0);
jf.getContentPane().add(jsl, BorderLayout.SOUTH);
jf.setSize(300, 400);
jf.setVisible(true);
final java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
jf.setBounds((screenSize.width - 800) / 2, (screenSize.height - 222) / 2, 1000, 222);
jbdTest.setHideEmptyPrePostfix(true);
}
/**
* DOCUMENT ME!
*
* @return the refreshAvoided
*/
public boolean isRefreshAvoided() {
return refreshAvoided;
}
/**
* DOCUMENT ME!
*
* @param refreshAvoided the refreshAvoided to set
*/
public void setRefreshAvoided(final boolean refreshAvoided) {
this.refreshAvoided = refreshAvoided;
}
/**
* DOCUMENT ME!
*
* @return the minValue
*/
public double getMinValue() {
return minValue;
}
/**
* DOCUMENT ME!
*
* @param minValue the minValue to set
*/
public void setMinValue(final double minValue) {
this.minValue = minValue;
setAdditionalZoomFactor();
}
/**
* DOCUMENT ME!
*
* @return the maxValue
*/
public double getMaxValue() {
return maxValue;
}
/**
* DOCUMENT ME!
*
* @param maxValue the maxValue to set
*/
public void setMaxValue(final double maxValue) {
this.maxValue = maxValue;
setAdditionalZoomFactor();
}
/**
* DOCUMENT ME!
*/
private void setAdditionalZoomFactor() {
additionalZoomFactor = (maxValue - minValue) / 1000;
if (additionalZoomFactor < 1) {
additionalZoomFactor = 1;
}
}
/**
* DOCUMENT ME!
*
* @param x DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private double getSationForXValue(final int x) {
return ((double)Math.round(((realWidth * (x) / (bandsPanel.getWidth())) + minValue)
* 10.0)) / 10.0;
}
/**
* DOCUMENT ME!
*
* @param bandMember DOCUMENT ME!
*/
public void scrollToBandMember(final BandMember bandMember) {
final double min = bandMember.getMin();
final double max = bandMember.getMax();
final double len = max - min;
final double mid = min + (len / 2);
final double fac = mid / (maxValue - minValue);
// it will be assumed that scrollPane.getHorizontalScrollBar().getMinimum() == 0
final double maxScrollBarValue = scrollPane.getHorizontalScrollBar().getMaximum()
- scrollPane.getHorizontalScrollBar().getVisibleAmount();
final double midOfMember = fac * scrollPane.getHorizontalScrollBar().getMaximum();
double halfVisibleAmountBeforeMid = midOfMember - (scrollPane.getHorizontalScrollBar().getVisibleAmount() / 2);
if (halfVisibleAmountBeforeMid < scrollPane.getHorizontalScrollBar().getMinimum()) {
halfVisibleAmountBeforeMid = scrollPane.getHorizontalScrollBar().getMinimum();
} else if (halfVisibleAmountBeforeMid > maxScrollBarValue) {
halfVisibleAmountBeforeMid = maxScrollBarValue;
}
scrollPane.getHorizontalScrollBar().setValue((int)(halfVisibleAmountBeforeMid));
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private static class SelectableSectionPanel extends JPanel implements Section, BandMember, BandMemberSelectable {
//~ Instance fields ----------------------------------------------------
private boolean selected;
private double from = 0;
private double to = 0;
//~ Constructors -------------------------------------------------------
/**
* Creates new form SimpleSectionPanel.
*
* @param from DOCUMENT ME!
* @param to DOCUMENT ME!
*/
public SelectableSectionPanel(final double from, final double to) {
this(Color.getHSBColor((float)Math.random(), 0.85f, 1.0f), from, to);
}
/**
* Creates a new SimpleSectionPanel object.
*
* @param c DOCUMENT ME!
* @param from DOCUMENT ME!
* @param to DOCUMENT ME!
*/
public SelectableSectionPanel(final Color c, final double from, final double to) {
initComponents();
this.from = from;
this.to = to;
setBackground(c);
}
//~ Methods ------------------------------------------------------------
/**
* This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code.
* The content of this method is always regenerated by the Form Editor.
*/
private void initComponents() {
setBackground(new java.awt.Color(255, 51, 0));
setOpaque(true);
setPreferredSize(new java.awt.Dimension(1, 1));
final org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(0, 1, Short.MAX_VALUE));
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(0, 1, Short.MAX_VALUE));
}
@Override
public boolean isSelected() {
return selected;
}
@Override
public void setSelected(final boolean selection) {
this.selected = selection;
if (selection) {
setBackground(getBackground().darker());
} else {
setBackground(getBackground().brighter());
}
}
@Override
public boolean isSelectable() {
return true;
}
@Override
public BandMember getBandMember() {
return this;
}
/**
* DOCUMENT ME!
*
* @param from DOCUMENT ME!
*/
public void setFrom(final double from) {
this.from = from;
}
/**
* DOCUMENT ME!
*
* @param to DOCUMENT ME!
*/
public void setTo(final double to) {
this.to = to;
}
@Override
public double getMax() {
return (from < to) ? to : from;
}
@Override
public double getMin() {
return (from < to) ? from : to;
}
@Override
public JComponent getBandMemberComponent() {
return this;
}
@Override
public double getFrom() {
return from;
}
@Override
public double getTo() {
return to;
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
class SnappingPoint implements Comparable<SnappingPoint> {
//~ Instance fields ----------------------------------------------------
private Double value;
private Component c;
//~ Constructors -------------------------------------------------------
/**
* Creates a new SnappingPoint object.
*
* @param value DOCUMENT ME!
* @param c DOCUMENT ME!
*/
public SnappingPoint(final double value, final Component c) {
this.value = value;
this.c = c;
}
//~ Methods ------------------------------------------------------------
@Override
public int compareTo(final SnappingPoint other) {
final double o = other.value;
if (Math.abs(value - o) < ((maxValue - minValue) / 100)) {
return 0;
} else {
return value.compareTo(o);
}
}
/**
* DOCUMENT ME!
*
* @return the c
*/
public Component getC() {
return c;
}
/**
* DOCUMENT ME!
*
* @param c the c to set
*/
public void setC(final Component c) {
this.c = c;
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
class JBandYDimension {
//~ Instance fields ----------------------------------------------------
private Band band;
private int yMin;
private int yMax;
//~ Constructors -------------------------------------------------------
/**
* Creates a new JBandYDimension object.
*
* @param band DOCUMENT ME!
* @param yMin DOCUMENT ME!
* @param yMax DOCUMENT ME!
*/
public JBandYDimension(final Band band, final int yMin, final int yMax) {
this.band = band;
this.yMin = yMin;
this.yMax = yMax;
}
//~ Methods ------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return the band
*/
public Band getBand() {
return band;
}
/**
* DOCUMENT ME!
*
* @param band the band to set
*/
public void setBand(final Band band) {
this.band = band;
}
/**
* DOCUMENT ME!
*
* @return the yMin
*/
public int getyMin() {
return yMin;
}
/**
* DOCUMENT ME!
*
* @param yMin the yMin to set
*/
public void setyMin(final int yMin) {
this.yMin = yMin;
}
/**
* DOCUMENT ME!
*
* @return the yMax
*/
public int getyMax() {
return yMax;
}
/**
* DOCUMENT ME!
*
* @param yMax the yMax to set
*/
public void setyMax(final int yMax) {
this.yMax = yMax;
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
class JLegendPanel extends JPanel {
//~ Constructors -------------------------------------------------------
/**
* Creates a new JBandsPanel object.
*/
public JLegendPanel() {
super(null);
setOpaque(false);
setForeground(new Color(50, 50, 50, 150));
}
//~ Methods ------------------------------------------------------------
@Override
public Dimension getPreferredSize() {
final Dimension d = super.getPreferredSize();
double maxWidth = 100;
for (int i = 0; i < getComponentCount(); ++i) {
final int tmp = (int)getComponent(i).getPreferredSize().getWidth();
if (tmp > maxWidth) {
maxWidth = tmp;
}
}
maxWidth += 2;
return new Dimension((int)maxWidth, d.height);
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
class JBandsPanel extends JPanel {
//~ Instance fields ----------------------------------------------------
private boolean measurementEnabled = false;
private int measurementx = 0;
private Color MIDDLE = new Color(50, 50, 50, 150);
private Color SIDE = new Color(250, 250, 250, 150);
private Color SIDER = new Color(220, 220, 220, 50);
//~ Constructors -------------------------------------------------------
/**
* Creates a new JBandsPanel object.
*/
public JBandsPanel() {
super(null);
setForeground(new Color(50, 50, 50, 150));
}
//~ Methods ------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public boolean isMeasurementEnabled() {
return measurementEnabled;
}
/**
* DOCUMENT ME!
*
* @param measurementEnabled DOCUMENT ME!
*/
public void setMeasurementEnabled(final boolean measurementEnabled) {
this.measurementEnabled = measurementEnabled;
repaint();
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public int getMeasurementx() {
return measurementx;
}
/**
* DOCUMENT ME!
*
* @param measurementx DOCUMENT ME!
*/
public void setMeasurementx(final int measurementx) {
if (measurementx < 0) {
this.measurementx = 0;
} else {
this.measurementx = measurementx;
}
if (measurementEnabled) {
repaint();
}
}
@Override
public Dimension getPreferredSize() {
final Dimension d = super.getPreferredSize();
// return new Dimension((int)(scrollPane.getWidth() * 0.9 * zoomFactor)
// - (int)legendPanel.getPreferredSize().getWidth(),
// d.height);
return new Dimension((int)(scrollPane.getWidth() * 0.9 * zoomFactor), d.height);
}
@Override
public void setSize(final int width, final int height) {
super.setSize(width, height);
layoutBandMemberComponents();
}
@Override
public void setSize(final Dimension d) {
setSize(d.width, d.height);
}
// @Override
// protected void paintComponent(Graphics g) {
//
// super.paintComponent(g);
//
//
// }
@Override
protected void paintChildren(final Graphics g) {
super.paintChildren(g);
if (measurementEnabled) {
final Graphics2D g2d = (Graphics2D)g;
final double station = getSationForXValue(measurementx);
g.setColor(SIDER);
g.drawLine(measurementx - 2, 0, measurementx - 2, getHeight());
g.drawLine(measurementx + 2, 0, measurementx + 2, getHeight());
g.setColor(SIDE);
g.drawLine(measurementx - 1, 0, measurementx - 1, getHeight());
g.drawLine(measurementx + 1, 0, measurementx + 1, getHeight());
g.setColor(MIDDLE);
g.drawLine(measurementx, 0, measurementx, getHeight());
final String s = String.valueOf(station);
final int sWidth = SwingUtilities.computeStringWidth(g.getFontMetrics(), s);
final int sPos = measurementx
+ 5;
if ((sPos + sWidth) <= (getWidth() - 10)) {
g.drawString(s, measurementx + 5, getHeight() - 3);
} else {
g.drawString(s, measurementx - sWidth - 5, getHeight() - 3);
}
}
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class BandMemberComparator implements Comparator<BandMember> {
//~ Methods ------------------------------------------------------------
@Override
public int compare(final BandMember o1, final BandMember o2) {
return (int)Math.signum(o1.getMin() - o2.getMin());
}
}
}