Package org.eclipse.sapphire.ui

Source Code of org.eclipse.sapphire.ui.SapphireAction$FiltersChangedEvent

/******************************************************************************
* Copyright (c) 2014 Oracle and Other Contributors
* 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:
*    Konstantin Komissarchik - initial implementation and ongoing maintenance
*    Greg Amerson - [342771] Support "image+label" hint for when actions are presented in a toolbar          
******************************************************************************/

package org.eclipse.sapphire.ui;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.sapphire.DisposeEvent;
import org.eclipse.sapphire.Event;
import org.eclipse.sapphire.Listener;
import org.eclipse.sapphire.LoggingService;
import org.eclipse.sapphire.Sapphire;
import org.eclipse.sapphire.modeling.el.Function;
import org.eclipse.sapphire.modeling.el.FunctionContext;
import org.eclipse.sapphire.modeling.el.FunctionResult;
import org.eclipse.sapphire.modeling.el.Literal;
import org.eclipse.sapphire.modeling.el.ModelElementFunctionContext;
import org.eclipse.sapphire.modeling.localization.LocalizationService;
import org.eclipse.sapphire.ui.def.ActionDef;
import org.eclipse.sapphire.ui.def.ISapphireHint;
import org.eclipse.sapphire.ui.def.KeyBindingBehavior;
import org.eclipse.sapphire.ui.def.PartDef;
import org.eclipse.sapphire.ui.def.SapphireActionType;
import org.eclipse.sapphire.ui.def.SapphireKeySequence;
import org.eclipse.sapphire.ui.util.TopologicalSorter;
import org.eclipse.sapphire.util.ListFactory;

/**
* @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
*/

public final class SapphireAction extends SapphireActionSystemPart
{
    private SapphireActionGroup parent;
    private SapphireActionType type;
    private String group;
    private SapphireKeySequence keyBinding;
    private KeyBindingBehavior keyBindingBehavior;
    private final List<SapphireActionHandler> handlers = new CopyOnWriteArrayList<SapphireActionHandler>();
    private final Map<SapphireActionHandlerFactory,List<SapphireActionHandler>> handlerFactories = new LinkedHashMap<SapphireActionHandlerFactory,List<SapphireActionHandler>>();
    private final List<SapphireActionHandlerFilter> filters = new CopyOnWriteArrayList<SapphireActionHandlerFilter>();
    private Listener handlerListener;
    private Map<String,Object> hints;
   
    public void init( final SapphireActionGroup parent,
                      final ActionDef def )
    {
        this.parent = parent;
       
        super.init( def );
       
        this.handlerListener = new Listener()
        {
            @Override
            public void handle( final Event event )
            {
                if( event instanceof VisibilityEvent )
                {
                    refreshVisibilityState();
                }
                else if( event instanceof EnablementChangedEvent )
                {
                    refreshEnablementState();
                }
                else if( event instanceof CheckedStateChangedEvent )
                {
                    refreshCheckedState();
                }
            }
        };
       
        attach
        (
            new Listener()
            {
                @Override
                public void handle( final Event event )
                {
                    if( event instanceof HandlersChangedEvent || event instanceof FiltersChangedEvent )
                    {
                        refreshVisibilityState();
                        refreshEnablementState();
                        refreshCheckedState();
                    }
                    else if( event instanceof DisposeEvent )
                    {
                        for( SapphireActionHandler handler : SapphireAction.this.handlers )
                        {
                            try
                            {
                                handler.dispose();
                            }
                            catch( Exception e )
                            {
                                Sapphire.service( LoggingService.class ).log( e );
                            }
                        }
                       
                        for( SapphireActionHandlerFactory factory : SapphireAction.this.handlerFactories.keySet() )
                        {
                            try
                            {
                                factory.dispose();
                            }
                            catch( Exception e )
                            {
                                Sapphire.service( LoggingService.class ).log( e );
                            }
                        }
                    }
                }
            }
        );

        this.hints = new HashMap<String,Object>();
       
        if( def != null )
        {
            this.type = def.getType().content();
            this.group = def.getGroup().content();
            this.keyBinding = def.getKeyBinding().content();
            this.keyBindingBehavior = def.getKeyBindingBehavior().content();

            for( ISapphireHint hint : def.getHints() )
            {
                final String name = hint.getName().text();
                Object parsedValue = null;
               
                if( name.equals( PartDef.HINT_STYLE ) )
                {
                    parsedValue = hint.getValue().text();
                }
              
                this.hints.put( name, parsedValue );
            }
        }
       
        setEnabled( false );
    }
   
