/*****************************************************************************
* Copyright (c) 2008 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.infra.core.sasheditor.internal;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IAbstractPanelModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashPanelModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
/**
* Part used as root. This is the one with no parent and no model. This class is intended for local
* use only.
*
* @author dumoulin
*
* @param T
* Common ancestor for the model provided for the sash windows by the application.
* This is the type used externally by the application. Sash implementation don't use this type,
* it just carry it to ask for the appropriate wrapper. Concrete implementation can specify
* a type.
*/
public class RootPart extends AbstractPart implements IPanelParent {
/** The SWT container used as parent of all */
private Composite container;
/**
* The first SWT controled part;
*/
private AbstractPanelPart child;
/** Raw model associated to this part. We store it because the PartModel do not provide it */
// private Object rawModel;
/**
* Constructor.
*/
public RootPart(SashWindowsContainer sashWindowsContainer) {
super(sashWindowsContainer);
}
/**
* Create the SWT controls.
* This Root as no control. Children are created by the {@link #synchronize2(PartLists)} method.
*/
public void createPartControl(Composite parent) {
this.container = parent;
}
/**
* Dispose this part and its children.
*/
public void disposeThisAndChildren() {
if(child != null)
child.disposeThisAndChildren();
// Detach properties to help GC
child = null;
}
/**
* Get control associated to this part.
*/
public Composite getControl() {
return container;
}
/**
* Create the part for the specified child model.
* The controls are also builds.
*
* TODO: delegate to sashContainer.
*
* @param rootPart
* @param partModel
* @return
*/
private AbstractPanelPart createChildPart(Object rawModel) {
// Create the child PartModel. Delegate creation to the root PartModel.
IAbstractPanelModel model = getPartModel().createChildSashModel(rawModel);
AbstractPanelPart createdPart;
if(model instanceof ITabFolderModel) {
createdPart = new TabFolderPart(this, (ITabFolderModel)model, rawModel);
} else if(model instanceof ISashPanelModel) {
createdPart = new SashPanelPart(this, (ISashPanelModel)model, rawModel);
} else {
// error
throw new IllegalArgumentException("Can't create child part for model of type '"
+ model.getClass().getName()
+ "'");
// TODO: Return an error Part showing the exception instead of throwing it ?
}
// Create controls
createdPart.createPartControl(getControl());
return createdPart;
}
/**
* Get the PartModel associated to this Part.
*
* @return
*/
private ISashWindowsContentProvider getPartModel() {
// The associated model for a root is the ContentProvider.
return getSashWindowContainer().getContentProvider();
}
/**
* Synchronize the part and its children.
*
* @param partMap
*/
public void synchronize2(PartLists partMap) {
// Synchronize locally the child
synchronizeChild(partMap);
// Synchronize recursively subchilds.
if(child != null)
child.synchronize2(partMap);
}
/**
* Synchronize locally the child
*
* @param partMap
*/
private void synchronizeChild(PartLists partMap) {
// Get the new raw model
Object rawModel = getContentProvider().getRootModel();
// Check if old child exist
// If exist, check if the current part is associated to the checked model
//
if(child != null) {
// If the tile is already for the model, there is nothing to do.
if(child.isPartFor(rawModel)) {
child.unchanged();
return;
}
// The current tile is not for the model: mark it as orphan
child.orphan();
}
// The child tile need to be updated. Do it.
// First check if already exist in the map
AbstractPanelPart newPart = partMap.findPartFor(rawModel);
if(newPart != null) {
// Reparent the tile
newPart.reparent(this, getControl());
} else {
// create the tile and its control
newPart = createChildPart(rawModel);
}
// Now, put the tile on the right side
setChild(newPart);
}
/**
* Set the child. If a child already exist at the specified index, it is lost.
*
* @param newTile
*/
private void setChild(AbstractPanelPart newTile) {
child = newTile;
}
/**
* Fill partMap with the children.
*
* @param partMap
*/
public void fillPartMap(PartLists partMap) {
if(child != null)
child.fillPartMap(partMap);
}
/**
* Find The AbstractPart under the specified position.
*/
public AbstractPart findPart(Point toFind) {
if(child != null)
try {
return child.findPart(toFind);
} catch (NotFoundException e) {
System.err.println(e.getMessage());
return null;
}
else
return null;
}
// /**
// * Locates the part that intersects the given point and that have the expected type
// *
// * @param toFind
// * @return
// */
// public AbstractPart findPartAt(Point toFind, Class<?> tileType) {
// return child.findPartAt(toFind, tileType);
// }
/**
*
*/
public AbstractPart findPart(Object control) {
if(child != null)
return child.findPart(control);
else
return null;
}
// /**
// * @see org.eclipse.papyrus.infra.core.sasheditor.sash.ITilePart#getDropTarget(java.lang.Object, org.eclipse.papyrus.infra.core.sasheditor.sash.TabFolderPart, org.eclipse.swt.graphics.Point)
// */
// public IDropTarget getDropTarget(Object draggedObject, TabFolderPart sourcePart, Point position) {
// return child.getDropTarget(draggedObject, sourcePart, position);
// }
/**
* Do nothing. This node can't be orphaned
*
*/
public void orphan() {
// Do nothing. This node can't be orphaned
}
/**
* Always return false. This Part can't be orphaned.
*
* @see org.eclipse.papyrus.infra.core.sasheditor.internal.AbstractPart#isOrphaned()
*
* @return
*/
public boolean isOrphaned() {
return false;
}
/**
* Get the Garbage state.
*
* @see org.eclipse.papyrus.infra.core.sasheditor.internal.AbstractPart#getGarbageState()
*
* @return
*/
public GarbageState getGarbageState() {
return GarbageState.UNVISITED;
}
/**
* Accept the provided visitor.
* Call the corresponding accept method in the visitor.
*
* @param visitor
* @return
*/
public boolean visit(IPartVisitor visitor) {
return visitor.accept(this);
}
/**
* Visit the children of this Tile.
*
* @param visitor
*/
public boolean visitChildren(IPartVisitor visitor) {
if(child != null)
return child.visit(visitor);
// Return the default value
return true;
}
/**
* Show tile status.
*/
protected void showStatus() {
org.eclipse.papyrus.infra.core.sasheditor.Activator.log.debug("rootPart (1)"
+ ", disposed=" + container.isDisposed()
+ ", visible=" + container.isVisible()
+ ", " + this);
}
}