/*******************************************************************************
* Copyright (c) 2008 Olivier Moises
*
* 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:
* Olivier Moises- initial API and implementation
*******************************************************************************/
package org.eclipse.wazaabi.ide.ui.outline;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TypedListener;
import org.eclipse.wazaabi.engine.core.editparts.WidgetEditPart;
import org.eclipse.wazaabi.engine.core.gef.EditPart;
import org.eclipse.wazaabi.engine.core.views.WidgetView;
import org.eclipse.wazaabi.engine.swt.commons.editparts.SWTRootEditPart;
import org.eclipse.wazaabi.engine.swt.commons.views.SWTWidgetView;
import org.eclipse.wazaabi.engine.swt.viewers.SWTControlViewer;
import org.eclipse.wazaabi.ide.ui.editparts.AbstractComponentTreeEditPart;
import org.eclipse.wazaabi.mm.core.widgets.AbstractComponent;
import org.eclipse.wazaabi.mm.core.widgets.Container;
public class OutlineViewer extends SWTControlViewer implements
ISelectionChangedListener {
private List<Control> selectedControls = new ArrayList<Control>();
private PaintListener paintListener = new PaintListener() {
public void paintControl(PaintEvent e) {
for (Control c : selectedControls) {
Point controlLocation = c.getLocation();
e.gc.setLineStyle(SWT.LINE_SOLID);
e.gc.setLineWidth(2);
Color previousColor = e.gc.getForeground();
e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_RED));
if (c.getParent() == e.widget)
e.gc.drawRectangle(controlLocation.x - 1,
controlLocation.y - 1, c.getSize().x + 2,
c.getSize().y + 2);
else if (c == OutlineViewer.this.getControl())
e.gc.drawRectangle(controlLocation.x + 1,
controlLocation.y + 1, c.getSize().x - 2,
c.getSize().y - 2);
e.gc.setForeground(previousColor);
}
}
};
public OutlineViewer(Composite parent) {
super(parent);
}
public OutlineViewer(Composite parent, SWTRootEditPart rootEditPart) {
super(parent, rootEditPart);
}
protected void addUniquePaintListener(Control control,
PaintListener paintListener) {
if (control == null || control.isDisposed() || paintListener == null)
return;
if (!hasPaintListener(control))
control.addPaintListener(paintListener);
}
private boolean hasPaintListener(Control control) {
for (Listener l : control.getListeners(SWT.Paint))
if (l instanceof TypedListener
&& ((TypedListener) l).getEventListener().equals(
paintListener))
return true;
return false;
}
protected void removeUniquePaintListener(Control control,
PaintListener paintListener) {
if (control == null || control.isDisposed() || paintListener == null)
return;
if (hasPaintListener(control))
control.removePaintListener(paintListener);
}
public void selectionChanged(SelectionChangedEvent event) {
if (getControl() == null || getControl().isDisposed()
|| event.getSelection() == null)
return;
List<Control> newlySelectedControls = new ArrayList<Control>();
if (event.getSelection() instanceof StructuredSelection) {
for (Object selected : ((StructuredSelection) event.getSelection())
.toList()) {
if (selected instanceof AbstractComponentTreeEditPart) {
AbstractComponent outlineComponent = getOutlineComponent(((AbstractComponentTreeEditPart) selected)
.getAbstractComponentModel());
WidgetEditPart ep = (WidgetEditPart) getEditPartRegistry()
.get(outlineComponent);
if (ep != null) {
WidgetView widgetView = ep.getWidgetView();
if (widgetView instanceof SWTWidgetView
&& ((SWTWidgetView) widgetView).getSWTWidget() instanceof Control)
newlySelectedControls
.add((Control) ((SWTWidgetView) widgetView)
.getSWTWidget());
}
}
}
}
List<Control> toUnselect = new ArrayList<Control>();
for (Control c : selectedControls)
if (c.isDisposed() || !newlySelectedControls.contains(c))
toUnselect.add(c);
for (Control c : toUnselect)
selectedControls.remove(c);
for (Control c : newlySelectedControls)
if (c.isDisposed() || !selectedControls.contains(c))
selectedControls.add(c);
List<Control> toRemovePaintListener = new ArrayList<Control>();
List<Control> toAddPaintListener = new ArrayList<Control>();
for (Control c : toUnselect)
if (!c.isDisposed()) {
if (c != getControl())
toRemovePaintListener.add(c.getParent());
else
toRemovePaintListener.add(c);
}
// we remove only what we don't need to add later
for (Control c : selectedControls)
if (c != getControl()) {
toAddPaintListener.add(c.getParent());
if (toRemovePaintListener.contains(c.getParent()))
toRemovePaintListener.remove(c.getParent());
} else {
toAddPaintListener.add(c);
if (toRemovePaintListener.contains(c))
toRemovePaintListener.remove(c);
}
for (Control c : toRemovePaintListener) {
removeUniquePaintListener(c, paintListener);
c.redraw();
}
for (Control c : toAddPaintListener) {
addUniquePaintListener(c, paintListener);
c.redraw();
}
}
public List<Control> getSelectedControls() {
return selectedControls;
}
public void refreshSelection() {
for (Control c : getSelectedControls()) {
c.getParent().redraw();
c.redraw();
}
}
protected AbstractComponent getOutlineComponent(
AbstractComponent editorComponent) {
if (editorComponent == null)
return null;
if (getRootEditPart().getContents() != null
&& getRootEditPart().getContents().getModel() instanceof AbstractComponent) {
AbstractComponent viewerRoot = (AbstractComponent) getRootEditPart()
.getContents().getModel();
if (editorComponent.eContainer() == null)
return viewerRoot;
if (!(viewerRoot instanceof Container))
return null;
List<Integer> indexes = new ArrayList<Integer>();
AbstractComponent current = editorComponent;
Container parent = null;
while ((parent = (Container) current.eContainer()) != null) {
indexes.add(parent.getChildren().indexOf(current));
current = parent;
}
if (!indexes.isEmpty()) {
current = viewerRoot;
for (int i = indexes.size() - 1; i >= 0; i--) {
int index = indexes.get(i);
if (current instanceof Container
&& ((Container) current).getChildren().size() > index)
current = ((Container) current).getChildren()
.get(index);
else
break;
}
return current;
}
}
return null;
}
@Override
public void setContents(EditPart editpart) {
super.setContents(editpart);
selectedControls.clear();
}
}