/*
* JAME 6.2.1
* http://jame.sourceforge.net
*
* Copyright 2001, 2016 Andrea Medeghini
*
* This file is part of JAME.
*
* JAME is an application for creating fractals and other graphics artifacts.
*
* JAME 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.
*
* JAME 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 JAME. If not, see <http://www.gnu.org/licenses/>.
*
*/
package net.sf.jame.twister.swing;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Point;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;
import net.sf.jame.core.common.ConfigurableExtensionReferenceElement;
import net.sf.jame.core.common.ExtensionReferenceElement;
import net.sf.jame.core.config.ValueChangeEvent;
import net.sf.jame.core.config.ValueChangeListener;
import net.sf.jame.core.extension.Extension;
import net.sf.jame.core.extension.ExtensionException;
import net.sf.jame.core.swing.ViewContext;
import net.sf.jame.core.tree.NodeSession;
import net.sf.jame.core.util.RenderContext;
import net.sf.jame.twister.swing.view.NavigatorViewRuntime;
import net.sf.jame.twister.swing.view.extension.ViewExtensionRuntime;
/**
* @author Andrea Medeghini
*/
public class NavigationFrame extends JFrame {
private static final long serialVersionUID = 1L;
private static final String CONFIG_FRAME_TITLE = "configFrame.title";
private static final String CONFIG_FRAME_WIDTH = "configFrame.width";
private static final String CONFIG_FRAME_MIN_HEIGHT = "configFrame.minHeight";
private static final String CONFIG_FRAME_MAX_HEIGHT = "configFrame.maxHeight";
private static final String CONFIG_FRAME_ICON = "configFrame.icon";
private final NavigationPanel navigationPanel;
private final NavigationModel model;
private ViewPanel viewPanel;
private final ConfigurableExtensionReferenceElement<?> configElement;
private final ValueChangeListener elementListener;
private final ViewContext viewContext;
private final String viewName;
/**
* @param configElement
* @param renderContext
* @param session
* @param viewName
* @throws HeadlessException
*/
public NavigationFrame(final ConfigurableExtensionReferenceElement<?> configElement, final RenderContext renderContext, final NodeSession session, final String viewName) throws HeadlessException {
this.configElement = configElement;
this.viewName = viewName;
setResizable(false);
final DefaultNavigationContainer container = new DefaultNavigationContainer();
model = new NavigationModel(container);
container.setOpaque(false);
container.setBorder(BorderFactory.createEmptyBorder(8, 0, 8, 0));
navigationPanel = new NavigationPanel(model);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(navigationPanel, BorderLayout.NORTH);
getContentPane().add(container, BorderLayout.CENTER);
setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
setTitle(TwisterSwingResources.getInstance().getString(NavigationFrame.CONFIG_FRAME_TITLE) + " - " + viewName);
viewContext = new DefaultViewContext(model);
final URL resource = NavigationFrame.class.getClassLoader().getResource(TwisterSwingResources.getInstance().getString(NavigationFrame.CONFIG_FRAME_ICON));
if (resource != null) {
setIconImage(getToolkit().createImage(resource));
}
elementListener = new ValueChangeListener() {
public void valueChanged(final ValueChangeEvent e) {
switch (e.getEventType()) {
case ExtensionReferenceElement.EXTENSION_REFERENCE_CHANGED: {
if (viewPanel != null) {
viewContext.removeComponent(viewPanel);
viewPanel.dispose();
viewPanel = null;
}
updateViewPanel(configElement, viewContext, renderContext, session);
if (viewPanel != null) {
viewContext.setComponent(viewPanel);
}
break;
}
default: {
break;
}
}
}
};
updateViewPanel(configElement, viewContext, renderContext, session);
configElement.addChangeListener(elementListener);
if (viewPanel != null) {
viewPanel.setVisible(false);
model.setComponent(viewPanel);
}
final Point p = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
p.x -= getWidth() / 2;
p.y -= getHeight() / 2;
setLocation(p);
}
private void updateViewPanel(final ConfigurableExtensionReferenceElement<?> configElement, final ViewContext viewContext, final RenderContext renderContext, final NodeSession session) {
if (configElement.getReference() != null) {
try {
final Extension<ViewExtensionRuntime> extension = TwisterSwingRegistry.getInstance().getViewExtension(configElement.getReference().getExtensionId());
viewPanel = extension.createExtensionRuntime().createView(configElement.getReference().getExtensionConfig(), viewContext, renderContext, session);
}
catch (final ExtensionException x) {
viewPanel = new NavigatorViewRuntime().createView(configElement.getReference().getExtensionConfig(), viewContext, renderContext, session);
}
}
else {
viewPanel = new EmptyViewPanel();
}
viewPanel.setName(viewName);
}
/**
* @see java.awt.Window#dispose()
*/
@Override
public void dispose() {
super.dispose();
configElement.removeChangeListener(elementListener);
if (viewPanel != null) {
viewPanel.dispose();
viewPanel = null;
}
}
public void setup() {
if (viewPanel != null) {
viewPanel.setVisible(true);
}
}
private class DefaultNavigationContainer extends JScrollPane implements NavigationContainer {
private static final long serialVersionUID = 1L;
/**
*
*/
public DefaultNavigationContainer() {
setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
}
/**
* @see net.sf.jame.twister.swing.NavigationContainer#loadComponent(java.awt.Component, int)
*/
public void loadComponent(final Component c, final int amount) {
final int defaultWidth = Integer.parseInt(TwisterSwingResources.getInstance().getString(NavigationFrame.CONFIG_FRAME_WIDTH));
final int defaultMinHeight = Integer.parseInt(TwisterSwingResources.getInstance().getString(NavigationFrame.CONFIG_FRAME_MIN_HEIGHT));
final int defaultMaxHeight = Integer.parseInt(TwisterSwingResources.getInstance().getString(NavigationFrame.CONFIG_FRAME_MAX_HEIGHT));
final int width = Integer.getInteger(NavigationFrame.CONFIG_FRAME_WIDTH, defaultWidth);
final int minHeight = Integer.getInteger(NavigationFrame.CONFIG_FRAME_MIN_HEIGHT, defaultMinHeight);
final int maxHeight = Integer.getInteger(NavigationFrame.CONFIG_FRAME_MAX_HEIGHT, defaultMaxHeight);
final Dimension newSize = c.getPreferredSize();
final Dimension size = new Dimension(width, 40 + Math.min(Math.max(navigationPanel.getHeight() + newSize.height + getInsets().top + getInsets().bottom + NavigationFrame.this.getInsets().top + NavigationFrame.this.getInsets().bottom + amount, minHeight), maxHeight));
NavigationFrame.this.setSize(size);
if (c != null) {
getViewport().setView(c);
}
}
}
private class DefaultViewContext implements ViewContext {
private final NavigationModel model;
/**
* @param model
*/
public DefaultViewContext(final NavigationModel model) {
this.model = model;
}
/**
* @see net.sf.jame.core.swing.ViewContext#setComponent(java.awt.Component)
*/
public void setComponent(final Component c) {
model.setComponent(c);
}
/**
* @see net.sf.jame.core.swing.ViewContext#removeComponent(java.awt.Component)
*/
public void removeComponent(final Component c) {
model.removeComponent(c);
}
/**
* @see net.sf.jame.core.swing.ViewContext#resize()
*/
public void resize() {
model.resize(0);
}
/**
* @see net.sf.jame.core.swing.ViewContext#resize(int)
*/
public void resize(final int amount) {
model.resize(amount + 20);
}
/**
* @see net.sf.jame.core.swing.ViewContext#restoreComponent(java.awt.Component)
*/
public void restoreComponent(final Component c) {
model.restoreComponent(c);
}
}
private class EmptyViewPanel extends ViewPanel {
private static final long serialVersionUID = 1L;
/**
* @see net.sf.jame.twister.swing.ViewPanel#dispose()
*/
@Override
public void dispose() {
}
}
}