package com.link_intersystems.gitdirstat.ui;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.DefaultListSelectionModel;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import com.link_intersystems.gitdirstat.domain.TreeObject;
import com.link_intersystems.gitdirstat.ui.treeobjects.TreeObjectsTreeModel;
import com.link_intersystems.swing.AbstractPropertyChangeSupport;
import com.link_intersystems.swing.ListAdapterListModel;
import com.link_intersystems.swing.ListModelSelection;
import com.link_intersystems.swing.SelectionModel;
public class PathModel {
public enum SelectionSource {
LIST_SELECTION, TREE_SELECTION;
}
private ListAdapterListModel<TreeObject> listAdapterListModel = new ListAdapterListModel<TreeObject>();
private ListSelectionModel pathSelectionModel = new DefaultListSelectionModel();
private ListModelSelection<TreeObject> pathListModelSelection = new ListModelSelection<TreeObject>(
listAdapterListModel, pathSelectionModel);
private TreeObjectsTreeModel treeModel = new TreeObjectsTreeModel();
private DefaultTreeSelectionModel treeSelectionModel = new DefaultTreeSelectionModel();
private TreeModelSelection treeModelSelection = new TreeModelSelection(
treeSelectionModel);
private ProxySelectionModel<TreeObject> proxySelectionModel = new ProxySelectionModel<TreeObject>(
pathListModelSelection);
PathModel() {
}
public void setRootTreeObject(TreeObject treeObject) {
if (treeObject == null) {
clear();
return;
}
List<TreeObject> fileList = treeObject.toFileList();
Comparator<Object> reverseOrder = Collections.reverseOrder();
Collections.sort(fileList, reverseOrder);
listAdapterListModel.setList(fileList);
treeModel.setCommitRangeTree(treeObject);
}
public void setSelectionSource(SelectionSource selectionSource) {
List<TreeObject> selection = null;
switch (selectionSource) {
case LIST_SELECTION:
selection = treeModelSelection.getSelection();
pathSelectionModel.clearSelection();
for (TreeObject treeObject : selection) {
List<TreeObject> files = treeObject.toFileList();
for (TreeObject file : files) {
int indexOf = listAdapterListModel.indexOf(file);
pathSelectionModel.addSelectionInterval(indexOf, indexOf);
}
}
proxySelectionModel.setSelectionModel(pathListModelSelection);
break;
case TREE_SELECTION:
selection = pathListModelSelection.getSelection();
treeSelectionModel.clearSelection();
for (TreeObject treeObject : selection) {
TreePath treePath = treeModel.getTreePath(treeObject);
treeSelectionModel.addSelectionPath(treePath);
}
proxySelectionModel.setSelectionModel(treeModelSelection);
break;
}
}
public ListModel getListModel() {
return listAdapterListModel;
}
public ListSelectionModel getListSelectionModel() {
return pathSelectionModel;
}
public SelectionModel<TreeObject> getSelectionModel() {
return proxySelectionModel;
}
public TreeObjectsTreeModel getTreeModel() {
return treeModel;
}
public void clear() {
List<? extends TreeObject> emptyList = Collections.emptyList();
listAdapterListModel.setList(emptyList);
treeModel.setCommitRangeTree(null);
pathSelectionModel.clearSelection();
treeSelectionModel.clearSelection();
}
public TreeSelectionModel getTreeSelectionModel() {
return treeSelectionModel;
}
private class TreeModelSelection extends AbstractPropertyChangeSupport
implements SelectionModel<TreeObject> {
private TreeSelectionModel treeSelectionModel;
public TreeModelSelection(TreeSelectionModel treeSelectionModel) {
this.treeSelectionModel = treeSelectionModel;
treeSelectionModel
.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
TreeModelSelection.this.firePropertyChange(
PROP_SELECTION, null, null);
}
});
}
@Override
public boolean isEmpty() {
return treeSelectionModel.isSelectionEmpty();
}
@Override
public List<TreeObject> getSelection() {
List<TreeObject> selection = new ArrayList<TreeObject>();
TreePath[] selectionPaths = treeSelectionModel.getSelectionPaths();
if (selectionPaths != null) {
TreeObject treeObject = null;
for (TreePath treePath : selectionPaths) {
Object lastPathComponent = treePath.getLastPathComponent();
lastPathComponent = unwrap(lastPathComponent);
if (lastPathComponent instanceof TreeObject) {
treeObject = (TreeObject) lastPathComponent;
selection.add(treeObject);
}
}
}
return selection;
}
private Object unwrap(Object lastPathComponent) {
if (lastPathComponent instanceof DefaultMutableTreeNode) {
lastPathComponent = ((DefaultMutableTreeNode) lastPathComponent)
.getUserObject();
}
return lastPathComponent;
}
}
private class ProxySelectionModel<E> extends AbstractPropertyChangeSupport
implements SelectionModel<E> {
private class SelectionModelSync implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
if (PROP_SELECTION.equals(propertyName)) {
ProxySelectionModel.this.firePropertyChange(PROP_SELECTION,
null, getSelection());
}
}
}
private SelectionModel<E> selectionModel;
private SelectionModelSync selectionModelSync = new SelectionModelSync();
public ProxySelectionModel(SelectionModel<E> selectionModel) {
this.selectionModel = selectionModel;
setSelectionModel(selectionModel);
}
public void setSelectionModel(SelectionModel<E> selectionModel) {
if (this.selectionModel != null) {
this.selectionModel
.removePropertyChangeListener(selectionModelSync);
}
this.selectionModel = selectionModel;
if (this.selectionModel != null) {
this.selectionModel
.addPropertyChangeListener(selectionModelSync);
firePropertyChange(PROP_SELECTION, null, getSelection());
}
}
@Override
public boolean isEmpty() {
return selectionModel.isEmpty();
}
@Override
public List<E> getSelection() {
return selectionModel.getSelection();
}
}
}