/* * Copyright 2010-2015 Institut Pasteur. * * This file is part of Icy. * * Icy 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. * * Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>. */ package icy.gui.preferences; import icy.gui.dialog.ConfirmDialog; import icy.gui.frame.IcyFrame; import icy.gui.util.ComponentUtil; import icy.gui.util.WindowPositionSaver; import icy.main.Icy; import icy.preferences.IcyPreferences; import icy.util.StringUtil; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTree; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeSelectionModel; /** * @author fab & stephane */ public class PreferenceFrame extends IcyFrame implements TreeSelectionListener { public static final String NODE_NAME = "Preferences"; /** singleton frame */ private static PreferenceFrame instance = null; // needed to keep trace of non singleton frame List<PreferencePanel> preferencePanels; private JTree tree; private JSplitPane mainPanel; private DefaultMutableTreeNode node; boolean needRestart; boolean doRestart; // we need to keep reference on it as the object only use weak reference WindowPositionSaver positionSaver; public PreferenceFrame(String section) { super(NODE_NAME, true, true, false, false); // frame already opened ? if (instance != null) { // just put it on front instance.toFront(); return; } instance = this; positionSaver = new WindowPositionSaver(this, "frame/preference", new Point(100, 100), new Dimension(640, 480)); needRestart = false; doRestart = false; preferencePanels = new ArrayList<PreferencePanel>(); preferencePanels.add(new GeneralPreferencePanel(this)); preferencePanels.add(new NetworkPreferencePanel(this)); preferencePanels.add(new CanvasPreferencePanel(this)); preferencePanels.add(new ChatPreferencePanel(this)); preferencePanels.add(new RepositoryPreferencePanel(this)); preferencePanels.add(new PluginPreferencePanel(this)); preferencePanels.add(new PluginLocalPreferencePanel(this)); preferencePanels.add(new PluginOnlinePreferencePanel(this)); preferencePanels.add(new PluginStartupPreferencePanel(this)); preferencePanels.add(new WorkspacePreferencePanel(this)); preferencePanels.add(new WorkspaceLocalPreferencePanel(this)); preferencePanels.add(new WorkspaceOnlinePreferencePanel(this)); // TODO : add here PreferencePanel type plugins // build selection tree node = new DefaultMutableTreeNode(NODE_NAME); for (PreferencePanel panel : preferencePanels) getNode(panel.getParentName()).add(panel.getNode()); tree = new JTree(node); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); // tree.setOpaque(true); tree.setRootVisible(false); // select first node tree.setSelectionRow(0); ComponentUtil.expandAllTree(tree); // disable double click expansion/reduction tree.setToggleClickCount(0); tree.addTreeSelectionListener(this); final JScrollPane treeScrollPane = new JScrollPane(tree); treeScrollPane.setMinimumSize(new Dimension(136, 100)); mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeScrollPane, null); mainPanel.setDividerSize(6); mainPanel.setDividerLocation(150); // final JButton helpButton = new Help(NODE_NAME).getHelpButton("Help"); final JButton resetButton = new JButton("Reset to default"); final JButton cancelButton = new JButton("Cancel"); final JButton okButton = new JButton("Ok"); final JButton applyButton = new JButton("Apply"); resetButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // need confirmation if (ConfirmDialog.confirm("Reset all setting to default values ?")) { // clear all preferences IcyPreferences.clear(); // reload for (PreferencePanel panel : preferencePanels) panel.load(); } } }); cancelButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // just close the frame close(); } }); okButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // set back panel informations in preferences for (PreferencePanel panel : preferencePanels) panel.save(); // validate the need restart state doRestart = needRestart; // then close the frame close(); } }); applyButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // set back panel informations in preferences for (PreferencePanel panel : preferencePanels) panel.save(); // validate the need restart state doRestart = needRestart; } }); final JPanel bottomPanel = new JPanel(); bottomPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS)); // bottomPanel.add(helpButton); // bottomPanel.add(Box.createHorizontalStrut(8)); bottomPanel.add(resetButton); bottomPanel.add(Box.createHorizontalStrut(8)); bottomPanel.add(Box.createHorizontalGlue()); bottomPanel.add(applyButton); bottomPanel.add(Box.createHorizontalStrut(8)); bottomPanel.add(okButton); bottomPanel.add(Box.createHorizontalStrut(8)); bottomPanel.add(cancelButton); final JPanel tmpPanel = new JPanel(); tmpPanel.setLayout(new BoxLayout(tmpPanel, BoxLayout.PAGE_AXIS)); tmpPanel.add(new JSeparator()); tmpPanel.add(bottomPanel); setLayout(new BorderLayout()); add(mainPanel, BorderLayout.CENTER); add(tmpPanel, BorderLayout.SOUTH); updateRightPanel(); setMinimumSize(new Dimension(480, 400)); setPreferredSize(new Dimension(800, 600)); addToDesktopPane(); setVisible(true); if (!StringUtil.isEmpty(section)) setSelection(section); } @Override public void onClosed() { // test if we are on singleton frame if (preferencePanels != null) { for (PreferencePanel panel : preferencePanels) panel.closed(); instance = null; // restart needed and validated, ask user if (doRestart) { Icy.confirmRestart(); doRestart = false; } } super.onClosed(); } private DefaultMutableTreeNode getNode(String name) { // first search directly on root node if (node.getUserObject().equals(name)) return node; // then search in children final int len = node.getChildCount(); for (int i = 0; i < len; i++) { final DefaultMutableTreeNode n = (DefaultMutableTreeNode) node.getChildAt(i); if (n.getUserObject().equals(name)) return n; } return null; } private void updateRightPanel() { final Object selected = tree.getSelectionPath().getLastPathComponent(); for (PreferencePanel panel : preferencePanels) { if (panel.getNode().equals(selected)) { final int divLocation = mainPanel.getDividerLocation(); panel.setVisible(true); mainPanel.setRightComponent(panel); // restore divider location (lost with setRightComponent) mainPanel.setDividerLocation(divLocation); } else panel.setVisible(true); } } @Override public void valueChanged(TreeSelectionEvent e) { updateRightPanel(); } public void setSelection(String selection) { for (PreferencePanel panel : preferencePanels) { final DefaultMutableTreeNode node = panel.getNode(); if (node.getUserObject().equals(selection)) { tree.setSelectionPath(ComponentUtil.buildTreePath(node)); return; } } } public void setNeedRestart() { needRestart = true; } }