/*******************************************************************************
* Copyright (c) 2007, 2014 compeople 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:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.ui.swt.utils;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.riena.core.util.StringUtils;
import org.eclipse.riena.ui.common.IComplexComponent;
/**
* Visits each control, starting with the given {@composite} and recursively
* continuing into each of it's children. The following rules apply:
* <ul>
* <li>{@link #handleControl(Control)} is invoked for every visited control</li>
* <li>{@link #handleBoundControl(Control, String)} is invoked for every visited
* control that has a binding property, unless {@link #skip(Control)} returns
* true for that control</li>
* <li>the visitor does not descent into controls that are an
* {@link IComplexComponent}, since those are manage their contents autonomously
* </li>
* </ul>
* Usage example:
*
* <pre>
* SWTControlFinder finder = new SWTControlFinder(composite) {
* public void handleBoundControl(Control control, String bindingProperty) {
* addUIControl(control, bindingProperty);
* }
* };
* finder.run();
* </pre>
*
* @see visitor pattern
* @since 2.0
*/
public abstract class SWTControlFinder {
private Composite start;
public SWTControlFinder(final Composite composite) {
Assert.isNotNull(composite);
start = composite;
}
/**
* Visits all controls, starting with the {@code composite} designated in
* the constructor and recursively descending into each of it's children.
* <p>
* This method can only be called once.
*
* @throws RuntimeException
* if called more than once
*/
public void run() {
if (start == null) {
throw new IllegalStateException("cannot run more than once!"); //$NON-NLS-1$
}
addUIControls(start);
start = null;
}
/**
* Returns true to skip calling {@link #handleBoundControl(Control, String)}
* for the given {@control}, false otherwise.
* <p>
* The default implementation always returns false. Subclasses may override.
*
* @param control
* the control; never null
*/
public boolean skip(final Control control) {
return false;
}
/**
* This method is invoked for every visited control.
* <p>
* Implementors may override, but <b>must</b> call super.
*
* @param control
* the control; never null
*/
public void handleControl(final Control control) {
if ((control instanceof Composite) && !(control instanceof IComplexComponent)) {
addUIControls((Composite) control);
}
}
/**
* This method is invoked for every bound control that is not skipped (see
* {@link #skip(Control)}).
* <p>
* Bound controls are those controls that have been assigned with a binding
* ID.
*
* @param control
* the control; never null
* @param bindingProperty
* the binding ID for that control (a non-null, non-empty String)
*/
public abstract void handleBoundControl(Control control, String bindingProperty);
// protected methods
////////////////////
private void addUIControls(final Composite composite) {
final SWTBindingPropertyLocator locator = SWTBindingPropertyLocator.getInstance();
for (final Control control : composite.getChildren()) {
final String bindingProperty = locator.locateBindingProperty(control);
if (StringUtils.isGiven(bindingProperty) && !skip(control)) {
handleBoundControl(control, bindingProperty);
}
handleControl(control);
}
}
}