/* * 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.tcv.swt.server; import com.common.util.ICollection; import com.common.util.IIterator; import com.common.util.IList; import com.common.util.LiteList; import com.foundation.util.IInlineCollectionObservable; import com.foundation.util.IInlineCollectionObserver; import com.foundation.util.IInlineIndexedCollectionObservable; import com.foundation.util.IInlineIndexedCollectionObserver; import com.foundation.view.*; import com.foundation.controller.RemoteViewController; import com.foundation.tcv.swt.*; import com.foundation.tcv.view.*; /* * Displays components in a stack such that only one component is visible at a time. */ public class StackViewer extends Container implements IStackViewer, 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); sendMessage(MESSAGE_INITIALIZE, new int[] {parent.getNumber(), style}); }//StackViewer()// /* (non-Javadoc) * @see com.foundation.tcv.swt.server.Container#setLayout(com.foundation.tcv.swt.Layout) */ public void setLayout(Layout layout) { //Does nothing. It does not make sense to change the layout of the wizard since it can only use the stack layout.// }//setLayout()// /* (non-Javadoc) * @see com.foundation.tcv.swt.server.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation) */ 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.tcv.swt.server.AbstractComponent#internalOnEventFired(com.foundation.tcv.swt.server.IEventAssociation, java.lang.Object[]) */ protected void internalOnEventFired(IEventAssociation eventAssociation, Object[] eventArguments) { super.internalOnEventFired(eventAssociation, eventArguments); }//internalOnEventFired()// /* (non-Javadoc) * @see com.foundation.tcv.view.IViewComponent#processMessage(com.foundation.tcv.model.ViewMessage) */ public Object processMessage(ViewMessage viewMessage) { Object retVal = null; switch(viewMessage.getMessageNumber()) { default: { retVal = super.processMessage(viewMessage); }//default// }//switch// return retVal; }//processMessage()// /** * 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.tcv.swt.server.AbstractComponent#getClientClassName() */ protected String getClientClassName() { return "com.foundation.tcv.swt.client.StackViewer"; }//getClientClassName()// /* (non-Javadoc) * @see com.foundation.tcv.swt.server.AbstractComponent#internalViewInitialize() */ protected void internalViewInitialize() { super.internalViewInitialize(); views.initialize(); visibleView.initialize(); }//internalViewInitialize()// /* (non-Javadoc) * @see com.foundation.tcv.swt.server.AbstractComponent#internalViewRelease() */ protected void internalViewRelease() { super.internalViewRelease(); views.release(); visibleView.release(); for(int index = 0; index < viewControllers.getSize(); index++) { ((RemoteViewController) viewControllers.get(index)).close(); }//for// }//internalViewRelease()// /* (non-Javadoc) * @see com.foundation.tcv.swt.server.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()) { addMessageHold(); 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++) { ((RemoteViewController) 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 RemoteViewController) { RemoteViewController controller = (RemoteViewController) 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 RemoteViewController) { RemoteViewController controller = (RemoteViewController) newValue; controller.openPartial(this, getViewContext()); //Add the one controller to the list of view controllers.// viewControllers.add(controller); }//else if// }//try// finally { removeMessageHold(); }//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) { sendMessage(MESSAGE_CHANGE_COMPONENT, null, null, index, -1); }//if// }//if// }//internalRefreshVisibleView()// /* (non-Javadoc) * @see com.foundation.util.IInlineIndexedCollectionObserver#startChanges(int) */ public void startChanges(int changeCount) { addMessageHold(); //suspendRedraw(); }//startChanges()// /* (non-Javadoc) * @see com.foundation.util.IInlineIndexedCollectionObserver#stopChanges() */ public void stopChanges() { //resumeRedraw(); removeMessageHold(); }//stopChanges()// /* (non-Javadoc) * @see com.foundation.util.IInlineCollectionObserver#valueAdded(java.lang.Object) */ public void valueAdded(Object value) { if((!suspendCollectionEvents) && (value instanceof RemoteViewController)) { viewControllers.add(value); ((RemoteViewController) 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))) { ((RemoteViewController) 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//