/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.pentaho.di.ui.core.dialog; import java.util.Hashtable; import java.util.StringTokenizer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.DropTarget; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.DropTargetListener; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Dialog; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.pentaho.di.core.Const; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.ui.core.PropsUI; import org.pentaho.di.ui.core.gui.GUIResource; import org.pentaho.di.ui.core.gui.WindowProperty; import org.pentaho.di.ui.trans.step.BaseStepDialog; /** * This dialogs allows you to select a number of items from a list of strings. * * @author Matt * @since 21-10-2004 */ public class EnterListDialog extends Dialog { private static Class<?> PKG = EnterListDialog.class; // for i18n purposes, needed by Translator2!! private PropsUI props; private String[] input; private String[] retval; private Hashtable<Integer, String> selection; private Shell shell; private List wListSource, wListDest; private Label wlListSource, wlListDest; private Button wOK; private Button wCancel; private Button wAddOne, wAddAll, wRemoveAll, wRemoveOne; private boolean opened; public EnterListDialog( Shell parent, int style, String[] input ) { super( parent, style ); this.props = PropsUI.getInstance(); this.input = input; this.retval = null; selection = new Hashtable<Integer, String>(); opened = false; } public String[] open() { Shell parent = getParent(); shell = new Shell( parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN ); props.setLook( shell ); shell.setImage( GUIResource.getInstance().getImageTransGraph() ); shell.setText( BaseMessages.getString( PKG, "EnterListDialog.Title" ) ); shell.setLayout( new FormLayout() ); int margin = Const.MARGIN; // ////////////////////////////////////////////////// // Top & Bottom regions. // ////////////////////////////////////////////////// Composite top = new Composite( shell, SWT.NONE ); FormLayout topLayout = new FormLayout(); topLayout.marginHeight = margin; topLayout.marginWidth = margin; top.setLayout( topLayout ); FormData fdTop = new FormData(); fdTop.left = new FormAttachment( 0, 0 ); fdTop.top = new FormAttachment( 0, 0 ); fdTop.right = new FormAttachment( 100, 0 ); fdTop.bottom = new FormAttachment( 100, -50 ); top.setLayoutData( fdTop ); props.setLook( top ); Composite bottom = new Composite( shell, SWT.NONE ); bottom.setLayout( new FormLayout() ); FormData fdBottom = new FormData(); fdBottom.left = new FormAttachment( 0, 0 ); fdBottom.top = new FormAttachment( top, 0 ); fdBottom.right = new FormAttachment( 100, 0 ); fdBottom.bottom = new FormAttachment( 100, 0 ); bottom.setLayoutData( fdBottom ); props.setLook( bottom ); // ////////////////////////////////////////////////// // Sashform // ////////////////////////////////////////////////// SashForm sashform = new SashForm( top, SWT.HORIZONTAL ); sashform.setLayout( new FormLayout() ); FormData fdSashform = new FormData(); fdSashform.left = new FormAttachment( 0, 0 ); fdSashform.top = new FormAttachment( 0, 0 ); fdSashform.right = new FormAttachment( 100, 0 ); fdSashform.bottom = new FormAttachment( 100, 0 ); sashform.setLayoutData( fdSashform ); // //////////////////////// // / LEFT // //////////////////////// Composite leftsplit = new Composite( sashform, SWT.NONE ); leftsplit.setLayout( new FormLayout() ); FormData fdLeftsplit = new FormData(); fdLeftsplit.left = new FormAttachment( 0, 0 ); fdLeftsplit.top = new FormAttachment( 0, 0 ); fdLeftsplit.right = new FormAttachment( 100, 0 ); fdLeftsplit.bottom = new FormAttachment( 100, 0 ); leftsplit.setLayoutData( fdLeftsplit ); props.setLook( leftsplit ); // Source list to the left... wlListSource = new Label( leftsplit, SWT.NONE ); wlListSource.setText( BaseMessages.getString( PKG, "EnterListDialog.AvailableItems.Label" ) ); props.setLook( wlListSource ); FormData fdlListSource = new FormData(); fdlListSource.left = new FormAttachment( 0, 0 ); fdlListSource.top = new FormAttachment( 0, 0 ); wlListSource.setLayoutData( fdlListSource ); wListSource = new List( leftsplit, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL ); props.setLook( wListSource ); FormData fdListSource = new FormData(); fdListSource.left = new FormAttachment( 0, 0 ); fdListSource.top = new FormAttachment( wlListSource, 0 ); fdListSource.right = new FormAttachment( 100, 0 ); fdListSource.bottom = new FormAttachment( 100, 0 ); wListSource.setLayoutData( fdListSource ); // ///////////////////////// // MIDDLE // ///////////////////////// Composite compmiddle = new Composite( sashform, SWT.NONE ); compmiddle.setLayout( new FormLayout() ); FormData fdCompMiddle = new FormData(); fdCompMiddle.left = new FormAttachment( 0, 0 ); fdCompMiddle.top = new FormAttachment( 0, 0 ); fdCompMiddle.right = new FormAttachment( 100, 0 ); fdCompMiddle.bottom = new FormAttachment( 100, 0 ); compmiddle.setLayoutData( fdCompMiddle ); props.setLook( compmiddle ); Composite gButtonGroup = new Composite( compmiddle, SWT.NONE ); GridLayout gridLayout = new GridLayout( 1, false ); gButtonGroup.setLayout( gridLayout ); wAddOne = new Button( gButtonGroup, SWT.PUSH ); wAddOne.setText( " > " ); wAddOne.setToolTipText( BaseMessages.getString( PKG, "EnterListDialog.AddOne.Tooltip" ) ); wAddAll = new Button( gButtonGroup, SWT.PUSH ); wAddAll.setText( " >> " ); wAddAll.setToolTipText( BaseMessages.getString( PKG, "EnterListDialog.AddAll.Tooltip" ) ); wRemoveOne = new Button( gButtonGroup, SWT.PUSH ); wRemoveOne.setText( " < " ); wRemoveOne.setToolTipText( BaseMessages.getString( PKG, "EnterListDialog.RemoveOne.Tooltip" ) ); wRemoveAll = new Button( gButtonGroup, SWT.PUSH ); wRemoveAll.setText( " << " ); wRemoveAll.setToolTipText( BaseMessages.getString( PKG, "EnterListDialog.RemoveAll.Tooltip" ) ); GridData gdAddOne = new GridData( GridData.FILL_BOTH ); wAddOne.setLayoutData( gdAddOne ); GridData gdAddAll = new GridData( GridData.FILL_BOTH ); wAddAll.setLayoutData( gdAddAll ); GridData gdRemoveAll = new GridData( GridData.FILL_BOTH ); wRemoveAll.setLayoutData( gdRemoveAll ); GridData gdRemoveOne = new GridData( GridData.FILL_BOTH ); wRemoveOne.setLayoutData( gdRemoveOne ); FormData fdButtonGroup = new FormData(); wAddAll.pack(); // get a size fdButtonGroup.left = new FormAttachment( 50, -( wAddAll.getSize().x / 2 ) - 5 ); fdButtonGroup.top = new FormAttachment( 30, 0 ); gButtonGroup.setBackground( shell.getBackground() ); // the default looks ugly gButtonGroup.setLayoutData( fdButtonGroup ); // /////////////////////////////// // RIGHT // /////////////////////////////// Composite rightsplit = new Composite( sashform, SWT.NONE ); rightsplit.setLayout( new FormLayout() ); FormData fdRightsplit = new FormData(); fdRightsplit.left = new FormAttachment( 0, 0 ); fdRightsplit.top = new FormAttachment( 0, 0 ); fdRightsplit.right = new FormAttachment( 100, 0 ); fdRightsplit.bottom = new FormAttachment( 100, 0 ); rightsplit.setLayoutData( fdRightsplit ); props.setLook( rightsplit ); wlListDest = new Label( rightsplit, SWT.NONE ); wlListDest.setText( BaseMessages.getString( PKG, "EnterListDialog.Selection.Label" ) ); props.setLook( wlListDest ); FormData fdlListDest = new FormData(); fdlListDest.left = new FormAttachment( 0, 0 ); fdlListDest.top = new FormAttachment( 0, 0 ); wlListDest.setLayoutData( fdlListDest ); wListDest = new List( rightsplit, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL ); props.setLook( wListDest ); FormData fdListDest = new FormData(); fdListDest.left = new FormAttachment( 0, 0 ); fdListDest.top = new FormAttachment( wlListDest, 0 ); fdListDest.right = new FormAttachment( 100, 0 ); fdListDest.bottom = new FormAttachment( 100, 0 ); wListDest.setLayoutData( fdListDest ); sashform.setWeights( new int[] { 40, 16, 40 } ); // ////////////////////////////////////////////////////////////// // THE BOTTOM BUTTONS... // ////////////////////////////////////////////////////////////// wOK = new Button( bottom, SWT.PUSH ); wOK.setText( BaseMessages.getString( PKG, "System.Button.OK" ) ); wCancel = new Button( bottom, SWT.PUSH ); wCancel.setText( BaseMessages.getString( PKG, "System.Button.Cancel" ) ); FormData fdOK = new FormData(); FormData fdCancel = new FormData(); fdOK.left = new FormAttachment( 35, 0 ); fdOK.bottom = new FormAttachment( 100, 0 ); wOK.setLayoutData( fdOK ); fdCancel.left = new FormAttachment( wOK, 10 ); fdCancel.bottom = new FormAttachment( 100, 0 ); wCancel.setLayoutData( fdCancel ); // Add listeners wCancel.addListener( SWT.Selection, new Listener() { public void handleEvent( Event e ) { dispose(); } } ); // Add listeners wOK.addListener( SWT.Selection, new Listener() { public void handleEvent( Event e ) { handleOK(); } } ); // Drag & Drop for steps Transfer[] ttypes = new Transfer[] { TextTransfer.getInstance() }; DragSource ddSource = new DragSource( wListSource, DND.DROP_MOVE | DND.DROP_COPY ); ddSource.setTransfer( ttypes ); ddSource.addDragListener( new DragSourceListener() { public void dragStart( DragSourceEvent event ) { } public void dragSetData( DragSourceEvent event ) { String[] ti = wListSource.getSelection(); String data = new String(); for ( int i = 0; i < ti.length; i++ ) { data += ti[i] + Const.CR; } event.data = data; } public void dragFinished( DragSourceEvent event ) { } } ); DropTarget ddTarget = new DropTarget( wListDest, DND.DROP_MOVE | DND.DROP_COPY ); ddTarget.setTransfer( ttypes ); ddTarget.addDropListener( new DropTargetListener() { public void dragEnter( DropTargetEvent event ) { } public void dragLeave( DropTargetEvent event ) { } public void dragOperationChanged( DropTargetEvent event ) { } public void dragOver( DropTargetEvent event ) { } public void drop( DropTargetEvent event ) { if ( event.data == null ) { // no data to copy, indicate failure in event.detail event.detail = DND.DROP_NONE; return; } StringTokenizer strtok = new StringTokenizer( (String) event.data, Const.CR ); while ( strtok.hasMoreTokens() ) { String source = strtok.nextToken(); addToDestination( source ); } } public void dropAccept( DropTargetEvent event ) { } } ); wListSource.addKeyListener( new KeyAdapter() { public void keyPressed( KeyEvent e ) { if ( e.character == SWT.CR ) { addToSelection( wListSource.getSelection() ); } } } ); wListDest.addKeyListener( new KeyAdapter() { public void keyPressed( KeyEvent e ) { if ( e.character == SWT.CR ) { delFromSelection( wListDest.getSelection() ); } } } ); // Double click adds to destination. wListSource.addSelectionListener( new SelectionAdapter() { public void widgetDefaultSelected( SelectionEvent e ) { addToSelection( wListSource.getSelection() ); } } ); // Double click adds to source wListDest.addSelectionListener( new SelectionAdapter() { public void widgetDefaultSelected( SelectionEvent e ) { delFromSelection( wListDest.getSelection() ); } } ); wAddOne.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { addToSelection( wListSource.getSelection() ); } } ); wRemoveOne.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { delFromSelection( wListDest.getSelection() ); } } ); wAddAll.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { addToSelection( wListSource.getItems() ); } } ); wRemoveAll.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { delFromSelection( wListDest.getItems() ); } } ); opened = true; getData(); BaseStepDialog.setSize( shell ); shell.open(); Display display = parent.getDisplay(); while ( !shell.isDisposed() ) { if ( !display.readAndDispatch() ) { display.sleep(); } } return retval; } public void getData() { if ( !opened ) { return; } wListSource.removeAll(); wListDest.removeAll(); for ( int i = 0; i < input.length; i++ ) { Integer idx = Integer.valueOf( i ); String str = selection.get( idx ); if ( str == null ) { // Not selected: show in source! wListSource.add( input[i] ); } else { // Selected, show in destination! wListDest.add( input[i] ); } } } public void addToSelection( String[] string ) { for ( int i = 0; i < string.length; i++ ) { addToDestination( string[i] ); } } public void delFromSelection( String[] string ) { for ( int i = 0; i < string.length; i++ ) { delFromDestination( string[i] ); } } public void addToDestination( String string ) { int idxInput = Const.indexOfString( string, input ); selection.put( Integer.valueOf( idxInput ), string ); getData(); } public void delFromDestination( String string ) { int idxInput = Const.indexOfString( string, input ); selection.remove( Integer.valueOf( idxInput ) ); getData(); } public void dispose() { WindowProperty winprop = new WindowProperty( shell ); props.setScreen( winprop ); shell.dispose(); } public void handleOK() { retval = wListDest.getItems(); dispose(); } }