diff options
Diffstat (limited to 'dozentenmodul/src/main/java/org/openslx/dozmod/gui')
22 files changed, 249 insertions, 143 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/AbstractControlWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/AbstractControlWrapper.java index 4f7f2145..e43b5393 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/AbstractControlWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/AbstractControlWrapper.java @@ -1,6 +1,10 @@ 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 @@ -9,23 +13,19 @@ 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 List<ValidationConstraint<T>> constraints; private final Comparator<T> cmp; - protected final String constraintErrorMessage; + 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, String errorMessage, Comparator<T> comp, - DialogChangeMonitor.ValidationConstraint<T> cons) { + protected AbstractControlWrapper(DialogChangeMonitor dcm, Comparator<T> comp) { this.dcm = dcm; - this.constraintErrorMessage = errorMessage; this.cmp = comp; - this.constraint = cons; } public boolean hasChangedSinceInit() { @@ -37,6 +37,24 @@ public abstract class AbstractControlWrapper<T> { } /** + * 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. */ @@ -48,7 +66,7 @@ public abstract class AbstractControlWrapper<T> { dcm.contentChanged(this); } } - + protected final void resetChangeState() { muted = false; isCurrentlyChanged = wasEverChanged = false; @@ -107,12 +125,18 @@ public abstract class AbstractControlWrapper<T> { } protected void checkValid(T text) { - if (muted) + if (muted || constraints == null || constraints.isEmpty()) return; - boolean valid = constraint == null || constraint.isValid(text); - if (isValid != valid) { - isValid = valid; + String error = null; + for (ValidationConstraint<T> i : constraints) { + error = i.checkStateValid(text); + if (error != null) + break; + } + if (error != currentError) { + currentError = error; dcm.validityChanged(this); } } + }
\ No newline at end of file diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/ButtonGroupWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/ButtonGroupWrapper.java index 3606a99b..1768efb6 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/ButtonGroupWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/ButtonGroupWrapper.java @@ -8,16 +8,14 @@ import javax.swing.AbstractButton; import javax.swing.ButtonGroup; import javax.swing.ButtonModel; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; - /** * Monitor a button group (e.g. group of radio boxes) */ class ButtonGroupWrapper extends AbstractControlWrapper<ButtonModel> { private final ButtonGroup buttons; - public ButtonGroupWrapper(DialogChangeMonitor dcm, ButtonGroup group, ValidationConstraint<ButtonModel> constraint, String errorMessage) { - super(dcm, errorMessage, null, constraint); + public ButtonGroupWrapper(DialogChangeMonitor dcm, ButtonGroup group) { + super(dcm, null); buttons = group; ItemListener listener = new ItemListener() { @Override diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/CheckBoxTreeWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/CheckBoxTreeWrapper.java index 23e8a742..5f3d8e2a 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/CheckBoxTreeWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/CheckBoxTreeWrapper.java @@ -4,7 +4,6 @@ import java.util.Comparator; import javax.swing.tree.TreePath; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; import org.openslx.dozmod.gui.control.JCheckBoxTree; import org.openslx.dozmod.gui.control.JCheckBoxTree.CheckChangeEvent; import org.openslx.dozmod.gui.control.JCheckBoxTree.CheckChangeEventListener; @@ -39,8 +38,8 @@ class CheckBoxTreeWrapper extends AbstractControlWrapper<TreePath[]> { private final JCheckBoxTree tree; - public CheckBoxTreeWrapper(DialogChangeMonitor dcm, JCheckBoxTree t, ValidationConstraint<TreePath[]> constraint, String errorMessage) { - super(dcm, errorMessage, COMPARATOR, constraint); + public CheckBoxTreeWrapper(DialogChangeMonitor dcm, JCheckBoxTree t) { + super(dcm, COMPARATOR); tree = t; tree.addCheckChangeEventListener(new CheckChangeEventListener() { public void checkStateChanged(CheckChangeEvent event) { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/CheckBoxWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/CheckBoxWrapper.java index 4683458e..74f94eb9 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/CheckBoxWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/CheckBoxWrapper.java @@ -5,8 +5,6 @@ import java.awt.event.ItemListener; import javax.swing.JCheckBox; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; - /** * Monitoring a JCheckBox */ @@ -14,8 +12,8 @@ class CheckBoxWrapper extends AbstractControlWrapper<Boolean> { private final JCheckBox checkbox; - public CheckBoxWrapper(DialogChangeMonitor dcm, JCheckBox box, ValidationConstraint<Boolean> constraint, String errorMessage) { - super(dcm, errorMessage, null, constraint); + public CheckBoxWrapper(DialogChangeMonitor dcm, JCheckBox box) { + super(dcm, null); checkbox = box; checkbox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/DatePickerWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/DatePickerWrapper.java index 40930862..5e471380 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/DatePickerWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/DatePickerWrapper.java @@ -4,7 +4,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import org.jdatepicker.JDatePicker; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; /** * Monitoring a JTextField etc. @@ -12,8 +11,8 @@ import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstr class DatePickerWrapper extends AbstractControlWrapper<Object> { private final JDatePicker component; - public DatePickerWrapper(DialogChangeMonitor dcm, JDatePicker picker, ValidationConstraint<Object> constr, String errorMessage) { - super(dcm, errorMessage, null, constr); + public DatePickerWrapper(DialogChangeMonitor dcm, JDatePicker picker) { + super(dcm, null); this.component = picker; picker.addActionListener(new ActionListener() { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/DialogChangeMonitor.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/DialogChangeMonitor.java index d05fac72..a1d01eaf 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/DialogChangeMonitor.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/DialogChangeMonitor.java @@ -3,6 +3,7 @@ package org.openslx.dozmod.gui.changemonitor; import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.Map; import javax.swing.ButtonGroup; import javax.swing.ButtonModel; @@ -14,6 +15,7 @@ import javax.swing.tree.TreePath; import org.apache.log4j.Logger; import org.jdatepicker.JDatePicker; +import org.openslx.bwlp.thrift.iface.LecturePermissions; import org.openslx.dozmod.gui.control.ComboBox; import org.openslx.dozmod.gui.control.JCheckBoxTree; import org.openslx.dozmod.gui.control.LectureCustomPermissionManager; @@ -37,83 +39,59 @@ public class DialogChangeMonitor { this.callback = cb; } - private void warnConstraint(Object component, ValidationConstraint<?> constraint, String errorMessage) { - if (callback != null && constraint != null && errorMessage == null) { - LOGGER.warn("Adding " + component.getClass().getSimpleName() - + " with constraint but no error message!"); - } - } - /* * Methods for adding various controls */ - private AbstractControlWrapper<?> add(AbstractControlWrapper<?> elem) { + private <T> AbstractControlWrapper<T> add(AbstractControlWrapper<T> elem) { controls.add(elem); elem.resetChangeState(); return elem; } - public AbstractControlWrapper<?> add(JTextComponent component, ValidationConstraint<String> constraint, - String errorMessage) { - warnConstraint(component, constraint, errorMessage); - return add(new TextControlWrapper(this, component, constraint, errorMessage)); - } - - public AbstractControlWrapper<?> add(JTextComponent component) { - return add(component, null, null); + public AbstractControlWrapper<String> add(JTextComponent component) { + return add(new TextControlWrapper(this, component)); } - public <T> AbstractControlWrapper<?> addFixedCombo(ComboBox<T> component, Comparator<T> comparator, - ValidationConstraint<T> constraint, String errorMessage) { - warnConstraint(component, constraint, errorMessage); - return add(new FixedComboBoxWrapper<T>(this, component, comparator, constraint, errorMessage)); + public <T> AbstractControlWrapper<T> addFixedCombo(ComboBox<T> component, Comparator<T> comparator) { + return add(new FixedComboBoxWrapper<T>(this, component, comparator)); } - public AbstractControlWrapper<?> addEditableCombo(ComboBox<?> component, Comparator<Object> comparator, - ValidationConstraint<Object> constraint, String errorMessage) { - warnConstraint(component, constraint, errorMessage); - return add(new EditableComboBoxWrapper(this, component, comparator, constraint, errorMessage)); + public AbstractControlWrapper<Object> addEditableCombo(ComboBox<?> component, + Comparator<Object> comparator) { + return add(new EditableComboBoxWrapper(this, component, comparator)); } - public AbstractControlWrapper<?> add(JCheckBox component, ValidationConstraint<Boolean> constraint, - String errorMessage) { - warnConstraint(component, constraint, errorMessage); - return add(new CheckBoxWrapper(this, component, constraint, errorMessage)); + public AbstractControlWrapper<Boolean> add(JCheckBox component) { + return add(new CheckBoxWrapper(this, component)); } - public AbstractControlWrapper<?> add(JCheckBox component) { - return add(component, null, null); + public AbstractControlWrapper<TreePath[]> add(JCheckBoxTree component) { + return add(new CheckBoxTreeWrapper(this, component)); } - public AbstractControlWrapper<?> add(JCheckBoxTree component, - ValidationConstraint<TreePath[]> constraint, String errorMessage) { - warnConstraint(component, constraint, errorMessage); - return add(new CheckBoxTreeWrapper(this, component, constraint, errorMessage)); + public AbstractControlWrapper<ButtonModel> add(ButtonGroup group) { + return add(new ButtonGroupWrapper(this, group)); } - public AbstractControlWrapper<?> add(ButtonGroup group, ValidationConstraint<ButtonModel> constraint, - String errorMessage) { - warnConstraint(group, constraint, errorMessage); - return add(new ButtonGroupWrapper(this, group, constraint, errorMessage)); + public AbstractControlWrapper<Object> add(JDatePicker picker) { + return add(new DatePickerWrapper(this, picker)); } - public AbstractControlWrapper<?> add(JDatePicker picker, ValidationConstraint<Object> constraint, - String errorMessage) { - warnConstraint(picker, constraint, errorMessage); - return add(new DatePickerWrapper(this, picker, constraint, errorMessage)); + public AbstractControlWrapper<Object> add(JSpinner spinner) { + return add(new TimeSpinnerWrapper(this, spinner)); } - public AbstractControlWrapper<?> add(JSpinner spinner) { - return add(new TimeSpinnerWrapper(this, spinner, null, null)); + public AbstractControlWrapper<Map<String, LecturePermissions>> add(LectureCustomPermissionManager manager) { + return add(new LecturePermissionManagerWrapper(this, manager)); } - public AbstractControlWrapper<?> add(LectureCustomPermissionManager manager) { - return add(new LecturePermissionManagerWrapper(this, manager, null, null)); + public AbstractControlWrapper<ClonedTableModel> add(JTable table) { + return add(new TableWrapper(this, table)); } - public AbstractControlWrapper<?> add(JTable table) { - return add(new TableWrapper(this, table, null, null)); + public <T> AbstractControlWrapper<List<T>> add(ListEditorWindow<T> editor) { + return add(new ListEditorWindowWrapper<T>(this, editor)); } /* @@ -149,19 +127,19 @@ public class DialogChangeMonitor { void validityChanged(AbstractControlWrapper<?> cw) { String error = null; - LOGGER.info(cw.getClass().getSimpleName() + " changed validity to " + cw.isValid); + //LOGGER.info(cw.getClass().getSimpleName() + " changed validity to " + cw.isValid); boolean oldValid = this.isValid; - if (!cw.isValid) { + if (cw.currentError != null) { this.isValid = false; - error = cw.constraintErrorMessage; + error = cw.currentError; } else { this.isValid = true; } if (error == null) { for (AbstractControlWrapper<?> c : controls) { - if (!c.isValid) { + if (c.currentError != null) { this.isValid = false; - error = c.constraintErrorMessage; + error = c.currentError; break; } } @@ -207,18 +185,38 @@ public class DialogChangeMonitor { */ public static interface ValidationConstraint<T> { - boolean isValid(T userInput); + /** + * Method should return <code>null</code> if the input is valid, an + * error message otherwise. + * + * @param userInput Current content/state of the control being monitored + * @return error message if invalid, <code>null</code> otherwise + */ + String checkStateValid(T userInput); } - /* - * Default validators + /** + * Simple validator that checks for text not being empty */ + public static class TextNotEmptyConstraint implements ValidationConstraint<String> { + private final String errorMsg; - public static final ValidationConstraint<String> VC_NOT_EMPTY = new ValidationConstraint<String>() { - public boolean isValid(String userInput) { - return !Util.isEmptyString(userInput); + public TextNotEmptyConstraint(String errorMessage) { + this.errorMsg = errorMessage; } - }; + + @Override + public String checkStateValid(String userInput) { + if (Util.isEmptyString(userInput)) + return errorMsg; + return null; + } + + } + + /* + * Default validators + */ /** * Callback for class using the monitor diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/EditableComboBoxWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/EditableComboBoxWrapper.java index d77a5aa5..c6b0245a 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/EditableComboBoxWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/EditableComboBoxWrapper.java @@ -4,7 +4,6 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Comparator; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; import org.openslx.dozmod.gui.control.ComboBox; /** @@ -13,8 +12,8 @@ import org.openslx.dozmod.gui.control.ComboBox; class EditableComboBoxWrapper extends AbstractControlWrapper<Object> { private final ComboBox<?> comboBox; - public EditableComboBoxWrapper(DialogChangeMonitor dcm, ComboBox<?> combo, Comparator<Object> comparator, ValidationConstraint<Object> constraint, String errorMessage) { - super(dcm, errorMessage, comparator, constraint); + public EditableComboBoxWrapper(DialogChangeMonitor dcm, ComboBox<?> combo, Comparator<Object> comparator) { + super(dcm, comparator); comboBox = combo; comboBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/FixedComboBoxWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/FixedComboBoxWrapper.java index 096aaa23..6b7a4b77 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/FixedComboBoxWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/FixedComboBoxWrapper.java @@ -4,7 +4,6 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Comparator; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; import org.openslx.dozmod.gui.control.ComboBox; /** @@ -13,8 +12,8 @@ import org.openslx.dozmod.gui.control.ComboBox; class FixedComboBoxWrapper<T> extends AbstractControlWrapper<T> { private final ComboBox<T> comboBox; - public FixedComboBoxWrapper(DialogChangeMonitor dcm, ComboBox<T> combo, Comparator<T> comparator, ValidationConstraint<T> constraint, String errorMessage) { - super(dcm, errorMessage, comparator, constraint); + public FixedComboBoxWrapper(DialogChangeMonitor dcm, ComboBox<T> combo, Comparator<T> comparator) { + super(dcm, comparator); comboBox = combo; comboBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/LecturePermissionManagerWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/LecturePermissionManagerWrapper.java index 88b618d6..a1f066a0 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/LecturePermissionManagerWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/LecturePermissionManagerWrapper.java @@ -4,7 +4,6 @@ import java.util.Comparator; import java.util.Map; import org.openslx.bwlp.thrift.iface.LecturePermissions; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; import org.openslx.dozmod.gui.control.LectureCustomPermissionManager; import org.openslx.dozmod.gui.control.LectureCustomPermissionManager.UserChangeEvent; import org.openslx.dozmod.gui.control.LectureCustomPermissionManager.UserChangeEventListener; @@ -23,9 +22,8 @@ class LecturePermissionManagerWrapper extends AbstractControlWrapper<Map<String, private final LectureCustomPermissionManager component; - public LecturePermissionManagerWrapper(DialogChangeMonitor dcm, LectureCustomPermissionManager manager, - ValidationConstraint<Map<String, LecturePermissions>> constr, String errorMessage) { - super(dcm, errorMessage, COMPARATOR, constr); + public LecturePermissionManagerWrapper(DialogChangeMonitor dcm, LectureCustomPermissionManager manager) { + super(dcm, COMPARATOR); this.component = manager; manager.addUserChangeEventListener(new UserChangeEventListener() { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/ListEditorWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/ListEditorWindow.java new file mode 100644 index 00000000..ebefd326 --- /dev/null +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/ListEditorWindow.java @@ -0,0 +1,40 @@ +package org.openslx.dozmod.gui.changemonitor; + +import java.util.List; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * For wrapping editors that contain controls to edit a list of some kind. + * When implementing inside a pop-up window, it should be sufficient to + * trigger the change event only once, when the user cancels or saves the + * changes, since the main window that's interested in the changes will + * be covered anyways during editing. + */ +public interface ListEditorWindow<T> { + + public List<T> getState(); + + public void addChangeListener(ChangeListener l); + +} + +class ListEditorWindowWrapper<T> extends AbstractControlWrapper<List<T>> { + private final ListEditorWindow<T> component; + + public ListEditorWindowWrapper(DialogChangeMonitor dcm, ListEditorWindow<T> comp) { + super(dcm, null); + this.component = comp; + + comp.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + contentChanged(); + } + }); + } + + List<T> getCurrentValue() { + return this.component.getState(); + } +}
\ No newline at end of file diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TableWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TableWrapper.java index f8bcfa01..5c03c2fc 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TableWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TableWrapper.java @@ -9,8 +9,6 @@ import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; - /** * Monitoring a JTable etc. */ @@ -47,9 +45,8 @@ class TableWrapper extends AbstractControlWrapper<ClonedTableModel> { private final JTable component; - public TableWrapper(DialogChangeMonitor dcm, JTable table, - ValidationConstraint<ClonedTableModel> constr, String errorMessage) { - super(dcm, errorMessage, COMPARATOR, constr); + public TableWrapper(DialogChangeMonitor dcm, JTable table) { + super(dcm, COMPARATOR); this.component = table; final TableModelListener changeListener = new TableModelListener() { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TextControlWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TextControlWrapper.java index 6535a113..0a06dd8e 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TextControlWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TextControlWrapper.java @@ -4,17 +4,14 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.JTextComponent; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; - /** * Monitoring a JTextField etc. */ class TextControlWrapper extends AbstractControlWrapper<String> { private final JTextComponent component; - public TextControlWrapper(DialogChangeMonitor dcm, JTextComponent textField, - ValidationConstraint<String> constr, String errorMessage) { - super(dcm, errorMessage, null, constr); + public TextControlWrapper(DialogChangeMonitor dcm, JTextComponent textField) { + super(dcm, null); this.component = textField; textField.getDocument().addDocumentListener(new DocumentListener() { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TimeSpinnerWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TimeSpinnerWrapper.java index ecb6e50c..a7d94f5d 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TimeSpinnerWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TimeSpinnerWrapper.java @@ -7,16 +7,14 @@ import javax.swing.JSpinner; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; - class TimeSpinnerWrapper extends AbstractControlWrapper<Object> { private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("k:m"); private final JSpinner component; - public TimeSpinnerWrapper(DialogChangeMonitor dcm, JSpinner picker, ValidationConstraint<Object> constr, String errorMessage) { - super(dcm, errorMessage, null, constr); + public TimeSpinnerWrapper(DialogChangeMonitor dcm, JSpinner picker) { + super(dcm, null); this.component = picker; picker.addChangeListener(new ChangeListener() { @@ -33,4 +31,5 @@ class TimeSpinnerWrapper extends AbstractControlWrapper<Object> { } return value; } + }
\ No newline at end of file diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LdapFilterConfigurator.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LdapFilterConfigurator.java index 1950327d..b4e5a4a8 100755 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LdapFilterConfigurator.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LdapFilterConfigurator.java @@ -163,8 +163,7 @@ public class LdapFilterConfigurator extends LdapFilterConfiguratorLayout { } public void addToChangeMonitor(DialogChangeMonitor changeMonitor) { - // TODO Auto-generated method stub - + changeMonitor.add(tblFilters); } } diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LocationSelector.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LocationSelector.java index f880cf7b..863028f0 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LocationSelector.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LocationSelector.java @@ -370,8 +370,8 @@ public class LocationSelector extends JPanel { } public void addToChangeMonitor(DialogChangeMonitor changeMonitor) { - treeChangeHandler = changeMonitor.add(locationTree, null, null); - changeMonitor.add(grpLocationExclusive, null, null); + treeChangeHandler = changeMonitor.add(locationTree); + changeMonitor.add(grpLocationExclusive); } public void addCheckChangeEventListener(CheckChangeEventListener checkChangeEventListener) { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetrulesConfigurator.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetrulesConfigurator.java index 4603cffd..036f3726 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetrulesConfigurator.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetrulesConfigurator.java @@ -122,9 +122,9 @@ public class NetrulesConfigurator extends NetrulesConfiguratorLayout { * * @return the list of rules as parsed by parseNetRules() */ - public List<NetRule> getState() { + public List<NetRule> getState(boolean silent) { // cleanup the TextPane for network rules if needed - return parseNetRules(false); + return parseNetRules(silent); } /** @@ -190,11 +190,16 @@ public class NetrulesConfigurator extends NetrulesConfiguratorLayout { // split it line by line boolean invalid = false; // True if the rules are invalid and null should be returned - DefaultStyledDocument newdoc = new DefaultStyledDocument(); // Used to build new document with colors + DefaultStyledDocument newdoc = null; + if (!silent) { + newdoc = new DefaultStyledDocument(); // Used to build new document with colors + } StringBuilder errors = new StringBuilder(); // Error messages to show (if not silent) int lineNo = 0; // Show line numbers in error messages Set<String> warnedHosts = new HashSet<>(); // Ask only once about each unknown host for (String ruleLine : rawNetRules.split("[\r\n]+")) { + if (silent && invalid) + return null; Color lineColor = null; LOGGER.debug("Parsing rule: " + ruleLine); // split the fields and check if we have 3 as expected. @@ -288,7 +293,9 @@ public class NetrulesConfigurator extends NetrulesConfiguratorLayout { + "an.", MessageType.ERROR, null, null); } - tpNetworkRules.setDocument(newdoc); + if (newdoc != null) { + tpNetworkRules.setDocument(newdoc); + } if (invalid) { return null; } @@ -297,6 +304,8 @@ public class NetrulesConfigurator extends NetrulesConfiguratorLayout { } private int addLine(DefaultStyledDocument doc, String line, Color color, boolean bold) { + if (doc == null) + return 0; if (color == null) { color = FOREGROUND_TEXT_COLOR; } diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/RunscriptConfigurator.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/RunscriptConfigurator.java index 49adce6e..3378294c 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/RunscriptConfigurator.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/RunscriptConfigurator.java @@ -200,7 +200,7 @@ public class RunscriptConfigurator extends RunscriptConfiguratorLayout { public void addToChangeMonitor(DialogChangeMonitor changeMonitor) { changeMonitor.add(taRunScript); - changeMonitor.addEditableCombo(cboRunscriptType, null, null, null); + changeMonitor.addEditableCombo(cboRunscriptType, null); } } diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/DateTimeHelper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/DateTimeHelper.java index 0b02bbf9..bd54a33c 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/DateTimeHelper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/DateTimeHelper.java @@ -14,19 +14,24 @@ public class DateTimeHelper { /** * Returns the Date composed of the given datePicker's date and the given - * timeSpinner's time + * timeSpinner's time. Returns null if the model of either one doesn't + * return a Date instance. * * @param datePicker to extract the date from * @param timeSpinner to extract the time from - * @return Date represented by datePicker's day and timeSpinner's time + * @return Date represented by datePicker's day and timeSpinner's time, + * {@code null} on error */ public static Date getDateFrom(JDatePicker datePicker, JSpinner timeSpinner) { // start date from the DatePicker int years = datePicker.getModel().getYear(); int months = datePicker.getModel().getMonth(); int days = datePicker.getModel().getDay(); + Object oTime = timeSpinner.getValue(); + if (!(oTime instanceof Date) || years < 1000) + return null; // start time from the Spinner - Date time = (Date) timeSpinner.getValue(); + Date time = (Date)oTime; Calendar calendar = Calendar.getInstance(); calendar.setTime(time); int hours = calendar.get(Calendar.HOUR_OF_DAY); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java index 512175a5..9794c37a 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java @@ -1,6 +1,5 @@ package org.openslx.dozmod.gui.window; -import java.awt.Color; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -35,6 +34,8 @@ import org.openslx.dozmod.gui.Gui; import org.openslx.dozmod.gui.MainWindow; import org.openslx.dozmod.gui.changemonitor.AbstractControlWrapper; import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; +import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.TextNotEmptyConstraint; +import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; import org.openslx.dozmod.gui.helper.DateTimeHelper; import org.openslx.dozmod.gui.helper.MessageType; import org.openslx.dozmod.gui.helper.UiFeedback; @@ -126,12 +127,31 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements }); // Add controls to change monitor - changeMonitor.addFixedCombo(cboVersions, Comparators.imageVersionDetails, + changeMonitor.addFixedCombo(cboVersions, Comparators.imageVersionDetails) + .addConstraint( new DialogChangeMonitor.ValidationConstraint<ImageVersionDetails>() { - public boolean isValid(ImageVersionDetails userInput) { - return userInput != null && userInput.isValid; + public String checkStateValid(ImageVersionDetails userInput) { + if (userInput != null && userInput.isValid) + return null; + return "Keine/Ungültige VM-Version ausgewählt"; } - }, "Keine/Ungültige VM-Version ausgewählt"); + }); + // Create constraint for date start/end + final Date maxValidity; + Calendar c = Calendar.getInstance(); + c.add(Calendar.DAY_OF_MONTH, Session.getSatelliteConfig().maxLectureValidityDays); + maxValidity = c.getTime(); + ValidationConstraint<Object> dateRangeValidator = new DialogChangeMonitor.ValidationConstraint<Object>() { + public String checkStateValid(Object ignored) { + Date start = DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime); + Date end = DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime); + if (!end.after(start)) + return "Enddatum darf nicht vor dem Startdatum liegen"; + if (end.after(maxValidity)) + return "Enddatum liegt nach dem " + FormatHelper.shortDate(maxValidity); + return null; + } + }; changeMonitor.add(chkAutoUpdate); changeMonitor.add(chkIsExam); changeMonitor.add(chkHasInternetAccess); @@ -139,20 +159,18 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements changeMonitor.add(chkIsActive); changeMonitor.add(chkCustomPermAdmin); changeMonitor.add(chkCustomPermEdit); - changeMonitor.add(txtTitle, DialogChangeMonitor.VC_NOT_EMPTY, "Veranstaltungsname darf nicht leer sein"); - changeMonitor.add(txtDescription, DialogChangeMonitor.VC_NOT_EMPTY, "Beschreibung darf nicht leer sein"); - changeMonitor.add(dtpEndDate, null, null); - changeMonitor.add(dtpStartDate, null, null); - changeMonitor.add(spnEndTime); - changeMonitor.add(spnStartTime); + changeMonitor.add(txtTitle).addConstraint(new TextNotEmptyConstraint("Veranstaltungsname darf nicht leer sein")); + changeMonitor.add(txtDescription).addConstraint(new TextNotEmptyConstraint("Beschreibung darf nicht leer sein")); + changeMonitor.add(dtpEndDate).addConstraint(dateRangeValidator); + changeMonitor.add(dtpStartDate).addConstraint(dateRangeValidator); + changeMonitor.add(spnEndTime).addConstraint(dateRangeValidator); + changeMonitor.add(spnStartTime).addConstraint(dateRangeValidator); changeListenerPermissions = changeMonitor.add(ctlPermissionManager); ctlLocationSelector.addToChangeMonitor(changeMonitor); ctlRunscriptConfigurator.addToChangeMonitor(changeMonitor); ctlNetshareConfigurator.addToChangeMonitor(changeMonitor); ctlLdapFilterConfigurator.addToChangeMonitor(changeMonitor); - // TODO: NetShare: Having uncommitted changes in the input fields should be handled too - // TODO: NetRules editor - // TODO: LDAP editor + // TODO: LDAP/NetShare: Having uncommitted changes in the input fields should be handled too // End change monitor addWindowListener(new WindowAdapter() { @@ -234,7 +252,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements btnNetrules.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - List<NetRule> newNetrules = LectureNetrulesWindow.open(me, lecture.networkExceptions); + List<NetRule> newNetrules = LectureNetrulesWindow.open(me, lecture.networkExceptions, changeMonitor); if (newNetrules != null) lecture.networkExceptions = newNetrules; } diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureNetrulesWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureNetrulesWindow.java index f570cc0e..e5b1659b 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureNetrulesWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureNetrulesWindow.java @@ -3,13 +3,18 @@ package org.openslx.dozmod.gui.window; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; +import javax.swing.event.ChangeListener; + import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.NetRule; import org.openslx.dozmod.gui.Gui; import org.openslx.dozmod.gui.Gui.GuiCallable; +import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; import org.openslx.dozmod.gui.helper.MessageType; import org.openslx.dozmod.gui.helper.UiFeedback; import org.openslx.dozmod.gui.window.layout.LectureNetrulesWindowLayout; @@ -24,13 +29,13 @@ public class LectureNetrulesWindow extends LectureNetrulesWindowLayout private List<NetRule> newRules = null; public LectureNetrulesWindow(Window modalParent, - List<NetRule> netrules) { + List<NetRule> netrules, DialogChangeMonitor changeMonitor) { super(modalParent); btnSave.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - newRules = ctlNetrulesConfigurator.getState(); + newRules = ctlNetrulesConfigurator.getState(false); if (newRules == null) { return; } @@ -46,6 +51,7 @@ public class LectureNetrulesWindow extends LectureNetrulesWindowLayout } }); ctlNetrulesConfigurator.setState(netrules); + changeMonitor.add(this).reset(); } /** @@ -64,17 +70,18 @@ public class LectureNetrulesWindow extends LectureNetrulesWindowLayout * * @param modalParent * parent to this window + * @param changeMonitor If you want to track changes... * @param locations * locations to preselect in the LocationSelector * @return forwards the return value of the window itself: list of ids of * the selected locations */ public static List<NetRule> open(final Window modalParent, - final List<NetRule> netrules) { + final List<NetRule> netrules, final DialogChangeMonitor changeMonitor) { return Gui.syncExec(new GuiCallable<List<NetRule>>() { @Override public List<NetRule> run() { - return new LectureNetrulesWindow(modalParent, netrules) + return new LectureNetrulesWindow(modalParent, netrules, changeMonitor) .runAndReturn(); } }); @@ -98,4 +105,20 @@ public class LectureNetrulesWindow extends LectureNetrulesWindowLayout dispose(); } } + + @Override + public List<NetRule> getState() { + return ctlNetrulesConfigurator.getState(true); + } + + @Override + public void addChangeListener(final ChangeListener l) { + addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + l.stateChanged(null); + } + }); + } + } diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureNetrulesWindowLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureNetrulesWindowLayout.java index 31a1a929..ce4067ce 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureNetrulesWindowLayout.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureNetrulesWindowLayout.java @@ -2,6 +2,9 @@ package org.openslx.dozmod.gui.window.layout; import java.awt.BorderLayout; import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.List; import javax.swing.BorderFactory; import javax.swing.Box; @@ -9,11 +12,14 @@ import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JPanel; +import javax.swing.event.ChangeListener; +import org.openslx.bwlp.thrift.iface.NetRule; import org.openslx.dozmod.gui.Gui; +import org.openslx.dozmod.gui.changemonitor.ListEditorWindow; import org.openslx.dozmod.gui.control.NetrulesConfigurator; -public class LectureNetrulesWindowLayout extends JDialog { +public abstract class LectureNetrulesWindowLayout extends JDialog implements ListEditorWindow<NetRule> { private static final long serialVersionUID = 5565439063675405598L; @@ -53,4 +59,5 @@ public class LectureNetrulesWindowLayout extends JDialog { pack(); Gui.centerShellOverShell(modalParent, this); } + } diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/LectureOptionsPage.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/LectureOptionsPage.java index 188d1c3b..73dc407e 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/LectureOptionsPage.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/LectureOptionsPage.java @@ -36,7 +36,7 @@ public class LectureOptionsPage extends LectureOptionsPageLayout { @Override public void actionPerformed(ActionEvent e) { List<NetRule> newNetrules = LectureNetrulesWindow.open( - SwingUtilities.getWindowAncestor(me), currentNetrules); + SwingUtilities.getWindowAncestor(me), currentNetrules, null); if (newNetrules != null) { currentNetrules = newNetrules; updateState(); |