blob: b72abcb4a1c7db68c4f498482d0c2a321841ddb2 [file] [log] [blame]
/*
* 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 java.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.getDecoder().decode( imageDataString );
}
}
}
/**
* 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 = null;
ByteArrayOutputStream baos = null;
try
{
fis = new FileInputStream( selectedFile );
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();
}
finally
{
if ( fis != null )
{
fis.close();
}
if ( baos != null )
{
baos.close();
}
}
}
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()
{
image.dispose();
}
/**
* 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();
}
}
}
}