/**
* Copyright (C) 2015 Valkyrie RCP
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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 org.valkyriercp.application.support;
import org.jdesktop.swingx.JXFrame;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
import org.valkyriercp.application.*;
import org.valkyriercp.application.config.ApplicationConfig;
import org.valkyriercp.application.config.ApplicationLifecycleAdvisor;
import org.valkyriercp.command.support.CommandGroup;
import org.valkyriercp.util.EventListenerListHelper;
import org.valkyriercp.util.WindowUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.Iterator;
public abstract class AbstractApplicationWindow implements ApplicationWindow, WindowFocusListener {
private int number;
private JFrame control;
private ApplicationPage currentApplicationPage;
private ApplicationConfig applicationConfig;
private ApplicationWindowConfigurer applicationWindowConfigurer;
private EventListenerListHelper pageListeners = new EventListenerListHelper(PageListener.class);
private CommandGroup menuBarCommandGroup;
private CommandGroup toolBarCommandGroup;
private StatusBar statusBar;
private WindowManager windowManager;
private ApplicationWindowCommandManager commandManager;
public AbstractApplicationWindow(ApplicationConfig config) {
this(config.windowManager().size(), config);
}
public AbstractApplicationWindow(int number, ApplicationConfig config) {
this.number = number;
applicationConfig = config;
windowManager = applicationConfig.windowManager();
applicationConfig.applicationLifecycleAdvisor().setOpeningWindow(this);
init();
getAdvisor().onCommandsCreated( this );
}
protected void init() {
this.commandManager = getAdvisor().createWindowCommandManager();
this.menuBarCommandGroup = getAdvisor().getMenuBarCommandGroup();
this.toolBarCommandGroup = getAdvisor().getToolBarCommandGroup();
this.statusBar = getAdvisor().getStatusBar();
}
public int getNumber() {
return number;
}
@Override
public JFrame getControl() {
return control;
}
@Override
public ApplicationPage getPage() {
return currentApplicationPage;
}
protected ApplicationLifecycleAdvisor getAdvisor() {
return applicationConfig.applicationLifecycleAdvisor();
}
@Override
public void showPage(String pageId) {
if (pageId == null)
throw new IllegalArgumentException("pageId == null");
if (getPage() == null || !getPage().getId().equals(pageId)) {
showPage(createPage(this, pageId));
} else {
// asking for the same page, so ignore
}
}
@Override
public void showPage(PageDescriptor pageDescriptor) {
Assert.notNull(pageDescriptor, "pageDescriptor == null");
if (getPage() == null || !getPage().getId().equals(pageDescriptor.getId())) {
showPage(createPage(pageDescriptor));
} else {
// asking for the same page, so ignore
}
}
/**
* Set the given <code>ApplicationPage</code> active (visible + selected if
* applicable)
*
* @param page the <code>ApplicationPage</code>
*/
protected abstract void setActivePage(ApplicationPage page);
@Override
public void showPage(ApplicationPage page) {
if (page == null)
throw new IllegalArgumentException("page == null");
if (this.currentApplicationPage == null) {
this.currentApplicationPage = page;
getAdvisor().onPreWindowOpen(getWindowConfigurer());
this.control = createNewWindowControl();
this.control.addWindowFocusListener(this);
initWindowControl(this.control);
getAdvisor().onWindowCreated(this);
setActivePage(page);
this.control.setVisible(true);
getAdvisor().onWindowOpened(this);
} else {
if (!currentApplicationPage.getId().equals(page.getId())) {
final ApplicationPage oldPage = this.currentApplicationPage;
this.currentApplicationPage = page;
setActivePage(page);
pageListeners.fire("pageClosed", oldPage);
} else {
// asking for the same page, so ignore
}
}
pageListeners.fire("pageOpened", this.currentApplicationPage);
}
protected final ApplicationPage createPage(ApplicationWindow window, String pageDescriptorId) {
PageDescriptor descriptor = getPageDescriptor(pageDescriptorId);
return createPage(descriptor);
}
/**
* Factory method for creating the page area managed by this window. Subclasses may
* override to return a custom page implementation.
*
* @param descriptor The page descriptor
* @return The window's page
*/
protected ApplicationPage createPage(PageDescriptor descriptor) {
return applicationConfig.applicationPageFactory().createApplicationPage(this, descriptor);
}
protected PageDescriptor getPageDescriptor(String pageDescriptorId) {
ApplicationContext ctx = applicationConfig.applicationContext();
Assert.state(ctx.containsBean(pageDescriptorId), "Do not know about page or view descriptor with name '"
+ pageDescriptorId + "' - check your context config");
Object desc = ctx.getBean(pageDescriptorId);
if (desc instanceof PageDescriptor) {
return (PageDescriptor) desc;
} else if (desc instanceof ViewDescriptor) {
return new SingleViewPageDescriptor((ViewDescriptor) desc);
} else {
throw new IllegalArgumentException("Page id '" + pageDescriptorId
+ "' is not backed by an ApplicationPageDescriptor");
}
}
protected ApplicationWindowConfigurer getWindowConfigurer() {
if (applicationWindowConfigurer == null) {
this.applicationWindowConfigurer = initWindowConfigurer();
}
return applicationWindowConfigurer;
}
protected ApplicationWindowConfigurer initWindowConfigurer() {
return new DefaultApplicationWindowConfigurer(this);
}
protected JFrame createNewWindowControl() {
JXFrame frame = new JXFrame();
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
WindowAdapter windowCloseHandler = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
close();
}
};
frame.addWindowListener(windowCloseHandler);
new DefaultButtonFocusListener();
return frame;
}
/**
* Close this window. First checks with the advisor by calling the
* {@link ApplicationLifecycleAdvisor#onPreWindowClose(ApplicationWindow)}
* method. Then tries to close it's currentPage. If both are successfull,
* the window will be disposed and removed from the {@link WindowManager}.
*
* @return boolean <code>true</code> if both, the advisor and the
* currentPage allow the closing action.
*/
public boolean close() {
boolean canClose = getAdvisor().onPreWindowClose(this);
if (canClose) {
// check if page can be closed
if (currentApplicationPage != null) {
canClose = currentApplicationPage.close();
// page cannot be closed, exit method and do not dispose
if (!canClose)
return canClose;
}
if (control != null) {
control.dispose();
control = null;
}
if (windowManager != null) {
windowManager.remove(this);
}
windowManager = null;
}
return canClose;
}
@Override
public void setWindowManager(WindowManager windowManager) {
this.windowManager = windowManager;
}
/**
* When gaining focus, set this window as the active one on it's manager.
*/
public void windowGainedFocus(WindowEvent e) {
if (this.windowManager != null)
this.windowManager.setActiveWindow(this);
}
/**
* When losing focus no action is done. This way the last focussed window will stay
* listed as the activeWindow.
*/
public void windowLostFocus(WindowEvent e) {
}
protected void initWindowControl(JFrame windowControl) {
ApplicationWindowConfigurer configurer = getWindowConfigurer();
applyStandardLayout(windowControl, configurer);
prepareWindowForView(windowControl, configurer);
}
protected void applyStandardLayout(JFrame windowControl, ApplicationWindowConfigurer configurer) {
windowControl.setTitle(configurer.getTitle());
windowControl.setIconImage(configurer.getImage());
windowControl.setJMenuBar(createMenuBarControl());
windowControl.getContentPane().setLayout(new BorderLayout());
windowControl.getContentPane().add(createToolBarControl(), BorderLayout.NORTH);
windowControl.getContentPane().add(createWindowContentPane());
windowControl.getContentPane().add(createStatusBarControl(), BorderLayout.SOUTH);
}
protected void prepareWindowForView(JFrame windowControl, ApplicationWindowConfigurer configurer) {
windowControl.pack();
windowControl.setSize(configurer.getInitialSize());
WindowUtils.centerOnScreen(windowControl);
}
@Override
public void addPageListener(PageListener listener) {
this.pageListeners.add(listener);
}
@Override
public void removePageListener(PageListener listener) {
this.pageListeners.remove(listener);
}
protected JMenuBar createMenuBarControl() {
JMenuBar menuBar = menuBarCommandGroup.createMenuBar();
menuBarCommandGroup.setVisible( getWindowConfigurer().getShowMenuBar() );
return menuBar;
}
protected JComponent createToolBarControl() {
JComponent toolBar = toolBarCommandGroup.createToolBar();
toolBarCommandGroup.setVisible( getWindowConfigurer().getShowToolBar() );
return toolBar;
}
protected JComponent createStatusBarControl() {
JComponent statusBarControl = statusBar.getControl();
statusBarControl.setVisible( getWindowConfigurer().getShowStatusBar() );
return statusBarControl;
}
/**
* Implementors create the component that contains the contents of this window.
*
* @return the content pane
*/
protected abstract JComponent createWindowContentPane();
public Iterator getSharedCommands() {
return commandManager.getSharedCommands();
}
@Override
public ApplicationWindowCommandManager getCommandManager() {
return commandManager;
}
@Override
public StatusBar getStatusBar() {
return statusBar;
}
}