/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * EditableIdentifierNameField.java * Creation date: (10/29/01 4:04:00 PM) * By: Edward Lam */ package org.openquark.gems.client; import javax.swing.JTextField; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.PlainDocument; import org.openquark.cal.compiler.LanguageInfo; /** * An editable text field that accepts valid CAL identifiers * Creation date: (10/29/01 4:04:00 PM) * @author Edward Lam */ public abstract class EditableIdentifierNameField extends JTextField implements java.awt.event.ActionListener{ /** The name this field starts out with*/ private String initialText; /** * Default constructor for this field * Creation date: (10/29/01 6:49:22 PM) */ EditableIdentifierNameField() { super(); // Set a thin border to prevent text from disappearing under it. setBorder(javax.swing.BorderFactory.createEmptyBorder(1,1,1,1)); // notify of any commit actions on the part of the user addActionListener(this); } /** * Sets the initial text * @param initialText */ protected void setInitialText(String initialText) { this.initialText = initialText; } /** * @return the initial text */ protected String getInitialText() { return initialText; } /** * Sets maximum length restriction of this document (currently 25 characters) * if not called there is no max restriction * @param limit */ protected void setMaxLength (int limit) { ((LetterNumberUnderscoreDocument)getDocument()).setMaxLength(limit); } /** * Invoked when an action occurs. * Creation date: (10/30/01 12:15:22 PM) * @param e java.awt.event.ActionEvent */ public void actionPerformed(java.awt.event.ActionEvent e){ // just commit the text commitText(); } /** * Cancel text entry (press "ESC" ..) * Creation date: (10/31/01 3:31:22 PM) */ protected void cancelEntry(){ // What to do, what to do.. textCommittedInvalid(); } /** * Commit the text currently in the text field * Creation date: (10/31/01 2:32:22 PM) */ protected void commitText(){ String newText = getText(); // the action we take depends on whether the new name is valid or invalid if (isValidName(newText) && (!newText.equals(initialText) )) { // The new name checks out. Take appropriate action textCommittedValid(); } else { // Invalid. No good. Bad. cancelEntry(); } } /** * Creates the default implementation of the model to be used at construction if one isn't explicitly given. * Overriden to return a LetterNumberUnderscoreDocument. * Creation date: (10/29/01 6:50:22 PM) * @return Document the default model implementation. */ @Override protected Document createDefaultModel() { return new LetterNumberUnderscoreDocument(); } /** * Returns whether a name is a valid name for this field * Creation date: (10/30/01 12:23:22 PM) * @param letName String the name to check for validity */ protected abstract boolean isValidName(String letName); /** * Notify that the text of this text field has changed. Called upon insertUpdate() and remove() completion. * Eg. If the current result is not valid, maybe do something about it (like warn the user somehow..) * Creation date: (10/30/01 11:43:22 AM) */ protected void textChanged(){ String updatedText = getText(); if (isValidName(updatedText)) { textChangeValid(); } else { textChangeInvalid(); } } /** * Take appropriate action if the result of the text change is invalid. * Creation date: (10/30/01 2:54:22 AM) */ protected abstract void textChangeInvalid(); /** * Take appropriate action if the result of the text change is valid. * Creation date: (10/30/01 2:54:22 AM) */ protected abstract void textChangeValid(); /** * Take appropriate action if the text committed is invalid. * Creation date: (10/30/01 2:54:22 AM) */ protected abstract void textCommittedInvalid(); /** * Take appropriate action if the text committed is valid. * Creation date: (10/30/01 3:28:22 AM) */ protected abstract void textCommittedValid(); /** * An editable text field that accepts valid CAL constructor names * Creation date: (10/29/01 4:04:00 PM) * @author Edward Lam */ public abstract static class ConstructorName extends EditableIdentifierNameField{ /** * Returns whether a name is a valid name for this field * Creation date: (11/01/01 2:44:22 PM) * @param name String the name to check for validity */ @Override protected boolean isValidName(String name){ return LanguageInfo.isValidDataConstructorName(name); } } /** * An editable text field that accepts valid CAL variable names * Creation date: (10/29/01 4:04:00 PM) * @author Edward Lam */ public abstract static class VariableName extends EditableIdentifierNameField{ /** * Returns whether a name is a valid name for this field * Creation date: (10/30/01 12:23:22 PM) * @param name String the name to check for validity */ @Override protected boolean isValidName(String name){ return LanguageInfo.isValidFunctionName(name); } } /** * The Document is a container for text that serves as the model for swing text components. * A warning signal is shown if the present text is not a valid identifier name. * Creation date: (10/29/01 6:53:22 PM) * @author Edward Lam */ private abstract class RestrictedTextDocument extends PlainDocument { /** whether the maximum length is in effect */ private boolean maxLengthInEffect = false; private int maxLength = 0; /** * Inserts a string of content. * Creation date: (10/29/01 6:55:22 PM) * @param offs int the offset into the document to insert the content >= 0. * All positions that track change at or after the given location will move. * @param str String the string to insert * @param a AttributeSet the attributes to associate with the inserted content. * This may be null if there are no attributes. */ @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { char[] source = str.toCharArray(); char[] result = new char[source.length]; int j = 0; // only letters, digits and underscores are allowed in identifiers for (int i = 0; i < result.length; i++) { if (characterValid(source[i])) { result[j++] = source[i]; } } if (!maxLengthInEffect || (getLength() + result.length) <= maxLength ) { super.insertString(offs, new String(result, 0, j), a); } // perform bookkeeping and other duties textChanged(); } /** * Checks whether a given character is allowed in the document * @param c character to check for validity * @return true if character is valid, false otherwise */ public abstract boolean characterValid(char c); /** * Removes a portion of the content of the document. * Creation date: (10/29/01 6:58:22 PM) * @param offs int the offset from the begining >= 0 * @param len int the number of characters to remove >= 0 */ @Override public void remove(int offs, int len) throws BadLocationException { super.remove(offs, len); // perform bookkeeping and other duties textChanged(); } /** * enables or disables the maximum length restriction of this document (currently 25 characters) * @param limit */ void setMaxLength (int limit) { maxLengthInEffect = true; this.maxLength = limit; } } /** * Document class that accepts letters, numbers and the underscore character as * valid characters. * @author Neil Corkum */ protected class LetterNumberUnderscoreDocument extends RestrictedTextDocument { private static final long serialVersionUID = -814558192378393767L; /** * {@inheritDoc} */ @Override public boolean characterValid(char c) { return (Character.isLetterOrDigit(c) || c == '_'); } } /** * Document class that accepts letters, numbers, the underscore character and the * pound (#) character as valid characters. * @author Neil Corkum */ protected class LetterNumberUnderscorePoundDocument extends RestrictedTextDocument { private static final long serialVersionUID = -1094709578204461360L; /** * {@inheritDoc} */ @Override public boolean characterValid(char c) { return (Character.isLetterOrDigit(c) || c == '_' || c == '#'); } } }