    @Override
    protected FunctionContext initFunctionContext()
    {
        final ISapphirePart part = getPart();
       
        return new ModelElementFunctionContext( part.getLocalModelElement(), part.definition().adapt( LocalizationService.class ) )
        {
            @Override
            public FunctionResult property( final Object element,
                                            final String name )
            {
                if( element == this && name.equalsIgnoreCase( "handlers" ) )
                {
                    final Function f = new Function()
                    {
                        @Override
                        public String name()
                        {
                            return "ReadProperty";
                        }
                       
                        @Override
                        public FunctionResult evaluate( final FunctionContext context )
                        {
                            return new FunctionResult( this, context )
                            {
                                private Listener listener;
                               
                                @Override
                                protected void init()
                                {
                                    super.init();
                                   
                                    this.listener = new Listener()
                                    {
                                        @Override
                                        public void handle( final Event event )
                                        {
                                            if( event instanceof HandlersChangedEvent )
                                            {
                                                refresh();
                                            }
                                        }
                                    };
                                   
                                    SapphireAction.this.attach( this.listener );
                                }

                                @Override
                                protected Object evaluate()
                                {
                                    return getActiveHandlers();
                                }

                                @Override
                                public void dispose()
                                {
                                    super.dispose();
                                    SapphireAction.this.detach( this.listener );
                                }
                            };
                        }
                    };
                   
                    f.init();
                   
                    return f.evaluate( this );
                }
                else if( element instanceof SapphireActionHandler && name.equalsIgnoreCase( "label" ) )
                {
                    return Literal.create( ( (SapphireActionHandler) element ).getLabel() ).evaluate( this );
                }
               
                return super.property( element, name );
            }
        };
    }

    public SapphireActionGroup getActionSet()
    {
        return this.parent;
    }
   
    public final ISapphirePart getPart()
    {
        return this.parent.getPart();
    }

    public String getContext()
    {
        return this.parent.getContext();
    }
   
    @SuppressWarnings( "unchecked" )
   
    public <T> T getRenderingHint( final String name,
                                   final T defaultValue )
    {
        final Object hintValue = this.hints == null ? null : this.hints.get( name );
        return hintValue == null ? defaultValue : (T) hintValue;
    }

    public SapphireActionType getType()
    {
        synchronized( this )
        {
            return this.type;
        }
    }
   
    public void setType( final SapphireActionType type )
    {
        synchronized( this )
        {
            this.type = type;
        }
       
        broadcast( new TypeChangedEvent() );
    }
   
    public String getGroup()
    {
        synchronized( this )
        {
            return this.group;
        }
    }
   
    public void setGroup( final String group )
    {
        synchronized( this )
        {
            this.group = group;
        }
       
        broadcast( new GroupChangedEvent() );
    }

    public SapphireKeySequence getKeyBinding()
    {
        synchronized( this )
        {
            return this.keyBinding;
        }
    }
   
    public void setKeyBinding( final SapphireKeySequence keyBinding )
    {
        synchronized( this )
        {
            this.keyBinding = keyBinding;
        }
       
        broadcast( new KeyBindingChangedEvent() );
    }
   
    public KeyBindingBehavior getKeyBindingBehavior()
    {
        synchronized( this )
        {
            return this.keyBindingBehavior;
        }
    }
   
    public void setKeyBindingBehavior( final KeyBindingBehavior keyBindingBehavior )
    {
        synchronized( this )
        {
            this.keyBindingBehavior = keyBindingBehavior;
        }
       
        broadcast( new KeyBindingBehaviorChangedEvent() );
    }
   
    public void addHandler( final SapphireActionHandler handler )
    {
        handler.attach( this.handlerListener );
        this.handlers.add( handler );
        broadcast( new HandlersChangedEvent() );
    }
   
    public void removeHandler( final SapphireActionHandler handler )
    {
        handler.detach( this.handlerListener );
        this.handlers.remove( handler );
        broadcast( new HandlersChangedEvent() );
    }
   
    public void removeHandlers( final Collection<SapphireActionHandler> handlers )
    {
        for( SapphireActionHandler handler : handlers )
        {
            handler.detach( this.handlerListener );
            this.handlers.remove( handler );
        }
       
        broadcast( new HandlersChangedEvent() );
    }
   
    public void addHandlerFactory( final SapphireActionHandlerFactory factory )
    {
        synchronized( this )
        {
            if( this.handlerFactories.containsKey( factory ) )
            {
                throw new IllegalArgumentException();
            }
           
            final List<SapphireActionHandler> handlers = new ArrayList<SapphireActionHandler>();
           
            for( SapphireActionHandler handler : factory.create() )
            {
                handler.init( this, null );
                handler.attach( this.handlerListener );
                handlers.add( handler );
            }
           
            factory.attach
            (
                new Listener()
                {
                    @Override
                    public void handle( final Event event )
                    {
                        refreshHandlerFactory( factory );
                    }
                }
            );
           
            this.handlerFactories.put( factory, handlers );
        }
       
        broadcast( new HandlersChangedEvent() );
    }
   
    public void removeHandlerFactory( final SapphireActionHandlerFactory factory )
    {
        boolean changed = false;
       
        synchronized( this )
        {
            final List<SapphireActionHandler> handlers = this.handlerFactories.remove( factory );
           
            if( handlers != null )
            {
                for( SapphireActionHandler handler : handlers )
                {
                    try
                    {
                        handler.dispose();
                    }
                    catch( Exception e )
                    {
                        Sapphire.service( LoggingService.class ).log( e );
                    }
                }
               
                changed = true;
            }
        }
       
        if( changed )
        {
            broadcast( new HandlersChangedEvent() );
        }
    }
   
