Back to Buoy resources page

BList

The aim of this tutorial is to create import/export lists. The frame should display two lists with the abitlity to exchange items between the two lists. It should also be possible to delete items from one list or the other. Such a window usually looks like the one below. The selected items are sent to the other list using the < or > buttons. The Delete buttons delete the currently selected items in the current list.

figure 1

As usual, the code is reproduced at the end of this page; it can also be downloaded here.

First, let's have a look at the widget layout. We'll use a FormContainer and a ColumnContainer. The FormContainer will define a 3x3 grid as shown below :

BLabel "List 1" BLabel "List 2"
BList list 1 (embedded in a BScrollPane) ColumnContainer:

>
<
BList list 2 (embedded in a BScrollPane)
BButton Delete BButton Delete

There is nothing much to say about this layout, except that:

Apart from illustrating the use of the BList widget, this tutorials also shows how to deal with events and widget arrays. In this example, the two lists are addressed as a BList array, as well as the export BButtons. The same method is link to any event type considered, e.g. doExchange is linked to both export buttons. In that case, it can be useful to specify the event object as a parameter to the method the event is linked to, so that the event source can be identified. There are, however, some cases where there is no need to know which widget generated the event, like for doSelect(), to which both lists are linked.

It is high time we define the (bare) functionalities of the sample app:

The selection business is addressed through linking the SelectionChangedEvent event of both BLists to the doSelect() method. The lists are then asked for selection ( getSelectedValues() ) and the buttons are disabled or enabled accordingly. This method is rough, since it doesn't take into account which BList has generated the event. Writing this tutorial, I realize that I forgot to enable/disable the export buttons : I guess that's your homework ;-).

The Delete buttons CommandEvent events are linked to doDelete(CommandEvent evt), which identifies the index of the button that generated the event and deletes the selection from the relevant list. BList.getSelectedIndices() gives the indices of the items to delete, which are deleted in reverse order. The Delete button is then disabled since the selection is now empty.

 int which = ( evt.getWidget() == deleteButtons[0] ? 0 : 1 );
 int[] selection = lists[which].getSelectedIndices();
 if ( selection != null )
 {
      for ( int i = selection.length - 1; i >= 0; --i )
     {
         lists[which].remove( selection[i] );
     }
     deleteButtons[which].setEnabled( false );
 }
 

The export buttons also generate a CommandEvent which is this time connected to the doExchange(CommandEvent evt). The source of the event is identified as before. The selection of the from list is added to the destination list. A following doDelete(evt) call could cut the selected items if the functionalities of the application asked for it.

int from = ( evt.getWidget() == importButtons[0] ? 0 : 1 );
 int to = 1 - from;
 Object[] selection = null;
 if ( lists[from].getSelectedIndex() >= 0 )
     selection = lists[from].getSelectedValues();
 if ( selection != null )
 {
     for ( int i = 0; i < selection.length; ++i )
     {
         lists[to].add( selection[i] );
     }
 }

