/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.internal.mindmap;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.xmind.core.Core;
import org.xmind.core.ILegend;
import org.xmind.core.IRelationship;
import org.xmind.core.IRelationshipEnd;
import org.xmind.core.ISheet;
import org.xmind.core.ITopic;
import org.xmind.core.event.CoreEvent;
import org.xmind.core.event.ICoreEventRegister;
import org.xmind.gef.GEF;
import org.xmind.gef.part.IGraphicalEditPart;
import org.xmind.gef.part.IPart;
import org.xmind.gef.part.IRequestHandler;
import org.xmind.ui.internal.decorators.SheetDecorator;
import org.xmind.ui.internal.figures.SheetFigure;
import org.xmind.ui.internal.graphicalpolicies.SheetGraphicalPolicy;
import org.xmind.ui.internal.layouts.SheetLayout;
import org.xmind.ui.mindmap.IBranchPart;
import org.xmind.ui.mindmap.IConnectionPart;
import org.xmind.ui.mindmap.ILegendPart;
import org.xmind.ui.mindmap.IMindMap;
import org.xmind.ui.mindmap.IMindMapViewer;
import org.xmind.ui.mindmap.IRelationshipPart;
import org.xmind.ui.mindmap.ISheetPart;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.util.MindMapUtils;
/**
*
* @author MANGOSOFT
*/
public class SheetPart extends MindMapPartBase
implements ISheetPart, ControlListener {
private IBranchPart centralBranch = null;
private List<IBranchPart> floatingBranches = null;
private List<IRelationshipPart> relationships = null;
private ILegendPart legend = null;
private final ChildSorter sorter = new ChildSorter(this);
public SheetPart() {
setDecorator(SheetDecorator.getInstance());
setGraphicalPolicy(SheetGraphicalPolicy.getInstance());
}
@SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(ISheet.class))
return getSheet();
return super.getAdapter(adapter);
}
public ISheet getSheet() {
return ((IMindMap) super.getModel()).getSheet();
}
public ITopic getRootTopic() {
return getSheet().getRootTopic();
}
public ITopic getCentralTopic() {
return ((IMindMap) super.getModel()).getCentralTopic();
}
protected void register() {
registerModel(getSheet());
super.register();
}
protected void unregister() {
super.unregister();
unregisterModel(getSheet());
}
public IBranchPart getCentralBranch() {
return centralBranch;
}
public void setCentralBranch(IBranchPart branch) {
this.centralBranch = branch;
}
public List<IBranchPart> getFloatingBranches() {
if (floatingBranches == null) {
floatingBranches = new ArrayList<IBranchPart>();
}
return floatingBranches;
}
public void addFloatingBranch(IBranchPart branch) {
getFloatingBranches().add(branch);
sorter.sort(getFloatingBranches());
}
public void removeFloatingBranch(IBranchPart branch) {
getFloatingBranches().remove(branch);
}
public List<IRelationshipPart> getRelationships() {
if (relationships == null) {
relationships = new ArrayList<IRelationshipPart>();
}
return relationships;
}
public void addRelationship(IRelationshipPart relationship) {
getRelationships().add(relationship);
sorter.sort(getRelationships());
}
public void removeRelationship(IConnectionPart relationship) {
getRelationships().remove(relationship);
}
public ILegendPart getLegend() {
return legend;
}
public void setLegend(ILegendPart legend) {
this.legend = legend;
}
protected IFigure createFigure() {
return new SheetFigure();
}
protected LayoutManager createLayoutManager() {
return new SheetLayout(this);
}
protected Object[] getModelChildren(Object model) {
List<Object> list = new ArrayList<Object>();
ILegend legend = getSheet().getLegend();
if (legend.isVisible()) {
list.add(new ViewerModel(LegendPart.class, legend));
}
ITopic rootTopic = getCentralTopic();
list.add(new ViewerModel(BranchPart.class, rootTopic));
for (ITopic floatingTopic : rootTopic.getChildren(ITopic.DETACHED)) {
list.add(new ViewerModel(BranchPart.class, floatingTopic));
}
for (IRelationship rel : getSheet().getRelationships()) {
if (isRelationshipVisible(rel, rootTopic)) {
ViewerModel m = new ViewerModel(RelationshipPart.class, rel);
list.add(m);
}
}
return list.toArray();
}
private boolean isRelationshipVisible(IRelationship r, ITopic rootTopic) {
IRelationshipEnd end1 = r.getEnd1();
if (end1 instanceof ITopic) {
if (!isTopicVisible((ITopic) end1, rootTopic))
return false;
}
IRelationshipEnd end2 = r.getEnd2();
if (end2 instanceof ITopic) {
if (!isTopicVisible((ITopic) end2, rootTopic))
return false;
}
return true;
}
private boolean isTopicVisible(ITopic t, ITopic rootTopic) {
if (t.equals(rootTopic))
return true;
if (isOverMaxLevel(t, rootTopic))
return false;
ITopic parent = t.getParent();
if (parent == null || parent.equals(rootTopic))
return true;
String topicType = t.getType();
if (!ITopic.ATTACHED.equals(topicType)
&& !ITopic.SUMMARY.equals(topicType))
return false;
return isTopicVisible(parent, rootTopic);
}
private boolean isOverMaxLevel(ITopic t, ITopic rootTopic) {
int maxLevel = getSite().getViewer().getProperties()
.getInteger(IMindMapViewer.VIEWER_MAX_TOPIC_LEVEL, -1);
if (maxLevel < 0)
return false;
int level = MindMapUtils.getLevel(t, rootTopic);
return level < 0 || level > maxLevel;
}
protected void reorderChild(IPart child, int index) {
super.reorderChild(child, index);
if (getFloatingBranches().contains(child)) {
sorter.sort(getFloatingBranches());
} else if (getRelationships().contains(child)) {
sorter.sort(getRelationships());
}
}
protected void declareEditPolicies(IRequestHandler reqHandler) {
super.declareEditPolicies(reqHandler);
reqHandler.installEditPolicy(GEF.ROLE_CREATABLE,
MindMapUI.POLICY_SHEET_CREATABLE);
reqHandler.installEditPolicy(GEF.ROLE_SCALABLE,
MindMapUI.POLICY_SHEET_SCALABLE);
reqHandler.installEditPolicy(GEF.ROLE_EDITABLE,
MindMapUI.POLICY_EDITABLE);
reqHandler.installEditPolicy(GEF.ROLE_MODIFIABLE,
MindMapUI.POLICY_MODIFIABLE);
reqHandler.installEditPolicy(GEF.ROLE_DROP_TARGET,
MindMapUI.POLICY_DROP_TARGET);
reqHandler.installEditPolicy(MindMapUI.ROLE_MAP, MindMapUI.POLICY_MAP);
}
protected void registerCoreEvents(Object source,
ICoreEventRegister register) {
super.registerCoreEvents(source, register);
register.register(Core.RelationshipAdd);
register.register(Core.RelationshipRemove);
register.register(Core.Style);
register.register(Core.ThemeId);
register.register(Core.SheetSettings);
ITopic rootTopic = getCentralTopic();
register.setNextSourceFrom(rootTopic);
register.register(Core.TopicAdd);
register.register(Core.TopicRemove);
ILegend legend = getSheet().getLegend();
register.setNextSourceFrom(legend);
register.register(Core.Visibility);
}
public void handleCoreEvent(CoreEvent event) {
String type = event.getType();
if (Core.TopicAdd.equals(type) || Core.TopicRemove.equals(type)) {
if (ITopic.DETACHED.equals(event.getData())) {
refresh();
}
} else if (Core.Style.equals(type)) {
update();
updateCentralBranchStyle();
refreshLegend();
} else if (Core.RelationshipAdd.equals(type)
|| Core.RelationshipRemove.equals(type)) {
refresh();
} else if (Core.Visibility.equals(type)) {
refresh();
} else if (Core.SheetSettings.equals(type)) {
refresh();
} else if (Core.ThemeId.equals(type)) {
refreshTheme();
} else {
super.handleCoreEvent(event);
}
}
private void updateCentralBranchStyle() {
IBranchPart b = getCentralBranch();
if (b instanceof BranchPart) {
((BranchPart) b).refreshStyles();
}
}
private void refreshLegend() {
if (getLegend() != null)
getLegend().refresh();
}
public void refreshTheme() {
refresh();
if (centralBranch != null && centralBranch instanceof BranchPart) {
((BranchPart) centralBranch).refreshStyles();
}
for (IBranchPart floatingBranch : getFloatingBranches()) {
if (floatingBranch instanceof BranchPart) {
((BranchPart) floatingBranch).refreshStyles();
}
}
for (IRelationshipPart r : getRelationships()) {
r.refresh();
}
if (legend != null) {
legend.refresh();
}
}
protected boolean isFigureAnimatable() {
return true;
}
public IPart findAt(Point position) {
IPart ret;
IPart focused = getSite().getViewer().getFocusedPart();
if (focused instanceof IGraphicalEditPart
&& focused.getParent() == this) {
ret = ((IGraphicalEditPart) focused).findAt(position);
if (ret != null)
return ret;
}
ret = super.findAt(position);
if (ret == this)
return null;
return ret;
}
@Override
public void setModel(Object model) {
super.setModel(model);
setAccessible(new SheetAccessible(this));
}
/*
* (non-Javadoc)
*
* @see org.xmind.ui.internal.mindmap.MindMapPartBase#onActivated()
*/
@Override
protected void onActivated() {
super.onActivated();
getSite().getViewer().getControl().addControlListener(this);
}
/*
* (non-Javadoc)
*
* @see org.xmind.ui.internal.mindmap.MindMapPartBase#onDeactivated()
*/
@Override
protected void onDeactivated() {
getSite().getViewer().getControl().removeControlListener(this);
super.onDeactivated();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.
* events .ControlEvent)
*/
public void controlMoved(ControlEvent e) {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt
* .events.ControlEvent)
*/
public void controlResized(ControlEvent e) {
getFigure().revalidate();
}
}