    private void refreshHandlerFactory( final SapphireActionHandlerFactory factory )
    {
        synchronized( this )
        {
            final List<SapphireActionHandler> handlers = this.handlerFactories.get( factory );
           
            if( handlers == null )
            {
                throw new IllegalStateException();
            }
           
            for( SapphireActionHandler handler : handlers )
            {
                try
                {
                    handler.dispose();
                }
                catch( Exception e )
                {
                    Sapphire.service( LoggingService.class ).log( e );
                }
            }
           
            handlers.clear();
           
            for( SapphireActionHandler handler : factory.create() )
            {
                handler.init( this, null );
                handler.attach( this.handlerListener );
                handlers.add( handler );
            }
        }
       
        broadcast( new HandlersChangedEvent() );
    }
   
    public List<SapphireActionHandler> getActiveHandlers()
    {
        synchronized( this )
        {
            final List<SapphireActionHandler> handlers = new ArrayList<SapphireActionHandler>();
           
            handlers.addAll( this.handlers );
           
            for( List<SapphireActionHandler> factoryHandlers : this.handlerFactories.values() )
            {
                handlers.addAll( factoryHandlers );
            }
           
            final TopologicalSorter<SapphireActionHandler> sorter = new TopologicalSorter<SapphireActionHandler>();
           
            for( SapphireActionHandler handler : handlers )
            {
                boolean ok = true;
               
                List<SapphireActionHandlerFilter> failedFilters = null;
               
                for( SapphireActionHandlerFilter filter : this.filters )
                {
                    try
                    {
                        ok = filter.check( handler );
                    }
                    catch( Exception e )
                    {
                        Sapphire.service( LoggingService.class ).log( e );
                       
                        // Filters are booted on first failure to keep malfunctioning filters from
                        // flooding the log, etc.
                       
                        if( failedFilters == null )
                        {
                            failedFilters = new ArrayList<SapphireActionHandlerFilter>();
                        }
                       
                        failedFilters.add( filter );
                    }
                   
                    if( ! ok )
                    {
                        break;
                    }
                }
               
                if( failedFilters != null )
                {
                    this.filters.removeAll( failedFilters );
                }
               
                if( ok )
                {
                    final TopologicalSorter.Entity handlerEntity = sorter.entity( handler.getId(), handler );
                   
                    for( SapphireActionLocationHint locationHint : handler.getLocationHints() )
                    {
                        handlerEntity.constraint( locationHint.toString() );
                    }
                }
            }
           
            return Collections.unmodifiableList( sorter.sort() );
        }
    }
   
    public SapphireActionHandler getFirstActiveHandler()
    {
        final List<SapphireActionHandler> handlers = getActiveHandlers();
        return ( handlers.isEmpty() ? null : handlers.get( 0 ) );
    }
   
    public boolean hasActiveHandlers()
    {
        return ( getFirstActiveHandler() != null );
    }
   
    public List<SapphireActionHandler> getEnabledHandlers()
    {
        final ListFactory<SapphireActionHandler> enabledHandlersListFactory = ListFactory.start();
       
        for( final SapphireActionHandler handler : getActiveHandlers() )
        {
            if( handler.isEnabled() )
            {
                enabledHandlersListFactory.add( handler );
            }
        }
       
        return enabledHandlersListFactory.result();
    }
   
    public void addFilter( final SapphireActionHandlerFilter filter )
    {
        this.filters.add( filter );
        broadcast( new FiltersChangedEvent() );
    }
   
    public void removeFilter( final SapphireActionHandlerFilter filter )
    {
        this.filters.remove( filter );
        broadcast( new FiltersChangedEvent() );
    }
   
    private void refreshVisibilityState()
    {
        boolean visible = false;
       
        for( SapphireActionHandler handler : getActiveHandlers() )
        {
            if( handler.isVisible() )
            {
                visible = true;
                break;
            }
        }
       
        setVisible( visible );
    }
   
    private void refreshEnablementState()
    {
        setEnabled( ! getEnabledHandlers().isEmpty() );
    }
   
    private void refreshCheckedState()
    {
        boolean checked = false;
        final SapphireActionHandler handler = getFirstActiveHandler();
       
        if( handler != null )
        {
            checked = handler.isChecked();
        }
       
        setChecked( checked );
    }
   
    public static final class TypeChangedEvent extends Event {}
    public static final class GroupChangedEvent extends Event {}
    public static final class KeyBindingChangedEvent extends Event {}
    public static final class KeyBindingBehaviorChangedEvent extends Event {}
    public static final class HandlersChangedEvent extends Event {}
    public static final class FiltersChangedEvent extends Event {}
   
}
TOP

Related Classes of org.eclipse.sapphire.ui.SapphireAction$FiltersChangedEvent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.