blob: bcb46b4335ab9d16545df65c54b132497023e7fc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2014 Xored Software Inc 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:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.tesla.properties.view;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.internal.WorkbenchPartReference;
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyComposite;
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyList;
import org.eclipse.rcptt.tesla.core.context.ContextManagement.Context;
import org.eclipse.rcptt.tesla.core.info.AdvancedInformation;
import org.eclipse.rcptt.tesla.core.info.Q7WaitInfoRoot;
import org.eclipse.rcptt.tesla.core.protocol.Click;
import org.eclipse.rcptt.tesla.core.protocol.ElementKind;
import org.eclipse.rcptt.tesla.core.protocol.GenericElementKind;
import org.eclipse.rcptt.tesla.core.protocol.IElementProcessorMapper;
import org.eclipse.rcptt.tesla.core.protocol.ProtocolFactory;
import org.eclipse.rcptt.tesla.core.protocol.SelectCommand;
import org.eclipse.rcptt.tesla.core.protocol.SelectResponse;
import org.eclipse.rcptt.tesla.core.protocol.raw.Command;
import org.eclipse.rcptt.tesla.core.protocol.raw.Element;
import org.eclipse.rcptt.tesla.core.protocol.raw.RawFactory;
import org.eclipse.rcptt.tesla.core.protocol.raw.Response;
import org.eclipse.rcptt.tesla.core.protocol.raw.ResponseStatus;
import org.eclipse.rcptt.tesla.internal.core.AbstractTeslaClient;
import org.eclipse.rcptt.tesla.internal.core.processing.ElementGenerator;
import org.eclipse.rcptt.tesla.internal.core.processing.ITeslaCommandProcessor;
import org.eclipse.rcptt.tesla.internal.ui.player.AbstractSWTUIPlayerExtension;
import org.eclipse.rcptt.tesla.internal.ui.player.ISWTUIPlayerExtension;
import org.eclipse.rcptt.tesla.internal.ui.player.SWTUIElement;
import org.eclipse.rcptt.tesla.internal.ui.player.SWTUIPlayer;
import org.eclipse.rcptt.tesla.internal.ui.player.TeslaSWTAccess;
import org.eclipse.rcptt.tesla.internal.ui.player.WorkbenchUIElement;
import org.eclipse.rcptt.tesla.internal.ui.processors.SWTUIProcessor;
@SuppressWarnings("restriction")
public class PropertiesViewProcessor implements ITeslaCommandProcessor {
private AbstractTeslaClient client;
private SWTUIProcessor swtUIProcessor;
private ISWTUIPlayerExtension extension = new AbstractSWTUIPlayerExtension() {
public GenericElementKind getKind(Object w) {
if (w instanceof TabbedPropertyList.ListElement)
return new GenericElementKind(ElementKind.PropertyTab);
return null;
}
};
public PropertiesViewProcessor() {
SWTUIPlayer.addExtension(extension);
}
public String getFeatureID() {
return "swt.properties.view";
}
public boolean isSelectorSupported(String kind) {
return kind.equals(ElementKind.PropertyTab.name());
}
public SelectResponse select(SelectCommand cmd, ElementGenerator generator,
IElementProcessorMapper mapper) {
if (!cmd.getData().getKind().equals(ElementKind.PropertyTab.name()))
return null;
SWTUIElement swtuiElement = getSWTUIProcessor().getMapper().get(
cmd.getData().getParent());
if (swtuiElement == null)
return selectError("Unable to resolve parent element (SWTUIElement).");
if (!(swtuiElement instanceof WorkbenchUIElement))
return selectError("Unable to resolve parent element (WorkbenchUIElement).");
WorkbenchUIElement workbenchUIElement = (WorkbenchUIElement) swtuiElement;
IWorkbenchPartReference iWorkbenchPartReference = workbenchUIElement
.getReference();
if (!(iWorkbenchPartReference instanceof WorkbenchPartReference))
return selectError("Unable to resolve parent element (WorkbenchPartReference).");
WorkbenchPartReference workbenchPartReference = (WorkbenchPartReference) iWorkbenchPartReference;
final Control control = workbenchPartReference.getPane().getControl();
if (control == null || !(control instanceof Composite))
return selectError("Unable to resolve parent element (Control).");
final String text = cmd.getData().getPattern();
final AtomicReference<Object> tab = new AtomicReference<Object>();
control.getDisplay().syncExec(new Runnable() {
public void run() {
final TabbedPropertyComposite tabbedPropertyComposite = findVisibleChild(
TabbedPropertyComposite.class, (Composite) control);
if (tabbedPropertyComposite == null)
return;
TabbedPropertyList list = tabbedPropertyComposite.getList();
int i = 0;
while (true) { // we do not know item count ahead
Object e = list.getElementAt(i);
if (e == null)
break;
if (e instanceof TabbedPropertyList.ListElement) {
TabbedPropertyList.ListElement listElement = (TabbedPropertyList.ListElement) e;
if (listElement.getTabItem().getText().equals(text)) {
tab.set(listElement);
break;
}
}
++i;
}
}
});
if (tab.get() == null)
return selectError("Property tab \"%s\" is not found.", text);
swtuiElement = getSWTUIProcessor().getPlayer().wrap(tab.get());
Element element = getSWTUIProcessor().getMapper().get(swtuiElement);
SelectResponse selectResponse = ProtocolFactory.eINSTANCE
.createSelectResponse();
selectResponse.getElements().add(element);
return selectResponse;
}
public boolean isCommandSupported(Command cmd) {
return cmd instanceof Click;
}
public Response executeCommand(Command command,
IElementProcessorMapper mapper) {
if (!(command instanceof Click))
return null;
Click click = (Click) command;
SWTUIElement swtuiElement = getSWTUIProcessor().getMapper().get(
click.getElement());
Widget widget = swtuiElement.widget;
if (!(widget instanceof TabbedPropertyList.ListElement))
return executeError("Unsupported widget class \"%s\".", widget
.getClass().getName());
TabbedPropertyList.ListElement listElement = (TabbedPropertyList.ListElement) widget;
final TabbedPropertyComposite tabbedPropertyComposite = findParent(
TabbedPropertyComposite.class, listElement);
if (tabbedPropertyComposite == null)
return executeError("Tabbed property composite is not found.");
final TabbedPropertyList tabbedPropertyList = tabbedPropertyComposite
.getList();
int i = 0;
while (true) { // we do not know item count ahead
Object e = tabbedPropertyList.getElementAt(i);
if (e == listElement) {
final int index = i;
final AtomicBoolean success = new AtomicBoolean(false);
tabbedPropertyList.getDisplay().syncExec(new Runnable() {
public void run() {
if (tabbedPropertyComposite.isVisible()) {
TeslaSWTAccess.callMethod(TabbedPropertyList.class,
tabbedPropertyList, "select",
new Class[] { int.class }, index);
success.set(true);
}
}
});
if (success.get())
return executeSuccess();
else
return executeError("Property tab \"%s\" is not visible.",
listElement.getTabItem().getText());
}
if (e == null)
break;
++i;
}
return executeError("Property tab \"%s\" is not found.", listElement
.getTabItem().getText());
}
public PreExecuteStatus preExecute(Command command,
PreExecuteStatus previousStatus, Q7WaitInfoRoot info) {
return null;
}
public void initialize(AbstractTeslaClient client, String id) {
this.client = client;
}
public void postSelect(Element element, IElementProcessorMapper mapper) {
}
public boolean isInactivityRequired() {
return false;
}
public boolean canProceed(Context context, Q7WaitInfoRoot info) {
return true;
}
public void clean() {
}
public void terminate() {
SWTUIPlayer.removeExtension(extension);
}
public void checkHang() {
}
public void collectInformation(AdvancedInformation information,
Command lastCommand) {
}
public void notifyUI() {
}
// --
private SWTUIProcessor getSWTUIProcessor() {
if (swtUIProcessor == null) {
swtUIProcessor = client.getProcessor(SWTUIProcessor.class);
}
return swtUIProcessor;
}
@SuppressWarnings("unused")
private static Status error(String message, Object... args) {
return new Status(Status.ERROR, PropertiesViewPlugin.PLUGIN_ID,
String.format(message, args));
}
private static SelectResponse selectError(String message, Object... args) {
SelectResponse selectResponse = ProtocolFactory.eINSTANCE
.createSelectResponse();
selectResponse.setStatus(ResponseStatus.FAILED);
selectResponse.setMessage(String.format(message, args));
return selectResponse;
}
private static Response executeError(String message, Object... args) {
Response response = RawFactory.eINSTANCE.createResponse();
response.setStatus(ResponseStatus.FAILED);
response.setMessage(String.format(message, args));
return response;
}
private static Response executeSuccess() {
Response response = RawFactory.eINSTANCE.createResponse();
response.setStatus(ResponseStatus.OK);
return response;
}
private static <T> T findVisibleChild(Class<T> class_, Composite parent) {
for (Control c : parent.getChildren()) {
if (class_ == c.getClass() && c.isVisible())
return class_.cast(c);
else if (c instanceof Composite) {
T result = findVisibleChild(class_, (Composite) c);
if (result != null)
return result;
}
}
return null;
}
private static <T> T findParent(Class<T> class_, Control child) {
do {
child = child.getParent();
if (child.getClass() == class_)
return class_.cast(child);
} while (child != null);
return null;
}
}