/*******************************************************************************
* Copyright (c) 2008, 2015 Innoopract Informationssysteme GmbH 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:
* Innoopract Informationssysteme GmbH - initial API and implementation
* EclipseSource - ongoing development
******************************************************************************/
package org.eclipse.rap.rwt.internal.theme;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil;
import org.eclipse.rap.rwt.internal.theme.css.ConditionalValue;
import org.eclipse.swt.widgets.Widget;
public final class WidgetMatcher implements ValueSelector {
public static interface Constraint {
boolean matches( Widget widget );
}
private final Map<String, Constraint> constraintMap;
public WidgetMatcher() {
// This map is accessed by all UI sessions simultaneously. However, We don't need to
// synchronize get and put since constraints are deterministic, i.e. in case of concurrent
// insertions one constraint overwriting the other is not critical.
constraintMap = new ConcurrentHashMap<>();
}
public void addStyle( String string, int style ) {
constraintMap.put( "[" + string, createStyleConstraint( style ) );
}
public void addState( String string, Constraint constraint ) {
constraintMap.put( ":" + string, constraint );
}
@Override
public CssValue select( Widget widget, ConditionalValue... values ) {
CssValue result = null;
for( int i = 0; i < values.length && result == null; i++ ) {
ConditionalValue condValue = values[ i ];
String[] constraints = condValue.constraints;
if( matches( widget, constraints ) ) {
result = condValue.value;
}
}
return result;
}
private boolean matches( Widget widget, String[] constraints ) {
for( String string : constraints ) {
Constraint constraint = getConstraint( string );
if( constraint == null || !constraint.matches( widget ) ) {
return false;
}
}
return true;
}
private Constraint getConstraint( String string ) {
Constraint constraint = constraintMap.get( string );
if( constraint == null && string.startsWith( "." ) ) {
constraint = createVariantConstraint( string.substring( 1 ) );
constraintMap.put( string, constraint );
}
return constraint;
}
private static Constraint createStyleConstraint( final int style ) {
return new Constraint() {
@Override
public boolean matches( Widget widget ) {
return ( widget.getStyle() & style ) != 0;
}
};
}
private static Constraint createVariantConstraint( final String variant ) {
return new Constraint() {
@Override
public boolean matches( Widget widget ) {
return hasVariant( widget, variant );
}
};
}
private static boolean hasVariant( Widget widget, String variant ) {
String actualVariant = WidgetUtil.getVariant( widget );
return actualVariant != null && actualVariant.equals( variant );
}
}