/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008 Sun Microsystems, Inc.
* Portions Copyright 2014-2015 ForgeRock AS
*/
package org.opends.guitools.controlpanel.ui.components;
import static org.opends.messages.AdminToolMessages.*;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.text.ParseException;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import org.opends.guitools.controlpanel.browser.IconPool;
import org.opends.guitools.controlpanel.datamodel.BinaryValue;
import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
import org.opends.guitools.controlpanel.util.Utilities;
/**
* A simple panel used in the LDAP entry viewers to display a binary value.
* It does not allow to edit the binary value. It is used for instance in the
* tables.
*
*/
public class BinaryCellPanel extends JPanel
{
private static final long serialVersionUID = 6607973945986559802L;
private JButton iconButton;
private JLabel label;
private CellEditorButton editButton;
private CellEditorButton deleteButton;
private boolean displayDelete;
private JLabel lockLabel = Utilities.createDefaultLabel();
private ImageIcon lockIcon =
Utilities.createImageIcon(IconPool.IMAGE_PATH+"/field-locked.png");
private Object value;
private static final int THUMBNAIL_HEIGHT = 50;
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
/**
* Default constructor.
*
*/
public BinaryCellPanel()
{
super(new GridBagLayout());
setOpaque(false);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 0;
iconButton = Utilities.createButton(LocalizableMessage.EMPTY);
label = Utilities.createDefaultLabel(
INFO_CTRL_PANEL_NO_VALUE_SPECIFIED.get());
add(iconButton);
iconButton.setVisible(false);
gbc.weightx = 1.0;
gbc.gridx ++;
add(label, gbc);
add(Box.createHorizontalGlue(), gbc);
gbc.gridx ++;
editButton = new CellEditorButton(INFO_CTRL_PANEL_EDIT_BUTTON_LABEL.get());
editButton.setForeground(ColorAndFontConstants.buttonForeground);
editButton.setOpaque(false);
gbc.insets.left = 5;
gbc.weightx = 0.0;
add(editButton, gbc);
gbc.gridx ++;
deleteButton =
new CellEditorButton(INFO_CTRL_PANEL_DELETE_BUTTON_LABEL.get());
deleteButton.setForeground(ColorAndFontConstants.buttonForeground);
deleteButton.setOpaque(false);
deleteButton.setVisible(isDisplayDelete());
add(deleteButton, gbc);
gbc.insets.left = 5;
gbc.gridx ++;
add(lockLabel, gbc);
lockLabel.setVisible(false);
}
/**
* Returns the message describing the provided array of bytes.
* @param value the array of bytes.
* @param isImage whether the array of bytes represents an image or not.
* @return the message describing the provided array of bytes.
*/
public LocalizableMessage getString(byte[] value, boolean isImage)
{
if (value == null)
{
return INFO_CTRL_PANEL_NO_VALUE_SPECIFIED.get();
}
else if (isImage)
{
return LocalizableMessage.EMPTY;
}
else
{
return INFO_CTRL_PANEL_BINARY_VALUE.get();
}
}
/**
* Updates the visibility of the lock icon.
* @param visible whether the lock icon is visible or not.
*/
public void setLockIconVisible(boolean visible)
{
if (visible)
{
lockLabel.setIcon(lockIcon);
lockLabel.setVisible(true);
}
else
{
lockLabel.setIcon(null);
lockLabel.setVisible(false);
}
}
/**
* Sets the text of the edit button (for instance if this panel is displaying
* a read-only value, the user might set a value of 'View...' that launches
* a viewer).
* @param text the text of the button.
*/
public void setEditButtonText(LocalizableMessage text)
{
editButton.setText(text.toString());
}
/**
* Returns the message describing the provided binary value.
* @param value the binary value.
* @param isImage whether the binary value represents an image or not.
* @return the message describing the provided binary value.
*/
public LocalizableMessage getMessage(BinaryValue value, boolean isImage)
{
LocalizableMessage returnValue;
if (value == null)
{
returnValue = INFO_CTRL_PANEL_NO_VALUE_SPECIFIED.get();
}
else if (isImage)
{
returnValue = LocalizableMessage.EMPTY;
}
else if (value.getType() == BinaryValue.Type.BASE64_STRING)
{
returnValue = INFO_CTRL_PANEL_BINARY_VALUE.get();
}
else
{
returnValue = INFO_CTRL_PANEL_CONTENTS_OF_FILE.get(value.getFile());
}
return returnValue;
}
/**
* Sets the value to be displayed by this panel.
* @param value the binary value as an array of bytes.
* @param isImage whether the binary value represents an image or not.
*/
public void setValue(byte[] value, boolean isImage)
{
label.setText(getString(value, isImage).toString());
deleteButton.setVisible(value != null && isDisplayDelete());
this.value = value;
if (!isImage)
{
label.setIcon(null);
label.setVisible(true);
iconButton.setVisible(false);
}
else
{
updateIcon(value);
}
}
/**
* Sets the value to be displayed by this panel.
* @param value the binary value as a BinaryValue object.
* @param isImage whether the binary value represents an image or not.
*/
public void setValue(BinaryValue value, boolean isImage)
{
label.setText(getMessage(value, isImage).toString());
deleteButton.setVisible(value != null && isDisplayDelete());
this.value = value;
if (!isImage)
{
label.setIcon(null);
label.setVisible(true);
iconButton.setVisible(false);
}
else
{
try
{
updateIcon(value.getBytes());
}
catch (ParseException pe)
{
logger.warn(LocalizableMessage.raw("Error decoding base 64 value: "+pe, pe));
Utilities.setWarningLabel(label, ERR_LOADING_IMAGE.get());
}
}
}
private void updateIcon(byte[] value)
{
if (value == null)
{
label.setVisible(true);
iconButton.setVisible(false);
}
else
{
Icon icon = getIcon(value);
if (icon == null || icon.getIconHeight() <= 0)
{
Utilities.setWarningLabel(label, ERR_LOADING_IMAGE.get());
label.setVisible(true);
iconButton.setVisible(false);
}
else
{
iconButton.setVisible(true);
iconButton.setIcon(icon);
label.setVisible(false);
}
}
}
/**
* Returns the object represented by this panel.
* @return the object represented by this panel.
*/
public Object getValue()
{
return value;
}
/**
* Explicitly request the focus for the edit button of this panel.
*
*/
public void requestFocusForButton()
{
editButton.requestFocusInWindow();
}
/**
* Adds an action listener to this panel. The action listener will be
* invoked when the user clicks on the 'Edit' button or the icon.
* @param listener the action listener.
*/
public void addEditActionListener(ActionListener listener)
{
editButton.addActionListener(listener);
iconButton.addActionListener(listener);
}
/**
* Removes an action listener previously added with the method
* addEditActionListener.
* @param listener the action listener.
*/
public void removeEditActionListener(ActionListener listener)
{
editButton.removeActionListener(listener);
iconButton.removeActionListener(listener);
}
/**
* Adds an action listener to this panel. The action listener will be
* invoked when the user clicks on the 'Delete'.
* @param listener the action listener.
*/
public void addDeleteActionListener(ActionListener listener)
{
deleteButton.addActionListener(listener);
}
/**
* Removes an action listener previously added with the method
* addDeleteActionListener.
* @param listener the action listener.
*/
public void removeDeleteActionListener(ActionListener listener)
{
deleteButton.removeActionListener(listener);
}
/** {@inheritDoc} */
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
int condition, boolean pressed)
{
// This method is used to transfer the key events to the button.
return editButton.processKeyBinding(ks, e, condition, pressed);
}
/**
* Tells whether the 'Delete' button is displayed or not.
* @return <CODE>true</CODE> if the 'Delete' button is visible and
* <CODE>false</CODE> otherwise.
*/
public boolean isDisplayDelete()
{
return displayDelete;
}
/**
* Sets whether the 'Delete' button must be displayed or not.
* @param displayDelete whether the 'Delete' button must be displayed or not.
*/
public void setDisplayDelete(boolean displayDelete)
{
this.displayDelete = displayDelete;
}
private Icon getIcon(byte[] bytes)
{
return Utilities.createImageIcon(bytes, THUMBNAIL_HEIGHT,
INFO_CTRL_PANEL_THUMBNAIL_DESCRIPTION.get(),
true);
}
}