314 lines
11 KiB
Java
314 lines
11 KiB
Java
/*
|
|
* Copyright (c) 2005,2009 Declarative Engineering LLC.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Declarative Engineering LLC
|
|
* verson 1 which accompanies this distribution, and is available at
|
|
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
|
*/
|
|
package com.foundation.view.swt;
|
|
|
|
import org.eclipse.swt.custom.StackLayout;
|
|
import org.eclipse.swt.widgets.Layout;
|
|
|
|
import com.common.util.ICollection;
|
|
import com.common.util.IIterator;
|
|
import com.common.util.IList;
|
|
import com.common.util.LiteList;
|
|
import com.foundation.controller.ViewController;
|
|
import com.foundation.util.IInlineCollectionObservable;
|
|
import com.foundation.util.IInlineCollectionObserver;
|
|
import com.foundation.util.IInlineIndexedCollectionObservable;
|
|
import com.foundation.util.IInlineIndexedCollectionObserver;
|
|
import com.foundation.view.IEventAssociation;
|
|
import com.foundation.view.SingleAssociationContainer;
|
|
import com.foundation.view.SingleResourceAssociation;
|
|
import com.foundation.view.swt.util.SwtUtilities;
|
|
|
|
/*
|
|
* Displays components in a stack such that only one component is visible at a time.
|
|
*/
|
|
public class StackViewer extends Container implements IInlineIndexedCollectionObserver, IInlineCollectionObserver {
|
|
/** The association that results in a collection of view controllers. */
|
|
private SingleResourceAssociation views = null;
|
|
/** The association that tracks which view is being displayed. */
|
|
private SingleResourceAssociation visibleView = null;
|
|
/** The previous collection of view controllers. */
|
|
private IList viewControllers = new LiteList(1, 15);
|
|
/** Temporarily suspends processing of events fired by registered collections. */
|
|
private boolean suspendCollectionEvents = false;
|
|
/**
|
|
* StackViewer constructor.
|
|
* @param parent A composite control which will be the parent of the new instance (cannot be null).
|
|
* @param name The unique component name.
|
|
* @param style The style of control to construct.
|
|
* @see #STYLE_NO_BACKGROUND
|
|
* @see #STYLE_NO_FOCUS
|
|
* @see #STYLE_NO_MERGE_PAINTS
|
|
* @see #STYLE_NO_REDRAW_RESIZE
|
|
* @see #STYLE_NO_RADIO_GROUP
|
|
* @see #STYLE_H_SCROLL
|
|
* @see #STYLE_V_SCROLL
|
|
* @see #STYLE_BORDER
|
|
* @see #STYLE_LEFT_TO_RIGHT
|
|
* @see #STYLE_RIGHT_TO_LEFT
|
|
*/
|
|
public StackViewer(Container parent, String name, int style) {
|
|
super(parent, name, style);
|
|
this.views = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_OBJECT, false, null);
|
|
this.visibleView = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_OBJECT, false, null);
|
|
}//StackViewer()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
|
|
*/
|
|
protected void initializeControl(int style, Object data) {
|
|
setSwtWidget(new org.eclipse.swt.widgets.Composite(((Container) getContainer()).getSwtParent(), style));
|
|
getSwtWidget().setData(this);
|
|
getSwtComposite().setLayout(new StackLayout());
|
|
}//initializeControl()//
|
|
/**
|
|
* Gets the stack layout used with the wizard.
|
|
* @return The wizard's stack layout.
|
|
*/
|
|
protected StackLayout getLayout() {
|
|
return (StackLayout) getSwtComposite().getLayout();
|
|
}//getLayout()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.view.swt.Container#setLayout(org.eclipse.swt.widgets.Layout)
|
|
*/
|
|
public void setLayout(Layout layout) {
|
|
//Does nothing. Layouts are not allowed here.//
|
|
}//setLayout()//
|
|
/**
|
|
* Gets the SWT composite that represents this panel.
|
|
* @return The SWT composite providing visualization for this panel.
|
|
*/
|
|
public org.eclipse.swt.widgets.Composite getSwtComposite() {
|
|
return (org.eclipse.swt.widgets.Composite) getSwtControl();
|
|
}//getSwtComposite()//
|
|
/**
|
|
* Sets the association container used to access the views in the stack.
|
|
* @param container The views association metadata.
|
|
*/
|
|
public void setViewsAssociation(SingleAssociationContainer container) {
|
|
verifyThread();
|
|
this.views.setAssociations(container);
|
|
}//setViewsAssociation()//
|
|
/**
|
|
* Sets the association container used to access the visible view.
|
|
* @param container The visible view association metadata.
|
|
*/
|
|
public void setVisibleViewAssociation(SingleAssociationContainer container) {
|
|
verifyThread();
|
|
this.visibleView.setAssociations(container);
|
|
}//setVisibleViewAssociation()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.view.swt.AbstractComponent#internalOnEventFired(com.foundation.view.swt.IEventAssociation, java.lang.Object[])
|
|
*/
|
|
protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) {
|
|
}//internalOnEventFired()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
|
|
*/
|
|
protected void internalViewInitialize() {
|
|
views.initialize();
|
|
visibleView.initialize();
|
|
super.internalViewInitialize();
|
|
}//internalViewInitialize()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
|
|
*/
|
|
protected void internalViewRelease() {
|
|
super.internalViewRelease();
|
|
views.release();
|
|
visibleView.release();
|
|
|
|
for(int index = 0; index < viewControllers.getSize(); index++) {
|
|
((ViewController) viewControllers.get(index)).close();
|
|
}//for//
|
|
}//internalViewRelease()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
|
|
*/
|
|
protected void internalViewRefresh() {
|
|
super.internalViewRefresh();
|
|
|
|
internalRefreshViews();
|
|
internalRefreshVisibleView();
|
|
}//internalViewRefresh()//
|
|
/**
|
|
* Refreshes the currently visible component.
|
|
*/
|
|
protected void internalRefreshViews() {
|
|
Object oldValue = views.getValue();
|
|
|
|
if(views.refresh()) {
|
|
stopRendering();
|
|
|
|
try {
|
|
Object newValue = views.getValue();
|
|
|
|
//Remove listeners from the old value.//
|
|
if(oldValue instanceof IInlineIndexedCollectionObservable) {
|
|
((IInlineIndexedCollectionObservable) oldValue).removeCollectionObserver(this);
|
|
}//if//
|
|
else if(oldValue instanceof IInlineCollectionObservable) {
|
|
((IInlineCollectionObservable) oldValue).removeCollectionObserver(this);
|
|
}//else if//
|
|
|
|
//Close the old view controllers.//
|
|
for(int index = 0; index < viewControllers.getSize(); index++) {
|
|
((ViewController) viewControllers.get(index)).close();
|
|
}//for//
|
|
|
|
viewControllers.removeAll();
|
|
|
|
//If the new value is a collection or object then add and remove pages as required, and add listeners as required.//
|
|
if(newValue instanceof ICollection) {
|
|
IIterator iterator = ((ICollection) newValue).iterator();
|
|
|
|
//Add tabs for all the view controllers.//
|
|
while(iterator.hasNext()) {
|
|
Object next = iterator.next();
|
|
|
|
//Ignore non-view controller objects.//
|
|
if(next instanceof ViewController) {
|
|
ViewController controller = (ViewController) next;
|
|
|
|
controller.openPartial(this, getViewContext());
|
|
}//if//
|
|
else {
|
|
throw new RuntimeException("Expecting a view controller.");
|
|
}//else//
|
|
}//while//
|
|
|
|
//Add the controllers to the list of view controllers.//
|
|
viewControllers.addAll((ICollection) newValue);
|
|
//Prevent collection events from notifying us of existing items in the collection.//
|
|
suspendCollectionEvents = true;
|
|
|
|
//Add a listener to the collection so we get change events.//
|
|
if(newValue instanceof IInlineIndexedCollectionObservable) {
|
|
((IInlineIndexedCollectionObservable) newValue).addCollectionObserver(this);
|
|
}//if//
|
|
else if(newValue instanceof IInlineCollectionObservable) {
|
|
((IInlineCollectionObservable) newValue).addCollectionObserver(this);
|
|
}//else if//
|
|
|
|
//Re-enable the collection events.//
|
|
suspendCollectionEvents = false;
|
|
}//if//
|
|
else if(newValue instanceof ViewController) {
|
|
ViewController controller = (ViewController) newValue;
|
|
|
|
controller.openPartial(this, getViewContext());
|
|
//Add the one controller to the list of view controllers.//
|
|
viewControllers.add(controller);
|
|
}//else if//
|
|
}//try//
|
|
finally {
|
|
startRendering();
|
|
}//finally//
|
|
}//if//
|
|
}//internalRefreshViews()//
|
|
/**
|
|
* Refreshes the currently visible component.
|
|
*/
|
|
protected void internalRefreshVisibleView() {
|
|
if(visibleView.refresh()) {
|
|
Object view = (Object) visibleView.getValue();
|
|
int index = viewControllers.getIndexOf(view);
|
|
|
|
if(index >= 0) {
|
|
((StackLayout) getSwtComposite().getLayout()).topControl = getSwtComposite().getChildren()[index];
|
|
getSwtComposite().layout(true, false);
|
|
}//if//
|
|
}//if//
|
|
}//internalRefreshVisibleView()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.view.swt.AbstractComponent#internalViewSynchronize()
|
|
*/
|
|
protected void internalViewSynchronize() {
|
|
//Since the page can only be set manually, this method should do nothing.//
|
|
super.internalViewSynchronize();
|
|
}//internalViewSynchronize()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.view.swt.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation, int)
|
|
*/
|
|
protected void internalOnValueChanged(SingleResourceAssociation association, int flags) {
|
|
if(association == visibleView) {
|
|
internalRefreshVisibleView();
|
|
}//if//
|
|
else if(association == views) {
|
|
internalRefreshViews();
|
|
}//else if//
|
|
else {
|
|
super.internalOnValueChanged(association, flags);
|
|
}//else//
|
|
}//internalOnValueChanged()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.util.IInlineIndexedCollectionObserver#startChanges(int)
|
|
*/
|
|
public void startChanges(int changeCount) {
|
|
startRendering();
|
|
}//startChanges()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.util.IInlineIndexedCollectionObserver#stopChanges()
|
|
*/
|
|
public void stopChanges() {
|
|
stopRendering();
|
|
}//stopChanges()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.util.IInlineCollectionObserver#valueAdded(java.lang.Object)
|
|
*/
|
|
public void valueAdded(Object value) {
|
|
if((!suspendCollectionEvents) && (value instanceof ViewController)) {
|
|
viewControllers.add(value);
|
|
((ViewController) value).openPartial(this, getViewContext());
|
|
}//if//
|
|
}//valueAdded()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueAdded(java.lang.Object, int)
|
|
*/
|
|
public void valueAdded(Object value, int index) {
|
|
valueAdded(value);
|
|
}//valueAdded()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.util.IInlineCollectionObserver#valueRemoved(java.lang.Object)
|
|
*/
|
|
public void valueRemoved(Object value) {
|
|
if((!suspendCollectionEvents) && (viewControllers.remove(value))) {
|
|
((ViewController) value).close();
|
|
}//if//
|
|
}//valueRemoved()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.util.IInlineIndexedCollectionObserver#valueRemoved(java.lang.Object, int)
|
|
*/
|
|
public void valueRemoved(Object value, int index) {
|
|
valueRemoved(value);
|
|
}//valueRemoved()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.util.IInlineIndexedCollectionObserver#removingAll()
|
|
*/
|
|
public void removingAll() {
|
|
if(!suspendCollectionEvents) {
|
|
IIterator iterator = viewControllers.iterator();
|
|
|
|
startChanges(viewControllers.getSize());
|
|
|
|
try {
|
|
while(iterator.hasNext()) {
|
|
valueRemoved(iterator.next());
|
|
}//while//
|
|
}//try//
|
|
finally {
|
|
stopChanges();
|
|
}//finally//
|
|
}//if//
|
|
}//removingAll()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.util.IInlineIndexedCollectionObserver#valuesSorted(int[])
|
|
*/
|
|
public void valuesSorted(int[] mapping) {
|
|
//Does nothing.//
|
|
}//valuesSorted()//
|
|
}//StackViewer// |