package comeon.ui.preferences;
import comeon.ui.preferences.main.PreferencesController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import java.beans.PropertyChangeListener;
public abstract class SubController<M extends Model, V extends SubPanel<M>> implements ListSelectionListener, PropertyChangeListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SubController.class);
private final PreferencesController mainController;
private V view;
private M model;
private M lastSelectedModel;
protected SubController(final PreferencesController mainController) {
this.mainController = mainController;
this.switchToBlankModel();
}
public void setView(V view) {
this.view = view;
this.registerViewInterval(view);
}
protected final V getView() {
return this.view;
}
protected final M getModel() {
return model;
}
public final PreferencesController getMainController() {
return mainController;
}
public final void switchToBlankModel() {
this.switchToModel(this.makeNewModel());
}
public final void commit(final int index) {
this.doCommit(model, lastSelectedModel, index);
}
protected abstract void doCommit(final M source, final M target, final int index);
protected abstract void registerViewInterval(final V view);
@SuppressWarnings("unchecked")
public final void rollback() {
try {
final M newModel;
if (lastSelectedModel == null) {
newModel = null;
} else {
newModel = (M) lastSelectedModel.clone();
}
this.switchToModel(newModel);
} catch (final CloneNotSupportedException e) {
LOGGER.error("Could not clone {}", lastSelectedModel, e);
}
}
public final void addCurrentModel() {
this.addModel(model);
this.switchToBlankModel();
}
private void switchToModel(final M model) {
final M oldModel = this.model;
if (oldModel != null) {
oldModel.removePropertyChangeListener(this);
}
this.model = model;
if (this.model != null) {
if (this.view != null) {
this.onModelChangedInternal(oldModel, model);
}
this.model.addPropertyChangeListener(this);
}
}
@Override
@SuppressWarnings("unchecked")
public final void valueChanged(final ListSelectionEvent e) {
final JList<M> list = (JList<M>) e.getSource();
final M selectedValue = list.getSelectedValue();
this.lastSelectedModel = selectedValue;
try {
final M newModel;
if (selectedValue == null) {
newModel = null;
} else {
newModel = (M) selectedValue.clone();
}
this.switchToModel(newModel);
} catch (final CloneNotSupportedException ex) {
LOGGER.error("Could not clone {}", selectedValue, e);
}
}
protected abstract void addModel(final M model);
protected abstract M makeNewModel();
public abstract void remove(final int index);
protected abstract void onModelChangedInternal(final M oldModel, final M newModel);
protected abstract class AbstractDocumentListener implements DocumentListener {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public final void removeUpdate(final DocumentEvent e) {
this.update(e);
}
@Override
public final void insertUpdate(final DocumentEvent e) {
this.update(e);
}
@Override
public final void changedUpdate(final DocumentEvent e) {
}
private void update(final DocumentEvent e) {
try {
this.doUpdate(getText(e));
} catch (final BadLocationException e1) {
logger.warn("Can't update field", e1);
}
}
private String getText(final DocumentEvent e) throws BadLocationException {
return e.getDocument().getText(0, e.getDocument().getLength());
}
protected abstract void doUpdate(final String text);
}
}