/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package edu.tufts.vue.preferences.ui;
import java.util.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.*;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.plaf.metal.MetalTreeUI;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.*;
import edu.tufts.vue.preferences.PreferenceConstants;
import edu.tufts.vue.preferences.PreferencesManager;
import edu.tufts.vue.preferences.interfaces.VuePreference;
import edu.tufts.vue.preferences.ui.tree.PrefCategoryTreeNode;
import edu.tufts.vue.preferences.ui.tree.PrefTreeNode;
import edu.tufts.vue.preferences.ui.tree.VuePrefRenderer;
import edu.tufts.vue.preferences.ui.tree.VueTreeUI;
import tufts.Util;
import tufts.vue.VueResources;
import tufts.vue.gui.GUI;
import java.util.prefs.*;
import java.util.List;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLDecoder;
/**
* @author Mike Korcynski
*
*/
public class PreferencesDialog extends JDialog {
private static final long serialVersionUID = 1L;
private GridBagConstraints gbConstraints = new GridBagConstraints();
private JTree prefTree;
private JSplitPane splitPane = null;
private DefaultMutableTreeNode rootNode = null;
private static PreferencesDialog dialog;
// private JTable editTable;
public PreferencesDialog(JFrame owner, String title, Class userObj,
boolean showUserPrefs, Object systemObj, boolean showSystemPrefs) {
super(owner, title);
dialog = this;
getContentPane().setLayout(new GridBagLayout());
setSize(640, 480);
Util.centerOnScreen(this);
setModal(true);
createTree();
// editTable = new JTable();
createSplitPane();
createButtonPanel();
String[] array = new String[2];
array[0] = new String(VueResources.getString("preferencedailog.vuepreference"));
array[1] = new String(VueResources.getString("preferences.category.mapdisplay"));
//array[2] = new String(VueResources.getString("preferencedailog.images"));
// array[2] = new String("Metadata:");
// array[3] = new String("Windows:");
try {
TreePath path = findByName(prefTree,array);
PrefCategoryTreeNode node = (PrefCategoryTreeNode) path.getLastPathComponent();
// splitPane.setRightComponent(node.getPrefObject().getPreferenceUI());
} catch (Throwable t) {
t.printStackTrace();
}
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
prefTree.setSelectionRow(1);
}
// Finds the path in tree as specified by the array of names. The names array is a
// sequence of names where names[0] is the root and names[i] is a child of names[i-1].
// Comparison is done using String.equals(). Returns null if not found.
public TreePath findByName(JTree tree, String[] names) {
TreeNode root = (TreeNode)tree.getModel().getRoot();
return find2(tree, new TreePath(root), names, 0, true);
}
private TreePath find2(JTree tree, TreePath parent, Object[] nodes, int depth, boolean byName) {
TreeNode node = (TreeNode)parent.getLastPathComponent();
Object o = node;
// If by name, convert node to a string
if (byName) {
o = o.toString();
}
// If equal, go down the branch
if (o.equals(nodes[depth])) {
// If at end, return match
if (depth == nodes.length-1) {
return parent;
}
// Traverse children
if (node.getChildCount() >= 0) {
for (Enumeration e=node.children(); e.hasMoreElements(); ) {
TreeNode n = (TreeNode)e.nextElement();
TreePath path = parent.pathByAddingChild(n);
TreePath result = find2(tree, path, nodes, depth+1, byName);
// Found a match
if (result != null) {
return result;
}
}
}
}
// No match at this branch
return null;
}
public static PreferencesDialog getDialog()
{
return dialog;
}
private void createTree() {
rootNode = new DefaultMutableTreeNode(
VueResources.getString("preferencedailog.vuepreference"));
Iterator i = PreferencesManager.getCategories().iterator();
// Build Category List.
while (i.hasNext()) {
String prefKey = (String)i.next();
String category = VueResources.getString("preferences.category." + prefKey);
System.out.println(category);
//System.out.println(category);
PrefCategoryTreeNode categoryNode = new PrefCategoryTreeNode(
category);
rootNode.add(categoryNode);
}
addPrefsToCats(rootNode);
DefaultTreeModel model = new DefaultTreeModel(rootNode);
prefTree = new JTree(model);
prefTree.setBorder(BorderFactory.createEmptyBorder());
prefTree.setCellRenderer(new VuePrefRenderer());
prefTree.setRootVisible(false);
prefTree.setShowsRootHandles(false);
prefTree.setUI(new VueTreeUI());
prefTree.putClientProperty("JTree.lineStyle", "None");
expandAll( prefTree, new TreePath( prefTree.getModel().getRoot() ) );
prefTree.addTreeSelectionListener(new PrefTreeSelectionListener());
}
/**
* Expand a tree node and all its child nodes recursively.
*
* @param tree the tree
* @param path the path to expand
*/
public static void expandAll( JTree tree, TreePath path )
{
Object node = path.getLastPathComponent();
TreeModel model = tree.getModel();
if( model.isLeaf( node ) )
return;
tree.expandPath( path );
int num = model.getChildCount( node );
for( int i = 0; i < num; i++ )
expandAll( tree, path.pathByAddingChild( model.getChild( node, i ) ) );
}
private VuePreference getPreferenceObject(Class a)
{
Method m = null;
VuePreference vp = null;
try {
m = a.getMethod("getInstance");
//m = a.getMethod("getInstance", null);
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NoSuchMethodException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
vp = (VuePreference)m.invoke(null);
//vp = (VuePreference)m.invoke(null, null);
} catch (IllegalArgumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvocationTargetException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return vp;
}
private void addPrefsToCats(DefaultMutableTreeNode node) {
String pckgname = "edu.tufts.vue.preferences.implementations";
List classes =PreferencesManager.getPreferences();
VuePreference vp = null;
Object[] classesA = classes.toArray();
Preferences p = Preferences
.userNodeForPackage(edu.tufts.vue.preferences.PreferencesManager.class);
for (int i = 0; i < classesA.length; i++)
{
Enumeration nodes = node.breadthFirstEnumeration();
if (classesA[i] instanceof VuePreference)
vp = (VuePreference)classesA[i];
else
vp = getPreferenceObject((Class)classesA[i]);
while (nodes.hasMoreElements()) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) nodes
.nextElement();
if ((n instanceof PrefCategoryTreeNode)
&& (((PrefCategoryTreeNode) n).toString().equals(PreferencesManager.mapCategoryKeyToName(vp
.getCategoryKey())))) {
try {
n.add(new PrefTreeNode(vp));
} catch (BackingStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
private void createSplitPane() {
splitPane = new JSplitPane();
splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setOneTouchExpandable(false);
splitPane.setEnabled(false);
JScrollPane pane = new JScrollPane(prefTree)
{
public Dimension getMaximumSize()
{
return new Dimension(180,prefTree.getHeight());
}
public Dimension getPreferredSize()
{
return new Dimension(180,prefTree.getHeight());
}
public Dimension getMinimumSize()
{
return new Dimension(180,prefTree.getHeight());
}
};
prefTree.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
splitPane.setLeftComponent(pane);
splitPane.setRightComponent(new JScrollPane());
gbConstraints.gridx = 0;
gbConstraints.gridy = 0;
gbConstraints.gridwidth = 1;
gbConstraints.fill = GridBagConstraints.BOTH;
gbConstraints.weightx = 1;
gbConstraints.weighty = 1;
gbConstraints.insets = new Insets(10, 10, 0, 10);
getContentPane().add(splitPane, gbConstraints);
}
private void createButtonPanel() {
JPanel buttonPanel = new JPanel(new BorderLayout(5, 5));
JButton closeButton = new JButton(VueResources.getString("button.close.label"));
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
PreferencesDialog.this.setVisible(false);
PreferencesDialog.this.dispose();
}
});
buttonPanel.add(closeButton, BorderLayout.EAST);
gbConstraints.gridx = 0;
gbConstraints.gridy = 1;
gbConstraints.gridwidth = 1;
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
gbConstraints.weightx = 1;
gbConstraints.weighty = 0;
gbConstraints.insets = new Insets(5, 0, 5, 10);
getContentPane().add(buttonPanel, gbConstraints);
}
class PrefTreeSelectionListener implements TreeSelectionListener {
public void valueChanged(TreeSelectionEvent e) {
try {
PrefTreeNode node = (PrefTreeNode) e.getPath()
.getLastPathComponent();
// Preferences pref = node.getPrefObject();
// editTable.setModel(new PrefTableModel(node));
splitPane.setRightComponent(node.getPrefObject().getPreferenceUI());
} catch (ClassCastException ce) {
//System.out.println("Node not PrefTreeNode!");
// editTable.setModel(new DefaultTableModel());
}
}
}
public static void main(String[] args) {
Preferences prefs = Preferences
.userNodeForPackage(edu.tufts.vue.preferences.PreferencesManager.class);
prefs.putBoolean("mapDisplay.AutoZoom", true);
PreferencesDialog dialog = new PreferencesDialog(null,
VueResources.getString("preferencedailog.vuepreference"),
edu.tufts.vue.preferences.PreferencesManager.class, true, null,
false);
dialog.show();
}
}