All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cayenne.modeler.util.ValidatorTextAdapter Maven / Gradle / Ivy

The newest version!
/*****************************************************************
 *   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.cayenne.modeler.util;

import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;

import org.apache.cayenne.validation.ValidationException;

/**
 * Text adapter with live validation, which is fired in
 * VALIDATION_DELAY time.
 */
public abstract class ValidatorTextAdapter extends TextAdapter {
    /**
     * Time between end of user input and validation firing
     */
    static final long VALIDATION_DELAY = 1500L;
    
    /**
     * Is the live-checking enabled for the text component
     */
    boolean liveCheckEnabled;
    
    public ValidatorTextAdapter(JTextField textField) {
        this(textField, true);
    }
    
    public ValidatorTextAdapter(JTextField textField, boolean liveCheckEnabled) {
        super(textField, true, false, true);
        setLiveCheckEnabled(liveCheckEnabled);
        install(textField);
    }
    
    public ValidatorTextAdapter(JTextArea textArea) {
        this(textArea, true);
    }
    
    public ValidatorTextAdapter(JTextArea textArea, boolean liveCheckEnabled) {
        super(textArea, true, false);
        setLiveCheckEnabled(liveCheckEnabled);
        install(textArea);
    }
    
    protected void install(JTextComponent textComponent) {
        TimerScheduler ts = new TimerScheduler();
        
        textComponent.getDocument().addDocumentListener(ts);
        textComponent.addFocusListener(ts);
    }
    
    /**
     * Live-checks if text is correct
     * @throws ValidationException if the text is incorrect
     */
    protected abstract void validate(String text) throws ValidationException;
 
    /**
     * @return Is the live-checking enabled for the text component
     */
    public boolean isLiveCheckEnabled() {
        return liveCheckEnabled;
    }
    
    /**
     * Enables/disables live-checking
     */
    public void setLiveCheckEnabled(boolean b) {
        liveCheckEnabled = b;
    }
    
    /**
     * Task to be fired after some delay 
     */
    class ValidationTimerTask extends TimerTask {
        @Override
        public void run() {
            validate();
        }
    }
    
    protected void validate() {
        try {
            validate(textComponent.getText());
            clear();
        }
        catch (ValidationException vex) {
            textComponent.setBackground(errorColor);
            textComponent.setToolTipText(wrapTooltip(vex.getUnlabeledMessage()));
        }
    }
    
    /**
     * Wraps the tooltip, making it multi-lined if needed.
     * Current implementation uses HTML markup to break the lines
     * @param tooltip single-line tooltip
     * @return multi-line tooltip.
     */
    protected String wrapTooltip(String tooltip) {
        tooltip = encodeHTMLAttribute(tooltip);
        tooltip = tooltip.replaceAll(System.getProperty("line.separator"), "
"); return "" + tooltip + ""; } /** * Encodes a string so that it can be used as an attribute value in an HMTL document. * Will do conversion of the greater/less signs and ampersands. * * *** * This method is almost a copy of Util.encodeXmlAttribute(), but it does not replace * single quotes. So only '<', '>', '&', '"' chars will be replaced. */ public static String encodeHTMLAttribute(String str) { if (str == null) { return null; } int len = str.length(); if (len == 0) { return str; } StringBuilder encoded = new StringBuilder(); for (int i = 0; i < len; i++) { char c = str.charAt(i); if (c == '<') { encoded.append("<"); } else if (c == '\"') { encoded.append("""); } else if (c == '>') { encoded.append(">"); } else if (c == '&') { encoded.append("&"); } else { encoded.append(c); } } return encoded.toString(); } /** * Listener to user input, which fires validation timer */ class TimerScheduler implements DocumentListener, FocusListener { /** * The timer, which fires validation after some delay */ Timer validationTimer; Object sync; //to prevent concurrent collisions TimerScheduler() { sync = new Object(); } public void insertUpdate(DocumentEvent e) { schedule(); } public void changedUpdate(DocumentEvent e) { schedule(); } public void removeUpdate(DocumentEvent e) { schedule(); } void schedule() { if(isLiveCheckEnabled()) { synchronized (sync) { if(validationTimer != null) { validationTimer.cancel(); } clear(); validationTimer = new Timer("cayenne-validation-timer"); validationTimer.schedule(new ValidationTimerTask(), VALIDATION_DELAY); } } } public void focusGained(FocusEvent e) { } public void focusLost(FocusEvent e) { synchronized (sync) { if(validationTimer != null) { validationTimer.cancel(); } } }; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy