You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2015/03/27 16:27:30 UTC

svn commit: r1669604 [5/14] - in /directory/studio/trunk/plugins/templateeditor: ./ 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/directory/ src/main...

Added: directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/messages_fr.properties
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/messages_fr.properties?rev=1669604&view=auto
==============================================================================
--- directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/messages_fr.properties (added)
+++ directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/messages_fr.properties Fri Mar 27 15:27:27 2015
@@ -0,0 +1,28 @@
+# 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.
+LdifEditorPage.LDIFEditor=Editeur LDIF
+
+TableEditorPage.TableEditor=Editeur Tabulaire
+
+TableEditorPageActionGroup.Advanced=Avanc\u00E9
+TableEditorPageActionGroup.OpenSchemaBrowser=Ouvrir le navigateur de sch\u00E9ma
+TableEditorPageActionGroup.ShowIn=Afficher dans
+
+TemplateEditorWidget.NoEntrySelected=Aucune entr\u00E9e s\u00E9lectionn\u00E9e
+TemplateEditorWidget.NoTemplateIsMatchingThisEntry=Aucun mod\u00E8le ne correspond \u00E0 cette entr\u00E9e
+TemplateEditorWidget.TemplateEditor=Editeur Format\u00E9
+TemplateEditorWidget.UnableToDisplayTheEntry=Impossible d''afficher l''entr\u00E9e
\ No newline at end of file

