/*******************************************************************************
* Copyright (c) 2014, 2016 itemis AG and others.
*
* 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:
* Matthias Wienand (itemis AG) - initial API & implementation
*
*******************************************************************************/
package org.eclipse.gef.zest.fx.behaviors;
import org.eclipse.gef.common.collections.MultisetChangeListener;
import org.eclipse.gef.layout.LayoutContext;
import org.eclipse.gef.mvc.fx.behaviors.AbstractBehavior;
import org.eclipse.gef.mvc.fx.parts.IVisualPart;
import org.eclipse.gef.zest.fx.parts.AbstractLabelPart;
import javafx.scene.Node;
/**
* The {@link AbstractLayoutBehavior} is an abstract behavior that schedules
* {@link #preLayout()} and {@link #postLayout()} to be called before or after a
* layout pass, respectively. The {@link #preLayout()} method can be used to
* write layout information into the layout model. Similarly, the
* {@link #postLayout()} method can be used to read layout information from the
* layout model.
*
* @author mwienand
*
*/
public abstract class AbstractLayoutBehavior extends AbstractBehavior {
private MultisetChangeListener<IVisualPart<? extends Node>> anchoredsChangeListener = new MultisetChangeListener<IVisualPart<? extends Node>>() {
@Override
public void onChanged(
org.eclipse.gef.common.collections.MultisetChangeListener.Change<? extends IVisualPart<? extends Node>> change) {
layoutLabels();
}
};
@Override
protected void doActivate() {
super.doActivate();
getHost().getAnchoredsUnmodifiable().addListener(anchoredsChangeListener);
}
@Override
protected void doDeactivate() {
getHost().getAnchoredsUnmodifiable().removeListener(anchoredsChangeListener);
super.doDeactivate();
}
/**
* Returns the {@link LayoutContext} for which {@link #preLayout()} and
* {@link #postLayout()} shall be called before or after a layout pass,
* respectively.
*
* @return The {@link LayoutContext} for which {@link #preLayout()} and
* {@link #postLayout()} shall be called before or after a layout
* pass, respectively.
*/
protected abstract LayoutContext getLayoutContext();
/**
* Called after a layout pass. Should be used to transfer layout information
* from the layout model.
*/
protected abstract void postLayout();
/**
* Called before a layout pass. Should be used to transfer layout
* information to the layout model.
*/
protected abstract void preLayout();
/**
* Called after a layout pass to adjust label positions.
*/
protected void layoutLabels() {
// iterate anchoreds
for (IVisualPart<? extends Node> anchored : getHost().getAnchoredsUnmodifiable().elementSet()) {
// FIXME: Layout should only be triggered when content-part-map
// is changed, not when the children are changed.
if (anchored.getViewer() == null) {
continue;
}
// filter for label parts
if (anchored instanceof AbstractLabelPart) {
AbstractLabelPart labelPart = (AbstractLabelPart) anchored;
// compute label position
labelPart.recomputeLabelPosition();
}
}
}
}