/*******************************************************************************
* Copyright (c) 2016 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.browsersim.widgets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.ExpandBar;
import org.eclipse.swt.widgets.ExpandItem;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Widget;
/**
* Widget resolver resolves children and parent of supported type.
* Note: Must be used in UI Thread.
*
* Supported widgets:
* <ul>
* <li>ExpandBar</li>
* <li>ExpandItem</li>
* <li>CTabFolder</li>
* <li>TabFolder</li>
* <li>CTabItem</li>
* <li>TabItem</li>
* <li>ToolBar</li>
* <li>Composite</li>
* <li>Control</li>
* <li>Text</li>
* </ul>
*
* @author Jiri Peterka
*
*/
public class WidgetResolver {
private static WidgetResolver instance = null;
private WidgetResolver() {}
/**
* Returns instance of WidgetResolver.
*
* @return widgetResolver instance
*/
public static WidgetResolver getInstance() {
if (instance == null) instance = new WidgetResolver();
return instance;
}
private static final Class<?>[] supported = {
ExpandBar.class,
ExpandItem.class,
CTabFolder.class,
TabFolder.class,
CTabItem.class,
TabItem.class,
ToolBar.class,
Composite.class,
Control.class
};
/**
* Returns parent of specified widget. If widget is not resolvable, return null.
* Must be called from UI Thread.
*
* @param w widget to resolve
* @return parent widget or null
*/
public Widget getParent(Widget w) {
if (w instanceof ExpandBar) {
return ((ExpandBar) w).getParent();
}
if (w instanceof ExpandItem) {
return ((ExpandItem) w).getParent();
}
else if (w instanceof CTabFolder) {
return ((CTabFolder) w).getParent();
}
else if (w instanceof TabFolder) {
return ((TabFolder) w).getParent();
}
else if (w instanceof CTabItem) {
return ((CTabItem) w).getParent();
}
else if (w instanceof TabItem) {
return ((TabItem) w).getParent();
}
else if (w instanceof ToolBar) {
return ((ToolBar) w).getParent();
}
else if (w instanceof ToolItem) {
return ((ToolItem) w).getParent();
}
else if (w instanceof TableItem) {
return ((TableItem) w).getParent();
}
else if (w instanceof Composite) {
Composite parent = ((Composite)w).getParent();
// If composite under TabFolder find widget under TabFolder siblings
if (parent instanceof TabFolder) {
if ((parent == null) || parent.isDisposed()) {
throw new IllegalArgumentException("TabFolder is null or disposed while resolving");
}
TabItem[] tabItems = ((TabFolder) parent).getItems();
int index = Arrays.asList(tabItems).indexOf(w);
if (index == -1) {
throw new IllegalArgumentException("Widget not found under TabFolder");
}
return tabItems[index];
}
return parent;
}
else if (w instanceof Control) {
return ((Control) w).getParent();
}
return null;
}
/**
* Returns children of specified widget. If widget is not resolvable, return null.
* Must be called from UI Thread.
*
* @param w widget to resolve
* @return list of children widgets
*/
public List<Widget> getChildren(Widget w) {
List<Widget> children = new ArrayList<Widget>();
if (w instanceof ExpandBar) {
Widget[] items = ((ExpandBar) w).getItems();
children = Arrays.asList(items);
} else if (w instanceof ExpandItem) {
Control control = ((ExpandItem) w).getControl();
if (control != null) children.add(control);
} else if (w instanceof CTabFolder) {
List<Widget> tempList = new ArrayList<>();
tempList.addAll(Arrays.asList(((CTabFolder) w).getChildren()));
tempList.addAll(Arrays.asList(((CTabFolder) w).getItems()));
children = tempList;
} else if (w instanceof TabFolder) {
Widget[] items = ((TabFolder) w).getItems();
children = Arrays.asList(items);
}
else if (w instanceof CTabItem) {
Control control = ((CTabItem) w).getControl();
if (control != null) children.add(control);
}
else if (w instanceof TabItem) {
Control control = ((TabItem) w).getControl();
if (control != null) children.add(control);
}
else if (w instanceof ToolBar) {
Widget[] items = ((ToolBar) w).getItems();
children = Arrays.asList(items);
} else if (w instanceof ToolItem) {
// do nothing
} else if (w instanceof Table) {
List<Widget> tempList = new ArrayList<Widget>();
tempList.addAll(Arrays.asList(((Table)w).getChildren()));
tempList.addAll(Arrays.asList(((Table)w).getItems()));
children = tempList;
}
else if (w instanceof TableItem) {
// do nothing
}
else if (w instanceof Composite) {
Widget[] items = ((Composite) w).getChildren();
children = Arrays.asList(items);
}
else if (w instanceof Control) {
// do nothing
}
return children;
}
/**
* Finds out whether specified widget has parent.
*
* @param w widget to resolve
* @return true if widget has a parent, false otherwise.
*/
public boolean hasParent(Widget w) {
return getParent(w) != null;
}
/**
* Find out whether specified widget has children.
*
* @param w widget to resolve
* @return true if widget has children, false otherwise
*/
public boolean hasChildren(Widget w) {
return isResolvable(w) && (getChildren(w).size() > 0) ;
}
/**
* Finds out whether specified widget is resolvable or not.
*
* @param w widget to resolve
* @return true if widget is resolvable, false otherwise.
*/
public boolean isResolvable(Widget w) {
// DateTime is not supported because of eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=206868
if (w instanceof DateTime) return false;
return Arrays.asList(supported).contains(w.getClass());
}
}