Added: directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorCheckbox.java
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorCheckbox.java?rev=1669604&view=auto
==============================================================================
--- directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorCheckbox.java (added)
+++ directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorCheckbox.java Fri Mar 27 15:27:27 2015
@@ -0,0 +1,361 @@
+/*
+ *  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.studio.templateeditor.editor.widgets;
+
+
+import org.apache.directory.studio.entryeditors.IEntryEditor;
+import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import org.apache.directory.studio.templateeditor.model.widgets.TemplateCheckbox;
+
+
+/**
+ * This class implements an editor checkbox.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EditorCheckbox extends EditorWidget<TemplateCheckbox>
+{
+    /** The checkbox */
+    private Button checkbox;
+
+    /** The enum used to determine the state of a checkbox*/
+    private enum CheckboxState
+    {
+        UNCHECKED, CHECKED, GRAYED
+    }
+
+    /** Constant for the 'false' string value */
+    private static final String FALSE_STRING_VALUE = "FALSE"; //$NON-NLS-1$
+
+    /** Constant for the 'true' string value */
+    private static final String TRUE_STRING_VALUE = "TRUE"; //$NON-NLS-1$
+
+    /** The current state of the checkbox */
+    private CheckboxState currentState = CheckboxState.UNCHECKED;
+
+    /** The selection listener */
+    private SelectionListener selectionListener = new SelectionAdapter()
+    {
+        public void widgetSelected( SelectionEvent e )
+        {
+            // Changing the state of the checkbox
+            changeCheckboxState();
+
+            // Getting the value
+            boolean value = checkbox.getSelection();
+
+            IAttribute attribute = getAttribute();
+            String checkedValue = getWidget().getCheckedValue();
+            String uncheckedValue = getWidget().getUncheckedValue();
+            if ( attribute == null )
+            {
+                // The attribute does not exist
+
+                if ( ( checkedValue == null ) && ( uncheckedValue == null ) )
+                {
+                    // Creating a new attribute with the value
+                    addNewAttribute( ( value ? TRUE_STRING_VALUE : FALSE_STRING_VALUE ) );
+                }
+                else if ( ( checkedValue != null ) && ( uncheckedValue == null ) && value )
+                {
+                    // Creating a new attribute with the value
+                    addNewAttribute( checkedValue );
+                }
+                else if ( ( checkedValue == null ) && ( uncheckedValue != null ) && !value )
+                {
+                    // Creating a new attribute with the value
+                    addNewAttribute( uncheckedValue );
+                }
+                else if ( ( checkedValue != null ) && ( uncheckedValue != null ) )
+                {
+                    // Creating a new attribute with the value
+                    addNewAttribute( ( value ? checkedValue : uncheckedValue ) );
+                }
+            }
+            else
+            {
+                // The attribute exists
+
+                if ( ( checkedValue == null ) && ( uncheckedValue == null ) )
+                {
+                    // Modifying the attribute
+                    modifyAttributeValue( ( value ? TRUE_STRING_VALUE : FALSE_STRING_VALUE ) );
+                }
+                else if ( ( checkedValue != null ) && ( uncheckedValue == null ) )
+                {
+                    if ( value )
+                    {
+                        // Modifying the attribute
+                        modifyAttributeValue( checkedValue );
+                    }
+                    else
+                    {
+                        // Deleting the attribute
+                        deleteAttribute();
+                    }
+                }
+                else if ( ( checkedValue == null ) && ( uncheckedValue != null ) )
+                {
+                    if ( value )
+                    {
+                        // Deleting the attribute
+                    }
+                    else
+                    {
+                        // Modifying the attribute
+                        modifyAttributeValue( uncheckedValue );
+                    }
+                }
+                else if ( ( checkedValue != null ) && ( uncheckedValue != null ) )
+                {
+                    // Modifying the attribute
+                    modifyAttributeValue( ( value ? checkedValue : uncheckedValue ) );
+                }
+            }
+        }
+    };
+
+
+    /**
+     * Creates a new instance of EditorCheckbox.
+     * 
+     * @param editor
+     *      the associated editor
+     * @param templateCheckbox
+     *      the associated template checkbox
+     * @param toolkit
+     *      the associated toolkit
+     */
+    public EditorCheckbox( IEntryEditor editor, TemplateCheckbox templateCheckbox, FormToolkit toolkit  )
+    {
+        super( templateCheckbox, editor, toolkit );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Composite createWidget( Composite parent )
+    {
+        // Creating and initializing the widget UI
+        Composite composite = initWidget( parent );
+
+        // Updating the widget's content
+        updateWidget();
+
+        // Adding the listeners
+        addListeners();
+
+        return composite;
+    }
+
+
+    /**
+     * Creates and initializes the widget UI.
+     *
+     * @param parent
+     *      the parent composite
+     * @return
+     *      the associated composite
+     */
+    private Composite initWidget( Composite parent )
+    {
+        // Creating the checkbox
+        checkbox = getToolkit().createButton( parent, getWidget().getLabel(), SWT.CHECK );
+        checkbox.setLayoutData( getGridata() );
+        checkbox.setEnabled( getWidget().isEnabled() );
+
+        return parent;
+    }
+
+
+    /**
+     * Updates the widget's content.
+     */
+    private void updateWidget()
+    {
+        IAttribute attribute = getAttribute();
+        if ( ( attribute != null ) && ( attribute.isString() ) && ( attribute.getValueSize() > 0 ) )
+        {
+            setCheckboxState( attribute.getStringValue() );
+        }
+    }
+
+
+    /**
+     * Sets the state of the checkbox.
+     *
+     * @param value
+     *      the value
+     */
+    private void setCheckboxState( String value )
+    {
+        String checkedValue = getWidget().getCheckedValue();
+        String uncheckedValue = getWidget().getUncheckedValue();
+
+        if ( ( checkedValue == null ) && ( uncheckedValue == null ) )
+        {
+            if ( TRUE_STRING_VALUE.equalsIgnoreCase( value ) )
+            {
+                setCheckboxCheckedState();
+            }
+            else if ( FALSE_STRING_VALUE.equalsIgnoreCase( value ) )
+            {
+                setCheckboxUncheckedState();
+            }
+            else
+            {
+                setCheckboxGrayedState();
+            }
+        }
+        else if ( ( checkedValue != null ) && ( uncheckedValue == null ) )
+        {
+            if ( checkedValue.equals( value ) )
+            {
+                setCheckboxCheckedState();
+            }
+            else
+            {
+                setCheckboxUncheckedState();
+            }
+        }
+        else if ( ( checkedValue == null ) && ( uncheckedValue != null ) )
+        {
+            if ( uncheckedValue.equals( value ) )
+            {
+                setCheckboxUncheckedState();
+            }
+            else
+            {
+                setCheckboxCheckedState();
+            }
+        }
+        else if ( ( checkedValue != null ) && ( uncheckedValue != null ) )
+        {
+            if ( checkedValue.equals( value ) )
+            {
+                setCheckboxCheckedState();
+            }
+            else if ( uncheckedValue.equals( value ) )
+            {
+                setCheckboxUncheckedState();
+            }
+            else
+            {
+                setCheckboxGrayedState();
+            }
+        }
+    }
+
+
+    /**
+     * Sets the checkbox in checked state.
+     */
+    private void setCheckboxCheckedState()
+    {
+        checkbox.setGrayed( false );
+        checkbox.setSelection( true );
+        currentState = CheckboxState.CHECKED;
+    }
+
+
+    /**
+     * Sets the checkbox in unchecked state.
+     *
+     */
+    private void setCheckboxUncheckedState()
+    {
+        checkbox.setGrayed( false );
+        checkbox.setSelection( false );
+        currentState = CheckboxState.UNCHECKED;
+    }
+
+
+    /**
+     * Sets the checkbox in grayed state.
+     */
+    private void setCheckboxGrayedState()
+    {
+        checkbox.setGrayed( true );
+        checkbox.setSelection( true );
+        currentState = CheckboxState.GRAYED;
+    }
+
+
+    /**
+     * Adds the listeners.
+     */
+    private void addListeners()
+    {
+        if ( ( checkbox != null ) && ( !checkbox.isDisposed() ) )
+        {
+            checkbox.addSelectionListener( selectionListener );
+        }
+    }
+
+
+    /**
+     * Changes the state of the checkbox.
+     */
+    private void changeCheckboxState()
+    {
+        switch ( currentState )
+        {
+            case UNCHECKED:
+                setCheckboxCheckedState();
+                currentState = CheckboxState.CHECKED;
+                break;
+            case CHECKED:
+                setCheckboxUncheckedState();
+                currentState = CheckboxState.UNCHECKED;
+                break;
+            case GRAYED:
+                setCheckboxCheckedState();
+                currentState = CheckboxState.CHECKED;
+                break;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void update()
+    {
+        updateWidget();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void dispose()
+    {
+        // Nothing to do
+    }
+}
\ No newline at end of file

Added: directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorComposite.java
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorComposite.java?rev=1669604&view=auto
==============================================================================
--- directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorComposite.java (added)
+++ directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorComposite.java Fri Mar 27 15:27:27 2015
@@ -0,0 +1,83 @@
+/*
+ *  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.studio.templateeditor.editor.widgets;
+
+
+import org.apache.directory.studio.entryeditors.IEntryEditor;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import org.apache.directory.studio.templateeditor.model.widgets.TemplateComposite;
+
+
+/**
+ * This class implements an editor composite.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EditorComposite extends EditorWidget<TemplateComposite>
+{
+    /**
+     * Creates a new instance of EditorComposite.
+     * 
+     * @param editor
+     *      the associated editor
+     * @param templateComposite
+     *      the associated template composite
+     * @param toolkit
+     *      the associated toolkit
+     */
+    public EditorComposite( IEntryEditor editor, TemplateComposite templateComposite, FormToolkit toolkit )
+    {
+        super( templateComposite, editor, toolkit );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Composite createWidget( Composite parent )
+    {
+        Composite composite = getToolkit().createComposite( parent );
+        composite.setLayout( new GridLayout( getWidget().getNumberOfColumns(), getWidget().isEqualColumns() ) );
+        composite.setLayoutData( getGridata() );
+
+        return composite;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void update()
+    {
+        // Nothing to do
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void dispose()
+    {
+        // Nothing to do
+    }
+}
\ No newline at end of file

Added: directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorDate.java
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorDate.java?rev=1669604&view=auto
==============================================================================
--- directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorDate.java (added)
+++ directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorDate.java Fri Mar 27 15:27:27 2015
@@ -0,0 +1,284 @@
+/*
+ *  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.studio.templateeditor.editor.widgets;
+
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.directory.api.util.GeneralizedTime;
+import org.apache.directory.studio.entryeditors.IEntryEditor;
+import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
+import org.apache.directory.studio.valueeditors.time.GeneralizedTimeValueDialog;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import org.apache.directory.studio.templateeditor.EntryTemplatePlugin;
+import org.apache.directory.studio.templateeditor.EntryTemplatePluginConstants;
+import org.apache.directory.studio.templateeditor.model.widgets.TemplateDate;
+
+
+/**
+ * This class implements an editor date.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EditorDate extends EditorWidget<TemplateDate>
+{
+    /** The main composite */
+    private Composite composite;
+
+    /** The date text widget */
+    private Text dateText;
+
+    /** The 'Browse...' toolbar item */
+    private ToolItem editToolItem;
+
+
+    /**
+     * Creates a new instance of EditorLabel.
+     * 
+     * @param editor
+     *      the associated editor
+     * @param templateDate
+     *      the associated template label
+     * @param toolkit
+     *      the associated toolkit
+     */
+    public EditorDate( IEntryEditor editor, TemplateDate templateDate, FormToolkit toolkit )
+    {
+        super( templateDate, editor, toolkit );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Composite createWidget( Composite parent )
+    {
+        // Creating and initializing the widget UI
+        Composite composite = initWidget( parent );
+
+        // Updating the widget's content
+        updateWidget();
+
+        // Adding the listeners
+        addListeners();
+
+        return composite;
+    }
+
+
+    /**
+     * Creates and initializes the widget UI.
+     *
+     * @param parent
+     *      the parent composite
+     * @return
+     *      the associated composite
+     */
+    private Composite initWidget( Composite parent )
+    {
+        // Creating the widget composite
+        composite = getToolkit().createComposite( parent );
+        composite.setLayoutData( getGridata() );
+
+        // Calculating the number of columns needed
+        int numberOfColumns = 1;
+        if ( getWidget().isShowEditButton() )
+        {
+            numberOfColumns++;
+        }
+
+        // Creating the layout
+        GridLayout gl = new GridLayout( numberOfColumns, false );
+        gl.marginHeight = gl.marginWidth = 0;
+        gl.horizontalSpacing = gl.verticalSpacing = 0;
+        composite.setLayout( gl );
+
+        // Creating the label
+        dateText = new Text( composite, SWT.NONE );
+        dateText.setEditable( false );
+        dateText.setBackground( composite.getBackground() );
+        dateText.setLayoutData( new GridData( SWT.FILL, SWT.CENTER, false, false ) );
+
+        // Creating the edit password button
+        if ( getWidget().isShowEditButton() )
+        {
+            ToolBar toolbar = new ToolBar( composite, SWT.HORIZONTAL | SWT.FLAT );
+
+            editToolItem = new ToolItem( toolbar, SWT.PUSH );
+            editToolItem.setToolTipText( Messages.getString( "EditorDate.EditDate" ) ); //$NON-NLS-1$
+            editToolItem.setImage( EntryTemplatePlugin.getDefault().getImage(
+                EntryTemplatePluginConstants.IMG_TOOLBAR_EDIT_DATE ) );
+        }
+
+        return parent;
+    }
+
+
+    /**
+     * Converts the given GeneralizedTime string representation of the date into 
+     * the desired string format.
+     *
+     * @param dateString
+     *      the GeneralizedTime string representation of the date
+     * @return
+     *      the given date in the desired string format
+     */
+    private String convertDate( String dateString )
+    {
+        try
+        {
+            // Creating a date
+            Date date = ( new GeneralizedTime( dateString ) ).getCalendar().getTime();
+
+            // Setting a default formatter
+            SimpleDateFormat formatter = new SimpleDateFormat();
+
+            // Getting the format defined in the template
+            String format = getWidget().getFormat();
+            if ( ( format != null ) && ( !format.equalsIgnoreCase( "" ) ) ) //$NON-NLS-1$
+            {
+                // Setting a custom formatter
+                formatter = new SimpleDateFormat( format );
+            }
+
+            // Returning the formatted date
+            return formatter.format( date );
+        }
+        catch ( ParseException pe )
+        {
+            // Returning the original value in that case
+            return dateString;
+        }
+    }
+
+
+    /**
+     * Adds the listeners.
+     */
+    private void addListeners()
+    {
+        // Edit toolbar item
+        if ( ( editToolItem != null ) && ( !editToolItem.isDisposed() ) )
+        {
+            editToolItem.addSelectionListener( new SelectionAdapter()
+            {
+                public void widgetSelected( SelectionEvent e )
+                {
+                    editToolItemAction();
+                }
+            } );
+        }
+    }
+
+
+    /**
+     * This method is called when the 'Edit...' toolbar item is clicked.
+     */
+    private void editToolItemAction()
+    {
+        // Creating and opening a GeneralizedTimeValueDialog
+        GeneralizedTimeValueDialog dialog = new GeneralizedTimeValueDialog( PlatformUI.getWorkbench()
+            .getActiveWorkbenchWindow().getShell(), getGeneralizedTimeValueFromAttribute() );
+        if ( dialog.open() == Dialog.OK )
+        {
+            // Updating the attribute with the new value
+            updateAttributeValue( dialog.getGeneralizedTime().toGeneralizedTime() );
+        }
+    }
+
+
+    /**
+     * Get the Generalized Time associated from the attribute.
+     *
+     * @return
+     *      the Generalized Time associated from the attribute or <code>null</code>.
+     */
+    private GeneralizedTime getGeneralizedTimeValueFromAttribute()
+    {
+        IAttribute attribute = getAttribute();
+        if ( ( attribute != null ) && ( attribute.isString() ) && ( attribute.getValueSize() > 0 ) )
+        {
+            try
+            {
+                return new GeneralizedTime( attribute.getStringValue() );
+            }
+            catch ( ParseException e )
+            {
+                // Nothing to do, will return null
+            }
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Updates the widget's content.
+     */
+    private void updateWidget()
+    {
+        IAttribute attribute = getAttribute();
+        if ( ( attribute != null ) && ( attribute.isString() ) && ( attribute.getValueSize() > 0 ) )
+        {
+            // Setting the date value
+            dateText.setText( convertDate( attribute.getStringValue() ) );
+        }
+        else
+        {
+            // No value
+            dateText.setText( Messages.getString( "EditorDate.NoValue" ) ); //$NON-NLS-1$
+        }
+
+        // Updating the layout of the composite
+        composite.layout();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void update()
+    {
+        updateWidget();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void dispose()
+    {
+        // Nothing to do
+    }
+}
\ No newline at end of file

Added: directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorFileChooser.java
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorFileChooser.java?rev=1669604&view=auto
==============================================================================
--- directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorFileChooser.java (added)
+++ directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorFileChooser.java Fri Mar 27 15:27:27 2015
@@ -0,0 +1,586 @@
+/*
+ *  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.studio.templateeditor.editor.widgets;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.directory.api.util.Base64;
+import org.apache.directory.studio.entryeditors.IEntryEditor;
+import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import org.apache.directory.studio.templateeditor.EntryTemplatePlugin;
+import org.apache.directory.studio.templateeditor.EntryTemplatePluginConstants;
+import org.apache.directory.studio.templateeditor.EntryTemplatePluginUtils;
+import org.apache.directory.studio.templateeditor.model.widgets.TemplateFileChooser;
+
+
+/**
+ * This class implements an Editor FileChooser.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EditorFileChooser extends EditorWidget<TemplateFileChooser>
+{
+    /** The widget's composite */
+    private Composite composite;
+
+    /** The icon label */
+    private Label iconLabel;
+
+    /** The size label */
+    private Label sizeLabel;
+
+    /** The 'Save As...' toolbar item */
+    private ToolItem saveAsToolItem;
+
+    /** The 'Clear' toolbar item */
+    private ToolItem clearToolItem;
+
+    /** The 'Browse...' toolbar item */
+    private ToolItem browseToolItem;
+
+    /** The file data as bytes array */
+    private byte[] fileBytes;
+
+
+    /**
+     * Creates a new instance of EditorFileChooser.
+     * 
+     * @param editor
+     *      the associated editor
+     * @param templateFileChooser
+     *      the associated template file chooser
+     * @param toolkit
+     *      the associated toolkit
+     */
+    public EditorFileChooser( IEntryEditor editor, TemplateFileChooser templateFileChooser, FormToolkit toolkit )
+    {
+        super( templateFileChooser, editor, toolkit );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Composite createWidget( Composite parent )
+    {
+        // Creating and initializing the widget UI
+        Composite composite = initWidget( parent );
+
+        // Updating the widget's content
+        updateWidget();
+
+        // Adding the listeners
+        addListeners();
+
+        return composite;
+    }
+
+
+    /**
+     * Creates and initializes the widget UI.
+     *
+     * @param parent
+     *      the parent composite
+     * @return
+     *      the associated composite
+     */
+    private Composite initWidget( Composite parent )
+    {
+        composite = getToolkit().createComposite( parent );
+        composite.setLayoutData( getGridata() );
+
+        // Creating the layout
+        GridLayout gl = new GridLayout( getLayoutNumberOfColumns(), false );
+        gl.marginHeight = gl.marginWidth = 0;
+        gl.horizontalSpacing = gl.verticalSpacing = 0;
+        composite.setLayout( gl );
+
+        // Icon Label
+        if ( getWidget().isShowIcon() )
+        {
+            // Creating the label for hosting the icon
+            iconLabel = getToolkit().createLabel( composite, null );
+            iconLabel.setLayoutData( new GridData( SWT.NONE, SWT.CENTER, false, false ) );
+
+            // Getting the icon (if available)
+            ImageData iconData = null;
+            String icon = getWidget().getIcon();
+            if ( ( icon != null ) && ( !icon.equals( "" ) ) ) //$NON-NLS-1$
+            {
+                try
+                {
+                    iconData = new ImageData( new ByteArrayInputStream( Base64.decode( icon.toCharArray() ) ) );
+                }
+                catch ( SWTException e )
+                {
+                    // Nothing to do, we just need to return the default image.
+                }
+            }
+
+            // Assigning the icon
+            if ( iconData != null )
+            {
+                iconLabel.setImage( new Image( PlatformUI.getWorkbench().getDisplay(), iconData ) );
+            }
+            else
+            {
+                iconLabel.setImage( EntryTemplatePlugin.getDefault().getImage( EntryTemplatePluginConstants.IMG_FILE ) );
+            }
+        }
+
+        // Size Label
+        sizeLabel = getToolkit().createLabel( composite, null );
+        sizeLabel.setLayoutData( new GridData( SWT.NONE, SWT.CENTER, true, false ) );
+
+        // Toolbar (if needed)
+        if ( needsToolbar() )
+        {
+            ToolBar toolbar = new ToolBar( composite, SWT.HORIZONTAL | SWT.FLAT );
+            toolbar.setLayoutData( new GridData( SWT.NONE, SWT.CENTER, false, false ) );
+
+            // Save As Button
+            if ( getWidget().isShowSaveAsButton() )
+            {
+                saveAsToolItem = new ToolItem( toolbar, SWT.PUSH );
+                saveAsToolItem.setToolTipText( Messages.getString( "EditorFileChooser.SaveAs" ) ); //$NON-NLS-1$
+                saveAsToolItem.setImage( EntryTemplatePlugin.getDefault().getImage(
+                    EntryTemplatePluginConstants.IMG_TOOLBAR_SAVE_AS ) );
+            }
+
+            // Clear Button
+            if ( getWidget().isShowClearButton() )
+            {
+                clearToolItem = new ToolItem( toolbar, SWT.PUSH );
+                clearToolItem.setToolTipText( Messages.getString( "EditorFileChooser.Clear" ) ); //$NON-NLS-1$
+                clearToolItem.setImage( EntryTemplatePlugin.getDefault().getImage(
+                    EntryTemplatePluginConstants.IMG_TOOLBAR_CLEAR ) );
+            }
+            // Browse Button
+            if ( getWidget().isShowBrowseButton() )
+            {
+                browseToolItem = new ToolItem( toolbar, SWT.PUSH );
+                browseToolItem.setToolTipText( Messages.getString( "EditorFileChooser.Browse" ) ); //$NON-NLS-1$
+                browseToolItem.setImage( EntryTemplatePlugin.getDefault().getImage(
+                    EntryTemplatePluginConstants.IMG_TOOLBAR_BROWSE_FILE ) );
+            }
+        }
+
+        return composite;
+    }
+
+
+    /**
+     * Gets the number of columns needed for the layout.
+     *
+     * @return
+     *      the number of columns needed
+     */
+    private int getLayoutNumberOfColumns()
+    {
+        int numberOfColumns = 1;
+
+        // Icon
+        if ( getWidget().isShowIcon() )
+        {
+            numberOfColumns++;
+        }
+        // Toolbar
+        if ( needsToolbar() )
+        {
+            numberOfColumns++;
+        }
+
+        return numberOfColumns;
+    }
+
+
+    /**
+     * Indicates if the widget needs a toolbar for actions.
+     *
+     * @return
+     *      <code>true</code> if the widget needs a toolbar for actions,
+     *      <code>false</code> if not
+     */
+    private boolean needsToolbar()
+    {
+        return getWidget().isShowSaveAsButton() || getWidget().isShowClearButton() || getWidget().isShowBrowseButton();
+    }
+
+
+    /**
+     * Updates the widget's content.
+     */
+    private void updateWidget()
+    {
+        // Initializing the image bytes from the given entry.
+        initImageBytesFromEntry();
+
+        // Updating the file label
+        updateSizeLabel();
+
+        // Updating the states of the buttons
+        updateButtonsStates();
+    }
+
+
+    /**
+     * Initializes the image bytes from the given entry.
+     */
+    private void initImageBytesFromEntry()
+    {
+        // Getting the file bytes in the attribute
+        IAttribute attribute = getAttribute();
+        if ( ( attribute != null ) && ( attribute.isBinary() ) && ( attribute.getValueSize() > 0 ) )
+        {
+            fileBytes = attribute.getBinaryValues()[0];
+            return;
+        }
+
+        fileBytes = null;
+    }
+
+
+    /**
+     * Updates the "Size" label.
+     */
+    private void updateSizeLabel()
+    {
+        sizeLabel.setText( getFileSizeString() );
+        sizeLabel.update();
+    }
+
+
+    /**
+     * Adds the listeners.
+     */
+    private void addListeners()
+    {
+        // Save As toolbar item
+        if ( ( saveAsToolItem != null ) && ( !saveAsToolItem.isDisposed() ) )
+        {
+            saveAsToolItem.addSelectionListener( new SelectionAdapter()
+            {
+                public void widgetSelected( SelectionEvent e )
+                {
+                    saveAsToolItemAction();
+                }
+            } );
+        }
+
+        // Clear toolbar item
+        if ( ( clearToolItem != null ) && ( !clearToolItem.isDisposed() ) )
+        {
+            clearToolItem.addSelectionListener( new SelectionAdapter()
+            {
+                public void widgetSelected( SelectionEvent e )
+                {
+                    clearToolItemAction();
+                }
+            } );
+        }
+
+        // Browse toolbar item
+        if ( ( browseToolItem != null ) && ( !browseToolItem.isDisposed() ) )
+        {
+            browseToolItem.addSelectionListener( new SelectionAdapter()
+            {
+                public void widgetSelected( SelectionEvent e )
+                {
+                    browseToolItemAction();
+                }
+            } );
+        }
+    }
+
+
+    /**
+     * Gets the size string.
+     * 
+     * @return the size string
+     */
+    private String getFileSizeString()
+    {
+        if ( fileBytes != null )
+        {
+            int length = fileBytes.length;
+            if ( length > 1000000 )
+            {
+                return NLS.bind( Messages.getString( "EditorFileChooser.MB" ), new Object[] //$NON-NLS-1$
+                    { ( length / 1000000 ), length } );
+            }
+            else if ( length > 1000 )
+            {
+                return NLS.bind( Messages.getString( "EditorFileChooser.KB" ), new Object[] //$NON-NLS-1$
+                    { ( length / 1000 ), length } );
+            }
+            else
+            {
+                return NLS.bind( Messages.getString( "EditorFileChooser.Bytes" ), new Object[] //$NON-NLS-1$
+                    { length } );
+            }
+        }
+        else
+        {
+            return Messages.getString( "EditorFileChooser.NoValue" ); //$NON-NLS-1$
+        }
+    }
+
+
+    /**
+     * This method is called when the 'Save As...' toolbar item is clicked.
+     */
+    private void saveAsToolItemAction()
+    {
+        // Launching a FileDialog to select where to save the file
+        FileDialog fd = new FileDialog( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.SAVE );
+        String selected = fd.open();
+        if ( selected != null )
+        {
+            // Getting the selected file
+            File selectedFile = new File( selected );
+            if ( ( !selectedFile.exists() ) || ( selectedFile.canWrite() ) )
+            {
+                try
+                {
+                    FileOutputStream fos = new FileOutputStream( selectedFile );
+                    fos.write( fileBytes );
+                    fos.close();
+                }
+                catch ( Exception e )
+                {
+                    // Logging the error
+                    EntryTemplatePluginUtils.logError( e, "An error occurred while saving the file to disk.", //$NON-NLS-1$
+                        new Object[0] );
+
+                    // Launching an error dialog
+                    MessageDialog
+                        .openError(
+                            PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                            Messages.getString( "EditorFileChooser.ErrorSavingMessageDialogTitle" ), Messages.getString( "EditorFileChooser.ErrorSavingMessageDialogMessage" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+                }
+            }
+        }
+    }
+
+
+    /**
+     * This method is called when the 'Clear...' toolbar item is clicked.
+     */
+    private void clearToolItemAction()
+    {
+        // Launching a confirmation dialog
+        if ( MessageDialog.openConfirm( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), Messages
+            .getString( "EditorFileChooser.Confirmation" ), Messages //$NON-NLS-1$
+            .getString( "EditorFileChooser.ConfirmationClearFile" ) ) ) //$NON-NLS-1$
+        {
+            // Removing the file bytes
+            fileBytes = null;
+
+            // Refreshing the states of the buttons
+            updateButtonsStates();
+
+            // Updating the size label
+            updateSizeLabel();
+
+            // Updating the entry
+            updateEntry();
+        }
+    }
+
+
+    /**
+     * This method is called when the 'Browse...' toolbar item is clicked.
+     */
+    private void browseToolItemAction()
+    {
+        // Launching a FileDialog to select the file to load
+        FileDialog fd = new FileDialog( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN );
+        String selected = fd.open();
+        if ( selected != null )
+        {
+            // Getting the selected file
+            File selectedFile = new File( selected );
+            if ( ( selectedFile.exists() ) && ( selectedFile.canRead() ) )
+            {
+                try
+                {
+                    FileInputStream fis = new FileInputStream( selectedFile );
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream( ( int ) selectedFile.length() );
+                    byte[] buf = new byte[4096];
+                    int len;
+                    while ( ( len = fis.read( buf ) ) > 0 )
+                    {
+                        baos.write( buf, 0, len );
+                    }
+
+                    fileBytes = baos.toByteArray();
+                }
+                catch ( Exception e )
+                {
+                    // Logging the error
+                    EntryTemplatePluginUtils.logError( e, "An error occurred while reading the file from disk.", //$NON-NLS-1$
+                        new Object[0] );
+
+                    // Launching an error dialog
+                    MessageDialog
+                        .openError(
+                            PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                            Messages.getString( "EditorFileChooser.ErrorReadingMessageDialogTitle" ), Messages.getString( "EditorFileChooser.ErrorReadingMessageDialogMessage" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+                }
+
+                // Refreshing the states of the buttons
+                updateButtonsStates();
+            }
+            else
+            {
+                // Logging the error
+                EntryTemplatePluginUtils.logError( null,
+                    "An error occurred while reading the file from disk. File does not exist or is not readable.", //$NON-NLS-1$
+                    new Object[0] );
+
+                // Launching an error dialog
+                MessageDialog
+                    .openError(
+                        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                        Messages.getString( "EditorFileChooser.ErrorReadingMessageDialogTitle" ), Messages.getString( "EditorFileChooser.ErrorReadingMessageDialogMessage" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+
+            // Updating the size label
+            updateSizeLabel();
+
+            // Updating the entry
+            updateEntry();
+        }
+    }
+
+
+    /**
+     * This method is called when the entry has been updated in the UI.
+     */
+    private void updateEntry()
+    {
+        // Getting the attribute
+        IAttribute attribute = getAttribute();
+        if ( attribute == null )
+        {
+            if ( ( fileBytes != null ) && ( fileBytes.length != 0 ) )
+            {
+                // Creating a new attribute with the value
+                addNewAttribute( fileBytes );
+            }
+        }
+        else
+        {
+            if ( ( fileBytes != null ) && ( fileBytes.length != 0 ) )
+            {
+                // Modifying the existing attribute
+                modifyAttributeValue( fileBytes );
+            }
+            else
+            {
+                // Deleting the attribute
+                deleteAttribute();
+            }
+        }
+    }
+
+
+    /**
+     * Updates the states of the buttons.
+     */
+    private void updateButtonsStates()
+    {
+        if ( ( fileBytes != null ) && ( fileBytes.length > 0 ) )
+        {
+            if ( ( saveAsToolItem != null ) && ( !saveAsToolItem.isDisposed() ) )
+            {
+                saveAsToolItem.setEnabled( true );
+            }
+
+            if ( ( clearToolItem != null ) && ( !clearToolItem.isDisposed() ) )
+            {
+                clearToolItem.setEnabled( true );
+            }
+
+            if ( ( browseToolItem != null ) && ( !browseToolItem.isDisposed() ) )
+            {
+                browseToolItem.setEnabled( true );
+            }
+        }
+        else
+        {
+            if ( ( saveAsToolItem != null ) && ( !saveAsToolItem.isDisposed() ) )
+            {
+                saveAsToolItem.setEnabled( false );
+            }
+
+            if ( ( clearToolItem != null ) && ( !clearToolItem.isDisposed() ) )
+            {
+                clearToolItem.setEnabled( false );
+            }
+
+            if ( ( browseToolItem != null ) && ( !browseToolItem.isDisposed() ) )
+            {
+                browseToolItem.setEnabled( true );
+            }
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void update()
+    {
+        updateWidget();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void dispose()
+    {
+        // Nothing to do
+    }
+}

Added: directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorImage.java
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorImage.java?rev=1669604&view=auto
==============================================================================
--- directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorImage.java (added)
+++ directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorImage.java Fri Mar 27 15:27:27 2015
@@ -0,0 +1,664 @@
+/*
+ *  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.studio.templateeditor.editor.widgets;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.directory.api.util.Base64;
+import org.apache.directory.studio.entryeditors.IEntryEditor;
+import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import org.apache.directory.studio.templateeditor.EntryTemplatePlugin;
+import org.apache.directory.studio.templateeditor.EntryTemplatePluginConstants;
+import org.apache.directory.studio.templateeditor.EntryTemplatePluginUtils;
+import org.apache.directory.studio.templateeditor.model.widgets.TemplateImage;
+import org.apache.directory.studio.templateeditor.model.widgets.TemplateWidget;
+
+
+/**
+ * This class implements an editor image.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EditorImage extends EditorWidget<TemplateImage>
+{
+    /** The widget's composite */
+    private Composite composite;
+
+    /** The image label, used to display the image */
+    private Label imageLabel;
+
+    /** The 'Save As...' button */
+    private ToolItem saveAsToolItem;
+
+    /** The 'Clear' button */
+    private ToolItem clearToolItem;
+
+    /** The 'Browse...' button */
+    private ToolItem browseToolItem;
+
+    /** The current image */
+    private Image image;
+
+    /** The image data as bytes array */
+    private byte[] imageBytes;
+
+    /** The default width */
+    private static int DEFAULT_WIDTH = 400;
+
+    /** The default height */
+    private static int DEFAULT_HEIGHT = 300;
+
+
+    /**
+     * Creates a new instance of EditorImage.
+     * 
+     * @param editor
+     *      the associated editor
+     * @param templateImage
+     *      the associated template image
+     * @param toolkit
+     *      the associated toolkit
+     */
+    public EditorImage( IEntryEditor editor, TemplateImage templateImage, FormToolkit toolkit )
+    {
+        super( templateImage, editor, toolkit );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Composite createWidget( Composite parent )
+    {
+        // Creating and initializing the widget UI
+        Composite composite = initWidget( parent );
+
+        // Updating the widget's content
+        updateWidget();
+
+        // Adding the listeners
+        addListeners();
+
+        return composite;
+    }
+
+
+    /**
+     * Creates and initializes the widget UI.
+     *
+     * @param parent
+     *      the parent composite
+     * @return
+     *      the associated composite
+     */
+    private Composite initWidget( Composite parent )
+    {
+        // Creating the widget composite
+        composite = getToolkit().createComposite( parent );
+        composite.setLayoutData( getGridata() );
+
+        // Creating the layout
+        GridLayout gl = new GridLayout( ( needsToolbar() ? 2 : 1 ), false );
+        gl.marginHeight = gl.marginWidth = 0;
+        gl.horizontalSpacing = gl.verticalSpacing = 0;
+        composite.setLayout( gl );
+
+        // Image Label
+        imageLabel = getToolkit().createLabel( composite, null );
+        imageLabel.setLayoutData( new GridData( SWT.CENTER, SWT.CENTER, false, false ) );
+
+        // Toolbar (if needed)
+        if ( needsToolbar() )
+        {
+            ToolBar toolbar = new ToolBar( composite, SWT.VERTICAL );
+            toolbar.setLayoutData( new GridData( SWT.NONE, SWT.FILL, false, true ) );
+
+            // Save As Button
+            if ( getWidget().isShowSaveAsButton() )
+            {
+                saveAsToolItem = new ToolItem( toolbar, SWT.PUSH );
+                saveAsToolItem.setToolTipText( Messages.getString( "EditorImage.SaveAs" ) ); //$NON-NLS-1$
+                saveAsToolItem.setImage( EntryTemplatePlugin.getDefault().getImage(
+                    EntryTemplatePluginConstants.IMG_TOOLBAR_SAVE_AS ) );
+            }
+
+            // Clear Button
+            if ( getWidget().isShowClearButton() )
+            {
+                clearToolItem = new ToolItem( toolbar, SWT.PUSH );
+                clearToolItem.setToolTipText( Messages.getString( "EditorImage.Clear" ) ); //$NON-NLS-1$
+                clearToolItem.setImage( EntryTemplatePlugin.getDefault().getImage(
+                    EntryTemplatePluginConstants.IMG_TOOLBAR_CLEAR ) );
+            }
+            // Browse Button
+            if ( getWidget().isShowBrowseButton() )
+            {
+                browseToolItem = new ToolItem( toolbar, SWT.PUSH );
+                browseToolItem.setToolTipText( Messages.getString( "EditorImage.Browse" ) ); //$NON-NLS-1$
+                browseToolItem.setImage( EntryTemplatePlugin.getDefault().getImage(
+                    EntryTemplatePluginConstants.IMG_TOOLBAR_BROWSE_IMAGE ) );
+            }
+        }
+
+        return composite;
+    }
+
+
+    /**
+     * Indicates if the widget needs a toolbar for actions.
+     *
+     * @return
+     *      <code>true</code> if the widget needs a toolbar for actions,
+     *      <code>false</code> if not
+     */
+    private boolean needsToolbar()
+    {
+        return getWidget().isShowSaveAsButton() || getWidget().isShowClearButton() || getWidget().isShowBrowseButton();
+    }
+
+
+    /**
+     * Updates the widget's content.
+     */
+    private void updateWidget()
+    {
+        // Initializing the image bytes from the given entry.
+        initImageBytesFromEntry();
+
+        // Constrains and displays it
+        constrainAndDisplayImage();
+
+        // Updating the states of the buttons
+        updateButtonsStates();
+    }
+
+
+    /**
+     * Initializes the image bytes from the given entry.
+     */
+    private void initImageBytesFromEntry()
+    {
+        // Checking is we need to display a value taken from the entry
+        // or use the given value
+        String attributeType = getWidget().getAttributeType();
+        if ( attributeType != null )
+        {
+            // Getting the image bytes in the attribute
+            IAttribute attribute = getAttribute();
+            if ( ( attribute != null ) && ( attribute.isBinary() ) && ( attribute.getValueSize() > 0 ) )
+            {
+                imageBytes = attribute.getBinaryValues()[0];
+            }
+            else
+            {
+                imageBytes = null;
+            }
+        }
+        else
+        {
+            // Getting the image bytes given in the template
+            String imageDataString = getWidget().getImageData();
+            if ( ( imageDataString != null ) && ( !imageDataString.equals( "" ) ) ) //$NON-NLS-1$
+            {
+                imageBytes = Base64.decode( imageDataString.toCharArray() );
+            }
+        }
+    }
+
+
+    /**
+     * Returns an {@link ImageData} constructed from an array of bytes.
+     *
+     * @param imageBytes
+     *      the array of bytes
+     * @return
+     *      the corresponding {@link ImageData}
+     * @throws SWTException
+     *      if an error occurs when constructing the {@link ImageData}
+     */
+    private ImageData getImageData( byte[] imageBytes ) throws SWTException
+    {
+        if ( imageBytes != null && imageBytes.length > 0 )
+        {
+            return new ImageData( new ByteArrayInputStream( imageBytes ) );
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    /**
+     * Returns the {@link ImageData} associated with the current image bytes.
+     *
+     * @return
+     *      the {@link ImageData} associated with the current image bytes.
+     */
+    private ImageData getImageData()
+    {
+        if ( imageBytes != null )
+        {
+            // Getting the image data associated with the bytes
+            try
+            {
+                return getImageData( imageBytes );
+            }
+            catch ( SWTException e )
+            {
+                // Nothing to do, we just need to return the default image.
+            }
+        }
+
+        // No image
+        return EntryTemplatePlugin.getDefault().getImage( EntryTemplatePluginConstants.IMG_NO_IMAGE ).getImageData();
+    }
+
+
+    /**
+     * Constrains and displays the image.
+     */
+    private void constrainAndDisplayImage()
+    {
+        // Getting the image data
+        ImageData imageData = getImageData();
+
+        // Getting width and height from the template image
+        int templateImageWidth = getWidget().getImageWidth();
+        int templateImageHeight = getWidget().getImageHeight();
+
+        // No resizing is required
+        if ( ( templateImageWidth == TemplateWidget.DEFAULT_SIZE )
+            && ( templateImageHeight == TemplateWidget.DEFAULT_SIZE ) )
+        {
+            // Checking if the dimensions of the image are greater than the default values
+            if ( ( imageData.width > DEFAULT_WIDTH ) || ( imageData.height > DEFAULT_HEIGHT ) )
+            {
+                // Calculating scale factors to determine whether width or height should be used
+                float widthScaleFactor = imageData.width / DEFAULT_WIDTH;
+                float heightScaleFactor = imageData.height / DEFAULT_HEIGHT;
+
+                // Resizing the image data
+                if ( widthScaleFactor >= heightScaleFactor )
+                {
+                    imageData = getScaledImageData( imageData, DEFAULT_WIDTH, TemplateWidget.DEFAULT_SIZE );
+                }
+                else
+                {
+                    imageData = getScaledImageData( imageData, TemplateWidget.DEFAULT_SIZE, DEFAULT_HEIGHT );
+                }
+            }
+        }
+        else
+        {
+            // Resizing the image data
+            imageData = getScaledImageData( imageData, templateImageWidth, templateImageHeight );
+        }
+
+        // Creating the image
+        image = new Image( PlatformUI.getWorkbench().getDisplay(), imageData );
+
+        // Setting the image
+        imageLabel.setImage( image );
+    }
+
+
+    /**
+     * Returns a scaled copy of the given data scaled to the given dimensions, 
+     * or the original image data if scaling is not needed.
+     *
+     * @param imageData
+     *      the image data
+     * @param width
+     *      the preferred width
+     * @param height
+     *      the preferred height
+     * @return
+     *      a scaled copy of the given data scaled to the given dimensions, 
+     *      or the original image data if scaling is not needed.
+     */
+    private ImageData getScaledImageData( ImageData imageData, int width, int height )
+    {
+        // Resizing the image with the given width value
+        if ( ( width != TemplateWidget.DEFAULT_SIZE ) && ( height == TemplateWidget.DEFAULT_SIZE ) )
+        {
+            // Computing the scale factor
+            float scaleFactor = ( float ) imageData.width / ( float ) width;
+
+            // Computing the final height
+            int finalHeight = ( int ) ( imageData.height / scaleFactor );
+
+            // Returning the scaled image data
+            return imageData.scaledTo( width, finalHeight );
+        }
+        // Resizing the image with the given height value
+        else if ( ( width == TemplateWidget.DEFAULT_SIZE ) && ( height != TemplateWidget.DEFAULT_SIZE ) )
+        {
+            // Computing the scale factor
+            float scaleFactor = ( float ) imageData.height / ( float ) height;
+
+            // Computing the final height
+            int finalWidth = ( int ) ( imageData.width / scaleFactor );
+
+            // Returning the scaled image data
+            return imageData.scaledTo( finalWidth, height );
+        }
+        // Resizing the image with the given width and height values
+        else if ( ( width != TemplateWidget.DEFAULT_SIZE ) && ( height != TemplateWidget.DEFAULT_SIZE ) )
+        {
+            // Returning the original image data
+            return imageData.scaledTo( width, height );
+        }
+
+        // No resizing needed
+        return imageData;
+    }
+
+
+    /**
+     * Adds the listeners.
+     */
+    private void addListeners()
+    {
+        // Save As button
+        if ( ( saveAsToolItem != null ) && ( !saveAsToolItem.isDisposed() ) )
+        {
+            saveAsToolItem.addSelectionListener( new SelectionAdapter()
+            {
+                public void widgetSelected( SelectionEvent e )
+                {
+                    saveAsToolItemAction();
+                }
+            } );
+        }
+
+        // Clear button
+        if ( ( clearToolItem != null ) && ( !clearToolItem.isDisposed() ) )
+        {
+            clearToolItem.addSelectionListener( new SelectionAdapter()
+            {
+                public void widgetSelected( SelectionEvent e )
+                {
+                    clearToolItemAction();
+                }
+            } );
+        }
+
+        // Browse button
+        if ( ( browseToolItem != null ) && ( !browseToolItem.isDisposed() ) )
+        {
+            browseToolItem.addSelectionListener( new SelectionAdapter()
+            {
+                public void widgetSelected( SelectionEvent e )
+                {
+                    browseToolItemAction();
+                }
+            } );
+        }
+    }
+
+
+    /**
+     * This method is called when the 'Save As...' toolbar item is clicked.
+     */
+    private void saveAsToolItemAction()
+    {
+        // Launching a FileDialog to select where to save the file
+        FileDialog fd = new FileDialog( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.SAVE );
+        String selected = fd.open();
+        if ( selected != null )
+        {
+            // Getting the selected file
+            File selectedFile = new File( selected );
+            if ( ( !selectedFile.exists() ) || ( selectedFile.canWrite() ) )
+            {
+                try
+                {
+                    FileOutputStream fos = new FileOutputStream( selectedFile );
+                    fos.write( imageBytes );
+                    fos.close();
+                }
+                catch ( Exception e )
+                {
+                    // Logging the error
+                    EntryTemplatePluginUtils.logError( e, "An error occurred while saving the image to disk.", //$NON-NLS-1$
+                        new Object[0] );
+
+                    // Launching an error dialog
+                    MessageDialog
+                        .openError(
+                            PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                            Messages.getString( "EditorImage.ErrorSavingMessageDialogTitle" ), Messages.getString( "EditorImage.ErrorSavingMessageDialogMessage" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+                }
+            }
+        }
+    }
+
+
+    /**
+     * This method is called when the 'Clear...' toolbar item is clicked.
+     */
+    private void clearToolItemAction()
+    {
+        // Launching a confirmation dialog
+        if ( MessageDialog.openConfirm( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), Messages
+            .getString( "EditorImage.Confirmation" ), Messages.getString( "EditorImage.ConfirmationClearImage" ) ) ) //$NON-NLS-1$ //$NON-NLS-2$
+        {
+            // Removing the image bytes
+            imageBytes = null;
+
+            // Constrains and displays the image
+            constrainAndDisplayImage();
+
+            // Refreshing the states of the buttons
+            updateButtonsStates();
+
+            // Updating the entry
+            updateEntry();
+
+            // Updating the image
+            composite.getParent().update();
+        }
+    }
+
+
+    /**
+     * This method is called when the 'Browse...' toolbar item is clicked.
+     */
+    private void browseToolItemAction()
+    {
+        // Launching a FileDialog to select the file to load
+        FileDialog fd = new FileDialog( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN );
+        String selected = fd.open();
+        if ( selected != null )
+        {
+            // Getting the selected file
+            File selectedFile = new File( selected );
+            if ( ( selectedFile.exists() ) && ( selectedFile.canRead() ) )
+            {
+                try
+                {
+                    FileInputStream fis = new FileInputStream( selectedFile );
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream( ( int ) selectedFile.length() );
+                    byte[] buf = new byte[4096];
+                    int len;
+                    while ( ( len = fis.read( buf ) ) > 0 )
+                    {
+                        baos.write( buf, 0, len );
+                    }
+
+                    imageBytes = baos.toByteArray();
+                }
+                catch ( Exception e )
+                {
+                    // Logging the error
+                    EntryTemplatePluginUtils.logError( e, "An error occurred while reading the image from disk.", //$NON-NLS-1$
+                        new Object[0] );
+
+                    // Launching an error dialog
+                    MessageDialog
+                        .openError(
+                            PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                            Messages.getString( "EditorImage.ErrorReadingMessageDialogTitle" ), Messages.getString( "EditorImage.ErrorReadingMessageDialogMessage" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+                }
+
+                // Constrains and displays the image
+                constrainAndDisplayImage();
+
+                // Refreshing the states of the buttons
+                updateButtonsStates();
+            }
+            else
+            {
+                // Logging the error
+                EntryTemplatePluginUtils
+                    .logError(
+                        null,
+                        "An error occurred while reading the image from disk. Image file does not exist or is not readable.", //$NON-NLS-1$
+                        new Object[0] );
+
+                // Launching an error dialog
+                MessageDialog
+                    .openError(
+                        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                        Messages.getString( "EditorImage.ErrorReadingMessageDialogTitle" ), Messages.getString( "EditorImage.ErrorReadingMessageDialogMessage" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+
+            // Updating the entry
+            updateEntry();
+
+            // Updating the image
+            composite.getParent().update();
+        }
+    }
+
+
+    /**
+     * Updates the states of the buttons.
+     */
+    private void updateButtonsStates()
+    {
+        if ( ( imageBytes != null ) && ( imageBytes.length > 0 ) )
+        {
+            if ( ( saveAsToolItem != null ) && ( !saveAsToolItem.isDisposed() ) )
+            {
+                saveAsToolItem.setEnabled( true );
+            }
+
+            if ( ( clearToolItem != null ) && ( !clearToolItem.isDisposed() ) )
+            {
+                clearToolItem.setEnabled( true );
+            }
+
+            if ( ( browseToolItem != null ) && ( !browseToolItem.isDisposed() ) )
+            {
+                browseToolItem.setEnabled( true );
+            }
+        }
+        else
+        {
+            if ( ( saveAsToolItem != null ) && ( !saveAsToolItem.isDisposed() ) )
+            {
+                saveAsToolItem.setEnabled( false );
+            }
+
+            if ( ( clearToolItem != null ) && ( !clearToolItem.isDisposed() ) )
+            {
+                clearToolItem.setEnabled( false );
+            }
+
+            if ( ( browseToolItem != null ) && ( !browseToolItem.isDisposed() ) )
+            {
+                browseToolItem.setEnabled( true );
+            }
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void update()
+    {
+        updateWidget();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void dispose()
+    {
+        // Nothing to do
+    }
+
+
+    /**
+     * This method is called when the entry has been updated in the UI.
+     */
+    private void updateEntry()
+    {
+        // Getting the attribute
+        IAttribute attribute = getAttribute();
+        if ( attribute == null )
+        {
+            if ( ( imageBytes != null ) && ( imageBytes.length != 0 ) )
+            {
+                // Creating a new attribute with the value
+                addNewAttribute( imageBytes );
+            }
+        }
+        else
+        {
+            if ( ( imageBytes != null ) && ( imageBytes.length != 0 ) )
+            {
+                // Modifying the existing attribute
+                modifyAttributeValue( imageBytes );
+            }
+            else
+            {
+                // Deleting the attribute
+                deleteAttribute();
+            }
+        }
+    }
+}
\ No newline at end of file

Added: directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorLabel.java
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorLabel.java?rev=1669604&view=auto
==============================================================================
--- directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorLabel.java (added)
+++ directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorLabel.java Fri Mar 27 15:27:27 2015
@@ -0,0 +1,211 @@
+/*
+ *  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.studio.templateeditor.editor.widgets;
+
+
+import org.apache.directory.studio.entryeditors.IEntryEditor;
+import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import org.apache.directory.studio.templateeditor.model.widgets.TemplateLabel;
+import org.apache.directory.studio.templateeditor.model.widgets.WidgetAlignment;
+
+
+/**
+ * This class implements an editor label.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EditorLabel extends EditorWidget<TemplateLabel>
+{
+    /** The label widget */
+    private Text label;
+
+
+    /**
+     * Creates a new instance of EditorLabel.
+     * 
+     * @param editor
+     *      the associated editor
+     * @param templateLabel
+     *      the associated template label
+     * @param toolkit
+     *      the associated toolkit
+     */
+    public EditorLabel( IEntryEditor editor, TemplateLabel templateLabel, FormToolkit toolkit )
+    {
+        super( templateLabel, editor, toolkit );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Composite createWidget( Composite parent )
+    {
+        // Creating and initializing the widget UI
+        Composite composite = initWidget( parent );
+
+        // Updating the widget's content
+        updateWidget();
+
+        return composite;
+    }
+
+
+    /**
+     * Creates and initializes the widget UI.
+     *
+     * @param parent
+     *      the parent composite
+     * @return
+     *      the associated composite
+     */
+    private Composite initWidget( Composite parent )
+    {
+        // Creating the label
+        label = new Text( parent, getStyle() );
+        label.setEditable( false );
+        label.setBackground( parent.getBackground() );
+
+        // Setting the layout data
+        GridData gd = getGridata();
+        label.setLayoutData( gd );
+
+        // Calculating height for multiple rows
+        int numberOfRows = getWidget().getNumberOfRows();
+        if ( numberOfRows != 1 )
+        {
+            GC gc = new GC( parent );
+            gc.setFont( label.getFont() );
+            FontMetrics fontMetrics = gc.getFontMetrics();
+            gc.dispose();
+            gd.heightHint = fontMetrics.getHeight() * numberOfRows;
+        }
+
+        return parent;
+    }
+
+
+    /**
+     * Gets the style of the widget.
+     *
+     * @return
+     *      the style of the widget
+     */
+    private int getStyle()
+    {
+        int style = SWT.WRAP;
+
+        // Multiple lines?
+        if ( getWidget().getNumberOfRows() == 1 )
+        {
+            style |= SWT.SINGLE;
+        }
+        else
+        {
+            style |= SWT.MULTI;
+        }
+
+        // Horizontal alignment set to end?
+        if ( getWidget().getHorizontalAlignment() == WidgetAlignment.END )
+        {
+            style |= SWT.RIGHT;
+        }
+        // Horizontal alignment set to center?
+        else if ( getWidget().getHorizontalAlignment() == WidgetAlignment.CENTER )
+        {
+            style |= SWT.CENTER;
+        }
+
+        return style;
+    }
+
+
+    /**
+     * Updates the widget's content.
+     */
+    private void updateWidget()
+    {
+        // Checking if we need to display a value taken from the entry
+        // or use the given value
+        String attributeType = getWidget().getAttributeType();
+        if ( ( attributeType != null ) || ( "".equals( attributeType ) ) ) //$NON-NLS-1$
+        {
+            IEntry entry = getEntry();
+            if ( entry != null )
+            {
+                // Getting the text to display
+                String text = EditorWidgetUtils.getConcatenatedValues( entry, attributeType );
+
+                // Replacing '$' by '/n' if needed
+                if ( getWidget().isDollarSignIsNewLine() )
+                {
+                    text = text.replace( '$', '\n' );
+                }
+
+                // Assigning the text to the label
+                label.setText( text );
+            }
+        }
+        else
+        {
+            // Getting the text to display
+            String text = getWidget().getValue();
+
+            // Replacing '$' by '/n' if needed
+            if ( getWidget().isDollarSignIsNewLine() )
+            {
+                text = text.replace( '$', '\n' );
+            }
+
+            // Assigning the text to the label
+            label.setText( text );
+        }
+
+        // Forcing the re-layout of the label from its parent 
+        label.getParent().layout();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void update()
+    {
+        updateWidget();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void dispose()
+    {
+        // Nothing to do
+        label.dispose();
+    }
+}
\ No newline at end of file

Added: directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorLink.java
URL: http://svn.apache.org/viewvc/directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorLink.java?rev=1669604&view=auto
==============================================================================
--- directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorLink.java (added)
+++ directory/studio/trunk/plugins/templateeditor/src/main/java/org/apache/directory/studio/templateeditor/editor/widgets/EditorLink.java Fri Mar 27 15:27:27 2015
@@ -0,0 +1,348 @@
+/*
+ *  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.studio.templateeditor.editor.widgets;
+
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.directory.studio.entryeditors.IEntryEditor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import org.apache.directory.studio.templateeditor.EntryTemplatePluginUtils;
+import org.apache.directory.studio.templateeditor.model.widgets.TemplateLink;
+
+
+/**
+ * This class implements an editor link.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class EditorLink extends EditorWidget<TemplateLink>
+{
+    /** The Regex for matching an URL */
+    private static final String REGEX_URL = "([a-zA-Z][a-zA-Z0-9+-.]*:[^\\s]+)"; //$NON-NLS-1$
+
+    /** The Regex for matching an email address*/
+    private static final String REGEX_EMAIL_ADDRESS = "([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4})"; //$NON-NLS-1$
+
+    /** The link widget */
+    private Link link;
+
+
+    /**
+     * Creates a new instance of EditorLink.
+     * 
+     * @param editor
+     *      the associated editor
+     * @param templateLink
+     *      the associated template link
+     * @param toolkit
+     *      the associated toolkit
+     */
+    public EditorLink( IEntryEditor editor, TemplateLink templateLink, FormToolkit toolkit )
+    {
+        super( templateLink, editor, toolkit );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Composite createWidget( Composite parent )
+    {
+        // Creating and initializing the widget UI
+        Composite composite = initWidget( parent );
+
+        // Updating the widget's content
+        updateWidget();
+
+        // Adding the listeners
+        addListeners();
+
+        return composite;
+    }
+
+
+    /**
+     * Creates and initializes the widget UI.
+     *
+     * @param parent
+     *      the parent composite
+     * @return
+     *      the associated composite
+     */
+    private Composite initWidget( Composite parent )
+    {
+        // Creating the link widget
+        link = new Link( parent, SWT.NONE );
+        link.setLayoutData( getGridata() );
+
+        return parent;
+    }
+
+
+    /**
+     * Updates the widget's content.
+     */
+    private void updateWidget()
+    {
+        // Checking is we need to display a value taken from the entry
+        // or use the given value
+        String attributeType = getWidget().getAttributeType();
+        if ( attributeType != null )
+        {
+            link.setText( addLinksTags( EditorWidgetUtils.getConcatenatedValues( getEntry(), attributeType ) ) );
+        }
+        else
+        {
+            link.setText( addLinksTags( getWidget().getValue() ) );
+        }
+    }
+
+
+    /**
+     * Adds the listeners.
+     */
+    private void addListeners()
+    {
+        link.addListener( SWT.Selection, new Listener()
+        {
+            public void handleEvent( Event event )
+            {
+                // Creating the URL
+                String url = null;
+
+                // Getting the text that was clicked
+                String text = event.text;
+                if ( isUrl( text ) )
+                {
+                    url = text;
+                }
+                else if ( isEmailAddress( text ) )
+                {
+                    url = "mailto:" + text; //$NON-NLS-1$
+                }
+
+                if ( url != null )
+                {
+                    try
+                    {
+                        PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL( new URL( url ) );
+                    }
+                    catch ( Exception e )
+                    {
+                        // Logging the error
+                        EntryTemplatePluginUtils.logError( e, "An error occurred while opening the link.", //$NON-NLS-1$
+                            new Object[0] );
+
+                        // Launching an error dialog
+                        MessageDialog
+                            .openError(
+                                PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                                Messages.getString( "EditorLink.ErrorMessageDialogTitle" ), Messages.getString( "EditorLink.ErrorMessageDialogMessage" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+                    }
+                }
+                else
+                {
+                    // Logging the error
+                    EntryTemplatePluginUtils.logError( null, "An error occurred while opening the link. URL is null.", //$NON-NLS-1$
+                        new Object[0] );
+
+                    // Launching an error dialog
+                    MessageDialog
+                        .openError(
+                            PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+                            Messages.getString( "EditorLink.ErrorMessageDialogTitle" ), Messages.getString( "EditorLink.ErrorMessageDialogMessage" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+                }
+            }
+        } );
+    }
+
+
+    /**
+     * Adds link tags (&lt;a&gt;link&lt;/a&gt;) to the links (URLs and email 
+     * addresses) found in the given string.
+     *
+     * @param s
+     *      the string
+     * @return
+     *      the string in which links have been added
+     */
+    private static String addLinksTags( String s )
+    {
+        List<String> links = new ArrayList<String>();
+
+        // Getting the URLs
+        links.addAll( Arrays.asList( getUrls( s ) ) );
+
+        // Getting the email addresses
+        links.addAll( Arrays.asList( getEmailAddresses( s ) ) );
+
+        // Creating the final string
+        StringBuilder sb = new StringBuilder();
+        try
+        {
+            // Inserting link tags
+            int start = 0;
+            for ( String link : links )
+            {
+                int indexOfLink = s.indexOf( link );
+                sb.append( s.subSequence( start, indexOfLink ) );
+                sb.append( "<a>" ); //$NON-NLS-1$
+                sb.append( link );
+                sb.append( "</a>" ); //$NON-NLS-1$
+
+                start = indexOfLink + link.length();
+            }
+            sb.append( s.substring( start, s.length() ) );
+        }
+        catch ( StringIndexOutOfBoundsException e )
+        {
+            // In case we hit a wrong index, we fail gracefully by
+            // returning the original string
+            return s;
+        }
+
+        // Returning the final string
+        return sb.toString();
+    }
+
+
+    /**
+     * Get the urls contained in the email address.
+     *
+     * @param s
+     *      the string
+     * @return
+     *      an array containing the urls found in the given string
+     */
+    private static String[] getUrls( String s )
+    {
+        return getMatchingStrings( s, Pattern.compile( REGEX_URL + ".*" ) ); //$NON-NLS-1$
+    }
+
+
+    /**
+     * Get the email addresses contained in the email address.
+     *
+     * @param s
+     *      the string
+     * @return
+     *      an array containing the email addresses found in the given string
+     */
+    private static String[] getEmailAddresses( String s )
+    {
+        return getMatchingStrings( s, Pattern.compile( REGEX_EMAIL_ADDRESS + ".*" ) ); //$NON-NLS-1$
+    }
+
+
+    /**
+     * Get the matching strings contained in a string using a pattern.
+     *
+     * @param s
+     *      the string
+     * @param p
+     *      the pattern
+     * @return
+     *      an array containing the matching strings found in the given string
+     */
+    private static String[] getMatchingStrings( String s, Pattern p )
+    {
+        List<String> matchingStrings = new ArrayList<String>();
+
+        while ( s.length() > 0 )
+        {
+            Matcher m = p.matcher( s );
+
+            if ( m.matches() )
+            {
+                String link = m.group( 1 );
+                matchingStrings.add( link );
+                s = s.substring( link.length() );
+            }
+            else
+            {
+                s = s.substring( 1 );
+            }
+        }
+
+        return matchingStrings.toArray( new String[0] );
+    }
+
+
+    /**
+     * Indicates if the given string is a URL.
+     *
+     * @param s
+     *      the string
+     * @return
+     *      <code>true</code> if the given string is a URL,
+     *      <code>false</code> if not.
+     */
+    private boolean isUrl( String s )
+    {
+        return Pattern.matches( REGEX_URL, s );
+    }
+
+
+    /**
+     * Indicates if the given string is an email address.
+     *
+     * @param s
+     *      the string
+     * @return
+     *      <code>true</code> if the given string is an email address,
+     *      <code>false</code> if not.
+     */
+    private boolean isEmailAddress( String s )
+    {
+        return Pattern.matches( REGEX_EMAIL_ADDRESS, s );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void update()
+    {
+        updateWidget();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void dispose()
+    {
+        // Nothing to do
+    }
+}
\ No newline at end of file