You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2007/04/09 11:49:57 UTC

svn commit: r526693 [9/17] - in /directory/ldapstudio/trunk/ldapstudio-browser-common: ./ META-INF/ resources/ resources/icons/ resources/templates/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/dir...

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/DnBuilderWidget.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/DnBuilderWidget.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/DnBuilderWidget.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/DnBuilderWidget.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,595 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.directory.ldapstudio.browser.common.widgets.search.EntryWidget;
+import org.apache.directory.ldapstudio.browser.core.model.DN;
+import org.apache.directory.ldapstudio.browser.core.model.IConnection;
+import org.apache.directory.ldapstudio.browser.core.model.RDN;
+import org.apache.directory.ldapstudio.browser.core.model.RDNPart;
+import org.eclipse.jface.fieldassist.ComboContentAdapter;
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
+import org.eclipse.jface.fieldassist.DecoratedField;
+import org.eclipse.jface.fieldassist.FieldDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
+import org.eclipse.jface.fieldassist.IControlCreator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+/**
+ * The DnBuilderWidget provides input elements to select a parent DN
+ * and to build a (multivalued) RDN.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class DnBuilderWidget extends BrowserWidget implements ModifyListener
+{
+
+    /** The attribute names that could be selected from drop-down list. */
+    private String[] attributeNames;
+
+    /** The initial RDN. */
+    private RDN currentRdn;
+
+    /** The initial parent DN. */
+    private DN currentParentDn;
+
+    /** True if the RDN input elements should be shown. */
+    private boolean showRDN;
+
+    /** True if the parent DN input elements should be shown. */
+    private boolean showParent;
+
+    /** The shell. */
+    private Shell shell;
+
+    /** The selected parent DN. */
+    private DN parentDn;
+
+    /** The entry widget to enter/select the parent DN. */
+    private EntryWidget parentEntryWidget;
+
+    /** The composite that contains the RdnLines. */
+    private Composite rdnComposite;
+
+    /** The resulting RDN. */
+    private RDN rdn;
+
+    /** The list of RdnLines. */
+    private ArrayList<RdnLine> rdnLineList;
+
+    /** The preview text. */
+    private Text previewText;
+
+
+    /**
+     * Creates a new instance of DnBuilderWidget.
+     * 
+     * @param showParent true if the parent DN input elements should be shown
+     * @param showRDN true if the RDN input elements should be shown
+     */
+    public DnBuilderWidget( boolean showRDN, boolean showParent )
+    {
+        this.showRDN = showRDN;
+        this.showParent = showParent;
+    }
+
+
+    /**
+     * Disposes this widget.
+     */
+    public void dispose()
+    {
+    }
+
+
+    /**
+     * Sets the input.
+     * 
+     * @param rdn the initial RDN
+     * @param attributeNames the attribute names that could be selected from drop-down list
+     * @param connection the connection
+     * @param parentDn the initial parent DN
+     */
+    public void setInput( IConnection connection, String[] attributeNames, RDN rdn, DN parentDn )
+    {
+        this.attributeNames = attributeNames;
+        this.currentRdn = rdn;
+        this.currentParentDn = parentDn;
+
+        if ( showRDN )
+        {
+            for ( int i = 0; i < rdnLineList.size(); i++ )
+            {
+                RdnLine rdnLine = rdnLineList.get( i );
+                String oldName = rdnLine.rdnNameCombo.getText();
+                rdnLine.rdnNameCombo.setItems( attributeNames );
+                rdnLine.rdnNameCPA.setContentProposalProvider( new ListContentProposalProvider( attributeNames ) );
+                if ( Arrays.asList( rdnLine.rdnNameCombo.getItems() ).contains( oldName ) )
+                {
+                    rdnLine.rdnNameCombo.setText( oldName );
+                }
+            }
+        }
+
+        if ( showRDN )
+        {
+            while ( !rdnLineList.isEmpty() )
+            {
+                deleteRdnLine( rdnComposite, 0 );
+            }
+            if ( currentRdn == null || currentRdn.getParts().length == 0 )
+            {
+                addRdnLine( rdnComposite, 0 );
+                rdnLineList.get( 0 ).rdnNameCombo.setFocus();
+            }
+            else
+            {
+                RDNPart[] parts = currentRdn.getParts();
+                for ( int i = 0; i < parts.length; i++ )
+                {
+                    addRdnLine( rdnComposite, i );
+                    rdnLineList.get( i ).rdnNameCombo.setText( parts[i].getType() );
+                    rdnLineList.get( i ).rdnValueText.setText( parts[i].getUnencodedValue() );
+                    if ( i == 0 )
+                    {
+                        if ( "".equals( rdnLineList.get( i ).rdnNameCombo ) )
+                        {
+                            rdnLineList.get( i ).rdnNameCombo.setFocus();
+                        }
+                        else
+                        {
+                            rdnLineList.get( i ).rdnValueText.selectAll();
+                            rdnLineList.get( i ).rdnValueText.setFocus();
+                        }
+                    }
+                }
+            }
+        }
+
+        if ( showParent )
+        {
+            parentEntryWidget.setInput( connection, currentParentDn );
+        }
+
+        validate();
+    }
+
+
+    /**
+     * Gets the RDN.
+     * 
+     * @return the RDN
+     */
+    public RDN getRdn()
+    {
+        return rdn;
+    }
+
+
+    /**
+     * Gets the parent DN.
+     * 
+     * @return the parent DN
+     */
+    public DN getParentDn()
+    {
+        return parentDn;
+    }
+
+
+    /**
+     * Creates the contents.
+     * 
+     * @param parent the parent composite
+     * 
+     * @return the created composite
+     */
+    public Composite createContents( Composite parent )
+    {
+        this.shell = parent.getShell();
+
+        Composite composite = BaseWidgetUtils.createColumnContainer( parent, 3, 1 );
+
+        // draw parent
+        if ( showParent )
+        {
+            BaseWidgetUtils.createLabel( composite, "Parent:", 1 );
+            parentEntryWidget = new EntryWidget();
+            parentEntryWidget.createWidget( composite );
+            parentEntryWidget.addWidgetModifyListener( new WidgetModifyListener()
+            {
+                public void widgetModified( WidgetModifyEvent event )
+                {
+                    validate();
+                }
+            } );
+
+            BaseWidgetUtils.createSpacer( composite, 3 );
+        }
+
+        // draw RDN group
+        if ( showRDN )
+        {
+            BaseWidgetUtils.createLabel( composite, "RDN:", 1 );
+            rdnComposite = BaseWidgetUtils.createColumnContainer( composite, 5, 2 );
+            rdnLineList = new ArrayList<RdnLine>();
+            BaseWidgetUtils.createSpacer( composite, 3 );
+        }
+
+        // draw dn/rdn preview
+        if ( showRDN )
+        {
+            BaseWidgetUtils.createLabel( composite, showParent ? "DN Preview: " : "RDN Preview: ", 1 );
+            previewText = BaseWidgetUtils.createReadonlyText( composite, "", 2 );
+            BaseWidgetUtils.createSpacer( composite, 3 );
+        }
+
+        return composite;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void modifyText( ModifyEvent e )
+    {
+        validate();
+    }
+
+
+    /**
+     * Saves the dialog settings.
+     */
+    public void saveDialogSettings()
+    {
+        if ( parentEntryWidget != null )
+        {
+            parentEntryWidget.saveDialogSettings();
+        }
+    }
+
+
+    /**
+     * Validates the input elements.
+     */
+    public void validate()
+    {
+
+        Exception rdnE = null;
+        if ( showRDN )
+        {
+            try
+            {
+                // calculate RDN
+                String[] rdnNames = new String[rdnLineList.size()];
+                String[] rdnValues = new String[rdnLineList.size()];
+                for ( int i = 0; i < rdnLineList.size(); i++ )
+                {
+                    RdnLine rdnLine = ( RdnLine ) rdnLineList.get( i );
+                    rdnNames[i] = rdnLine.rdnNameCombo.getText();
+                    rdnValues[i] = rdnLine.rdnValueText.getText();
+
+                    if ( rdnLineList.size() > 1 )
+                    {
+                        rdnLine.rdnDeleteButton.setEnabled( true );
+                    }
+                    else
+                    {
+                        rdnLine.rdnDeleteButton.setEnabled( false );
+                    }
+                }
+                rdn = new RDN( rdnNames, rdnValues, false );
+            }
+            catch ( Exception e )
+            {
+                rdnE = e;
+                rdn = null;
+            }
+        }
+
+        Exception parentE = null;
+        if ( showParent )
+        {
+            try
+            {
+                // calculate DN
+                parentDn = new DN( parentEntryWidget.getDn() );
+            }
+            catch ( Exception e )
+            {
+                parentE = e;
+                parentDn = null;
+            }
+        }
+
+        String s = "";
+        if ( rdnE != null )
+        {
+            s += rdnE.getMessage() != null ? rdnE.getMessage() : "Error in RDN ";
+        }
+        if ( parentE != null )
+        {
+            s += ", " + parentE.getMessage() != null ? parentE.getMessage() : "Error in Parent DN ";
+        }
+
+        if ( previewText != null )
+        {
+            if ( s.length() > 0 )
+            {
+                previewText.setText( s );
+            }
+            else
+            {
+                DN dn;
+                if ( showParent && showRDN )
+                {
+                    dn = new DN( rdn, parentDn );
+                }
+                else if ( showParent )
+                {
+                    dn = new DN( parentDn );
+                }
+                else if ( showRDN )
+                {
+                    dn = new DN( rdn );
+                }
+                else
+                {
+                    dn = new DN();
+                }
+                previewText.setText( dn.toString() );
+            }
+        }
+
+        notifyListeners();
+    }
+
+
+    /**
+     * Adds an RDN line at the given index.
+     * 
+     * @param rdnComposite the RDN composite
+     * @param index the index
+     */
+    private void addRdnLine( Composite rdnComposite, int index )
+    {
+        RdnLine[] rdnLines = ( RdnLine[] ) rdnLineList.toArray( new RdnLine[rdnLineList.size()] );
+
+        if ( rdnLines.length > 0 )
+        {
+            for ( int i = 0; i < rdnLines.length; i++ )
+            {
+                RdnLine oldRdnLine = rdnLines[i];
+
+                // remember values
+                String oldName = oldRdnLine.rdnNameCombo.getText();
+                String oldValue = oldRdnLine.rdnValueText.getText();
+
+                // delete old
+                oldRdnLine.rdnNameComboField.getLayoutControl().dispose();
+                oldRdnLine.rdnEqualsLabel.dispose();
+                oldRdnLine.rdnValueText.dispose();
+                oldRdnLine.rdnAddButton.dispose();
+                oldRdnLine.rdnDeleteButton.dispose();
+                rdnLineList.remove( oldRdnLine );
+
+                // add new
+                RdnLine newRdnLine = createRdnLine( rdnComposite );
+                rdnLineList.add( newRdnLine );
+
+                // restore value
+                newRdnLine.rdnNameCombo.setText( oldName );
+                newRdnLine.rdnValueText.setText( oldValue );
+
+                // check
+                if ( index == i + 1 )
+                {
+                    RdnLine rdnLine = createRdnLine( rdnComposite );
+                    rdnLineList.add( rdnLine );
+                }
+            }
+        }
+        else
+        {
+            RdnLine rdnLine = createRdnLine( rdnComposite );
+            rdnLineList.add( rdnLine );
+        }
+
+        shell.layout( true, true );
+    }
+
+
+    /**
+     * Creates and returns an RDN line.
+     * 
+     * @param rdnComposite the RDN composite
+     * 
+     * @return the created RDN line
+     */
+    private RdnLine createRdnLine( final Composite rdnComposite )
+    {
+        final RdnLine rdnLine = new RdnLine();
+
+        final FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault().getFieldDecoration(
+            FieldDecorationRegistry.DEC_CONTENT_PROPOSAL );
+        rdnLine.rdnNameComboField = new DecoratedField( rdnComposite, SWT.NONE, new IControlCreator()
+        {
+            public Control createControl( Composite parent, int style )
+            {
+                Combo combo = new Combo( parent, SWT.DROP_DOWN | SWT.BORDER );
+                GridData gd = new GridData();
+                gd.widthHint = 180;
+                combo.setLayoutData( gd );
+                combo.setVisibleItemCount( 20 );
+                return combo;
+            }
+        } );
+        rdnLine.rdnNameComboField.addFieldDecoration( fieldDecoration, SWT.TOP | SWT.LEFT, true );
+        GridData gd = new GridData();
+        gd.widthHint = 180;
+        rdnLine.rdnNameComboField.getLayoutControl().setLayoutData( gd );
+        rdnLine.rdnNameCombo = ( Combo ) rdnLine.rdnNameComboField.getControl();
+
+        rdnLine.rdnNameCPA = new ContentProposalAdapter( rdnLine.rdnNameCombo, new ComboContentAdapter(),
+            new ListContentProposalProvider( attributeNames ), null, null );
+        rdnLine.rdnNameCPA.setFilterStyle( ContentProposalAdapter.FILTER_NONE );
+        rdnLine.rdnNameCPA.setProposalAcceptanceStyle( ContentProposalAdapter.PROPOSAL_REPLACE );
+
+        rdnLine.rdnEqualsLabel = new Label( rdnComposite, SWT.NONE );
+        rdnLine.rdnEqualsLabel.setText( "=" );
+
+        rdnLine.rdnValueText = new Text( rdnComposite, SWT.BORDER );
+        gd = new GridData( GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL );
+        rdnLine.rdnValueText.setLayoutData( gd );
+
+        rdnLine.rdnAddButton = new Button( rdnComposite, SWT.PUSH );
+        rdnLine.rdnAddButton.setText( "  +   " );
+        rdnLine.rdnAddButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                int index = rdnLineList.size();
+                for ( int i = 0; i < rdnLineList.size(); i++ )
+                {
+                    RdnLine rdnLine = ( RdnLine ) rdnLineList.get( i );
+                    if ( rdnLine.rdnAddButton == e.widget )
+                    {
+                        index = i + 1;
+                    }
+                }
+                addRdnLine( rdnComposite, index );
+
+                validate();
+            }
+        } );
+
+        rdnLine.rdnDeleteButton = new Button( rdnComposite, SWT.PUSH );
+        rdnLine.rdnDeleteButton.setText( "  \u2212  " ); // \u2013
+        rdnLine.rdnDeleteButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                int index = 0;
+                for ( int i = 0; i < rdnLineList.size(); i++ )
+                {
+                    RdnLine rdnLine = ( RdnLine ) rdnLineList.get( i );
+                    if ( rdnLine.rdnDeleteButton == e.widget )
+                    {
+                        index = i;
+                    }
+                }
+                deleteRdnLine( rdnComposite, index );
+
+                validate();
+            }
+        } );
+
+        if ( attributeNames != null )
+        {
+            rdnLine.rdnNameCombo.setItems( attributeNames );
+        }
+
+        rdnLine.rdnNameCombo.addModifyListener( this );
+        rdnLine.rdnValueText.addModifyListener( this );
+
+        return rdnLine;
+    }
+
+
+    /**
+     * Delete thd RDN line on the given index.
+     * 
+     * @param rdnComposite the RDN composite
+     * @param index the index
+     */
+    private void deleteRdnLine( Composite rdnComposite, int index )
+    {
+        RdnLine rdnLine = ( RdnLine ) rdnLineList.remove( index );
+        if ( rdnLine != null )
+        {
+            rdnLine.rdnNameComboField.getLayoutControl().dispose();
+            rdnLine.rdnEqualsLabel.dispose();
+            rdnLine.rdnValueText.dispose();
+            rdnLine.rdnAddButton.dispose();
+            rdnLine.rdnDeleteButton.dispose();
+
+            if ( !rdnComposite.isDisposed() )
+            {
+                shell.layout( true, true );
+            }
+        }
+    }
+
+    /**
+     * The Class RdnLine is a wrapper for all input elements
+     * of an RDN line. It contains a combo for the RDN attribute, 
+     * an input field for the RDN value and + and - buttons
+     * to add and remove other RDN lines. It looks like this:
+     * <pre>
+     * --------------------------------------------------
+     * | attribute type v | = | attribute value | + | - |
+     * --------------------------------------------------
+     * </pre>
+     */
+    private class RdnLine
+    {
+
+        /** The rdn name combo. */
+        private DecoratedField rdnNameComboField;
+
+        /** The rdn name combo. */
+        private Combo rdnNameCombo;
+
+        /** The content proposal adapter */
+        private ContentProposalAdapter rdnNameCPA;
+
+        /** The rdn value text. */
+        private Text rdnValueText;
+
+        /** The rdn equals label. */
+        private Label rdnEqualsLabel;
+
+        /** The rdn add button. */
+        private Button rdnAddButton;
+
+        /** The rdn delete button. */
+        private Button rdnDeleteButton;
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/FileBrowserWidget.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/FileBrowserWidget.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/FileBrowserWidget.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/FileBrowserWidget.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,199 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.io.File;
+
+import org.apache.directory.ldapstudio.browser.common.BrowserCommonActivator;
+import org.apache.directory.ldapstudio.browser.common.BrowserCommonConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+
+
+/**
+ * The FileBrowserWidget provides a combo with a history of recently
+ * used files an a browse button to open the file browser.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class FileBrowserWidget extends BrowserWidget
+{
+
+    /** The Constant TYPE_OPEN is used to create a Open file dialog. */
+    public static final int TYPE_OPEN = SWT.OPEN;
+
+    /** The Constant TYPE_SAVE is used to create a Save file dialog. */
+    public static final int TYPE_SAVE = SWT.SAVE;
+
+    /** The combo with the history of recently used files */
+    private Combo fileCombo;
+
+    /** The button to launch the file browser */
+    private Button browseButton;
+
+    /** The title */
+    private String title;
+
+    /** File extensions used within the lauched file browser */
+    private String[] extensions;
+
+    /** The type */
+    private int type;
+
+
+    /**
+     * Creates a new instance of FileBrowserWidget.
+     *
+     * @param title The title
+     * @param extensions The valid file extensions
+     * @param type The type, one of {@link #TYPE_OPEN} or {@link #TYPE_SAVE}
+     */
+    public FileBrowserWidget( String title, String[] extensions, int type )
+    {
+        this.title = title;
+        this.extensions = extensions;
+        this.type = type;
+    }
+
+
+    /**
+     * Creates the widget.
+     * 
+     * @param parent the parent
+     */
+    public void createWidget( final Composite parent )
+    {
+
+        // Combo
+        fileCombo = BaseWidgetUtils.createCombo( parent, new String[0], -1, 1 );
+        fileCombo.addModifyListener( new ModifyListener()
+        {
+            public void modifyText( ModifyEvent e )
+            {
+                notifyListeners();
+            }
+        } );
+
+        // Button
+        browseButton = BaseWidgetUtils.createButton( parent, "Bro&wse...", 1 );
+        browseButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent event )
+            {
+                FileDialog fileDialog = new FileDialog( parent.getShell(), type );
+                fileDialog.setText( title );
+
+                fileDialog.setFilterExtensions( extensions );
+
+                File file = new File( fileCombo.getText() );
+                if ( file.isFile() )
+                {
+                    fileDialog.setFilterPath( file.getParent() );
+                    fileDialog.setFileName( file.getName() );
+                }
+                else if ( file.isDirectory() )
+                {
+                    fileDialog.setFilterPath( file.getPath() );
+                }
+                else
+                {
+                    fileDialog.setFilterPath( BrowserCommonActivator.getDefault().getDialogSettings().get(
+                        BrowserCommonConstants.DIALOGSETTING_KEY_RECENT_FILE_PATH ) );
+                }
+
+                String returnedFileName = fileDialog.open();
+                if ( returnedFileName != null )
+                {
+                    fileCombo.setText( returnedFileName );
+                    File file2 = new File( returnedFileName );
+                    BrowserCommonActivator.getDefault().getDialogSettings().put(
+                        BrowserCommonConstants.DIALOGSETTING_KEY_RECENT_FILE_PATH, file2.getParent() );
+                }
+            }
+        } );
+
+        // file history
+        String[] history = HistoryUtils.load( BrowserCommonConstants.DIALOGSETTING_KEY_FILE_HISTORY );
+        fileCombo.setItems( history );
+    }
+
+
+    /**
+     * Gets the filename.
+     * 
+     * @return the filename
+     */
+    public String getFilename()
+    {
+        return fileCombo.getText();
+    }
+
+
+    /**
+     * Sets the filename.
+     * 
+     * @param filename the filename
+     */
+    public void setFilename( String filename )
+    {
+        fileCombo.setText( filename );
+    }
+
+
+    /**
+     * Saves dialog settings.
+     */
+    public void saveDialogSettings()
+    {
+        HistoryUtils.save( BrowserCommonConstants.DIALOGSETTING_KEY_FILE_HISTORY, fileCombo.getText() );
+    }
+
+
+    /**
+     * Sets the focus.
+     */
+    public void setFocus()
+    {
+        fileCombo.setFocus();
+    }
+
+
+    /**
+     * Enables or disables the widget.
+     * 
+     * @param b true to enable the widget, false otherwise
+     */
+    public void setEnabled( boolean b )
+    {
+        fileCombo.setEnabled( b );
+        browseButton.setEnabled( b );
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/FileEncodingInput.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/FileEncodingInput.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/FileEncodingInput.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/FileEncodingInput.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,130 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.nio.charset.Charset;
+
+import org.apache.directory.ldapstudio.browser.core.BrowserCoreConstants;
+
+
+/**
+ * The FileEncodingInput is an OptionInput with fixed options. 
+ * It is used to select the file encoding. The default
+ * value is always the platform's default encoding.
+ * The other options are the values return from 
+ * {@link Charset#availableCharsets()}. No custom input is allowed.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class FileEncodingInput extends OptionsInput
+{
+
+    /**
+     * Creates a new instance of FileEncodingInput.
+     *
+     * @param initialRawValue the initial raw value
+     * @param asGroup the asGroup flag
+     */
+    public FileEncodingInput( String initialRawValue, boolean asGroup )
+    {
+        super( "File Encoding", getDefaultDisplayValue(), getDefaultRawValue(), getOtherDisplayValues(),
+            getOtherRawValues(), initialRawValue, asGroup, false );
+
+    }
+
+
+    /**
+     * Gets the default display value.
+     * 
+     * @return the default display value
+     */
+    private static String getDefaultDisplayValue()
+    {
+        return getCharsetDisplayValue( getDefaultRawValue() );
+    }
+
+
+    /**
+     * Gets the default raw value, always the platform's
+     * default encoding.
+     * 
+     * @return the default raw value
+     */
+    private static String getDefaultRawValue()
+    {
+        return BrowserCoreConstants.DEFAULT_ENCODING;
+    }
+
+
+    /**
+     * Gets the other display values.
+     * 
+     * @return the other display values
+     */
+    private static String[] getOtherDisplayValues()
+    {
+        String[] otherEncodingsRawValues = getOtherRawValues();
+        String[] otherEncodingsDisplayValues = new String[otherEncodingsRawValues.length];
+        for ( int i = 0; i < otherEncodingsDisplayValues.length; i++ )
+        {
+            String rawValue = otherEncodingsRawValues[i];
+            otherEncodingsDisplayValues[i] = getCharsetDisplayValue( rawValue );
+        }
+        return otherEncodingsDisplayValues;
+    }
+
+
+    /**
+     * Gets the other raw values. That are all values
+     * returned from {@link Charset#availableCharsets()}. 
+     * 
+     * @return the other raw values
+     */
+    private static String[] getOtherRawValues()
+    {
+        String[] otherEncodingsRawValues = ( String[] ) Charset.availableCharsets().keySet().toArray( new String[0] );
+        return otherEncodingsRawValues;
+    }
+
+
+    /**
+     * Gets the charset display value.
+     * 
+     * @param charsetRawValue the charset raw value
+     * 
+     * @return the charset display value
+     */
+    private static String getCharsetDisplayValue( String charsetRawValue )
+    {
+        try
+        {
+            Charset charset = Charset.forName( charsetRawValue );
+            return charset.displayName();
+        }
+        catch ( Exception e )
+        {
+            return charsetRawValue;
+        }
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/HistoryUtils.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/HistoryUtils.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/HistoryUtils.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/HistoryUtils.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,89 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.directory.ldapstudio.browser.common.BrowserCommonActivator;
+import org.apache.directory.ldapstudio.browser.common.BrowserCommonConstants;
+
+
+/**
+ * The HistoryUtils are used to save and load the history of input fields.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HistoryUtils
+{
+
+    /**
+     * Saves the the given value under the given key in the dialog settings.
+     *
+     * @param key the key
+     * @param value the value
+     */
+    public static void save( String key, String value )
+    {
+        // get current history
+        String[] history = load( key );
+        List<String> list = new ArrayList<String>( Arrays.asList( history ) );
+
+        // add new value or move to first position
+        if ( list.contains( value ) )
+        {
+            list.remove( value );
+        }
+        list.add( 0, value );
+
+        // check history size
+        while ( list.size() > BrowserCommonConstants.HISTORYSIZE )
+        {
+            list.remove( list.size() - 1 );
+        }
+
+        // save
+        history = list.toArray( new String[list.size()] );
+        BrowserCommonActivator.getDefault().getDialogSettings().put( key, history );
+
+    }
+
+
+    /**
+     * Loads the value of the given key from the dialog settings
+     *
+     * @param key the key
+     * @return the value
+     */
+    public static String[] load( String key )
+    {
+        String[] history = BrowserCommonActivator.getDefault().getDialogSettings().getArray( key );
+        if ( history == null )
+        {
+            history = new String[0];
+        }
+        return history;
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/LineSeparatorInput.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/LineSeparatorInput.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/LineSeparatorInput.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/LineSeparatorInput.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,133 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.directory.ldapstudio.browser.core.BrowserCoreConstants;
+import org.eclipse.core.runtime.Platform;
+
+
+/**
+ * The LineSeparatorInput is an OptionInput with fixed options. 
+ * It is used to select the line separator. The default
+ * value is always the platform's default line separator.
+ * The other options are the values return from 
+ * {@link Platform#knownPlatformLineSeparators()}. 
+ * No custom input is allowed.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class LineSeparatorInput extends OptionsInput
+{
+
+    /**
+     * Creates a new instance of LineSeparatorInput.
+     *
+     * @param initialRawValue the initial raw value
+     * @param asGroup the asGroup flag
+     */
+    public LineSeparatorInput( String initialRawValue, boolean asGroup )
+    {
+        super( "Line Separator", getDefaultDisplayValue(), getDefaultRawValue(), getOtherDisplayValues(),
+            getOtherRawValues(), initialRawValue, asGroup, false );
+
+    }
+
+
+    /**
+     * Gets the default display value.
+     * 
+     * @return the default display value
+     */
+    private static String getDefaultDisplayValue()
+    {
+        Map lsMap = Platform.knownPlatformLineSeparators();
+        for ( Iterator iter = lsMap.keySet().iterator(); iter.hasNext(); )
+        {
+            String k = ( String ) iter.next();
+            String v = ( String ) lsMap.get( k );
+            if ( v.equals( getDefaultRawValue() ) )
+            {
+                k = k + " (" + ( v.replaceAll( "\n", "\\\\n" ).replaceAll( "\r", "\\\\r" ) ) + ")";
+                return k;
+            }
+        }
+        return getDefaultRawValue();
+    }
+
+
+    /**
+     * Gets the default raw value, always the platform's default
+     * line separator.
+     * 
+     * @return the default raw value
+     */
+    private static String getDefaultRawValue()
+    {
+        return BrowserCoreConstants.LINE_SEPARATOR;
+    }
+
+
+    /**
+     * Gets the other display values That are all values
+     * returned from {@link Platform#knownPlatformLineSeparators()}. 
+     * 
+     * @return the other display values
+     */
+    @SuppressWarnings("unchecked")
+    private static String[] getOtherDisplayValues()
+    {
+        Map<String, String> lsMap = Platform.knownPlatformLineSeparators();
+        String[] displayValues = lsMap.keySet().toArray( new String[lsMap.size()] );
+        for ( int i = 0; i < displayValues.length; i++ )
+        {
+            displayValues[i] = displayValues[i]
+                + " ("
+                + ( ( ( String ) lsMap.get( displayValues[i] ) ).replaceAll( "\n", "\\\\n" ).replaceAll( "\r", "\\\\r" ) )
+                + ")";
+        }
+        return displayValues;
+    }
+
+
+    /**
+     * Gets the other raw values.
+     * 
+     * @return the other raw values
+     */
+    @SuppressWarnings("unchecked")
+    private static String[] getOtherRawValues()
+    {
+        Map<String, String> lsMap = Platform.knownPlatformLineSeparators();
+        String[] displayValues = lsMap.keySet().toArray( new String[lsMap.size()] );
+        String[] rawValues = new String[displayValues.length];
+        for ( int i = 0; i < rawValues.length; i++ )
+        {
+            rawValues[i] = ( String ) lsMap.get( displayValues[i] );
+        }
+        return rawValues;
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ListContentProposalProvider.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ListContentProposalProvider.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ListContentProposalProvider.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ListContentProposalProvider.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,112 @@
+package org.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.fieldassist.IContentProposal;
+import org.eclipse.jface.fieldassist.IContentProposalProvider;
+
+
+/**
+ * ListContentProposalProvider is a class designed to map a dynamic list of
+ * Strings to content proposals.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ListContentProposalProvider implements IContentProposalProvider
+{
+
+    /** The dynamic list of proposals */
+    private List<String> proposals;
+
+
+    /**
+     * Creates a new instance of ListContentProposalProvider.
+     *
+     * @param proposals the dynamic list of proposals
+     */
+    public ListContentProposalProvider( List<String> proposals )
+    {
+        setProposals( proposals );
+    }
+
+
+    /**
+     * Creates a new instance of ListContentProposalProvider.
+     *
+     * @param proposals the proposals
+     */
+    public ListContentProposalProvider( String[] proposals )
+    {
+        setProposals( new ArrayList<String>( Arrays.asList( proposals ) ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public IContentProposal[] getProposals( String contents, int position )
+    {
+        String string = contents.substring( 0, position );
+
+        Collections.sort( proposals );
+
+        List<IContentProposal> proposalList = new ArrayList<IContentProposal>();
+        for ( int k = 0; k < proposals.size(); k++ )
+        {
+            final String proposal = proposals.get( k );
+            if ( proposal.toUpperCase().startsWith( string.toUpperCase() ) && !proposal.equalsIgnoreCase( string )
+                && !"".equals( string ) )
+            {
+                IContentProposal p = new IContentProposal()
+                {
+                    public String getContent()
+                    {
+                        return proposal;
+                    }
+
+
+                    public String getDescription()
+                    {
+                        return proposal;
+                    }
+
+
+                    public String getLabel()
+                    {
+                        return proposal;
+                    }
+
+
+                    public int getCursorPosition()
+                    {
+                        return proposal.length();
+                    }
+                };
+                proposalList.add( p );
+            }
+        }
+        return proposalList.toArray( new IContentProposal[proposalList.size()] );
+    }
+
+
+    /**
+     * Sets the possible strings.
+     * 
+     * @param proposals the possible strings
+     */
+    public void setProposals( List<String> proposals )
+    {
+        if ( proposals == null )
+        {
+            proposals = new ArrayList<String>();
+        }
+
+        this.proposals = proposals;
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ModWidget.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ModWidget.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ModWidget.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ModWidget.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,604 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.directory.ldapstudio.browser.core.BrowserCoreConstants;
+import org.apache.directory.ldapstudio.browser.core.model.schema.Schema;
+import org.eclipse.jface.fieldassist.ComboContentAdapter;
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
+import org.eclipse.jface.fieldassist.DecoratedField;
+import org.eclipse.jface.fieldassist.FieldDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
+import org.eclipse.jface.fieldassist.IControlCreator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+/**
+ * The ModWidget provides input elements to define an LDAP modify 
+ * operation.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ModWidget extends BrowserWidget implements ModifyListener
+{
+
+    /** The schema with the possible attribute types */
+    private Schema schema;
+
+    /** The shell */
+    private Shell shell;
+
+    /** The composite that contains the ModSpecs */
+    private Composite modComposite;
+
+    /** The list of ModSpecs */
+    private ArrayList<ModSpec> modSpecList;
+
+    /** The resulting LDIF */
+    private String ldif;
+
+
+    /**
+     * Creates a new instance of ModWidget.
+     *
+     * @param schema the schema with the possible attribute types
+     */
+    public ModWidget( Schema schema )
+    {
+        this.schema = schema;
+        this.modSpecList = new ArrayList<ModSpec>();
+        this.ldif = null;
+    }
+
+
+    /**
+     * Disposes this widget.
+     */
+    public void dispose()
+    {
+    }
+
+
+    /**
+     * Gets the ldif.
+     * 
+     * @return the ldif
+     */
+    public String getLdif()
+    {
+        return ldif;
+    }
+
+
+    /**
+     * Creates the contents.
+     * 
+     * @param parent the parent composite
+     * 
+     * @return the created composite
+     */
+    public Composite createContents( Composite parent )
+    {
+        shell = parent.getShell();
+
+        modComposite = BaseWidgetUtils.createColumnContainer( parent, 3, 1 );
+        addModSpec( modComposite, 0 );
+
+        return modComposite;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void modifyText( ModifyEvent e )
+    {
+        validate();
+    }
+
+
+    /**
+     * Validates the input elements.
+     */
+    public void validate()
+    {
+        for ( int i = 0; i < modSpecList.size(); i++ )
+        {
+            ModSpec modSpec = ( ModSpec ) modSpecList.get( i );
+            if ( modSpecList.size() > 1 )
+            {
+                modSpec.modDeleteButton.setEnabled( true );
+            }
+            else
+            {
+                modSpec.modDeleteButton.setEnabled( false );
+            }
+            for ( int k = 0; k < modSpec.valueLineList.size(); k++ )
+            {
+                ValueLine valueLine = ( ValueLine ) modSpec.valueLineList.get( k );
+                if ( modSpec.valueLineList.size() > 1 )
+                {
+                    valueLine.valueDeleteButton.setEnabled( true );
+                }
+                else
+                {
+                    valueLine.valueDeleteButton.setEnabled( false );
+                }
+            }
+        }
+
+        notifyListeners();
+    }
+
+
+    /**
+     * Adds a modification spec at the given index.
+     * 
+     * @param modComposite the composite
+     * @param index the index
+     */
+    private void addModSpec( Composite modComposite, int index )
+    {
+
+        ModSpec[] modSpecs = ( ModSpec[] ) modSpecList.toArray( new ModSpec[modSpecList.size()] );
+
+        if ( modSpecs.length > 0 )
+        {
+            for ( int i = 0; i < modSpecs.length; i++ )
+            {
+                ModSpec oldModSpec = modSpecs[i];
+
+                // remember values
+                String oldType = oldModSpec.modType.getText();
+                String oldAttribute = oldModSpec.modAttributeCombo.getText();
+                String[] oldValues = new String[oldModSpec.valueLineList.size()];
+                for ( int k = 0; k < oldValues.length; k++ )
+                {
+                    oldValues[k] = ( ( ValueLine ) oldModSpec.valueLineList.get( k ) ).valueText.getText();
+                }
+
+                // delete old
+                oldModSpec.modGroup.dispose();
+                oldModSpec.modAddButton.dispose();
+                oldModSpec.modDeleteButton.dispose();
+                modSpecList.remove( oldModSpec );
+
+                // add new
+                ModSpec newModSpec = createModSpec( modComposite );
+                modSpecList.add( newModSpec );
+
+                // restore values
+                newModSpec.modType.setText( oldType );
+                newModSpec.modAttributeCombo.setText( oldAttribute );
+                deleteValueLine( newModSpec, 0 );
+                for ( int k = 0; k < oldValues.length; k++ )
+                {
+                    addValueLine( newModSpec, k );
+                    ValueLine newValueLine = ( ValueLine ) newModSpec.valueLineList.get( k );
+                    newValueLine.valueText.setText( oldValues[k] );
+                }
+
+                // check
+                if ( index == i + 1 )
+                {
+                    ModSpec modSpec = createModSpec( modComposite );
+                    modSpecList.add( modSpec );
+                }
+            }
+        }
+        else
+        {
+            ModSpec modSpec = createModSpec( modComposite );
+            modSpecList.add( modSpec );
+        }
+
+        shell.layout( true, true );
+    }
+
+
+    /**
+     * Creates and returns a modification spec.
+     * 
+     * @param modComposite the composite
+     * 
+     * @return the created modification spec
+     */
+    private ModSpec createModSpec( final Composite modComposite )
+    {
+        final ModSpec modSpec = new ModSpec();
+
+        modSpec.modGroup = BaseWidgetUtils.createGroup( modComposite, "", 1 );
+        Composite modSpecComposite = BaseWidgetUtils.createColumnContainer( modSpec.modGroup, 2, 1 );
+        modSpec.modType = BaseWidgetUtils.createCombo( modSpecComposite, new String[]
+            { "add", "replace", "delete" }, 0, 1 );
+        modSpec.modType.addModifyListener( this );
+        String[] attributeDescriptions = schema.getAttributeTypeDescriptionNames();
+        Arrays.sort( attributeDescriptions );
+
+        // attribute combo with field decoration
+        final FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault().getFieldDecoration(
+            FieldDecorationRegistry.DEC_CONTENT_PROPOSAL );
+        modSpec.modAttributeComboField = new DecoratedField( modSpecComposite, SWT.NONE, new IControlCreator()
+        {
+            public Control createControl( Composite parent, int style )
+            {
+                Combo combo = BaseWidgetUtils.createCombo( parent, new String[0], -1, 1 );
+                combo.setVisibleItemCount( 20 );
+                return combo;
+            }
+        } );
+        modSpec.modAttributeComboField.addFieldDecoration( fieldDecoration, SWT.TOP | SWT.LEFT, true );
+        modSpec.modAttributeComboField.getLayoutControl().setLayoutData(
+            new GridData( SWT.FILL, SWT.CENTER, true, false ) );
+        modSpec.modAttributeCombo = ( Combo ) modSpec.modAttributeComboField.getControl();
+        modSpec.modAttributeCombo.setItems( attributeDescriptions );
+        modSpec.modAttributeCombo.addModifyListener( this );
+
+        // content proposal adapter
+        modSpec.modAttributeCPA = new ContentProposalAdapter( modSpec.modAttributeCombo, new ComboContentAdapter(),
+            new ListContentProposalProvider( attributeDescriptions ), null, null );
+        modSpec.modAttributeCPA.setFilterStyle( ContentProposalAdapter.FILTER_NONE );
+        modSpec.modAttributeCPA.setProposalAcceptanceStyle( ContentProposalAdapter.PROPOSAL_REPLACE );
+
+        // add button with listener
+        modSpec.modAddButton = new Button( modComposite, SWT.PUSH );
+        modSpec.modAddButton.setText( "  +   " );
+        modSpec.modAddButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                int index = modSpecList.size();
+                for ( int i = 0; i < modSpecList.size(); i++ )
+                {
+                    ModSpec modSpec = modSpecList.get( i );
+                    if ( modSpec.modAddButton == e.widget )
+                    {
+                        index = i + 1;
+                    }
+                }
+
+                addModSpec( modComposite, index );
+
+                validate();
+            }
+        } );
+
+        // delete button with listener
+        modSpec.modDeleteButton = new Button( modComposite, SWT.PUSH );
+        modSpec.modDeleteButton.setText( "  \u2212  " ); // \u2013
+        modSpec.modDeleteButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                int index = 0;
+                for ( int i = 0; i < modSpecList.size(); i++ )
+                {
+                    ModSpec modSpec = modSpecList.get( i );
+                    if ( modSpec.modDeleteButton == e.widget )
+                    {
+                        index = i;
+                    }
+                }
+
+                deleteModSpec( modComposite, index );
+
+                validate();
+            }
+        } );
+
+        addValueLine( modSpec, 0 );
+
+        return modSpec;
+    }
+
+
+    /**
+     * Delets a modification spec.
+     *
+     * @param modComposite the composite
+     * @param index the index
+     */
+    private void deleteModSpec( Composite modComposite, int index )
+    {
+        ModSpec modSpec = modSpecList.remove( index );
+        if ( modSpec != null )
+        {
+            modSpec.modGroup.dispose();
+            modSpec.modAddButton.dispose();
+            modSpec.modDeleteButton.dispose();
+
+            if ( !modComposite.isDisposed() )
+            {
+                shell.layout( true, true );
+            }
+        }
+    }
+
+
+    /**
+     * Adds a value line to the given modification spec.
+     * 
+     * @param modSpec the modification spec
+     * @param index the index
+     */
+    private void addValueLine( ModSpec modSpec, int index )
+    {
+
+        ValueLine[] valueLines = modSpec.valueLineList.toArray( new ValueLine[modSpec.valueLineList.size()] );
+
+        if ( valueLines.length > 0 )
+        {
+            for ( int i = 0; i < valueLines.length; i++ )
+            {
+                ValueLine oldValueLine = valueLines[i];
+
+                // remember values
+                String oldValue = oldValueLine.valueText.getText();
+
+                // delete old
+                oldValueLine.valueComposite.dispose();
+                modSpec.valueLineList.remove( oldValueLine );
+
+                // add new
+                ValueLine newValueLine = createValueLine( modSpec );
+                modSpec.valueLineList.add( newValueLine );
+
+                // restore value
+                newValueLine.valueText.setText( oldValue );
+
+                // check
+                if ( index == i + 1 )
+                {
+                    ValueLine valueLine = createValueLine( modSpec );
+                    modSpec.valueLineList.add( valueLine );
+                }
+            }
+        }
+        else
+        {
+            ValueLine valueLine = createValueLine( modSpec );
+            modSpec.valueLineList.add( valueLine );
+        }
+
+        shell.layout( true, true );
+    }
+
+
+    /**
+     * Creates the value line.
+     * 
+     * @param modSpec the modification spec
+     * 
+     * @return the value line
+     */
+    private ValueLine createValueLine( final ModSpec modSpec )
+    {
+        final ValueLine valueLine = new ValueLine();
+
+        // text field
+        valueLine.valueComposite = BaseWidgetUtils.createColumnContainer( modSpec.modGroup, 3, 1 );
+        valueLine.valueText = BaseWidgetUtils.createText( valueLine.valueComposite, "", 1 );
+        valueLine.valueText.addModifyListener( this );
+
+        // add button with listener
+        valueLine.valueAddButton = new Button( valueLine.valueComposite, SWT.PUSH );
+        valueLine.valueAddButton.setText( "  +   " );
+        valueLine.valueAddButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                int index = modSpec.valueLineList.size();
+                for ( int i = 0; i < modSpec.valueLineList.size(); i++ )
+                {
+                    ValueLine valueLine = modSpec.valueLineList.get( i );
+                    if ( valueLine.valueAddButton == e.widget )
+                    {
+                        index = i + 1;
+                    }
+                }
+
+                addValueLine( modSpec, index );
+
+                validate();
+            }
+        } );
+
+        // delete button with listener
+        valueLine.valueDeleteButton = new Button( valueLine.valueComposite, SWT.PUSH );
+        valueLine.valueDeleteButton.setText( "  \u2212  " ); // \u2013
+        valueLine.valueDeleteButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                int index = 0;
+                for ( int i = 0; i < modSpec.valueLineList.size(); i++ )
+                {
+                    ValueLine valueLine = modSpec.valueLineList.get( i );
+                    if ( valueLine.valueDeleteButton == e.widget )
+                    {
+                        index = i;
+                    }
+                }
+
+                deleteValueLine( modSpec, index );
+
+                validate();
+            }
+        } );
+
+        return valueLine;
+    }
+
+
+    /**
+     * Delete value line.
+     * 
+     * @param modSpec the mod spec
+     * @param index the index
+     */
+    private void deleteValueLine( ModSpec modSpec, int index )
+    {
+        ValueLine valueLine = ( ValueLine ) modSpec.valueLineList.remove( index );
+        if ( valueLine != null )
+        {
+            valueLine.valueComposite.dispose();
+
+            if ( !modComposite.isDisposed() )
+            {
+                shell.layout( true, true );
+            }
+        }
+    }
+
+
+    /**
+     * Gets the LDIF fragment.
+     * 
+     * @return the LDIF fragment
+     */
+    public String getLdifFragment()
+    {
+
+        StringBuffer sb = new StringBuffer();
+        sb.append( "changetype: modify" ).append( BrowserCoreConstants.LINE_SEPARATOR );
+
+        ModSpec[] modSpecs = ( ModSpec[] ) modSpecList.toArray( new ModSpec[modSpecList.size()] );
+
+        if ( modSpecs.length > 0 )
+        {
+            for ( int i = 0; i < modSpecs.length; i++ )
+            {
+                ModSpec modSpec = modSpecs[i];
+
+                // get values
+                String type = modSpec.modType.getText();
+                String attribute = modSpec.modAttributeCombo.getText();
+                String[] values = new String[modSpec.valueLineList.size()];
+                for ( int k = 0; k < values.length; k++ )
+                {
+                    values[k] = ( ( ValueLine ) modSpec.valueLineList.get( k ) ).valueText.getText();
+                }
+
+                // build ldif
+                sb.append( type ).append( ": " ).append( attribute ).append( BrowserCoreConstants.LINE_SEPARATOR );
+                for ( int k = 0; k < values.length; k++ )
+                {
+                    if ( values[k].length() > 0 )
+                    {
+                        sb.append( attribute ).append( ": " ).append( values[k] ).append(
+                            BrowserCoreConstants.LINE_SEPARATOR );
+                    }
+                }
+                sb.append( "-" ).append( BrowserCoreConstants.LINE_SEPARATOR );
+                // sb.append(BrowserCoreConstants.NEWLINE);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * The Class ModSpec is a wrapper for all input elements
+     * of an modification. It contains a combo for the modify
+     * operation, a combo for the attribute to modify, 
+     * value lines and + and - buttons to add and remove 
+     * other modifications. It looks like this:
+     * <pre>
+     * ----------------------------------
+     * | operation v | attribute type v |--------
+     * ------------------------ --------| + | - |
+     * | value                  | + | - |--------
+     * ----------------------------------
+     * </pre>
+     */
+    private class ModSpec
+    {
+
+        /** The mod group. */
+        private Group modGroup;
+
+        /** The mod type. */
+        private Combo modType;
+
+        /** The modification attribute field. */
+        private DecoratedField modAttributeComboField;
+
+        /** The modification attribute. */
+        private Combo modAttributeCombo;
+
+        /** The modification content proposal adapter */
+        private ContentProposalAdapter modAttributeCPA;
+
+        /** The mod add button. */
+        private Button modAddButton;
+
+        /** The mod delete button. */
+        private Button modDeleteButton;
+
+        /** The value line list. */
+        private ArrayList<ValueLine> valueLineList = new ArrayList<ValueLine>();;
+    }
+
+    /**
+     * The Class ValueLine is a wrapper for all input elements
+     * of an value line. It contains an input field for the value
+     * and + and - buttons to add and remove other value lines. 
+     * It looks like this:
+     * <pre>
+     * -------------------------------------
+     * | value                     | + | - |
+     * -------------------------------------
+     * </pre>
+     */
+    private class ValueLine
+    {
+
+        /** The value composite. */
+        private Composite valueComposite;
+
+        /** The value text. */
+        private Text valueText;
+
+        /** The value add button. */
+        private Button valueAddButton;
+
+        /** The value delete button. */
+        private Button valueDeleteButton;
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/OptionsInput.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/OptionsInput.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/OptionsInput.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/OptionsInput.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,253 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.util.Arrays;
+
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+
+
+/**
+ * The OptionsInput could be used to select one option out of several options.
+ * It consists of two radio buttons. With the first radio button you could 
+ * select the most likely default option. With the second radio button a combo 
+ * is activated where you could select another option from a drop-down list.
+ * <p>
+ * Both, the default option and the options in the drop-down list have a raw
+ * value that is returned by {@link #getRawValue()} and a display value
+ * that is shown to the user. 
+ * <p>
+ * If the initial raw value is equal to the default raw value then the 
+ * default radio is checked and the drop-down list is disabled. Otherwise 
+ * the second radio is checked, the drop-down list is enabled and the
+ * initial value is selected. 
+ * <p>
+ * The OptionsInput is used by {@link TextFormatsPreferencePage}.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class OptionsInput extends BrowserWidget
+{
+
+    /** The option's title */
+    private String title;
+
+    /** The group, only used when asGroup is true */
+    private Group titleGroup;
+
+    /** The default raw value */
+    private String defaultRawValue;
+
+    /** The default display value */
+    private String defaultDisplayValue;
+
+    /** The radio button to select the default value */
+    private Button defaultButton;
+
+    /** The other raw values */
+    private String[] otherRawValues;
+
+    /** The other display values */
+    private String[] otherDisplayValues;
+
+    /** The radio button to select a value from drop-down list */
+    private Button otherButton;
+
+    /** The combo with the other values */
+    private Combo otherCombo;
+
+    /** The initial raw value */
+    private String initialRawValue;
+
+    /** If true the options are aggregated in a group widget */
+    private boolean asGroup;
+
+    /** If true it is possible to enter a custom value into the combo field */
+    private boolean allowCustomInput;
+
+
+    /**
+     * Creates a new instance of OptionsInput.
+     *
+     * @param title the option's title
+     * @param defaultDisplayValue the default display value
+     * @param defaultRawValue the default raw value
+     * @param otherDisplayValues the other display values
+     * @param otherRawValues the other raw vaues
+     * @param initialRawValue the initial raw value
+     * @param asGroup a flag indicating if the options should be 
+     *                aggregated in a group widget
+     * @param allowCustomInput true to make it possible to enter a 
+     *                         custom value into the combo field
+     */
+    public OptionsInput( String title, String defaultDisplayValue, String defaultRawValue, String[] otherDisplayValues,
+        String[] otherRawValues, String initialRawValue, boolean asGroup, boolean allowCustomInput )
+    {
+        super();
+        this.title = title;
+        this.defaultDisplayValue = defaultDisplayValue;
+        this.defaultRawValue = defaultRawValue;
+        this.otherDisplayValues = otherDisplayValues;
+        this.otherRawValues = otherRawValues;
+        this.initialRawValue = initialRawValue;
+        this.asGroup = asGroup;
+        this.allowCustomInput = allowCustomInput;
+    }
+
+
+    /**
+     * Creates the widget.
+     *
+     * @param parent the parent
+     */
+    public void createWidget( Composite parent )
+    {
+
+        Composite composite;
+        if ( asGroup )
+        {
+            titleGroup = BaseWidgetUtils.createGroup( parent, title, 1 );
+            composite = BaseWidgetUtils.createColumnContainer( titleGroup, 1, 1 );
+        }
+        else
+        {
+            composite = parent;
+            Composite labelComposite = BaseWidgetUtils.createColumnContainer( composite, 1, 1 );
+            BaseWidgetUtils.createLabel( labelComposite, title + ":", 1 );
+        }
+
+        Composite defaultComposite = BaseWidgetUtils.createColumnContainer( composite, 1, 1 );
+        defaultButton = BaseWidgetUtils.createRadiobutton( defaultComposite, defaultDisplayValue, 1 );
+        defaultButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                otherButton.setSelection( false );
+                otherCombo.setEnabled( false );
+                notifyListeners();
+            }
+        } );
+
+        Composite otherComposite = BaseWidgetUtils.createColumnContainer( composite, 2, 1 );
+        otherButton = BaseWidgetUtils.createRadiobutton( otherComposite, "Other: ", 1 );
+        otherButton.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                defaultButton.setSelection( false );
+                otherCombo.setEnabled( true );
+                notifyListeners();
+            }
+        } );
+
+        if ( allowCustomInput )
+        {
+            otherCombo = BaseWidgetUtils.createCombo( otherComposite, otherDisplayValues, 0, 1 );
+        }
+        else
+        {
+            otherCombo = BaseWidgetUtils.createReadonlyCombo( otherComposite, otherDisplayValues, 0, 1 );
+        }
+        otherCombo.addModifyListener( new ModifyListener()
+        {
+            public void modifyText( ModifyEvent e )
+            {
+                notifyListeners();
+            }
+        } );
+
+        setRawValue( initialRawValue );
+    }
+
+
+    /**
+     * Gets the raw value. Either the default value or
+     * the selected value from the combo.
+     *
+     * @return the raw value
+     */
+    public String getRawValue()
+    {
+        if ( defaultButton.getSelection() )
+        {
+            return defaultRawValue;
+        }
+        else
+        {
+            String t = otherCombo.getText();
+            for ( int i = 0; i < otherDisplayValues.length; i++ )
+            {
+                if ( t.equals( otherDisplayValues[i] ) )
+                {
+                    return otherRawValues[i];
+                }
+            }
+            return t;
+        }
+    }
+
+
+    /**
+     * Sets the raw value.
+     *
+     * @param rawValue the raw value
+     */
+    public void setRawValue( String rawValue )
+    {
+        int index = Arrays.asList( otherRawValues ).indexOf( rawValue );
+        if ( index == -1 )
+        {
+            index = Arrays.asList( otherDisplayValues ).indexOf( rawValue );
+        }
+
+        if ( defaultRawValue.equals( rawValue ) )
+        {
+            defaultButton.setSelection( true );
+            otherButton.setSelection( false );
+            otherCombo.setEnabled( false );
+            otherCombo.select( index );
+        }
+        else if ( index > -1 )
+        {
+            defaultButton.setSelection( false );
+            otherButton.setSelection( true );
+            otherCombo.setEnabled( true );
+            otherCombo.select( index );
+        }
+        else
+        {
+            defaultButton.setSelection( false );
+            otherButton.setSelection( true );
+            otherCombo.setEnabled( true );
+            otherCombo.setText( rawValue );
+        }
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ViewFormWidget.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ViewFormWidget.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ViewFormWidget.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/ViewFormWidget.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,256 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import org.apache.directory.ldapstudio.browser.common.BrowserCommonActivator;
+import org.apache.directory.ldapstudio.browser.common.BrowserCommonConstants;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ViewForm;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+
+/**
+ * The ViewFormWidget is a widget that provides an info text,
+ * a tool bar, a menu and a main content composite including
+ * a context menu. 
+ * It looks like this:
+ * <pre>
+ * -----------------------------------
+ * | info text     | tool bar | menu |
+ * -----------------------------------
+ * |                                 |
+ * |          main content           |
+ * |                                 |
+ * -----------------------------------
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public abstract class ViewFormWidget
+{
+
+    /** The view form control */
+    protected ViewForm control;
+
+    /** The info text, positioned at the top left */
+    protected Text infoText;
+
+    /** The action tool bar */
+    protected ToolBar actionToolBar;
+
+    /** The action tool bar manager */
+    protected IToolBarManager actionToolBarManager;
+
+    /** The menu tool bar. */
+    protected ToolBar menuToolBar;
+
+    /** The menu manager. */
+    protected MenuManager menuManager;
+
+    /** The context menu manager. */
+    protected MenuManager contextMenuManager;
+
+
+    /**
+     * Creates the widget.
+     *
+     * @param parent the parent composite
+     */
+    public void createWidget( Composite parent )
+    {
+
+        control = new ViewForm( parent, SWT.NONE );
+        // control.marginWidth = 0;
+        // control.marginHeight = 0;
+        // control.horizontalSpacing = 0;
+        // control.verticalSpacing = 0;
+        control.setLayoutData( new GridData( GridData.FILL_BOTH ) );
+
+        // infoText = BaseWidgetUtils.createLabeledText(control, "", 1);
+        Composite infoTextControl = BaseWidgetUtils.createColumnContainer( control, 1, 1 );
+        infoTextControl.setLayoutData( new GridData( GridData.FILL_BOTH ) );
+        infoText = BaseWidgetUtils.createLabeledText( infoTextControl, "", 1 );
+        infoText.setLayoutData( new GridData( SWT.FILL, SWT.CENTER, true, true ) );
+        control.setTopLeft( infoTextControl );
+
+        // tool bar
+        actionToolBar = new ToolBar( control, SWT.FLAT | SWT.RIGHT );
+        actionToolBar.setLayoutData( new GridData( SWT.END, SWT.NONE, true, false ) );
+        actionToolBarManager = new ToolBarManager( actionToolBar );
+        control.setTopCenter( actionToolBar );
+
+        // local menu
+        this.menuManager = new MenuManager();
+        menuToolBar = new ToolBar( control, SWT.FLAT | SWT.RIGHT );
+        ToolItem ti = new ToolItem( menuToolBar, SWT.PUSH, 0 );
+        ti.setImage( BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_PULLDOWN ) );
+        ti.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                showViewMenu();
+            }
+        } );
+        control.setTopRight( menuToolBar );
+
+        // content
+        Composite composite = BaseWidgetUtils.createColumnContainer( control, 1, 1 );
+        GridLayout gl = new GridLayout();
+        gl.horizontalSpacing = 0;
+        gl.verticalSpacing = 0;
+        gl.marginHeight = 0;
+        gl.marginWidth = 0;
+        composite.setLayout( gl );
+        Control childControl = this.createContent( composite );
+        control.setContent( composite );
+
+        // context menu
+        this.contextMenuManager = new MenuManager();
+        Menu menu = this.contextMenuManager.createContextMenu( childControl );
+        childControl.setMenu( menu );
+    }
+
+
+    /**
+     * Creates the content.
+     * 
+     * @param control the control
+     * 
+     * @return the control
+     */
+    protected abstract Control createContent( Composite control );
+
+
+    /**
+     * Shows the local view menu.
+     */
+    private void showViewMenu()
+    {
+        Menu aMenu = menuManager.createContextMenu( control );
+        Point topLeft = new Point( 0, 0 );
+        topLeft.y += menuToolBar.getBounds().height;
+        topLeft = menuToolBar.toDisplay( topLeft );
+        aMenu.setLocation( topLeft.x, topLeft.y );
+        aMenu.setVisible( true );
+    }
+
+
+    /**
+     * Disposes this widget.
+     */
+    public void dispose()
+    {
+        if ( control != null )
+        {
+
+            if ( contextMenuManager != null )
+            {
+                contextMenuManager.removeAll();
+                contextMenuManager.dispose();
+                contextMenuManager = null;
+            }
+            if ( menuToolBar != null )
+            {
+                menuToolBar.dispose();
+                menuToolBar = null;
+                menuManager.dispose();
+                menuManager = null;
+            }
+            if ( actionToolBar != null )
+            {
+                actionToolBar.dispose();
+                actionToolBar = null;
+                actionToolBarManager.removeAll();
+                actionToolBarManager = null;
+            }
+
+            if ( infoText != null )
+            {
+                infoText.dispose();
+                infoText = null;
+            }
+
+            control.dispose();
+            control = null;
+        }
+    }
+
+
+    /**
+     * Gets the info text.
+     * 
+     * @return the info text
+     */
+    public Text getInfoText()
+    {
+        return infoText;
+    }
+
+
+    /**
+     * Gets the tool bar manager.
+     * 
+     * @return the tool bar manager
+     */
+    public IToolBarManager getToolBarManager()
+    {
+        return this.actionToolBarManager;
+    }
+
+
+    /**
+     * Gets the menu manager.
+     * 
+     * @return the menu manager
+     */
+    public IMenuManager getMenuManager()
+    {
+        return menuManager;
+    }
+
+
+    /**
+     * Gets the context menu manager.
+     * 
+     * @return the context menu manager
+     */
+    public IMenuManager getContextMenuManager()
+    {
+        return this.contextMenuManager;
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/WidgetModifyEvent.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/WidgetModifyEvent.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/WidgetModifyEvent.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/WidgetModifyEvent.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+import java.util.EventObject;
+
+
+/**
+ * A WidgetModifyEvent indicates that a {@link BrowserWidget} has
+ * been modified.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class WidgetModifyEvent extends EventObject
+{
+
+    /** The serialVersionUID */
+    private static final long serialVersionUID = 2421335730580648878L;
+
+
+    /**
+     * Creates a new instance of WidgetModifyEvent.
+     *
+     * @param source the event source
+     */
+    public WidgetModifyEvent( Object source )
+    {
+        super( source );
+
+    }
+
+}

Added: directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/WidgetModifyListener.java
URL: http://svn.apache.org/viewvc/directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/WidgetModifyListener.java?view=auto&rev=526693
==============================================================================
--- directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/WidgetModifyListener.java (added)
+++ directory/ldapstudio/trunk/ldapstudio-browser-common/src/main/java/org/apache/directory/ldapstudio/browser/common/widgets/WidgetModifyListener.java Mon Apr  9 02:49:48 2007
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.directory.ldapstudio.browser.common.widgets;
+
+
+/**
+ * A WidgetModifyListener listens for modifications of a
+ * {@link BrowserWidget}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public interface WidgetModifyListener
+{
+
+    /**
+     * Notified about the modification of a {@link BrowserWidget}.
+     * 
+     * @param event the event
+     */
+    public void widgetModified( WidgetModifyEvent event );
+
+}