diff options
| author | Simon Rettberg | 2018-06-20 17:02:18 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2018-06-20 17:02:18 +0200 |
| commit | d0b6c9c7243472d66b3e11fc733c19b01ae92749 (patch) | |
| tree | d567e33d2846e9d5ee36d1a5113bb7f44dcaeb85 | |
| parent | [client] Add GUI change handling classes (diff) | |
| download | tutor-module-d0b6c9c7243472d66b3e11fc733c19b01ae92749.tar.gz tutor-module-d0b6c9c7243472d66b3e11fc733c19b01ae92749.tar.xz tutor-module-d0b6c9c7243472d66b3e11fc733c19b01ae92749.zip | |
[client] Switch over LectureDetailsWindow to new change monitor system
This saves ~230 LOC, making the class about 25% smaller
10 files changed, 209 insertions, 451 deletions
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 03a2b553..1950327d 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 @@ -20,6 +20,7 @@ import javax.swing.event.TableModelListener; import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.LdapFilter; import org.openslx.dozmod.gui.Gui; +import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; import org.openslx.dozmod.gui.control.table.LectureLdapFilterTable; import org.openslx.dozmod.gui.control.table.QScrollPane; import org.openslx.dozmod.gui.helper.GridManager; @@ -160,6 +161,12 @@ public class LdapFilterConfigurator extends LdapFilterConfiguratorLayout { listener.stateChanged(null); } } + + public void addToChangeMonitor(DialogChangeMonitor changeMonitor) { + // TODO Auto-generated method stub + + } + } /** diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LectureCustomPermissionManager.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LectureCustomPermissionManager.java index d943d4c6..b853f7e2 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LectureCustomPermissionManager.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/LectureCustomPermissionManager.java @@ -3,6 +3,8 @@ package org.openslx.dozmod.gui.control; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.EventListener; import java.util.EventObject; @@ -53,8 +55,7 @@ public class LectureCustomPermissionManager extends JPanel { protected JButton btnAddUser; protected JButton btnRemoveUser; - private ArrayList<UserLecturePermissions> permissionList = new ArrayList<UserLecturePermissions>(); - private Map<String, LecturePermissions> newPermissionMap; + private final ArrayList<UserLecturePermissions> permissionList = new ArrayList<UserLecturePermissions>(); private LecturePermissions defaultPermissions; @@ -108,7 +109,7 @@ public class LectureCustomPermissionManager extends JPanel { permissionList.add(new UserLecturePermissions(newUser.userId, new LecturePermissions( defaultPermissions))); permissionTable.setData(permissionList, false); - fireUserChangeEvent(new UserChangeEvent(new Object())); + fireUserChangeEvent(); } }, "Hinzufügen", ownerId); } @@ -123,7 +124,7 @@ public class LectureCustomPermissionManager extends JPanel { LOGGER.debug("Could not remove: " + selected); } permissionTable.setData(permissionList, false); - fireUserChangeEvent(new UserChangeEvent(new Object())); + fireUserChangeEvent(); } }); @@ -136,9 +137,14 @@ public class LectureCustomPermissionManager extends JPanel { btnRemoveUser.doClick(); } }); - } - public LecturePermissionTable getTable() { - return permissionTable; + permissionTable.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + // TODO: This is stupid; permissionTable should fire an event + // if one of the check boxes changes. + fireUserChangeEvent(); + } + }); } /** @@ -152,13 +158,12 @@ public class LectureCustomPermissionManager extends JPanel { public void initPanel(Map<String, LecturePermissions> permissionMap, final LecturePermissions defaultPermissions, String ownerId) { this.ownerId = ownerId; - this.newPermissionMap = permissionMap == null ? new HashMap<String, LecturePermissions>() - : permissionMap; this.defaultPermissions = defaultPermissions; - permissionList.clear(); - for (Entry<String, LecturePermissions> e : newPermissionMap.entrySet()) { - permissionList.add(new UserLecturePermissions(e.getKey(), e.getValue())); + if (permissionMap != null) { + for (Entry<String, LecturePermissions> e : permissionMap.entrySet()) { + permissionList.add(new UserLecturePermissions(e.getKey(), e.getValue())); + } } permissionTable.setData(permissionList, false); } @@ -168,12 +173,8 @@ public class LectureCustomPermissionManager extends JPanel { * * @return Map with new custom permissions, null if something went wrong */ - public Map<String, LecturePermissions> updatePermissionReferences() { - if (permissionList == null) - return null; - - newPermissionMap.clear(); - + public Map<String, LecturePermissions> getPermissions() { + Map<String, LecturePermissions> newPermissionMap = new HashMap<>(permissionList.size()); // put permissions of the list into the map for (UserLecturePermissions perm : permissionList) { newPermissionMap.put(perm.userId, perm.permissions); @@ -198,11 +199,16 @@ public class LectureCustomPermissionManager extends JPanel { * (Mostly needed for the reactToChange() stuff in LectureDetailsWindow) */ protected EventListenerList listenerList = new EventListenerList(); + + /** + * Shared instance, since there is no data attached (yet) + */ + private static final UserChangeEvent CHANGE_EVENT = new UserChangeEvent(); - public class UserChangeEvent extends EventObject { + public static class UserChangeEvent extends EventObject { - public UserChangeEvent(Object source) { - super(source); + public UserChangeEvent() { + super(new Object()); } } @@ -218,12 +224,12 @@ public class LectureCustomPermissionManager extends JPanel { listenerList.remove(UserChangeEventListener.class, listener); } - void fireUserChangeEvent(UserChangeEvent evt) { + void fireUserChangeEvent() { Object[] listeners = listenerList.getListenerList(); for (int i = 0; i < listeners.length; i++) { if (listeners[i] == UserChangeEventListener.class) { ((UserChangeEventListener) listeners[i + 1]) - .stateChanged(evt); + .stateChanged(CHANGE_EVENT); } } } 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 29a3d570..f880cf7b 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 @@ -22,6 +22,9 @@ import javax.swing.tree.TreePath; import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.Location; import org.openslx.dozmod.gui.Gui; +import org.openslx.dozmod.gui.changemonitor.AbstractControlWrapper; +import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; +import org.openslx.dozmod.gui.control.JCheckBoxTree.CheckChangeEventListener; import org.openslx.dozmod.gui.helper.GridManager; import org.openslx.dozmod.thrift.Session; import org.openslx.dozmod.thrift.cache.MetaDataCache; @@ -43,7 +46,8 @@ public class LocationSelector extends JPanel { private final static Logger LOGGER = Logger.getLogger(LocationSelector.class); private final JRadioButton btnLimitToLocations; - private final JRadioButton btnPrioritizeInLocations; + private final JRadioButton btnPrioritizeInLocations; + private final ButtonGroup grpLocationExclusive; /** * Flag for the initialization state */ @@ -53,10 +57,13 @@ public class LocationSelector extends JPanel { * List of IDs of locations to set the selection to when we finished * initializing */ - private List<Integer> preselection; + private List<Integer> preselection = null; + private JCheckBoxTree locationTree = new JCheckBoxTree(); private HashMap<Integer, DefaultMutableTreeNode> locationNodesMap = new HashMap<Integer, DefaultMutableTreeNode>(); + private AbstractControlWrapper<?> treeChangeHandler = null; + /** * Constructor. Initializes the grid layout, the location lists and * initializes the data @@ -68,9 +75,9 @@ public class LocationSelector extends JPanel { "Veranstaltung mit höherer Priorität in den ausgewählten Räumen anzeigen"); btnPrioritizeInLocations.setSelected(true); - ButtonGroup grpButtons = new ButtonGroup(); - grpButtons.add(btnLimitToLocations); - grpButtons.add(btnPrioritizeInLocations); + grpLocationExclusive = new ButtonGroup(); + grpLocationExclusive.add(btnLimitToLocations); + grpLocationExclusive.add(btnPrioritizeInLocations); // build the grid GridManager grid = new GridManager(this, 1); @@ -88,34 +95,29 @@ public class LocationSelector extends JPanel { init(); } - public JCheckBoxTree getTree() { - return locationTree; - } - public JRadioButton[] getButtons() { - JRadioButton[] buttons = new JRadioButton[2]; - buttons[0] = btnLimitToLocations; - buttons[1] = btnPrioritizeInLocations; - return buttons; - } - /** * Async fetching of the list of the locations from the server */ private void init() { QuickTimer.scheduleOnce(new Task() { - List<Location> locsList = null; - @Override public void fire() { - locsList = MetaDataCache.getLocations(); + final List<Location> locsList = MetaDataCache.getLocations(); + if (locsList == null) + return; Gui.asyncExec(new Runnable() { @Override public void run() { - initDone = fillLocationsList(locsList); + fillLocationsList(locsList); + initDone = true; // check if preselection was set before we were done // initialising - if (initDone && preselection != null) { + if (preselection != null) { setSelectionInternal(preselection); + preselection = null; + if (treeChangeHandler != null) { + treeChangeHandler.reset(); + } } } }); @@ -131,12 +133,8 @@ public class LocationSelector extends JPanel { * of this widget. * * @param locations list of locations to set the available list to - * @return true if setting the list worked, false otherwise */ - public boolean fillLocationsList(final List<Location> locations) { - if (locations == null) - return false; - + private void fillLocationsList(final List<Location> locations) { DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(Session.getSatelliteAddress()); DefaultTreeModel treeModel = new DefaultTreeModel(rootNode, true); // build map containing the node object for each location @@ -184,7 +182,6 @@ public class LocationSelector extends JPanel { locationTree.setModel(treeModel); locationTree.updateUI(); locationTree.repaint(); - return true; } /** @@ -218,10 +215,14 @@ public class LocationSelector extends JPanel { LOGGER.error("No list given!"); return; } - preselection = list; - // if we are initialised, we need to explicitly set the selection if (initDone) { - setSelectionInternal(preselection); + // if we are already initialised, we need to explicitly set the selection + setSelectionInternal(list); + } else { + if (treeChangeHandler != null) { + treeChangeHandler.mute(); + } + preselection = list; } } @@ -367,6 +368,15 @@ public class LocationSelector extends JPanel { locationTree.setCheckedState(selectedPathsList, true); locationTree.repaint(); } + + public void addToChangeMonitor(DialogChangeMonitor changeMonitor) { + treeChangeHandler = changeMonitor.add(locationTree, null, null); + changeMonitor.add(grpLocationExclusive, null, null); + } + + public void addCheckChangeEventListener(CheckChangeEventListener checkChangeEventListener) { + locationTree.addCheckChangeEventListener(checkChangeEventListener); + } } @SuppressWarnings("serial") diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetshareConfigurator.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetshareConfigurator.java index 317e172b..d80ba8b3 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetshareConfigurator.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/NetshareConfigurator.java @@ -32,6 +32,7 @@ import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.NetShare; import org.openslx.bwlp.thrift.iface.NetShareAuth; import org.openslx.dozmod.gui.Gui; +import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; import org.openslx.dozmod.gui.control.ComboBox.ComboBoxRenderer; import org.openslx.dozmod.gui.control.table.NetshareTable; import org.openslx.dozmod.gui.control.table.QScrollPane; @@ -54,17 +55,7 @@ public class NetshareConfigurator extends NetshareConfiguratorLayout { 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; public NetshareConfigurator() { - super(); - - tblNetshare.getModel().addTableModelListener(new TableModelListener() { - @Override - public void tableChanged(TableModelEvent e) { - fireNetshareConfigurationChangeEvent( - new NetshareConfigurationChangeEvent(NetshareConfigurator.this)); - } - }); - tblNetshare.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { @@ -268,39 +259,13 @@ public class NetshareConfigurator extends NetshareConfiguratorLayout { tblNetshare.setData(tblNetshareData, false); return true; } - - protected EventListenerList listenerList = new EventListenerList(); - - public class NetshareConfigurationChangeEvent extends EventObject { - - private static final long serialVersionUID = -511509960878320591L; - - public NetshareConfigurationChangeEvent(Object source) { - super(source); - } - } - - public interface NetshareConfigurationChangeEventListener extends EventListener { - public void stateChanged(NetshareConfigurationChangeEvent event); - } - - public void addNetshareConfigurationChangeEventListener( - NetshareConfigurationChangeEventListener listener) { - listenerList.add(NetshareConfigurationChangeEventListener.class, listener); + + public void addTableModelListener(TableModelListener listener) { + tblNetshare.getModel().addTableModelListener(listener); } - public void removeNetshareConfigurationChangeEventListener( - NetshareConfigurationChangeEventListener listener) { - listenerList.remove(NetshareConfigurationChangeEventListener.class, listener); - } - - void fireNetshareConfigurationChangeEvent(NetshareConfigurationChangeEvent evt) { - Object[] listeners = listenerList.getListenerList(); - for (int i = 0; i < listeners.length; i++) { - if (listeners[i] == NetshareConfigurationChangeEventListener.class) { - ((NetshareConfigurationChangeEventListener) listeners[i + 1]).stateChanged(evt); - } - } + public void addToChangeMonitor(DialogChangeMonitor changeMonitor) { + changeMonitor.add(tblNetshare); } } @@ -315,14 +280,14 @@ class NetshareConfiguratorLayout extends JPanel { + " die automatisch beim Start der Veranstaltung eingebunden werden sollen." + " Der Platzhalter <em>%loginuser%</em> wird im Pfad durch den Loginnamen des Nutzers ersetzt.</html>"; - protected QLabel lblShareAuth, lblSharePath, lblShareName, lblMountPoint, lblUsername, lblPassword, + protected final QLabel lblShareAuth, lblSharePath, lblShareName, lblMountPoint, lblUsername, lblPassword, lblError; - protected NetshareTable tblNetshare = new NetshareTable(); - protected JTextField tfSharePath, tfShareName, tfUsername; - protected JPasswordField tfPassword; - protected JButton btnAdd, btnDel; - protected JCheckBox chkShowPass; - protected ComboBox<NetShareAuth> cboNetshareAuth = new ComboBox<>(new ComboBoxRenderer<NetShareAuth>() { + protected final NetshareTable tblNetshare = new NetshareTable(); + protected final JTextField tfSharePath, tfShareName, tfUsername; + protected final JPasswordField tfPassword; + protected final JButton btnAdd, btnDel; + protected final JCheckBox chkShowPass; + protected final ComboBox<NetShareAuth> cboNetshareAuth = new ComboBox<>(new ComboBoxRenderer<NetShareAuth>() { @Override public String renderItem(NetShareAuth item) { if (item == null) @@ -330,7 +295,7 @@ class NetshareConfiguratorLayout extends JPanel { return FormatHelper.netShareAuthName(item); } }); - protected ComboBox<Character> cboNetshareMountPoint = new ComboBox<>(new ComboBoxRenderer<Character>() { + protected final ComboBox<Character> cboNetshareMountPoint = new ComboBox<>(new ComboBoxRenderer<Character>() { @Override public String renderItem(Character letter) { if (letter == null) 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 d3935b62..49adce6e 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 @@ -19,6 +19,7 @@ import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.event.EventListenerList; +import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; import org.openslx.dozmod.gui.control.ComboBox.ComboBoxRenderer; import org.openslx.dozmod.gui.control.RunscriptConfigurator.RunscriptType; import org.openslx.dozmod.gui.helper.GridManager; @@ -196,6 +197,12 @@ public class RunscriptConfigurator extends RunscriptConfiguratorLayout { } } } + + public void addToChangeMonitor(DialogChangeMonitor changeMonitor) { + changeMonitor.add(taRunScript); + changeMonitor.addEditableCombo(cboRunscriptType, null, null, null); + } + } /** 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 4ae8af93..512175a5 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 @@ -6,8 +6,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; @@ -15,18 +13,13 @@ import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import javax.swing.DefaultComboBoxModel; import javax.swing.JFrame; import javax.swing.JOptionPane; -import javax.swing.JRadioButton; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import org.apache.log4j.Logger; import org.apache.thrift.TException; @@ -37,21 +30,13 @@ import org.openslx.bwlp.thrift.iface.LecturePermissions; import org.openslx.bwlp.thrift.iface.LectureRead; import org.openslx.bwlp.thrift.iface.LectureWrite; import org.openslx.bwlp.thrift.iface.NetRule; -import org.openslx.bwlp.thrift.iface.NetShare; import org.openslx.bwlp.thrift.iface.UserInfo; import org.openslx.dozmod.gui.Gui; import org.openslx.dozmod.gui.MainWindow; -import org.openslx.dozmod.gui.control.JCheckBoxTree.CheckChangeEvent; -import org.openslx.dozmod.gui.control.JCheckBoxTree.CheckChangeEventListener; -import org.openslx.dozmod.gui.control.LectureCustomPermissionManager.UserChangeEvent; -import org.openslx.dozmod.gui.control.LectureCustomPermissionManager.UserChangeEventListener; -import org.openslx.dozmod.gui.control.NetshareConfigurator.NetshareConfigurationChangeEvent; -import org.openslx.dozmod.gui.control.NetshareConfigurator.NetshareConfigurationChangeEventListener; -import org.openslx.dozmod.gui.control.RunscriptConfigurator.RunscriptConfigurationChangeEvent; -import org.openslx.dozmod.gui.control.RunscriptConfigurator.RunscriptConfigurationChangeEventListener; +import org.openslx.dozmod.gui.changemonitor.AbstractControlWrapper; +import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; import org.openslx.dozmod.gui.helper.DateTimeHelper; import org.openslx.dozmod.gui.helper.MessageType; -import org.openslx.dozmod.gui.helper.TextChangeListener; import org.openslx.dozmod.gui.helper.UiFeedback; import org.openslx.dozmod.gui.window.UserListWindow.UserAddedCallback; import org.openslx.dozmod.gui.window.layout.LectureDetailsWindowLayout; @@ -64,7 +49,7 @@ import org.openslx.dozmod.thrift.ThriftActions.LectureMetaCallback; import org.openslx.dozmod.thrift.ThriftError; import org.openslx.dozmod.thrift.cache.UserCache; import org.openslx.dozmod.util.FormatHelper; -import org.openslx.dozmod.util.MapHelper; +import org.openslx.thrifthelper.Comparators; import org.openslx.thrifthelper.ThriftManager; /** @@ -98,53 +83,18 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements private LectureRead lecture = null; /** - * The custom permissions of the lecture - */ - private Map<String, LecturePermissions> customPermissions; - - /** - * The original custom permissions as fetched from the server - */ - private Map<String, LecturePermissions> originalCustomPermissions; - - /** - * The original default permissions as fetched from the server - */ - private LecturePermissions originalDefaultPermissions; - /** * Image, that the lecture is linked to. */ private ImageDetailsRead image = null; - - /** - * Flag indicating a change in this lecture's linked image - */ - private boolean imageLinkChanged = false; - - /** - * Flag indicating a change in this lecture's metadata - */ - private boolean metadataChanged = false; - + /** - * Flag indicating a change in this lecture's permissions + * Per-User permissions of this lecture */ - private boolean permissionsChanged = false; + private Map<String, LecturePermissions> customPermissions; - /** - * Holder of the location information of this lecture - */ - private LocationInfo locationInfo = null; + private final DialogChangeMonitor changeMonitor; - /** - * Holder of the netrules/runscript of this lecture - */ - private List<NetRule> currentNetrules = null; - private List<NetRule> originalNetrules = null; - private String currentRunscript = null; - private String originalRunscript = null; - private List<NetShare> currentNetshares = null; - private List<NetShare> originalNetshares = null; + private final AbstractControlWrapper<?> changeListenerPermissions; /** * Constructor @@ -159,6 +109,51 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements this.callback = callback; setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + // Set up change monitor + changeMonitor = new DialogChangeMonitor(new DialogChangeMonitor.Callback() { + @Override + public void validityChanged(String errorMessage) { + lblError.setText(errorMessage); + btnSaveChanges.setEnabled(changeMonitor.isValid() && changeMonitor.wasEverModified()); + LOGGER.info("Valid: " + changeMonitor.isValid()); + } + @Override + public void modificationChanged() { + btnSaveChanges.setEnabled(changeMonitor.isValid() && changeMonitor.wasEverModified()); + LOGGER.info("Changed: " + changeMonitor.isCurrentlyModified()); + } + }); + + // Add controls to change monitor + changeMonitor.addFixedCombo(cboVersions, Comparators.imageVersionDetails, + new DialogChangeMonitor.ValidationConstraint<ImageVersionDetails>() { + public boolean isValid(ImageVersionDetails userInput) { + return userInput != null && userInput.isValid; + } + }, "Keine/Ungültige VM-Version ausgewählt"); + changeMonitor.add(chkAutoUpdate); + changeMonitor.add(chkIsExam); + changeMonitor.add(chkHasInternetAccess); + changeMonitor.add(chkHasUsbAccess); + 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); + 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 + // End change monitor addWindowListener(new WindowAdapter() { @Override @@ -173,6 +168,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements ImageSummaryRead newImage = LectureChangeImage.open(me); if (newImage != null) { try { + // TODO: Async!? image = ThriftManager.getSatClient().getImageDetails(Session.getSatelliteToken(), newImage.imageBaseId); } catch (TException e1) { @@ -184,9 +180,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements fillVersionsCombo(); cboVersions.setEnabled(false); chkAutoUpdate.setSelected(true); - imageLinkChanged = true; txtImageName.setText(newImage.getImageName()); - reactToChange(); } } }); @@ -203,9 +197,9 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements performImageDownload(); } }); - chkAutoUpdate.addActionListener(new ActionListener() { + chkAutoUpdate.addItemListener(new ItemListener() { @Override - public void actionPerformed(ActionEvent e) { + public void itemStateChanged(ItemEvent e) { cboVersions.setEnabled(!chkAutoUpdate.isSelected()); } }); @@ -224,117 +218,28 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements }, "Besitzer festlegen", lecture.ownerId); } }); - - final ActionListener changeReacter = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - reactToChange(); - } - }; - ctlLocationSelector.getTree().addCheckChangeEventListener(new CheckChangeEventListener() { - @Override - public void checkStateChanged(CheckChangeEvent event) { - reactToChange(); - } - }); - for (JRadioButton btn : ctlLocationSelector.getButtons()) { - btn.addActionListener(changeReacter); - } - final ActionListener updateDefaultPermissionListener = new ActionListener() { + // Update default permissions in the permission manager immediately, so it affects + // newly added users + final ItemListener updateDefaultPermissionListener = new ItemListener() { @Override - public void actionPerformed(ActionEvent e) { + public void itemStateChanged(ItemEvent e) { ctlPermissionManager.updateDefaultPermissions(chkCustomPermAdmin.isSelected(), chkCustomPermEdit.isSelected()); - reactToChange(); } }; - chkCustomPermAdmin.addActionListener(updateDefaultPermissionListener); - chkCustomPermEdit.addActionListener(updateDefaultPermissionListener); - ctlPermissionManager.getTable().addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - reactToChange(); - } - }); - ctlPermissionManager.addUserChangeEventListener(new UserChangeEventListener() { - @Override - public void stateChanged(UserChangeEvent event) { - reactToChange(); - } - }); - chkCustomPermAdmin.addActionListener(changeReacter); - chkCustomPermEdit.addActionListener(changeReacter); - + chkCustomPermAdmin.addItemListener(updateDefaultPermissionListener); + chkCustomPermEdit.addItemListener(updateDefaultPermissionListener); + btnNetrules.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - List<NetRule> newNetrules = LectureNetrulesWindow.open(me, currentNetrules); + List<NetRule> newNetrules = LectureNetrulesWindow.open(me, lecture.networkExceptions); if (newNetrules != null) - currentNetrules = newNetrules; - reactToChange(); - } - }); - - final TextChangeListener docListener = new TextChangeListener() { - @Override - public void changed() { - reactToChange(); - } - }; - - txtTitle.getDocument().addDocumentListener(docListener); - txtDescription.getDocument().addDocumentListener(docListener); - ctlRunscriptConfigurator.addRunscriptConfigurationChangeEventListener(new RunscriptConfigurationChangeEventListener() { - @Override - public void stateChanged(RunscriptConfigurationChangeEvent event) { - reactToChange(); - } - - }); - ctlNetshareConfigurator.addNetshareConfigurationChangeEventListener(new NetshareConfigurationChangeEventListener() { - @Override - public void stateChanged(NetshareConfigurationChangeEvent event) { - reactToChange(); + lecture.networkExceptions = newNetrules; } }); - // Comboboxes - final ItemListener comboItemListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - reactToChange(); - } - } - }; - cboVersions.addItemListener(comboItemListener); - // Listener to detect changes in checkboxes - final ActionListener actionListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - reactToChange(); - } - }; - ChangeListener changeListener = new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - reactToChange(); - } - }; - chkAutoUpdate.addActionListener(actionListener); - chkIsExam.addActionListener(actionListener); - chkHasInternetAccess.addActionListener(actionListener); - chkHasUsbAccess.addActionListener(actionListener); - chkIsActive.addActionListener(actionListener); - dtpStartDate.addActionListener(actionListener); - dtpEndDate.addActionListener(actionListener); - spnStartTime.addChangeListener(changeListener); - spnEndTime.addChangeListener(changeListener); - ctlLdapFilterConfigurator.addLdapFilterListTableContentConfigurationChangeEventListener(changeListener); - - // save default color of date/time stuff to reset the background later - dateTimeTextColor = dtpStartDate.getForeground(); // last step, the save button btnSaveChanges.addActionListener(new ActionListener() { @Override @@ -393,41 +298,13 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements txtImageName.setText(image.getImageName()); lblImageNameInfo.setText(image.getImageName()); } - - // remember original netrules and runscript - originalNetrules = lecture.networkExceptions != null ? lecture.networkExceptions : new ArrayList<NetRule>(); - originalRunscript = lecture.runscript != null ? lecture.runscript : new String(""); - originalNetshares = lecture.networkShares != null ? new ArrayList<NetShare>(lecture.networkShares) : new ArrayList<NetShare>(); - - currentNetrules = originalNetrules; - currentRunscript = originalRunscript; - currentNetshares = originalNetshares; - - - // remember default permissions - if (lecture.defaultPermissions != null) { - originalDefaultPermissions = new LecturePermissions(lecture.defaultPermissions); - } - // remember custom permissions - if (customPermissions != null) { - // need a deep copy of the permission map to be able to check for changes after ImageCustomPermissionWindow - if (originalCustomPermissions == null) - originalCustomPermissions = new HashMap<String, LecturePermissions>(); - else - originalCustomPermissions.clear(); - // fill it - for (Entry<String, LecturePermissions> entry : customPermissions.entrySet()) { - originalCustomPermissions.put(entry.getKey(), new LecturePermissions(entry.getValue())); - } - } // init permission info ctlPermissionManager.initPanel(customPermissions, lecture.defaultPermissions, lecture.ownerId); chkCustomPermAdmin.setSelected(lecture.defaultPermissions.admin); chkCustomPermEdit.setSelected(lecture.defaultPermissions.edit); // init location info - locationInfo = new LocationInfo(lecture.locationIds, lecture.limitToLocations); - ctlLocationSelector.setOnlyInSelection(locationInfo.limitToLocations); - ctlLocationSelector.setSelectedLocationsAsIds(locationInfo.locationList); + ctlLocationSelector.setOnlyInSelection(lecture.limitToLocations); + ctlLocationSelector.setSelectedLocationsAsIds(lecture.locationIds); // init advanced info ctlRunscriptConfigurator.setState(lecture.runscript); @@ -473,6 +350,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements // and always switch to the "About" tab pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Übersicht")); setVisible(true); + changeMonitor.reset(); } /** @@ -571,107 +449,6 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements } /** - * Checks whether the user changed any fields of the image details and - * enables the save button if so. - */ - private void reactToChange() { - // before checks we need to update the local objects holding the information of the "widgets" - // update the location information - locationInfo = new LocationInfo(ctlLocationSelector.getSelectedLocationsAsIds(), - ctlLocationSelector.getOnlyInSelection()); - // update the custom permissions - customPermissions = ctlPermissionManager.updatePermissionReferences(); - // NOTE: AdvancedConfiguration stuff will only get checked when clicking "Save" since - // checking for rules syntax while the user is still typing does not make much sense... - // now we can check for changes - metadataChanged = reactToChangeInternal(); - permissionsChanged = MapHelper.hasChanged(originalCustomPermissions, customPermissions); - btnSaveChanges.setEnabled(metadataChanged || permissionsChanged); - } - - /** - * Checks whether the user changed any fields of the image details and - * enables the save button if so. - */ - private boolean reactToChangeInternal() { - if (lecture == null) - return false; - - boolean changed = false; - // mandatory fields checks - if (txtTitle.getText().isEmpty()) { - pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Allgemein")); - lblError.setText("Kein Veranstaltungsname gesetzt!"); - return false; - } - if (txtDescription.getText().isEmpty()) { - pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Allgemein")); - lblError.setText("Keine Beschreibung angegeben!"); - return false; - } - // version checkbox changed? - ImageVersionDetails currentVersion = cboVersions.getItemAt(cboVersions.getSelectedIndex()); - if (currentVersion == null) { - pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Allgemein")); - lblError.setText("Keine Version ausgewählt!"); - return false; - } - // Date stuff - Date start = DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime); - Date end = DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime); - if (!isPeriodValid(start, end, false) && dateHasChanged()) { - pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Allgemein")); - lblError.setText("Ungültiger Zeitraum!"); - return false; - } - // runscript stuff - String newState = ctlRunscriptConfigurator.getState(); - if (newState == null) { - // script extension was missing from the user input. - // feedback happens in the configurator, just switch to the tab. - pnlTabs.setSelectedIndex(pnlTabs.indexOfTab("Startskript")); - return false; - } else { - currentRunscript = newState; - } - - // netshare stuff - List<NetShare> newNetshareList = ctlNetshareConfigurator.getState(); - if (newNetshareList != null) { - currentNetshares = newNetshareList; - } - // done with mandatory checks, remove error message - lblError.setText(null); - - - // TODO: Refactor change detection and error display so you don't lose your mind when - // trying to work with it. - return true; - - /* - // check for changes in all fields - changed = !txtTitle.getText().equals(lecture.getLectureName()) - || !txtDescription.getText().equals(lecture.getDescription()) - || !currentVersion.getVersionId().equals(lecture.getImageVersionId()) - || (DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime).getTime() / 1000L) != lecture.getStartTime() - || (DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime).getTime() / 1000L) != lecture.getEndTime() - || chkAutoUpdate.isSelected() != lecture.autoUpdate - || chkIsExam.isSelected() != lecture.isExam - || chkHasInternetAccess.isSelected() != lecture.hasInternetAccess - || chkHasUsbAccess.isSelected() != lecture.hasUsbAccess - || chkIsActive.isSelected() != lecture.isEnabled - || !lecture.defaultPermissions.equals(originalDefaultPermissions) - || (locationInfo != null && lecture.locationIds != null && !lecture.locationIds.equals(locationInfo.locationList)) - || (locationInfo != null && lecture.limitToLocations != locationInfo.limitToLocations) - || (currentNetrules != null && !currentNetrules.equals(originalNetrules)) - || (currentRunscript != null && !currentRunscript.equals(originalRunscript)) - || (currentNetshares != null && !currentNetshares.equals(originalNetshares)) - || imageLinkChanged; - return changed; - */ - } - - /** * Triggers the saving of the changes of this lecture * And inform the callback function about the outcome */ @@ -691,56 +468,55 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements * @return true if saving succeeded, false otherwise. */ private boolean saveChangesInternal() { + long startTime = DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime).getTime() / 1000L; + long endTime = DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime).getTime() / 1000L; + if (!isPeriodValid(startTime, endTime, true)) + return false; + // check, whether autoupdate is selected and choose version accordingly if (image != null) { lecture.imageVersionId = chkAutoUpdate.isSelected() ? image.latestVersionId : cboVersions.getItemAt(cboVersions.getSelectedIndex()).versionId; } - metadataChanged |= (currentNetrules != lecture.networkExceptions - || currentRunscript != lecture.runscript - || currentNetshares != lecture.networkShares); - // now check if we need to push a new LectureWrite - if (metadataChanged) { - // first build the LectureWrite from the GUI fields - final LectureWrite metadata = new LectureWrite(txtTitle.getText(), txtDescription.getText(), - lecture.getImageVersionId(), chkAutoUpdate.isSelected(), chkIsActive.isSelected(), - DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime).getTime() / 1000L, - DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime).getTime() / 1000L, currentRunscript, null, - chkIsExam.isSelected(), chkHasInternetAccess.isSelected(), // TODO USBACCESS - lecture.getDefaultPermissions(), locationInfo.locationList, locationInfo.limitToLocations, - // TODO: coming "false" is Location related - false, chkHasUsbAccess.isSelected()); - metadata.setNetworkExceptions(currentNetrules); - metadata.setNetworkShares(currentNetshares); - metadata.setLdapFilters(ctlLdapFilterConfigurator.getState()); - - // now trigger the actual action - try { - ThriftManager.getSatClient().updateLecture(Session.getSatelliteToken(), - lecture.getLectureId(), metadata); - metadataChanged = false; - LOGGER.info("Successfully save new metadata"); - } catch (TException e) { - ThriftError.showMessage(JOptionPane.getFrameForComponent(this), LOGGER, e, - "Fehler beim Updaten der Veranstaltung!"); - callback.updated(false); - return false; - } + // first build the LectureWrite from the GUI fields + final LectureWrite metadata = new LectureWrite(txtTitle.getText(), txtDescription.getText(), + lecture.getImageVersionId(), chkAutoUpdate.isSelected(), chkIsActive.isSelected(), + startTime, endTime, + ctlRunscriptConfigurator.getState(), null, + chkIsExam.isSelected(), + chkHasInternetAccess.isSelected(), + lecture.getDefaultPermissions(), ctlLocationSelector.getSelectedLocationsAsIds(), + ctlLocationSelector.getOnlyInSelection(), + // TODO: coming "false" is Location related + false, chkHasUsbAccess.isSelected()); + metadata.setNetworkExceptions(lecture.networkExceptions); + metadata.setNetworkShares(ctlNetshareConfigurator.getState()); + metadata.setLdapFilters(ctlLdapFilterConfigurator.getState()); + + // now trigger the actual action + try { + ThriftManager.getSatClient().updateLecture(Session.getSatelliteToken(), + lecture.getLectureId(), metadata); + LOGGER.info("Successfully save new metadata"); + } catch (TException e) { + ThriftError.showMessage(JOptionPane.getFrameForComponent(this), LOGGER, e, + "Fehler beim Speichern der Veranstaltung!"); + return false; } - if (permissionsChanged) { + + if (changeListenerPermissions.isCurrentlyChanged()) { try { ThriftManager.getSatClient().writeLecturePermissions(Session.getSatelliteToken(), lecture.lectureId, customPermissions); - permissionsChanged = false; LOGGER.info("Successfully save new permissions"); } catch (TException e) { ThriftError.showMessage(JOptionPane.getFrameForComponent(this), LOGGER, e, "Fehler beim Übertragen der Berechtigungen!"); - callback.updated(true); return false; } } + changeMonitor.reset(); return true; } @@ -754,33 +530,22 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements * otherwise * @return true if the period is valid, false otherwise */ - private boolean isPeriodValid(final Date start, final Date end, boolean feedback) { - if (start == null || end == null) + private boolean isPeriodValid(long start, long end, boolean feedback) { + if (start <= 0 || end <= 0) return false; // analyse time stuff to see if its valid - if (start.after(end)) { - dtpStartDate.setForeground(Color.red); - if (feedback) - Gui.showMessageBox(me, "Start der Veranstaltung ist nach dem Enddatum!", MessageType.ERROR, - LOGGER, null); - } else { - dtpStartDate.setForeground(dateTimeTextColor); + if (end > start) return true; + String msg = "Start der Veranstaltung ist nach dem Enddatum!"; + if (feedback) { + Gui.showMessageBox(me, msg, MessageType.ERROR, + LOGGER, null); } + lblError.setText(msg); return false; } /** - * Check whether the date has been changed - * - * @return true if it has changed, false otherwise - */ - private boolean dateHasChanged() { - return (DateTimeHelper.getDateFrom(dtpStartDate, spnStartTime).getTime() / 1000L) != lecture.getStartTime() - || (DateTimeHelper.getDateFrom(dtpEndDate, spnEndTime).getTime() / 1000L) != lecture.getEndTime(); - } - - /** * Enables/Disables the tabs based on the given flag 'editable'. * * @param editable when true, will enable the tabs if the user is allowed to see them. @@ -839,7 +604,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements ********************************************************************************/ @Override public boolean wantConfirmQuit() { - return metadataChanged || permissionsChanged; + return changeMonitor.isCurrentlyModified(); } @Override @@ -853,7 +618,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements * confirmation if so */ private void safeClose() { - if ((metadataChanged || permissionsChanged) + if (changeMonitor.isCurrentlyModified() && !Gui.showMessageBox(me, "Änderungen werden verworfen, wollen Sie wirklich schließen?", MessageType.QUESTION_YESNO, null, null)) return; diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LecturePermissionWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LecturePermissionWindow.java index a134fedd..332835f9 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LecturePermissionWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LecturePermissionWindow.java @@ -76,7 +76,7 @@ public class LecturePermissionWindow extends LecturePermissionWindowLayout imple private void run() { setVisible(true); if (okUsed) - ctlPermissionManager.updatePermissionReferences(); + ctlPermissionManager.getPermissions(); } /** diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LocationSelectionWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LocationSelectionWindow.java index 4ce0309f..bf818cf5 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LocationSelectionWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LocationSelectionWindow.java @@ -66,7 +66,7 @@ public class LocationSelectionWindow extends LocationSelectionWindowLayout imple }); // addCheckChangeEventListener - ctlLocationSelector.getTree().addCheckChangeEventListener(new CheckChangeEventListener() { + ctlLocationSelector.addCheckChangeEventListener(new CheckChangeEventListener() { @Override public void checkStateChanged(CheckChangeEvent event) { List<Integer> tempIntList = ctlLocationSelector.getSelectedLocationsAsIds(); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java index 6f2a383b..f0e03375 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/LectureDetailsWindowLayout.java @@ -87,8 +87,6 @@ public abstract class LectureDetailsWindowLayout extends JDialog { protected final JSpinner spnStartTime; protected final JSpinner spnEndTime; - protected Color dateTimeTextColor; - protected JTabbedPane pnlTabs; protected final LectureCustomPermissionManager ctlPermissionManager; protected final LocationSelector ctlLocationSelector; diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/LectureCustomPermissionPage.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/LectureCustomPermissionPage.java index 4500b7e6..2d37238a 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/LectureCustomPermissionPage.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/LectureCustomPermissionPage.java @@ -47,7 +47,7 @@ public class LectureCustomPermissionPage extends LectureCustomPermissionPageLayo // save the table stuff to our upload wizard state state.defaultPermissions.edit = chkPermissionEdit.isSelected(); state.defaultPermissions.admin = chkPermissionAdmin.isSelected(); - Map<String, LecturePermissions> newPermissionMap = lectureCustomPermissionManager.updatePermissionReferences(); + Map<String, LecturePermissions> newPermissionMap = lectureCustomPermissionManager.getPermissions(); if (newPermissionMap == null || newPermissionMap.isEmpty()) { return true; } |
