//{HEADER
/**
* This class is part of jnex 'Nexirius Application Framework for Java'
*
* Copyright (C) Nexirius GmbH, CH-4450 Sissach, Switzerland (www.nexirius.ch)
*
* <p>This library is free software; you can redistribute it and/or<br>
* modify it under the terms of the GNU Lesser General Public<br>
* License as published by the Free Software Foundation; either<br>
* version 2.1 of the License, or (at your option) any later version.</p>
*
* <p>This library is distributed in the hope that it will be useful,<br>
* but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU<br>
* Lesser General Public License for more details.</p>
*
* <p>You should have received a copy of the GNU Lesser General Public<br>
* License along with this library; if not, write to the Free Software<br>
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</p>
* </blockquote>
*
* <p>
* Nexirius GmbH, hereby disclaims all copyright interest in<br>
* the library jnex' 'Nexirius Application Framework for Java' written<br>
* by Marcel Baumann.</p>
*/
//}HEADER
package com.nexirius.framework.dataviewer;
import com.nexirius.framework.datamodel.DataModel;
import sun.awt.dnd.SunDragSourceContextPeer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.ref.WeakReference;
public class DataModelTreeHeaderPanel extends JPanel {
WeakReference treeComponent;
IconLabel iconLabel;
JLabel textLabel;
public DataModelTreeHeaderPanel(DataModelTreeComponent treeComponent) {
super(new BorderLayout());
this.treeComponent = new WeakReference(treeComponent);
initAll();
// TODO: Do I really need more than one assignement of the tranfer handler instance?
TransferHandler transferHandler = getTreeComponent().getTreeViewer().getTransferHandler();
setTransferHandler(transferHandler);
}
public void initAll() {
initLabels();
layoutAll();
}
public void layoutAll() {
add(iconLabel, BorderLayout.WEST);
add(textLabel, BorderLayout.CENTER);
}
public void initLabels() {
TransferHandler transferHandler = getTreeComponent().getTreeViewer().getTransferHandler();
iconLabel = createIconLabel();
textLabel = createTextLabel();
textLabel.setTransferHandler(transferHandler);
BasicDragGestureRecognizer basicDragGestureRecognizer = new BasicDragGestureRecognizer();
textLabel.addMouseListener(basicDragGestureRecognizer);
textLabel.addMouseMotionListener(basicDragGestureRecognizer);
textLabel.addMouseListener(new TextMouseListener());
iconLabel.addMouseListener(new IconMouseListener());
}
public JLabel createTextLabel() {
JLabel ret = new JLabel();
ret.setBackground(Color.blue);
updateTextLabel(ret);
return ret;
}
public void updateTextLabel(JLabel ret) {
DataModel childModel = getTreeComponent().getChildModel();
int columns = childModel.getColumns();
if (childModel.getColumns() > 0) {
StringBuffer text = new StringBuffer("<html><table><tr>");
for (int i = 0; i < columns; ++i) {
text.append("<td>");
text.append(getTreeComponent().getChildModel().getLabel(i));
text.append("</td>");
}
text.append("</tr></table></html>");
ret.setText(text.toString());
} else if (childModel.getLabel() != null) {
ret.setText(childModel.getLabel());
} else {
ret.setText(childModel.getCaption());
}
if (childModel.getIconId() != null) {
Icon icon = getTreeComponent().getTreeViewer().getFactory().getClientResource().getIcon(childModel.getIconId());
ret.setIcon(icon);
}
}
public IconLabel createIconLabel() {
IconLabel ret = new IconLabel();
return ret;
}
public void setSelected(boolean on) {
textLabel.setOpaque(on);
textLabel.setForeground(on ? Color.white : Color.black);
}
public void setFolded(boolean on) {
iconLabel.setFolded(on);
}
public DataModelTreeComponent getTreeComponent() {
return (DataModelTreeComponent) treeComponent.get();
}
public void setHasChildren(boolean on) {
iconLabel.setHasChildren(on);
}
public void update() {
if (textLabel != null) {
updateTextLabel(textLabel);
}
}
class IconMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (e.getButton() > 1) {
return;
}
getTreeComponent().toggleFolded(e.isControlDown(), e.isShiftDown());
}
}
class TextMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (e.getButton() > 1) {
return;
}
getTreeComponent().toggleSelected(e.isControlDown(), e.isShiftDown());
}
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopupMenu(e);
}
}
}
private void showPopupMenu(MouseEvent e) {
Point position = e.getPoint();
JPopupMenu popup = new DefaultTreePopupMenu().createPopupMenu(getTreeComponent().getTreeViewer().getFactory(), getTreeComponent().getChildModel());
if (popup != null) {
// Display popup menu at the given mouse position
popup.show(this, position.x, position.y);
}
}
class IconLabel extends JLabel {
int w = 20;
int h = 20;
boolean hasChildren = true;
boolean folded = false;
public IconLabel() {
//setIcon(getTreeComponent().getTreeViewer().getExpandedIcon());
setPreferredSize(new Dimension(w, h));
}
public void setFolded(boolean on) {
folded = on;
if (hasChildren) {
//setIcon(on ? getTreeComponent().getTreeViewer().getFoldedIcon() : getTreeComponent().getTreeViewer().getExpandedIcon());
}
repaint();
}
public void setHasChildren(boolean on) {
hasChildren = on;
if (hasChildren) {
// setIcon(getTreeComponent().isFolded() ? getTreeComponent().getTreeViewer().getFoldedIcon() : getTreeComponent().getTreeViewer().getExpandedIcon());
} else {
// setIcon(getTreeComponent().getTreeViewer().getNoChildrenIcon());
}
repaint();
}
public void paint(Graphics g) {
super.paint(g);
int unit = h / 10;
if (!hasChildren) {
//g.fillRect(0, 0, twidth, theight);
return;
}
g.drawRect(unit, unit, 8 * unit, 8 * unit);
g.drawLine(3 * unit, 5 * unit, 7 * unit, 5 * unit);
if (folded) {
g.drawLine(5 * unit, 3 * unit, 5 * unit, 7 * unit);
}
}
}
//TODO this class comes more or less 'as is' from basic look and feel (javax.swing.plaf.basic)
class BasicDragGestureRecognizer implements MouseListener, MouseMotionListener {
private MouseEvent dndArmedEvent = null;
//TODO remove
// private int motionThreshold;
// private boolean checkedMotionThreshold = false;
private int getMotionThreshold() {
return 2;
// TODO remove
// if (checkedMotionThreshold) {
// return motionThreshold;
// } else {
// checkedMotionThreshold = true;
// try {
// motionThreshold = ((Integer) Toolkit.getDefaultToolkit().getDesktopProperty("DnD.gestureMotionThreshold")).intValue();
// } catch (Exception e) {
// motionThreshold = 5;
// }
// }
// return motionThreshold;
}
protected int mapDragOperationFromModifiers(MouseEvent e) {
int mods = e.getModifiersEx();
if ((mods & InputEvent.BUTTON1_DOWN_MASK) != InputEvent.BUTTON1_DOWN_MASK) {
return TransferHandler.NONE;
}
JComponent c = getComponent(e);
TransferHandler th = c.getTransferHandler();
return SunDragSourceContextPeer.convertModifiersToDropAction(mods, th.getSourceActions(c));
}
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
dndArmedEvent = null;
System.out.println("mouse pressed dndArmedEvent = " + dndArmedEvent);
if (isDragPossible(e) && mapDragOperationFromModifiers(e) != TransferHandler.NONE) {
dndArmedEvent = e;
e.consume();
}
}
public void mouseReleased(MouseEvent e) {
System.out.println("mouse released");
dndArmedEvent = null;
}
public void mouseEntered(MouseEvent e) {
//dndArmedEvent = null;
}
public void mouseExited(MouseEvent e) {
//if (dndArmedEvent != null && mapDragOperationFromModifiers(e) == TransferHandler.NONE) {
// dndArmedEvent = null;
//}
}
public void mouseDragged(MouseEvent e) {
System.out.println("mouse dagged dndArmedEvent = " + dndArmedEvent);
if (dndArmedEvent != null) {
e.consume();
int action = mapDragOperationFromModifiers(e);
System.out.println("action = " + action);
if (action == TransferHandler.NONE) {
return;
}
int dx = Math.abs(e.getX() - dndArmedEvent.getX());
int dy = Math.abs(e.getY() - dndArmedEvent.getY());
if ((dx > getMotionThreshold()) || (dy > getMotionThreshold())) {
// start transfer... shouldn't be a click at this point
JComponent c = getComponent(e);
TransferHandler th = c.getTransferHandler();
th.exportAsDrag(c, dndArmedEvent, action);
dndArmedEvent = null;
}
}
}
public void mouseMoved(MouseEvent e) {
}
/**
* Determines if the following are true:
* <ul>
* <li>the press event is located over a selection
* <li>the dragEnabled property is true
* <li>A TranferHandler is installed
* </ul>
* <p/>
* This is implemented to check for a TransferHandler.
* Subclasses should perform the remaining conditions.
*/
protected boolean isDragPossible(MouseEvent e) {
JComponent c = getComponent(e);
return (c == null) ? true : (c.getTransferHandler() != null);
}
protected JComponent getComponent(MouseEvent e) {
Object src = e.getSource();
if (src instanceof JComponent) {
JComponent c = (JComponent) src;
return c;
}
return null;
}
}
}