summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/AbstractControlWrapper.java
blob: e43b5393c2e572a45c32ee7062b592eff9424787 (plain) (tree)
1
2
3
4
5
6
7

                                             
                           
                            


                                                                                     







                                                 
                                  
                                                          
                                        
                                             





                                                                             
                                                                                       
                               
                                










                                              

















                                                                                            










                                                                             
        

























































                                                                                 
                                                                          
                               







                                                               


                                                  
 
 
package org.openslx.dozmod.gui.changemonitor;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint;

/**
 * Control/element wrapper
 */
public abstract class AbstractControlWrapper<T> {
	private final DialogChangeMonitor dcm;
	protected boolean wasEverChanged;
	protected boolean isCurrentlyChanged;
	private T originalContent;
	private List<ValidationConstraint<T>> constraints;
	private final Comparator<T> cmp;
	protected String currentError = null;
	/**
	 * If muted, this wrapper will not react to changes of the underlying
	 * control.
	 */
	private boolean muted = false;

	protected AbstractControlWrapper(DialogChangeMonitor dcm, Comparator<T> comp) {
		this.dcm = dcm;
		this.cmp = comp;
	}

	public boolean hasChangedSinceInit() {
		return wasEverChanged;
	}

	public boolean isCurrentlyChanged() {
		return isCurrentlyChanged;
	}

	/**
	 * Returns the current error message for the first failed constraint. If no
	 * constraint currently yields invalid, null is returned.
	 * 
	 * @return
	 */
	public String currentConstraintError() {
		return currentError;
	}
	
	public AbstractControlWrapper<T> addConstraint(ValidationConstraint<T> constraint) {
		if (constraints == null) {
			constraints = new ArrayList<>();
		}
		constraints.add(constraint);
		return this;
	}

	/**
	 * Resets the change state of this control
	 * and removes the "muted" flag, if set.
	 */
	public void reset() {
		boolean wasChanged = wasEverChanged;
		resetChangeState();
		if (wasChanged) {
			// It's possible that the global change state changed
			dcm.contentChanged(this);
		}
	}
	
	protected final void resetChangeState() {
		muted = false;
		isCurrentlyChanged = wasEverChanged = false;
		originalContent = getCurrentValue();
		checkValid(originalContent);
	}

	/**
	 * To be called by the implementation whenever the content of the control
	 * changed and according checks should be triggered.
	 */
	protected final void contentChanged() {
		T text = getCurrentValue();
		checkChanged(text);
		checkValid(text);
	}

	/**
	 * Ignore any changes, don't trigger callbacks regarding
	 * this component. This flag can be removed by calling
	 * reset() on this ControlWrapper or the enclosing
	 * DialogChangeMonitor.
	 */
	public void mute() {
		muted = true;
	}

	/**
	 * Method MUST return the current value of the monitored component, so
	 * that the current state can be considered as the original unmodified
	 * state.
	 */
	abstract T getCurrentValue();

	protected void checkChanged(T newContent) {
		if (muted)
			return;
		final boolean changed;
		if (cmp == null) {
			if (originalContent == null) {
				if (newContent == null) {
					changed = false;
				} else {
					changed = true;
				}
			} else {
				changed = !originalContent.equals(newContent);
			}
		} else {
			changed = cmp.compare(originalContent, newContent) != 0;
		}
		if (isCurrentlyChanged != changed) {
			isCurrentlyChanged = changed;
			dcm.contentChanged(this);
		}
	}

	protected void checkValid(T text) {
		if (muted || constraints == null || constraints.isEmpty())
			return;
		String error = null;
		for (ValidationConstraint<T> i : constraints) {
			error = i.checkStateValid(text);
			if (error != null)
				break;
		}
		if (error != currentError) {
			currentError = error;
			dcm.validityChanged(this);
		}
	}

}