The full source code is given below:

 import java.awt.*;
 import buoy.event.*;
 import buoy.widget.*;
 
 /**
  *  BList demo
  *
  *@author     Fran├žois Guillet
  *@created    2004/05/28
  */
 public class BListDemo
          extends BFrame
 {
     BList[] lists;
     BButton[] importButtons;
     BButton[] deleteButtons;
 
 
     /**
      *  Constructor for the BListDemo object
      */
     public BListDemo()
     {
         super( "BListDemo" );
 
         BorderContainer border = new BorderContainer();
         setContent( border );
 
         importButtons = new BButton[2];
         importButtons[0] = new BButton( ">" );
         importButtons[1] = new BButton( "<" );
 
         ColumnContainer buttonsCc = new ColumnContainer();
         buttonsCc.add( importButtons[0], new LayoutInfo( LayoutInfo.SOUTH, LayoutInfo.NONE, new Insets( 5, 5, 5, 5 ), null ) );
         buttonsCc.add( importButtons[1], new LayoutInfo( LayoutInfo.NORTH, LayoutInfo.NONE, new Insets( 5, 5, 5, 5 ), null ) );
 
         LayoutInfo layout = new LayoutInfo( LayoutInfo.CENTER, LayoutInfo.NONE, new Insets( 5, 5, 5, 5 ), null );
         for ( int i = 0; i < 2; ++i )
             importButtons[i].addEventLink( CommandEvent.class, this, "doExchange" );
 
         lists = new BList[2];
         lists[0] = new BList( new String[]{"1", "2", "3"} );
         lists[1] = new BList( new String[]{"one", "two", "three"} );
 
         BScrollPane[] scrollPanes = new BScrollPane[2];
 
         for ( int i = 0; i < 2; ++i )
         {
             scrollPanes[i] = new BScrollPane( lists[i] );
             scrollPanes[i].setForceWidth( true );
         }
 
         LayoutInfo listLayout = new LayoutInfo( LayoutInfo.CENTER, LayoutInfo.BOTH, new Insets( 5, 5, 5, 5 ), null );
         FormContainer fc = new FormContainer( 3, 3 );
         fc.add( new BLabel( "list 1" ), 0, 0, layout );
         fc.add( new BLabel( "list 2" ), 2, 0, layout );
         fc.add( scrollPanes[0], 0, 1, listLayout );
         fc.add( buttonsCc, 1, 1, layout );
         fc.add( scrollPanes[1], 2, 1, listLayout );
 
         deleteButtons = new BButton[2];
         deleteButtons[0] = new BButton( "Delete" );
         deleteButtons[1] = new BButton( "Delete" );
         for ( int i = 0; i < 2; ++i )
             deleteButtons[i].addEventLink( CommandEvent.class, this, "doDelete" );
 
         fc.add( deleteButtons[0], 0, 2, layout );
         fc.add( deleteButtons[1], 2, 2, layout );
 
         setContent( fc );
 
         addEventLink( WindowClosingEvent.class, this, "doQuit" );
         for ( int i = 0; i < 2; ++i )
         {
             lists[i].addEventLink( SelectionChangedEvent.class, this, "doSelect" );
             deleteButtons[i].setEnabled( false );
         }
 
         pack();
         setVisible( true );
 
     }
 
 
     /**
      *  Quit
      */
     private void doQuit()
     {
         System.exit( 0 );
     }
 
 
     /**
      *  Exchange items from one list to another
      *
      *@param  evt  The command event
      */
     private void doExchange( CommandEvent evt )
     {
         int from = ( evt.getWidget() == importButtons[0] ? 0 : 1 );
         int to = 1 - from;
 
         Object[] selection = null;
 
         if ( lists[from].getSelectedIndex() >= 0 )
             selection = lists[from].getSelectedValues();
 
         if ( selection != null )
         {
             for ( int i = 0; i < selection.length; ++i )
             {
                 lists[to].add( selection[i] );
             }
         }
     }
 
 
     /**
      *  Delete items
      *
      *@param  evt  The command event
      */
     private void doDelete( CommandEvent evt )
     {
         int which = ( evt.getWidget() == deleteButtons[0] ? 0 : 1 );
 
         int[] selection = lists[which].getSelectedIndices();
         if ( selection != null )
         {
             for ( int i = selection.length - 1; i >= 0; --i )
             {
                 lists[which].remove( selection[i] );
             }
             deleteButtons[which].setEnabled( false );
         }
     }
 
 
     /**
      *  What to do when an item is selected
      */
     private void doSelect()
     {
         for ( int i = 0; i < 2; ++i )
         {
             if ( lists[i].getSelectedIndex() >= 0 )
                 deleteButtons[i].setEnabled( true );
             else
                 deleteButtons[i].setEnabled( false );
         }
     }
 
 
     /**
      *  Main
      *
      *@param  args  The command line arguments
      */
     public static void main( String[] args )
     {
         new BListDemo();
     }
 }