package org.korsakow.ide.ui.laf;
import java.awt.Point;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.TooManyListenersException;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTableUI;
import org.korsakow.ide.util.Platform;
import org.korsakow.ide.util.UIUtil;
public class KorsakowTableUI extends BasicTableUI implements PropertyChangeListener
{
protected static DropTargetListener defaultDropTargetListener = null;
public static ComponentUI createUI(JComponent c) {
return new KorsakowTableUI();
}
public void installUI(JComponent c)
{
super.installUI(c);
c.addPropertyChangeListener("transferHandler", this);
c.putClientProperty("JTable.autoStartsEdit", false);
}
public void propertyChange(PropertyChangeEvent event) {
DropTarget dropTarget = table.getDropTarget();
// this compensates for BasicTableUI only doing it for UIResource instances
if (dropTarget instanceof UIResource == false) {
if (defaultDropTargetListener == null) {
defaultDropTargetListener =
new MyTableDropTargetListener();
}
try {
dropTarget.addDropTargetListener(
defaultDropTargetListener);
} catch (TooManyListenersException tmle) {
// should not happen... swing drop target is multicast
}
}
}
protected MouseInputListener createMouseInputListener() {
return new MouseHandler(super.createMouseInputListener());
}
public static class MouseHandler implements MouseInputListener
{
private boolean isFix = false;
private MouseListener delegate;
private MouseEvent fixEventObject(MouseEvent event)
{
int modifiers = event.getModifiers();
// BasicUI really sucks and doesn't even try to be platform friendly.
if (Platform.isMacOS()) {
if ((modifiers & MouseEvent.META_MASK) == MouseEvent.META_MASK) {
modifiers = (modifiers ^ MouseEvent.META_MASK) | MouseEvent.CTRL_MASK;
event = new MouseEvent(event.getComponent(), event.getID(), event.getWhen(), modifiers, event.getX(), event.getY(), event.getClickCount(), UIUtil.isPopupTrigger(event));
}
}
return event;
}
public MouseHandler(MouseInputListener delegate)
{
this.delegate = delegate;
}
public MouseHandler(MouseListener delegate)
{
this.delegate = delegate;
}
public void mouseClicked(MouseEvent e) {
delegate.mouseClicked(fixEventObject(e));
}
public void mouseEntered(MouseEvent e) {
delegate.mouseEntered(e);
}
public void mouseExited(MouseEvent e) {
delegate.mouseExited(e);
}
public void mousePressed(MouseEvent e) {
if (UIUtil.isPopupTrigger(e)) // osx ctrl-click fix
isFix = true;
else
delegate.mousePressed(fixEventObject(e));
}
public void mouseReleased(MouseEvent e) {
if (!isFix) // osx ctrl-click fix
delegate.mouseReleased(fixEventObject(e));
isFix = false;
}
public void mouseDragged(MouseEvent e) {
if (delegate instanceof MouseMotionListener)
((MouseMotionListener)delegate).mouseDragged(e);
}
public void mouseMoved(MouseEvent e) {
if (delegate instanceof MouseMotionListener)
((MouseMotionListener)delegate).mouseMoved(e);
}
}
/**
* A DropTargetListener to extend the default Swing handling of drop operations
* by moving the tree selection to the nearest location to the mouse pointer.
* Also adds autoscroll capability.
*/
protected static class MyTableDropTargetListener extends MyBasicDropTargetListener {
/**
* called to save the state of a component in case it needs to
* be restored because a drop is not performed.
*/
protected void saveComponentState(JComponent comp) {
JTable table = (JTable) comp;
rows = table.getSelectedRows();
cols = table.getSelectedColumns();
}
/**
* called to restore the state of a component
* because a drop was not performed.
*/
protected void restoreComponentState(JComponent comp) {
JTable table = (JTable) comp;
table.clearSelection();
for (int i = 0; i < rows.length; i++) {
table.addRowSelectionInterval(rows[i], rows[i]);
}
for (int i = 0; i < cols.length; i++) {
table.addColumnSelectionInterval(cols[i], cols[i]);
}
}
/**
* called to set the insertion location to match the current
* mouse pointer coordinates.
*/
protected void updateInsertionLocation(JComponent comp, Point p) {
JTable table = (JTable) comp;
int row = table.rowAtPoint(p);
int col = table.columnAtPoint(p);
if (row != -1) {
table.setRowSelectionInterval(row, row);
}
if (col != -1) {
table.setColumnSelectionInterval(col, col);
}
}
private int[] rows;
private int[] cols;
}
}