Java/GWT/Editable Label
Editable Label class
package com.jexp.gwt.client;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.core.client.*;
public class GWTClient implements EntryPoint{
public void onModuleLoad() {
EditableLabel label = new EditableLabel("editable label",true);
label.setText("click to edit me");
RootPanel.get().add(label);
}
}
/*
* Copyright 2006 Robert Hanson <iamroberthanson AT gmail.ru>
*
* Licensed 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.
*/
/*
* This code is part of the GWT Widget Library
*/
/**
* Editable Label class, funcionality displays a Label UI
* Element until clicked on, then if element is set to be
* editable (default) then an editable area and Buttons are
* displayed instead.
*
* If the Label is not set to be word wrapped (default) then
* the editable area is a Text Box and clicking the OK button
* or hitting return key in the TextBox will display the Label with
* the updated text.
*
* If the Label is set to be word wrapped, using the setWordWrap(boolean)
* method, then the editable area is a Text Area and clicking the OK
* button will display the Label with the updated text.
*
* In both cases, clicking Cancel button or hitting Escape key in the
* TextBox/TextArea then the Label is displayed with original text.
*
* @author Adam Tacy
* @version 0.0.2
*
* Changes since version 0.0.1
* + made cancelLabelChange public [ref request id: 1518134]
* + made originalText have default value of empty string [to support ref request id: 1518134]
* *End*
*/
class EditableLabel extends Composite implements HasWordWrap,
HasText,
HasHorizontalAlignment,
SourcesClickEvents,
SourcesChangeEvents,
SourcesMouseEvents
{
/**
* TextBox element to enable text to be changed if Label is not word wrapped
*/
private TextBox changeText;
/**
* TextArea element to enable text to be changed if Label is wordwrapped
*/
private TextArea changeTextArea;
/**
* Label element, which is initially is diplayed.
*/
private Label text;
/**
* String element that contains the original text of a
* Label prior to it being edited.
*/
private String originalText;
/**
* Simple button to confirm changes
*/
private Widget confirmChange;
/**
* Simple button to cancel changes
*/
private Widget cancelChange;
/**
* Flag to indicate that Label is in editing mode.
*/
private boolean isEditing = false;
/**
* Flag to indicate that label can be edited.
*/
private boolean isEditable = true;
ChangeListenerCollection changeListeners;
/**
* Default String value for OK button
*/
private String defaultOkButtonText = "OK";
/**
* Default String value for Cancel button
*/
private String defaultCancelButtonText = "Cancel";
/**
* Allows the setting of the isEditable flag, marking
* the label as editable or not.
*
* @param flag True or False value depending if the Label is to be editable or not
*/
public void setEditable (boolean flag)
{
isEditable = flag;
}
/**
* Returns the value of the isEditable flag.
*
* @return
*/
public boolean isFieldEditable ()
{
return isEditable;
}
/**
* Returns the value of the isEditing flag, allowing outside
* users to see if the Label is being edited or not.
*
* @return
*/
public boolean isInEditingMode ()
{
return isEditing;
}
/**
* Change the displayed label to be a TextBox and copy label
* text into the TextBox.
*
*/
private void changeTextLabel ()
{
if (isEditable) {
// Set up the TextBox
originalText = text.getText();
// Change the view from Label to TextBox and Buttons
text.setVisible(false);
confirmChange.setVisible(true);
cancelChange.setVisible(true);
if (text.getWordWrap()){
// If Label word wrapped use the TextArea to edit
changeTextArea.setText(originalText);
changeTextArea.setVisible(true);
changeTextArea.setFocus(true);
} else {
// Otherwise use the TextBox to edit.
changeText.setText(originalText);
changeText.setVisible(true);
changeText.setFocus(true);
}
//Set instance as being in editing mode.
isEditing = true;
}
}
/**
* Restores visibility of Label and hides the TextBox and Buttons
*
*/
private void restoreVisibility ()
{
// Change appropriate visibilities
text.setVisible(true);
confirmChange.setVisible(false);
cancelChange.setVisible(false);
if(text.getWordWrap()){
// If Label is word wrapped hide the TextArea
changeTextArea.setVisible(false);
} else {
// Otherwise hide the TextBox
changeText.setVisible(false);
}
// Set isEditing flag to false as we are no longer editing
isEditing = false;
}
/**
* Sets the Label text to the new value, restores the
* display and calls the update method.
*
*/
private void setTextLabel ()
{
if(text.getWordWrap()){
// Set the Label to be the text in the Text Box
text.setText(changeTextArea.getText());
} else {
// Set the Label to be the text in the Text Box
text.setText(changeText.getText());
}
// Set the object back to display label rather than TextBox and Buttons
restoreVisibility();
// Call the update method provided in the Constructor
// (this could be anything from alerting the user through to
// Making an AJAX call to store the data.
//updater.onChange(this);
if (changeListeners!=null)changeListeners.fireChange(this);
}
/**
* Sets the Label text to the original value, restores the display.
*
*/
public void cancelLabelChange ()
{
// Set the Label text back to what it was originally
text.setText(originalText);
// Set the object back to display Label rather than TextBox and Buttons
restoreVisibility();
}
/**
* Creates the Label, the TextBox and Buttons. Also associates
* the update method provided in the constructor with this instance.
*
* @param labelText The value of the initial Label.
* @param visibleLength The visible length (width) of the TextBox/TextArea.
* @param maxLength The maximum length of text in the TextBox.
* @param maxHeight The maximum number of visible lines of the TextArea
* @param okButtonText The text diplayed in the OK button.
* @param cancelButtonText The text displayed in the Cancel button.
*/
private void createEditableLabel (String labelText,
String okButtonText, String cancelButtonText)
{
// Put everything in a VerticalPanel
FlowPanel instance = new FlowPanel();
// Create the Label element and add a ClickListener to call out Change method when clicked
text = new Label(labelText);
text.setStyleName("editableLabel-label");
text.addClickListener(new ClickListener()
{
public void onClick (Widget sender)
{
changeTextLabel();
}
});
// Create the TextBox element used for non word wrapped Labels
// and add a KeyboardListener for Return and Esc key presses
changeText = new TextBox();
changeText.setStyleName("editableLabel-textBox");
changeText.addKeyboardListener(new KeyboardListenerAdapter()
{
public void onKeyPress (Widget sender, char keyCode, int modifiers)
{
// If return then save, if Esc cancel the change, otherwise do nothing
switch (keyCode) {
case 13:
setTextLabel();
break;
case 27:
cancelLabelChange();
break;
}
}
});
// Create the TextAre element used for word-wrapped Labels
// and add a KeyboardListener for Esc key presses (not return in this case)
changeTextArea = new TextArea();
changeTextArea.setStyleName("editableLabel-textArea");
changeTextArea.addKeyboardListener(new KeyboardListenerAdapter()
{
public void onKeyPress (Widget sender, char keyCode, int modifiers)
{
// If Esc then cancel the change, otherwise do nothing
switch (keyCode) {
case 27:
cancelLabelChange();
break;
}
}
});
// Set up Confirmation Button
confirmChange = createConfirmButton(okButtonText);
if (!(confirmChange instanceof SourcesClickEvents)) {
throw new RuntimeException("Confirm change button must allow for click events");
}
((SourcesClickEvents) confirmChange).addClickListener(new ClickListener()
{
public void onClick (Widget sender)
{
setTextLabel();
}
});
// Set up Cancel Button
cancelChange = createCancelButton(cancelButtonText);
if (!(cancelChange instanceof SourcesClickEvents)) {
throw new RuntimeException("Cancel change button must allow for click events");
}
((SourcesClickEvents)cancelChange).addClickListener(new ClickListener()
{
public void onClick (Widget sender)
{
cancelLabelChange();
}
});
// Put the buttons in a panel
FlowPanel buttonPanel = new FlowPanel();
buttonPanel.setStyleName("editableLabel-buttonPanel");
buttonPanel.add(confirmChange);
buttonPanel.add(cancelChange);
// Add panels/widgets to the widget panel
instance.add(text);
instance.add(changeText);
instance.add(changeTextArea);
instance.add(buttonPanel);
// Set initial visibilities. This needs to be after
// adding the widgets to the panel because the FlowPanel
// will mess them up when added.
text.setVisible(true);
changeText.setVisible(false);
changeTextArea.setVisible(false);
confirmChange.setVisible(false);
cancelChange.setVisible(false);
// Assume that this is a non word wrapped Label unless explicitly set otherwise
text.setWordWrap(false);
// Set the widget that this Composite represents
initWidget(instance);
}
/**
* @param cancelButtonText
*/
protected Widget createCancelButton (String cancelButtonText)
{
Button result = new Button();
result.setStyleName("editableLabel-buttons");
result.addStyleName("editableLabel-cancel");
result.setText(cancelButtonText);
return result;
}
/**
* @param okButtonText
*/
protected Widget createConfirmButton (String okButtonText)
{
Button result = new Button();
result.setStyleName("editableLabel-buttons");
result.addStyleName("editableLabel-confirm");
result.setText(okButtonText);
return result;
}
/**
* Set the word wrapping on the label (if word wrapped then the editable
* field becomes a TextArea, if not then the editable field is a TextBox.
* @param b Boolean value, true means Label is word wrapped, false means it is not.
*/
public void setWordWrap(boolean b) {
text.setWordWrap(b);
}
/**
* Return whether the Label is word wrapped or not.
*/
public boolean getWordWrap() {
return text.getWordWrap();
}
/**
* Return the text value of the Label
*/
public String getText() {
return text.getText();
}
/**
* Set the text value of the Label
*/
public void setText(String newText) {
text.setText(newText);
}
/**
* Sets the number of visible lines for a word-wrapped editable label.
* @param number Number of visible lines.
* @throws RuntimeException if the editable label is not word-wrapped.
*/public void setVisibleLines(int number){
if (text.getWordWrap()){
changeTextArea.setVisibleLines(number);
} else {
throw new RuntimeException("Cannnot set number of visible lines for a non word-wrapped Editable Label");
}
}
/**
* Get the number of Visible Lines of editable area of a word-wrapped editable Label.
* @return Number of Visible Lines.
* @throws RuntimeException If the Label is not word-wrapped.
*/
public int getVisibleLines(){
if (text.getWordWrap()){
return changeTextArea.getVisibleLines();
} else {
throw new RuntimeException("Editable Label that is not word-wrapped has no number of Visible Lines");
}
}
/**
* Set maximum length of editable area.
* @param length Length of editable area.
*/
public void setMaxLength(int length){
if (text.getWordWrap()){
changeTextArea.setCharacterWidth(length);
} else {
changeText.setMaxLength(length);
}
}
/**
* Get maximum length of editable area.
* @return maximum length of editable area.
*/
public int getMaxLength(){
if (text.getWordWrap()){
return changeTextArea.getCharacterWidth();
} else {
return changeText.getMaxLength();
}
}
/**
* Set the visible length of the editable area.
* @throws RuntimeExcpetion If editable label is word wrapped.
*/
public void setVisibleLength(int length){
if (text.getWordWrap()){
throw new RuntimeException("Cannnot set visible length for a word-wrapped Editable Label");
} else {
changeText.setVisibleLength(length);
}
}
/**
* Get the visible length of the editable area.
* @return Visible length of editable area if not a word wrapped label.
* @throws RuntimeExcpetion If editable label is word wrapped.
*/
public int getVisibleLength(){
if (text.getWordWrap()){
throw new RuntimeException("Cannnot get visible length for a word-wrapped Editable Label");
} else {
return changeText.getVisibleLength();
}
}
/**
* Constructor that changes default text for buttons and allows the setting of the wordwrap property directly.
*
* @param labelText The initial text of the label.
* @param onUpdate Handler object for performing actions once label is updated.
* @param okText Text for use in overiding the default OK button text.
* @param cancelText Text for use in overiding the default CANCEL button text.
* @param wordWrap Boolean representing if the label should be word wrapped or not
*/
public EditableLabel (String labelText, String okText,
String cancelText, boolean wordWrap)
{
createEditableLabel(labelText, okText, cancelText);
text.setWordWrap(wordWrap);
}
/**
* Constructor that uses default text values for buttons and sets the word wrap property.
*
* @param labelText The initial text of the label.
* @param onUpdate Handler object for performing actions once label is updated.
* @param wordWrap Boolean representing if the label should be word wrapped or not
*/
public EditableLabel (String labelText, boolean wordWrap)
{
createEditableLabel(labelText, defaultOkButtonText, defaultCancelButtonText);
text.setWordWrap(wordWrap);
}
/**
* Constructor that changes default button text.
*
* @param labelText The initial text of the label.
* @param onUpdate Handler object for performing actions once label is updated.
* @param okText Text for use in overiding the default OK button text.
* @param cancelText Text for use in overiding the default CANCEL button text.
*/
public EditableLabel (String labelText, String okText,
String cancelText)
{
createEditableLabel(labelText, okText, cancelText);
}
/**
* Constructor that uses default text values for buttons.
*
* @param labelText The initial text of the label.
* @param onUpdate Handler object for performing actions once label is updated.
*/
public EditableLabel (String labelText)
{
createEditableLabel(labelText, defaultOkButtonText, defaultCancelButtonText);
}
public HorizontalAlignmentConstant getHorizontalAlignment() {
return text.getHorizontalAlignment();
}
public void setHorizontalAlignment(HorizontalAlignmentConstant align) {
text.setHorizontalAlignment(align);
}
public void addClickListener(ClickListener listener) {
this.text.addClickListener(listener);
}
public void removeClickListener(ClickListener listener) {
this.text.removeClickListener(listener);
}
public void addMouseListener(MouseListener listener) {
this.text.addMouseListener(listener);
}
public void removeMouseListener(MouseListener listener) {
this.text.removeMouseListener(listener);
}
public void addChangeListener(ChangeListener listener) {
if (changeListeners == null){
changeListeners = new ChangeListenerCollection();
}
changeListeners.add(listener);
}
public void removeChangeListener(ChangeListener listener) {
if (changeListeners != null){
changeListeners.remove(listener);;
}
}
}