summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/AbstractControlWrapper.java
blob: 4f7f214550c18434d88be1a7f4c000d0cf9150c4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package org.openslx.dozmod.gui.changemonitor;

import java.util.Comparator;

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

	protected AbstractControlWrapper(DialogChangeMonitor dcm, String errorMessage, Comparator<T> comp,
			DialogChangeMonitor.ValidationConstraint<T> cons) {
		this.dcm = dcm;
		this.constraintErrorMessage = errorMessage;
		this.cmp = comp;
		this.constraint = cons;
	}

	public boolean hasChangedSinceInit() {
		return wasEverChanged;
	}

	public boolean isCurrentlyChanged() {
		return isCurrentlyChanged;
	}

	/**
	 * 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)
			return;
		boolean valid = constraint == null || constraint.isValid(text);
		if (isValid != valid) {
			isValid = valid;
			dcm.validityChanged(this);
		}
	}
}