001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017 018package org.opends.guitools.controlpanel.ui.components; 019 020import static org.opends.messages.AdminToolMessages.*; 021 022import java.awt.GridBagConstraints; 023import java.awt.GridBagLayout; 024import java.awt.event.ActionListener; 025import java.awt.event.KeyEvent; 026import java.text.ParseException; 027 028import javax.swing.Box; 029import javax.swing.Icon; 030import javax.swing.ImageIcon; 031import javax.swing.JButton; 032import javax.swing.JLabel; 033import javax.swing.JPanel; 034import javax.swing.KeyStroke; 035 036import org.forgerock.i18n.LocalizableMessage; 037import org.forgerock.i18n.slf4j.LocalizedLogger; 038import org.opends.guitools.controlpanel.browser.IconPool; 039import org.opends.guitools.controlpanel.datamodel.BinaryValue; 040import org.opends.guitools.controlpanel.ui.ColorAndFontConstants; 041import org.opends.guitools.controlpanel.util.Utilities; 042 043/** 044 * A simple panel used in the LDAP entry viewers to display a binary value. 045 * It does not allow to edit the binary value. It is used for instance in the 046 * tables. 047 */ 048public class BinaryCellPanel extends JPanel 049{ 050 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 051 private static final long serialVersionUID = 6607973945986559802L; 052 private static final int THUMBNAIL_HEIGHT = 50; 053 054 private final JButton iconButton; 055 private final JLabel label; 056 private final CellEditorButton editButton; 057 private final CellEditorButton deleteButton; 058 private boolean displayDelete; 059 private final JLabel lockLabel = Utilities.createDefaultLabel(); 060 061 private final ImageIcon lockIcon = 062 Utilities.createImageIcon(IconPool.IMAGE_PATH+"/field-locked.png"); 063 064 private Object value; 065 066 067 /** Default constructor. */ 068 public BinaryCellPanel() 069 { 070 super(new GridBagLayout()); 071 setOpaque(false); 072 GridBagConstraints gbc = new GridBagConstraints(); 073 gbc.fill = GridBagConstraints.HORIZONTAL; 074 gbc.gridx = 0; 075 gbc.gridy = 0; 076 iconButton = Utilities.createButton(LocalizableMessage.EMPTY); 077 label = Utilities.createDefaultLabel( 078 INFO_CTRL_PANEL_NO_VALUE_SPECIFIED.get()); 079 add(iconButton); 080 iconButton.setVisible(false); 081 gbc.weightx = 1.0; 082 gbc.gridx ++; 083 add(label, gbc); 084 add(Box.createHorizontalGlue(), gbc); 085 gbc.gridx ++; 086 editButton = new CellEditorButton(INFO_CTRL_PANEL_EDIT_BUTTON_LABEL.get()); 087 editButton.setForeground(ColorAndFontConstants.buttonForeground); 088 editButton.setOpaque(false); 089 gbc.insets.left = 5; 090 gbc.weightx = 0.0; 091 add(editButton, gbc); 092 093 gbc.gridx ++; 094 deleteButton = 095 new CellEditorButton(INFO_CTRL_PANEL_DELETE_BUTTON_LABEL.get()); 096 deleteButton.setForeground(ColorAndFontConstants.buttonForeground); 097 deleteButton.setOpaque(false); 098 deleteButton.setVisible(isDisplayDelete()); 099 add(deleteButton, gbc); 100 101 gbc.insets.left = 5; 102 gbc.gridx ++; 103 add(lockLabel, gbc); 104 lockLabel.setVisible(false); 105 } 106 107 /** 108 * Returns the message describing the provided array of bytes. 109 * @param value the array of bytes. 110 * @param isImage whether the array of bytes represents an image or not. 111 * @return the message describing the provided array of bytes. 112 */ 113 public LocalizableMessage getString(byte[] value, boolean isImage) 114 { 115 if (value == null) 116 { 117 return INFO_CTRL_PANEL_NO_VALUE_SPECIFIED.get(); 118 } 119 else if (isImage) 120 { 121 return LocalizableMessage.EMPTY; 122 } 123 else 124 { 125 return INFO_CTRL_PANEL_BINARY_VALUE.get(); 126 } 127 } 128 129 /** 130 * Updates the visibility of the lock icon. 131 * @param visible whether the lock icon is visible or not. 132 */ 133 public void setLockIconVisible(boolean visible) 134 { 135 if (visible) 136 { 137 lockLabel.setIcon(lockIcon); 138 lockLabel.setVisible(true); 139 } 140 else 141 { 142 lockLabel.setIcon(null); 143 lockLabel.setVisible(false); 144 } 145 } 146 147 /** 148 * Sets the text of the edit button (for instance if this panel is displaying 149 * a read-only value, the user might set a value of 'View...' that launches 150 * a viewer). 151 * @param text the text of the button. 152 */ 153 public void setEditButtonText(LocalizableMessage text) 154 { 155 editButton.setText(text.toString()); 156 } 157 158 /** 159 * Returns the message describing the provided binary value. 160 * @param value the binary value. 161 * @param isImage whether the binary value represents an image or not. 162 * @return the message describing the provided binary value. 163 */ 164 public LocalizableMessage getMessage(BinaryValue value, boolean isImage) 165 { 166 LocalizableMessage returnValue; 167 if (value == null) 168 { 169 returnValue = INFO_CTRL_PANEL_NO_VALUE_SPECIFIED.get(); 170 } 171 else if (isImage) 172 { 173 returnValue = LocalizableMessage.EMPTY; 174 } 175 else if (value.getType() == BinaryValue.Type.BASE64_STRING) 176 { 177 returnValue = INFO_CTRL_PANEL_BINARY_VALUE.get(); 178 } 179 else 180 { 181 returnValue = INFO_CTRL_PANEL_CONTENTS_OF_FILE.get(value.getFile()); 182 } 183 return returnValue; 184 } 185 186 /** 187 * Sets the value to be displayed by this panel. 188 * @param value the binary value as an array of bytes. 189 * @param isImage whether the binary value represents an image or not. 190 */ 191 public void setValue(byte[] value, boolean isImage) 192 { 193 label.setText(getString(value, isImage).toString()); 194 deleteButton.setVisible(value != null && isDisplayDelete()); 195 this.value = value; 196 if (!isImage) 197 { 198 label.setIcon(null); 199 label.setVisible(true); 200 iconButton.setVisible(false); 201 } 202 else 203 { 204 updateIcon(value); 205 } 206 } 207 208 /** 209 * Sets the value to be displayed by this panel. 210 * @param value the binary value as a BinaryValue object. 211 * @param isImage whether the binary value represents an image or not. 212 */ 213 public void setValue(BinaryValue value, boolean isImage) 214 { 215 label.setText(getMessage(value, isImage).toString()); 216 deleteButton.setVisible(value != null && isDisplayDelete()); 217 this.value = value; 218 if (!isImage) 219 { 220 label.setIcon(null); 221 label.setVisible(true); 222 iconButton.setVisible(false); 223 } 224 else 225 { 226 try 227 { 228 updateIcon(value.getBytes()); 229 } 230 catch (ParseException pe) 231 { 232 logger.warn(LocalizableMessage.raw("Error decoding base 64 value: "+pe, pe)); 233 Utilities.setWarningLabel(label, ERR_LOADING_IMAGE.get()); 234 } 235 } 236 } 237 238 private void updateIcon(byte[] value) 239 { 240 if (value == null) 241 { 242 label.setVisible(true); 243 iconButton.setVisible(false); 244 } 245 else 246 { 247 Icon icon = getIcon(value); 248 if (icon == null || icon.getIconHeight() <= 0) 249 { 250 Utilities.setWarningLabel(label, ERR_LOADING_IMAGE.get()); 251 label.setVisible(true); 252 iconButton.setVisible(false); 253 } 254 else 255 { 256 iconButton.setVisible(true); 257 iconButton.setIcon(icon); 258 label.setVisible(false); 259 } 260 } 261 } 262 263 /** 264 * Returns the object represented by this panel. 265 * @return the object represented by this panel. 266 */ 267 public Object getValue() 268 { 269 return value; 270 } 271 272 /** 273 * Adds an action listener to this panel. The action listener will be 274 * invoked when the user clicks on the 'Edit' button or the icon. 275 * @param listener the action listener. 276 */ 277 public void addEditActionListener(ActionListener listener) 278 { 279 editButton.addActionListener(listener); 280 iconButton.addActionListener(listener); 281 } 282 283 /** 284 * Removes an action listener previously added with the method 285 * addEditActionListener. 286 * @param listener the action listener. 287 */ 288 public void removeEditActionListener(ActionListener listener) 289 { 290 editButton.removeActionListener(listener); 291 iconButton.removeActionListener(listener); 292 } 293 294 /** 295 * Adds an action listener to this panel. The action listener will be 296 * invoked when the user clicks on the 'Delete'. 297 * @param listener the action listener. 298 */ 299 public void addDeleteActionListener(ActionListener listener) 300 { 301 deleteButton.addActionListener(listener); 302 } 303 304 /** 305 * Removes an action listener previously added with the method 306 * addDeleteActionListener. 307 * @param listener the action listener. 308 */ 309 public void removeDeleteActionListener(ActionListener listener) 310 { 311 deleteButton.removeActionListener(listener); 312 } 313 314 @Override 315 protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, 316 int condition, boolean pressed) 317 { 318 // This method is used to transfer the key events to the button. 319 return editButton.processKeyBinding(ks, e, condition, pressed); 320 } 321 322 /** 323 * Tells whether the 'Delete' button is displayed or not. 324 * @return <CODE>true</CODE> if the 'Delete' button is visible and 325 * <CODE>false</CODE> otherwise. 326 */ 327 public boolean isDisplayDelete() 328 { 329 return displayDelete; 330 } 331 332 /** 333 * Sets whether the 'Delete' button must be displayed or not. 334 * @param displayDelete whether the 'Delete' button must be displayed or not. 335 */ 336 public void setDisplayDelete(boolean displayDelete) 337 { 338 this.displayDelete = displayDelete; 339 } 340 341 private Icon getIcon(byte[] bytes) 342 { 343 return Utilities.createImageIcon(bytes, THUMBNAIL_HEIGHT, 344 INFO_CTRL_PANEL_THUMBNAIL_DESCRIPTION.get(), 345 true); 346 } 347}