/* ******************************************************************************
* 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.gef.tool;
import static org.xmind.gef.GEF.ST_CONTROL_PRESSED;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.viewers.StructuredSelection;
import org.xmind.gef.part.IGraphicalPart;
import org.xmind.gef.part.IPart;
/**
* @author Brian Sun
* @version 2005
*/
public abstract class AreaSelectTool extends AreaCreateTool {
private List<IPart> lastSelected = null;
private List<IPart> newSelected = null;
protected void start() {
super.start();
if (getStatus().isStatus(ST_CONTROL_PRESSED)) {
lastSelected = new ArrayList<IPart>(
getSelectedParts(getTargetViewer()));
} else {
lastSelected = new ArrayList<IPart>();
}
newSelected = new ArrayList<IPart>();
getTargetViewer().setFocused(null);
}
protected void end() {
lastSelected = null;
newSelected = null;
}
protected void updateArea(Rectangle area, Point currentPos) {
super.updateArea(area, currentPos);
IPart rootPart = getTargetViewer().getRootPart();
areaSelect(rootPart, area);
List<IPart> selection = getMergedSelection();
updateSelectionStatus(rootPart, selection);
IPart toFocus = selection.isEmpty() ? null : selection.get(selection
.size() - 1);
getTargetViewer().setFocused(toFocus);
}
protected void updateSelectionStatus(IPart part, List<IPart> selection) {
if (selection.contains(part)) {
part.getStatus().select();
} else {
part.getStatus().deSelect();
}
for (IPart child : part.getChildren()) {
updateSelectionStatus(child, selection);
}
}
protected void areaSelect(IPart part, Rectangle area) {
select(part, area);
for (IPart child : part.getChildren()) {
areaSelect(child, area);
}
}
protected void select(IPart part, Rectangle area) {
if (isSelectable(part, area)) {
if (!newSelected.contains(part)) {
newSelected.add(part);
}
} else {
newSelected.remove(part);
}
}
protected boolean isSelectable(IPart part, Rectangle area) {
if (getTargetViewer().getSelectionSupport().isSelectable(part)) {
if (part instanceof IGraphicalPart) {
IGraphicalPart gp = (IGraphicalPart) part;
return area.intersects(gp.getFigure().getBounds());
}
}
return false;
}
protected List<IPart> getMergedSelection() {
Set<IPart> inter = new HashSet<IPart>(newSelected);
inter.retainAll(lastSelected);
List<IPart> selection = new ArrayList<IPart>(lastSelected);
selection.addAll(newSelected);
selection.removeAll(inter);
return selection;
}
public void finish() {
applySelection();
super.finish();
}
protected void applySelection() {
getTargetViewer().setSelection(
new StructuredSelection(getMergedSelection()), true);
}
public void cancel() {
revertSelection();
super.cancel();
}
protected void revertSelection() {
getTargetViewer().getSelectionSupport().refresh();
}
}