/* * #%L * gitools-ui-app * %% * Copyright (C) 2013 Universitat Pompeu Fabra - Biomedical Genomics group * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ package org.gitools.ui.core.pages.common; import org.gitools.ui.core.utils.DocumentChangeListener; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.tree.TreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Enumeration; /** * @noinspection ALL */ public abstract class FilteredTreePanel extends javax.swing.JPanel { private String lastFilterText = ""; /** * Creates new form FilteredTreePanel */ public FilteredTreePanel() { initComponents(); filterField.getDocument().addDocumentListener(new DocumentChangeListener() { @Override protected void update(DocumentEvent e) { updateFilter(); } }); clearBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { filterField.setText(""); filterField.requestFocusInWindow(); } }); expandBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { expandAll(); } }); collapseBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { collapseAll(); } }); updateFilter(); } private void updateFilter() { final String filterText = getFilterText(); clearBtn.setEnabled(!filterText.isEmpty()); if (!filterText.equalsIgnoreCase(lastFilterText)) { lastFilterText = filterText; tree.setModel(updateModel(getFilterText())); expandAll(); } } protected abstract TreeModel updateModel(String filterText); private String getFilterText() { return filterField.getText(); } public TreeModel getModel() { return tree.getModel(); } public void setModel(TreeModel model) { tree.setModel(model); updateExpandCollapseButtons(); } private void updateExpandCollapseButtons() { boolean enabled = false; TreeModel model = tree.getModel(); if (model != null) { enabled = model.getRoot() != null; } expandBtn.setEnabled(enabled); collapseBtn.setEnabled(enabled); } // If expand is true, expands all nodes in the tree. // Otherwise, collapses all nodes in the tree. void expandCollapse(JTree tree, boolean expand) { TreeModel model = tree.getModel(); if (model == null) { return; } TreeNode root = (TreeNode) model.getRoot(); // Traverse tree from root expandCollapse(tree, new TreePath(root), expand); // Do not collapse first level nodes if (!tree.isRootVisible() && !expand) { tree.expandPath(new TreePath(root)); } } private void expandCollapse(JTree tree, TreePath parent, boolean expand) { // Traverse children TreeNode node = (TreeNode) parent.getLastPathComponent(); if (node.getChildCount() >= 0) { for (Enumeration<?> e = node.children(); e.hasMoreElements(); ) { TreeNode n = (TreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); expandCollapse(tree, path, expand); } } // Expansion or collapse must be done bottom-up if (expand) { tree.expandPath(parent); } else { tree.collapsePath(parent); } } public void expandAll() { expandCollapse(tree, true); filterField.requestFocusInWindow(); } void collapseAll() { expandCollapse(tree, false); filterField.requestFocusInWindow(); } /** * This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { filterField = new javax.swing.JTextField(); clearBtn = new javax.swing.JButton(); jScrollPane1 = new javax.swing.JScrollPane(); tree = new javax.swing.JTree(); collapseBtn = new javax.swing.JButton(); expandBtn = new javax.swing.JButton(); filterField.setFocusCycleRoot(true); clearBtn.setText("Clear"); tree.setModel(null); jScrollPane1.setViewportView(tree); collapseBtn.setText("Collapse all"); expandBtn.setText("Expand all"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup().addContainerGap().addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING).addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 378, Short.MAX_VALUE).addGroup(layout.createSequentialGroup().addComponent(filterField, javax.swing.GroupLayout.DEFAULT_SIZE, 327, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(clearBtn)).addGroup(layout.createSequentialGroup().addComponent(expandBtn).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(collapseBtn))).addContainerGap())); layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(clearBtn).addComponent(filterField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(collapseBtn).addComponent(expandBtn)).addContainerGap())); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton clearBtn; private javax.swing.JButton collapseBtn; private javax.swing.JButton expandBtn; protected javax.swing.JTextField filterField; private javax.swing.JScrollPane jScrollPane1; public javax.swing.JTree tree; // End of variables declaration//GEN-END:variables }