/*******************************************************************************
* 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.osgi.service.log.LogService;
import org.eclipse.core.runtime.Assert;
import org.eclipse.equinox.log.Logger;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.riena.core.Log4r;
import org.eclipse.riena.core.util.StringUtils;
import org.eclipse.riena.internal.ui.swt.Activator;
import org.eclipse.riena.ui.common.IComplexComponent;
import org.eclipse.riena.ui.ridgets.uibinding.IBindingPropertyLocator;
/**
* Helper class to get the ID of a SWT UI control used for binding.
*/
public final class SWTBindingPropertyLocator implements IBindingPropertyLocator {
/**
* Key to retrieve a control's binding property.
* <p>
* That value (String) will also be assigned to the Ridget that is paired to the control.
*/
public final static String BINDING_PROPERTY = "binding_property"; //$NON-NLS-1$
private static SWTBindingPropertyLocator locator;
private SWTBindingPropertyLocator() {
// prevent instantiation
}
/**
* Returns an instance of this class.
*
* @return
*/
public static SWTBindingPropertyLocator getInstance() {
if (locator == null) {
locator = new SWTBindingPropertyLocator();
}
return locator;
}
/**
* Returns all bounds controls in the given composite and it's children.
*
* @param composite
* a Composite instance; never null
* @return a List of bounds Controls (exluding composite); never null; may be empty. Will not continue into {@link IComplexComponent}s - as they are
* repsonsible for they own children.
* @since 1.2
*/
public static List<Object> getControlsWithBindingProperty(final Composite composite) {
final Map<String, Object> id2control = new HashMap<String, Object>();
final SWTControlFinder finder = new SWTControlFinder(composite) {
@Override
public void handleBoundControl(final Control control, final String bindingProperty) {
if (id2control.containsKey(bindingProperty)) {
final String format = "conflict: control with id '%s' already defined: %s, %s"; //$NON-NLS-1$
final String msg = String.format(format, bindingProperty, id2control.get(bindingProperty), control);
throw new RuntimeException(msg);
}
id2control.put(bindingProperty, control);
}
};
finder.run();
return new ArrayList<Object>(id2control.values());
}
/**
* Returns true if the given UI control has a binding property, false otherwise.
*
* @param uiControl
* UI control; may be null
* @since 2.0
*/
public boolean hasBindingProperty(final Object uiControl) {
final String prop = locateBindingProperty(uiControl);
return !StringUtils.isDeepEmpty(prop);
}
public String locateBindingProperty(final Object uiControl) {
String result = null;
if (uiControl instanceof Widget) {
final Widget widget = (Widget) uiControl;
if (!widget.isDisposed()) {
result = (String) widget.getData(BINDING_PROPERTY);
}
} else if (uiControl instanceof IPropertyNameProvider) {
result = ((IPropertyNameProvider) uiControl).getPropertyName();
}
return result;
}
/**
* Set the ID (binding property) for the given {@code uiControl}.
*
* @param uiControl
* an instanceof {@link Widget} or {@link IPropertyNameProvider}
* @param id
* the binding property; never null; must not be empty.The given value will also be assigned to the Ridget that is paired to the control.
*/
public void setBindingProperty(final Object uiControl, final String id) {
Assert.isNotNull(id, "The binding property must not be null"); //$NON-NLS-1$
Assert.isLegal(id.length() > 0, "The binding property must not be empty"); //$NON-NLS-1$
if (uiControl instanceof Widget) {
final Widget widget = (Widget) uiControl;
if (widget.isDisposed()) {
return;
}
widget.setData(BINDING_PROPERTY, id);
} else if (uiControl instanceof IPropertyNameProvider) {
((IPropertyNameProvider) uiControl).setPropertyName(id);
} else {
final Logger log = Log4r.getLogger(Activator.getDefault(), SWTBindingPropertyLocator.class);
final String className = uiControl != null ? uiControl.getClass().getName() : "null"; //$NON-NLS-1$
final String msg = String.format("Failed to set binding property '%s' for %s", id, className); //$NON-NLS-1$
log.log(LogService.LOG_WARNING, msg);
}
}
/**
* @since 5.0
*/
public String getComplexBindingId(final Object uiControl) {
if (uiControl instanceof Control) {
final Control swtControl = (Control) uiControl;
if (!swtControl.isDisposed()) {
final IComplexComponent parent = getComplexParent(swtControl);
if (parent != null) {
final String parentId = locateBindingProperty(parent);
if (parentId != null) {
String id = locateBindingProperty(uiControl);
id = parentId + "." + id; //$NON-NLS-1$
return id;
}
}
}
}
return locateBindingProperty(uiControl);
}
/**
* Returns the complex component that is a parent of the given control.
*
* @param control
* child control
* @return complex parent or {@code null} if the control has no complex parent
*/
private IComplexComponent getComplexParent(final Control control) {
final Composite parent = control.getParent();
if (parent == null) {
return null;
}
if (parent instanceof IComplexComponent) {
return (IComplexComponent) parent;
}
return getComplexParent(parent);
}
}