Tuesday, September 2, 2008

Easy drag and drop in JList using MouseMotionListener without using TransferHandlers

Easy way to drag and drop in JList is to use MouseMotionListeners rather than using TransferHandlers.

Following is a demo program displays list box in which the order of the items can be changed by dnd.


public class DragDropDemo extends JPanel {

int index = -1;
String value = "";
JList list;
JScrollPane listScroll;
MouseDragDropListener mouseDragDropListener;
DefaultListModel listModel = new DefaultListModel();

public DragDropDemo() {
listModel.addElement( "0 (list 1)" );
listModel.addElement( "1 (list 1)" );
listModel.addElement( "2 (list 1)" );
listModel.addElement( "3 (list 1)" );
listModel.addElement( "4 (list 1)" );
listModel.addElement( "5 (list 1)" );
listModel.addElement( "6 (list 1)" );
list = new JList( listModel );
list.setSelectionMode(
ListSelectionModel.SINGLE_INTERVAL_SELECTION );
mouseDragDropListener = new MouseDragDropListener();
list.addMouseMotionListener( mouseDragDropListener );
list.addMouseListener( mouseDragDropListener );
listScroll = new JScrollPane( list );
setLayout( new BorderLayout() );
add( listScroll, BorderLayout.CENTER );
setPreferredSize( new Dimension(200,200) );
}

/**
* Create the GUI and show it. For thread safety, this method
* should be invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated( true );
JFrame frame = new JFrame( "DragDropDemo" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
DragDropDemo demo = new DragDropDemo();
frame.setContentPane( demo );
frame.pack();
frame.setVisible( true );
}

public static void main( String[] args ) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater( new Runnable() {
public void run() {
createAndShowGUI();
}
} );
}


/**
* Listener class to implement Drag and Drop functionality
*
*/
private class MouseDragDropListener extends MouseInputAdapter
{

/**
* Invoked when a mouse button is pressed on a component and then
* dragged
*/
public void mouseDragged(MouseEvent dragEvent)
{
if ( dragEvent.getSource() instanceof JList )
{
if ( dragEvent.getY() >= 0 &&
dragEvent.getY() <= list.getHeight()
&& dragEvent.getX() >= 0 &&
dragEvent.getX() <= list.getWidth() )
{
((JComponent) dragEvent.getSource()).
setCursor( new Cursor( Cursor.HAND_CURSOR ) );
drawField( value, dragEvent.getX(),
dragEvent.getY(), 150, 20 );
} else
{
((JComponent) dragEvent.getSource()).
setCursor( Cursor.getDefaultCursor() );
}
listScroll.repaint();
}
}

/**
* Method to draw a drag tooltip box at the given point
*/
private void drawField( String name, int xX, int yY, int width, int height )
{
final int x = xX;
final int y = yY;
final int w = width;
final int h = height;
final String fname = name;
Thread t = new Thread() {
public void run() {
Graphics g = list.getGraphics();
g.drawRect( x, y, w, h );
g.drawString( fname, x + 10, y + 15 );
}
};
t.start();
}

/**
* Invoked when a mouse button is pressed on a component
*
*/
public void mousePressed( MouseEvent pressEvent )
{
if ( pressEvent.getSource() instanceof JList )
{
JList list = (JList) pressEvent.getComponent();
index = list.getSelectedIndex();
if ( index >= 0 )
{
index = list.locationToIndex(
pressEvent.getPoint() );
}
value = list.getSelectedValue().toString();
list.setSelectedIndex( index );
}
}

/**
* Invoked when a mouse button is released on a component
* Passes the curIndex to moveToIndex method to move the
* dragginIndex.
*
*/
public void mouseReleased( MouseEvent releaseEvent )
{
if ( releaseEvent.getSource() instanceof JList )
{
if ( releaseEvent.getModifiers() > 16 )
{
return;
}
((JComponent) releaseEvent.getSource()).
setCursor( new Cursor( Cursor.DEFAULT_CURSOR ) );
int curIndex = list.locationToIndex(
releaseEvent.getPoint() );
if ( curIndex == -1 )
{
if ( list.getModel().getSize()>0 )
{
if ( releaseEvent.getY() >=
list.getHeight() )
{
curIndex =
list.getModel().getSize() - 1;
} else if ( releaseEvent.getY()<=0)
{
curIndex = 0;
} else
{
curIndex = index;
}
} else
{
return;
}
}
if ( curIndex == index )
{
return;
}
moveToIndex( curIndex );
list.repaint();
listScroll.repaint();
}
}

/**
* Move the dragginField to the curIndex position.
* Where curIndex position is set to the index where mouse released.
*
* @param curIndex
*/
public void moveToIndex( int curIndex )
{
int listSize = list.getModel().getSize();
int moveToPos = curIndex + 1;
if ( moveToPos != 0 && value != null )
{
int newPos = moveToPos;
if ( moveToPos > 0 )
{
if ( newPos > listSize )
{
newPos = listSize;
}
newPos--;
} else if ( newPos < 0 )
{
newPos = 0;
}

listModel.remove( index );
listModel.add( newPos, value );
list.setSelectedIndex( newPos );
}
index = 0;
value = null;
}
}
}


