/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cli_fmw.directory.dialogs;
import cli_fmw.delegate.directory.DirectoryItemRO;
import cli_fmw.delegate.directory.DirectoryItemRecursive;
import cli_fmw.main.ClipsException;
import cli_fmw.main.MainWindow;
import cli_fmw.main.audit.AuditManager;
import cli_fmw.utils.ModalDialog;
import cli_fmw.utils.Selector;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JTree;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.JTextComponent;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
/**
*
* @author Axe Ilshat
*/
abstract public class GenericChooseDialog extends ModalDialog {
private JTree tree;
private JButton selectBtn;
private Object items[];
private TreeDblClicked treeDblClicked = new TreeDblClicked();
private boolean multipleSelected;
private String rootTitle;
private Object initialSelected;
private SearchEngine se = new SearchEngine();
private TreeListener tl = new TreeListener();
private JButton cancelBtn;
private CancelActionListener cal = new CancelActionListener();
private OkActionListener oal = new OkActionListener();
/**
*
* @param multipleSelected
* @param selected
* @param rootTitle
*/
public GenericChooseDialog(boolean multipleSelected, Object selected, String rootTitle, AuditManager am) {
super(MainWindow.mainWindow, rootTitle, am);
this.multipleSelected = multipleSelected;
this.rootTitle = rootTitle;
initialSelected = selected;
}
public GenericChooseDialog(Window parent, boolean multipleSelected, Object selected, String rootTitle, AuditManager am) {
super(parent, rootTitle, am);
this.multipleSelected = multipleSelected;
this.rootTitle = rootTitle;
initialSelected = selected;
}
@Override
public void setVisible(boolean arg0) {
//center dialog
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension dlgSize = this.getSize();
this.setLocation((scrSize.width - dlgSize.width) / 2, (scrSize.height - dlgSize.height) / 2);
super.setVisible(arg0);
}
/**
*
* @param tree
* @param selectBtn
* @param items
* @param cancelBtn
* @throws ClipsException
*/
public void setData(Object items[], JTree tree, JButton selectBtn, JButton cancelBtn) throws ClipsException {
this.tree = tree;
this.selectBtn = selectBtn;
this.cancelBtn = cancelBtn;
this.items = items;
tree.addMouseListener(treeDblClicked);
tree.getSelectionModel().setSelectionMode(multipleSelected
? TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION
: TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setModel(getModel(items, rootTitle));
tree.addTreeSelectionListener(tl);
cancelBtn.addActionListener(cal);
selectBtn.addActionListener(oal);
if (initialSelected != null) {
se.doSearch(initialSelected, null);
initialSelected = null;
}
}
/**
*
* @param items
* @param rootTitle
* @return
* @throws ClipsException
*/
abstract protected TreeModel getModel(Object items[], String rootTitle) throws ClipsException;
abstract protected boolean isFit(Object item) throws ClipsException;
/**
* Список выбранных итемов
* @return
*/
final public Selector getSelectedItems() {
return new SelectorA();
}
private class SelectorA implements Selector {
@Override
public int size() {
return tree.getSelectionCount();
}
@Override
@SuppressWarnings("unchecked")
public Object get(int index) {
TreePath path[] = tree.getSelectionPaths();
return path[index].getLastPathComponent();
}
}
/**
*
* @param text
*/
final public void attachSearchEngine(JTextComponent text) {
text.getDocument().addDocumentListener(new SearchListener(text));
}
private class SearchListener implements DocumentListener {
JTextComponent text;
public SearchListener(JTextComponent text) {
this.text = text;
}
@Override
public void insertUpdate(DocumentEvent arg0) {
silentSearch();
}
@Override
public void removeUpdate(DocumentEvent arg0) {
silentSearch();
}
@Override
public void changedUpdate(DocumentEvent arg0) {
silentSearch();
}
protected void silentSearch() {
se.doSearch(text.getText().toLowerCase(), null);
}
}
/**
* Further Search
* @param text
* @param furtherBtn
*/
final public void attachSearchFurtherEngine(JTextComponent text, JButton furtherBtn) {
furtherBtn.addActionListener(new SearchListenerFurther(text));
}
private class SearchListenerFurther implements ActionListener {
JTextComponent text;
public SearchListenerFurther(JTextComponent text) {
this.text = text;
}
@Override
public void actionPerformed(ActionEvent arg0) {
Object selected = null;
TreePath path = tree.getSelectionPath();
if (path != null) {
selected = path.getLastPathComponent();
}
se.doSearch(text.getText().toLowerCase(), selected);
}
}
/**
* Search
*/
class SearchEngine {
private Object startFrom;
@SuppressWarnings({"unchecked", "unchecked"})
final private void doSearch(Object pattern, Object startFrom) {
if (pattern == null) {
return;
}
if (pattern instanceof String) {
String value = (String) pattern;
if (value.trim().isEmpty()) {
return;
}
}
this.startFrom = startFrom;
try {
for (int i = 0; i < items.length; i++) {
Object item = items[i];
List found = findMatch(item, pattern);
if (found != null) {
found.add(tree.getModel().getRoot());
ArrayList reversed = new ArrayList();
for (int j = found.size() - 1; j >= 0; j--) {
reversed.add(found.get(j));
}
TreePath fullPath = new TreePath(reversed.toArray());
tree.setSelectionPath(fullPath);
tree.expandPath(fullPath);
tree.scrollPathToVisible(fullPath);
tree.updateUI();
return;
}
}
} catch (ClipsException ex) {
//do nothing
}
}
@SuppressWarnings("unchecked")
private List findMatch(Object item, Object pattern) throws ClipsException {
if (item == startFrom) {
//if start found, clear it and pass search
startFrom = null;
} else {
if (startFrom == null) {
if (pattern instanceof String) {
String str = (String) pattern;
int pos = getItemSearchText(item).indexOf(str);
if (pos == 0
|| (!fullMatch() && pos > 0)) {
LinkedList path = new LinkedList();
path.add(item);
return path;
}
} else {
if (item == pattern) {
LinkedList path = new LinkedList();
path.add(item);
return path;
}
}
}
}
if (item instanceof DirectoryItemRecursive) {
DirectoryItemRecursive par = (DirectoryItemRecursive) item;
Selector ii = par.getItems();
for (int i = 0; i < ii.size(); i++) {
Object child = ii.get(i);
List path = findMatch(child, pattern);
if (path != null) {
path.add(par);
return path;
}
}
}
return null;
}
}
protected class TreeDblClicked extends MouseAdapter {
private Object doubleClicked;
@Override
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() < 2) {
return;
}
if (selectBtn.isEnabled()) {
Selector sel = getSelectedItems();
for (int i = 0; i < sel.size(); i++) {
Object item = sel.get(i);
if (item instanceof DirectoryItemRecursive) {
DirectoryItemRecursive mi = (DirectoryItemRecursive) item;
// try {
if (mi.getItems().size() == 0) {
selectBtn.doClick();
} else {
if (doubleClicked == mi || evt.getClickCount() > 2) {
doubleClicked = null;
selectBtn.doClick();
} else {
doubleClicked = mi;
}
}
/* } catch (ClipsException ex) {
ex.printStackTrace();
//do nothing
}*/
} else if (item instanceof DirectoryItemRO) {
selectBtn.doClick();
}
}
}
}
}
/**
*
*/
protected class TreeListener implements TreeSelectionListener {
@Override
public void valueChanged(TreeSelectionEvent arg0) {
selectBtn.setEnabled(false);
if (tree.getSelectionCount() > 0) {
Selector sel = getSelectedItems();
boolean enable = sel.size() > 0;
for (int i = 0; i < sel.size(); i++) {
try {
if (!isFit(sel.get(i))) {
enable = false;
break;
}
} catch (ClipsException ex) {
ex.printStackTrace();
enable = false;
break;
}
}
selectBtn.setEnabled(enable);
}
}
}
protected class OkActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
setDlgResult(ModalDialog.DLG_OK);
setVisible(false);
}
}
protected class CancelActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
setDlgResult(ModalDialog.DLG_CANCEL);
setVisible(false);
}
}
protected String getItemSearchText(Object item) {
return item.toString().toLowerCase();
}
protected boolean fullMatch() {
return true;
}
}