/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.framework.internal;
import java.awt.Component;
import java.awt.Dimension;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.prefs.Preferences;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import org.eclipse.persistence.tools.workbench.framework.app.AbstractPreferencesNode;
import org.eclipse.persistence.tools.workbench.framework.app.PreferencesNode;
import org.eclipse.persistence.tools.workbench.framework.uitools.OSplitPane;
import org.eclipse.persistence.tools.workbench.framework.uitools.SwingTools;
import org.eclipse.persistence.tools.workbench.uitools.app.BufferedPropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.SimplePropertyValueModel;
/**
* A preferences view is placed inside a preferences dialog.
* There is a single preferences view per application that is
* shared among multiple preferences dialogs (although, there
* should only be *one* preferences dialog instantiated at a time).
* A preferences view contains a preferences navigator view and
* a preferences editor view.
*
* @see PreferencesDialog
* @see PreferencesNavigatorView
* @see PreferencesEditorView
*/
final class PreferencesView {
/** save the root preferences node so we can import/export */
private Preferences rootPreferences;
/** the trigger pulled by the dialog's OK button */
private BufferedPropertyValueModel.Trigger bufferTrigger;
/** this holds the navigator on the "left" and the editor on the "right" */
private JSplitPane splitPane;
/** the "left" side view */
private PreferencesNavigatorView navigatorView;
/** the "right" side view */
private PreferencesEditorView editorView;
/** this holds either the selected node or an empty "pseudo-node" */
private PropertyValueModel selectedNodeHolder;
/** the pseudo-node used when none of the nodes in the tree are selected */
private PreferencesNode emptySelectionNode;
// ********** construction/initialization **********
PreferencesView(AbstractPreferencesNode rootNode, BufferedPropertyValueModel.Trigger bufferTrigger) {
super();
this.initialize(rootNode, bufferTrigger);
}
private void initialize(AbstractPreferencesNode rootNode, BufferedPropertyValueModel.Trigger bufferTrigger) {
rootPreferences = rootNode.getPreferences();
this.bufferTrigger = bufferTrigger;
emptySelectionNode = new PreferencesEmptySelectionPseudoNode();
selectedNodeHolder = new SimplePropertyValueModel(emptySelectionNode);
navigatorView = new PreferencesNavigatorView(rootNode);
navigatorView.addTreeSelectionListener(this.buildTreeSelectionListener());
editorView = new PreferencesEditorView(selectedNodeHolder);
splitPane = this.buildSplitPane();
navigatorView.selectFirstChild();
}
private TreeSelectionListener buildTreeSelectionListener() {
return new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
PreferencesView.this.selectedNodeChanged(e.getNewLeadSelectionPath());
}
};
}
private JSplitPane buildSplitPane() {
JSplitPane splitPane = new OSplitPane();
splitPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
splitPane.setDoubleBuffered(false);
splitPane.setSize(new Dimension(750, 550));
splitPane.setDividerLocation(0.2);
SwingTools.setSplitPaneDividerBorder(splitPane, BorderFactory.createEmptyBorder());
splitPane.setDividerSize(3);
splitPane.setContinuousLayout(false);
splitPane.setLeftComponent(navigatorView.getComponent());
splitPane.setRightComponent(editorView.getComponent());
return splitPane;
}
// ********** queries **********
Component getComponent() {
return splitPane;
}
PreferencesNavigatorView getView() {
return navigatorView;
}
Component initialFocusComponent() {
return navigatorView.initialFocusComponent();
}
// ********** behavior **********
/**
* Whenever a node is selected or deselected, notify interested parties.
*/
private void selectedNodeChanged(TreePath path) {
if (path == null) {
selectedNodeHolder.setValue(emptySelectionNode);
} else {
selectedNodeHolder.setValue(path.getLastPathComponent());
}
}
/**
* Trigger that the OK button has been pressed.
*/
void triggerAccept() {
bufferTrigger.accept();
}
/**
* Trigger that the Reset button has been pressed.
*/
void triggerReset() {
bufferTrigger.reset();
}
/**
* Export the entire tree of preferences to the specified file.
*/
void exportPreferences(File file) {
OutputStream stream;
try {
stream = new BufferedOutputStream(new FileOutputStream(file), 2048);
} catch (FileNotFoundException ex) {
throw new RuntimeException(ex);
}
try {
rootPreferences.exportSubtree(stream);
} catch (Exception ex) {
throw new RuntimeException(ex);
} finally {
try {
stream.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* Import the specified file of preferences.
*/
void importPreferences(File file) {
InputStream stream;
try {
stream = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException ex) {
throw new RuntimeException(ex);
}
try {
Preferences.importPreferences(stream);
} catch (Exception ex) {
throw new RuntimeException(ex);
} finally {
try {
stream.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
// ********** inner classes **********
/**
* This is the node placed in the selectedNodeHolder when nothing
* in the navigator is selected.
*/
private static final class PreferencesEmptySelectionPseudoNode extends AbstractPreferencesNode {
PreferencesEmptySelectionPseudoNode() {
super(null); // no context needed here
}
protected Component buildPropertiesPage() {
return new JPanel();
}
protected String buildDisplayString() {
return " "; // put a space so the label preserves its size
}
public String helpTopicId() {
return "preferences";
}
}
}