Point to note:
When a MouseMotionListener is set for a Jlist component to perform drag and drop manually, then

list.setDragEnabled( true ); - to enable dragging in Jlist

should not be given. Since enabling this will consume the source mouse event in Jlist and that event will be sent to mousedrag event and hence will does nothing.

Monday, August 4, 2008

Search column name in SQL DB

This query returns the complete details of a searched column in the entire database

SELECT table_name = sysobjects.name,
column_name = syscolumns.name,
datatype = systypes.name,
length = syscolumns.length
FROM sysobjects
JOIN syscolumns ON sysobjects.id = syscolumns.id
JOIN systypes ON syscolumns.xtype = systypes.xtype
WHERE sysobjects.xtype='U' and syscolumns.name like '%ColumnName%'
ORDER BY sysobjects.name, syscolumns.colid

Might be simple.. But useful at times..!!

Enabling USB through registry hack

To disable usb storage devices:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\
DWORD "start" value=4

To enable usb storage devices:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\
DWORD "start" value=3

To Disable Write protect:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies,"Writeprotect"=0

Override the focus traversal keys of a JTable

In a JTable, there are some predefined focus traversal keys. For example, CTRL+TAB to move out of JTable.

If that needs to be overrided with some other key combination the FocusTraversalKeySet should be replaced with a new set containing the new key combinations.

Following example shows the overriding of ForwardTraversalKey set with new KeySet containing CTRL+Z as the forward traversal key and also BackwardTraversalKey set with an EmptySet to disable all the backward traversals.


JTable table = new JTable(2,2);

TreeSet forwardSet = new TreeSet();

forwardSet.add(AWTKeyStroke.getAWTKeyStroke( KeyEvent.VK_Z,
InputEvent.CTRL_DOWN_MASK
| InputEvent.CTRL_MASK, false ) );

Set unmodifiableForwardSet =
Collections.unmodifiableSortedSet( forwardSet );

// To override the existing forward_traversal_key set
// with new unmodifiable set containing new
// key combination(CTRL+Z)
table.setFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
unmodifiableForwardSet );

// To disable all the backward traversal keys,
// an empty set can be used
table.setFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
Collections.EMPTY_SET );

Add rows on tabbing to a cell beyond the last cell

JTable by defaults selects the next cell when TAB is pressed. When the current selection is last cell, pressing tab selects the first cell. But here we want a new row to be inserted and selected the next newly created cell.

JTable table = new JTable(2, 2){
private final KeyStroke tabKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
AWTEvent currentEvent = EventQueue.getCurrentEvent();
if(currentEvent instanceof KeyEvent){
KeyEvent ke = (KeyEvent)currentEvent;
if(ke.getSource()!=this)
return;
// focus change with keyboard
if(rowIndex==0 && columnIndex==0
&& KeyStroke.getKeyStrokeForEvent(ke).equals(tabKeyStroke)){
((DefaultTableModel)getModel()).addRow(new Object[getColumnCount()]);
rowIndex = getRowCount()-1;
}
}
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
};

Tweaking JTable Editing

There are two client properties supported by JTable which are related to editing.

JTable.autoStartsEdit:
The value is of type Java.lang.Boolean. This property tells whether JTable should start edit when a key is types. If the value of this property is null, it defaults to Boolean.TRUE. So this feature is enabled by default in JTable.

terminateEditOnFocusLost:
The value is of type Java.lang.Boolean. This property tells whether what to do when focus goes outside of JTable. It first tries to commit the changes in editor, if can't be committed then the changes are cancelled. If the value of this property is null, it default to Boolean.FALSE. So this feature is disabled by default in JTable.

You can enable this feature as follows:

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);


I suggest to make this feature to be enabled for JTable.

Thursday, July 31, 2008

Code to set a Jtable column to fit its contents

Code to set a column to fit its contents,


TableColumn column = table.getColumnModel().getColumn(columnIndex);
int w = column.getWidth();
int n = table.getRowCount();
for (int i = 0; i < n; i ++)
{
TableCellRenderer r = table.getCellRenderer(i, this.columnIndex);
Component c = r.getTableCellRendererComponent(
table,
table.getValueAt(i, columnIndex),
false,
false,
i,
columnIndex);
w = Math.max(w, c.getPreferredSize().width);
}
column.setPreferredWidth(w);