/**
* Copyright (c) 2014 - 2017 Frank Appel
* 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:
* Frank Appel - initial API and implementation
*/
package com.codeaffine.eclipse.ui.swt.theme;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeApplicator.attach;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeSetter.ADAPTER_BACKGROUND_SETTER;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeSetter.ADAPTER_DEMEANOR_SETTER;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeSetter.DEMEANOR_PREFERENCE_SETTER;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeSetter.FLAT_SCROLLBAR_BACKGROUND_SETTER;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeSetter.FLAT_SCROLLBAR_INCREMENT_SETTER;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeSetter.FLAT_SCROLLBAR_PAGE_INCRECMENT_COLOR_SETTER;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeSetter.FLAT_SCROLLBAR_THUMB_COLOR_SETTER;
import static com.codeaffine.eclipse.ui.swt.theme.AttributeSetter.INCREMENT_LENGTH_PREFERENCE_SETTER;
import static com.codeaffine.eclipse.ui.swt.theme.ControlElements.extractControl;
import static com.codeaffine.eclipse.ui.swt.theme.ControlElements.extractScrollable;
import static com.codeaffine.eclipse.ui.swt.theme.ControlElements.isControlElement;
import static com.codeaffine.eclipse.ui.swt.theme.TypeToAdapterMapping.tryFindTypeToAdapterMapping;
import static java.lang.Boolean.parseBoolean;
import java.util.Optional;
import org.eclipse.e4.ui.css.core.dom.properties.ICSSPropertyHandler;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.swt.widgets.Scrollable;
import org.w3c.dom.css.CSSValue;
import com.codeaffine.eclipse.swt.widget.scrollable.ScrollableAdapterFactory;
import com.codeaffine.eclipse.swt.widget.scrollable.ScrollableAdapterFactory.Adapter;
import com.codeaffine.eclipse.swt.widget.scrollable.ScrollbarStyle;
@SuppressWarnings( "restriction" )
public class ScrollableAdapterContribution implements ICSSPropertyHandler {
public static final String FLAT_SCROLL_BAR_PAGE_INCREMENT = "flat-scroll-bar-page-increment";
public static final String FLAT_SCROLL_BAR_BACKGROUND = "flat-scroll-bar-background";
public static final String FLAT_SCROLL_BAR_THUMB = "flat-scroll-bar-thumb";
public static final String FLAT_SCROLL_BAR_INCREMENT_LENGTH = "flat-scroll-bar-increment-length";
public static final String FLAT_SCROLL_BAR = "flat-scroll-bar";
public static final String ADAPTER_DEMEANOR = "adapter-demeanor";
public static final String ADAPTER_BACKGROUND = "adapter-background";
public static final String DEMEANOR_FIXED_WIDTH = "fixed-width";
public static final String DEMEANOR_EXPAND_ON_MOUSE_OVER = "expand-on-mouse-over";
public static final String TOP_LEVEL_WINDOW_SELECTOR = "-top-level";
private final ScrollbarPreference incrementButtonLengthPreference;
private final ScrollbarPreference demeanorPreference;
private final DemeanorApplicator demeanorApplicator;
private final ScrollableAdapterFactory factory;
private final ColorApplicator colorApplicator;
private final N0Applicator n0Applicator;
public ScrollableAdapterContribution() {
incrementButtonLengthPreference = new ScrollbarPreference( FLAT_SCROLL_BAR_INCREMENT_LENGTH );
demeanorPreference = new ScrollbarPreference( ADAPTER_DEMEANOR );
factory = new ScrollableAdapterFactory();
colorApplicator = new ColorApplicator( factory );
demeanorApplicator = new DemeanorApplicator( factory );
n0Applicator = new N0Applicator( factory );
}
@Override
public String retrieveCSSProperty( Object element, String property, String pseudo, CSSEngine engine )
throws Exception
{
return null;
}
@Override
public boolean applyCSSProperty( Object element, String property, CSSValue value, String pseudo, CSSEngine engine )
throws Exception
{
if( mustApply( element ) ) {
doApplyCssProperty( extractScrollable( element ), property, value );
}
return false;
}
private static boolean mustApply( Object element ) {
return isControlElement( element ) && tryFindTypeToAdapterMapping( extractControl( element ) ).isPresent();
}
private void doApplyCssProperty( Scrollable element, String property, CSSValue value ) {
switch( property ) {
case FLAT_SCROLL_BAR:
adapt( element, value );
colorApplicator.apply( element, FLAT_SCROLL_BAR_BACKGROUND, FLAT_SCROLLBAR_BACKGROUND_SETTER );
colorApplicator.apply( element, FLAT_SCROLL_BAR_THUMB, FLAT_SCROLLBAR_THUMB_COLOR_SETTER );
colorApplicator.apply( element, FLAT_SCROLL_BAR_PAGE_INCREMENT, FLAT_SCROLLBAR_PAGE_INCRECMENT_COLOR_SETTER );
n0Applicator.apply( element, FLAT_SCROLL_BAR_INCREMENT_LENGTH, FLAT_SCROLLBAR_INCREMENT_SETTER );
colorApplicator.apply( element, ADAPTER_BACKGROUND, ADAPTER_BACKGROUND_SETTER );
demeanorApplicator.apply( element, ADAPTER_DEMEANOR, ADAPTER_DEMEANOR_SETTER );
break;
case FLAT_SCROLL_BAR_BACKGROUND:
colorApplicator.apply( element, value, property, FLAT_SCROLLBAR_BACKGROUND_SETTER );
break;
case FLAT_SCROLL_BAR_THUMB:
colorApplicator.apply( element, value, property, FLAT_SCROLLBAR_THUMB_COLOR_SETTER );
break;
case FLAT_SCROLL_BAR_PAGE_INCREMENT:
colorApplicator.apply( element, value, property, FLAT_SCROLLBAR_PAGE_INCRECMENT_COLOR_SETTER );
break;
case FLAT_SCROLL_BAR_INCREMENT_LENGTH:
n0Applicator.apply( element, wrap( property, value ), property, FLAT_SCROLLBAR_INCREMENT_SETTER );
break;
case ADAPTER_DEMEANOR:
demeanorApplicator.apply( element, wrap( property, value ), property, ADAPTER_DEMEANOR_SETTER );
break;
case ADAPTER_BACKGROUND:
colorApplicator.apply( element, value, property, ADAPTER_BACKGROUND_SETTER );
break;
case FLAT_SCROLL_BAR_BACKGROUND + TOP_LEVEL_WINDOW_SELECTOR:
colorApplicator.apply( element, value, property, FLAT_SCROLLBAR_BACKGROUND_SETTER );
break;
case FLAT_SCROLL_BAR_THUMB + TOP_LEVEL_WINDOW_SELECTOR:
colorApplicator.apply( element, value, property, FLAT_SCROLLBAR_THUMB_COLOR_SETTER );
break;
case FLAT_SCROLL_BAR_PAGE_INCREMENT + TOP_LEVEL_WINDOW_SELECTOR:
colorApplicator.apply( element, value, property, FLAT_SCROLLBAR_PAGE_INCRECMENT_COLOR_SETTER );
break;
case FLAT_SCROLL_BAR_INCREMENT_LENGTH + TOP_LEVEL_WINDOW_SELECTOR:
CSSValue incrementButtonValue = wrap( FLAT_SCROLL_BAR_INCREMENT_LENGTH, value );
n0Applicator.apply( element, incrementButtonValue, property, FLAT_SCROLLBAR_INCREMENT_SETTER );
break;
case ADAPTER_DEMEANOR + TOP_LEVEL_WINDOW_SELECTOR:
demeanorApplicator.apply( element, wrap( ADAPTER_DEMEANOR, value ), property, ADAPTER_DEMEANOR_SETTER );
break;
case ADAPTER_BACKGROUND + TOP_LEVEL_WINDOW_SELECTOR:
colorApplicator.apply( element, value, property, ADAPTER_BACKGROUND_SETTER );
break;
default:
throw new IllegalArgumentException( "Unsupported attribute '" + property + "'" );
}
}
@SuppressWarnings( { "rawtypes", "unchecked" } )
private void adapt( Scrollable scrollable, CSSValue value ) {
if( !factory.isAdapted( scrollable ) && parseBoolean( value.getCssText() ) ) {
TypeToAdapterMapping<? extends Scrollable, ? extends Adapter> mapping = lookupMapping( scrollable );
Scrollable scrollableExtension = mapping.scrollableType.cast( scrollable );
Optional adapter = factory.create( scrollableExtension, mapping.adapterType );
if( adapter.isPresent() ) {
ScrollbarStyle result = ( ScrollbarStyle )adapter.get();
attach( scrollable, result );
incrementButtonLengthPreference.apply( result, INCREMENT_LENGTH_PREFERENCE_SETTER );
demeanorPreference.apply( result, DEMEANOR_PREFERENCE_SETTER );
}
}
}
@SuppressWarnings("rawtypes")
private static TypeToAdapterMapping<? extends Scrollable, ? extends Adapter> lookupMapping( Scrollable scrollable ) {
return tryFindTypeToAdapterMapping( scrollable ).get();
}
private static CSSValue wrap( String property, CSSValue value ) {
return new CssOrPreferenceValue( property, value );
}
}