Package org.eclipse.sapphire.ui.forms.swt.internal

Source Code of org.eclipse.sapphire.ui.forms.swt.internal.CheckBoxGroupPropertyEditorPresentation$VerticalFactory

/******************************************************************************
* Copyright (c) 2014 Oracle
* 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
******************************************************************************/

package org.eclipse.sapphire.ui.forms.swt.internal;

import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gd;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gdvalign;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gdvindent;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.glayout;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.glspacing;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;

import org.eclipse.sapphire.Disposable;
import org.eclipse.sapphire.Element;
import org.eclipse.sapphire.ElementList;
import org.eclipse.sapphire.ElementType;
import org.eclipse.sapphire.Event;
import org.eclipse.sapphire.FilteredListener;
import org.eclipse.sapphire.ImageData;
import org.eclipse.sapphire.ImageService;
import org.eclipse.sapphire.Listener;
import org.eclipse.sapphire.LocalizableText;
import org.eclipse.sapphire.LoggingService;
import org.eclipse.sapphire.PossibleValuesService;
import org.eclipse.sapphire.PropertyContentEvent;
import org.eclipse.sapphire.PropertyDef;
import org.eclipse.sapphire.PropertyEvent;
import org.eclipse.sapphire.PropertyValidationEvent;
import org.eclipse.sapphire.Sapphire;
import org.eclipse.sapphire.Text;
import org.eclipse.sapphire.ValueProperty;
import org.eclipse.sapphire.modeling.CapitalizationType;
import org.eclipse.sapphire.modeling.localization.LocalizationService;
import org.eclipse.sapphire.services.ValueImageService;
import org.eclipse.sapphire.services.ValueLabelService;
import org.eclipse.sapphire.ui.DelayedTasksExecutor;
import org.eclipse.sapphire.ui.DelayedTasksExecutor.Task;
import org.eclipse.sapphire.ui.assist.internal.PropertyEditorAssistDecorator;
import org.eclipse.sapphire.ui.def.Orientation;
import org.eclipse.sapphire.ui.forms.FormComponentPart;
import org.eclipse.sapphire.ui.forms.PropertyEditorPart;
import org.eclipse.sapphire.ui.forms.swt.ListPropertyEditorPresentation;
import org.eclipse.sapphire.ui.forms.swt.PropertyEditorPresentation;
import org.eclipse.sapphire.ui.forms.swt.SwtPresentation;
import org.eclipse.sapphire.util.SetFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

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

public final class CheckBoxGroupPropertyEditorPresentation extends ListPropertyEditorPresentation
{
    @Text( "<empty>" )
    private static LocalizableText emptyIndicator;
   
    static
    {
        LocalizableText.init( CheckBoxGroupPropertyEditorPresentation.class );
    }

    private final Orientation orientation;
    private ValueProperty memberProperty;
    private PossibleValuesService possibleValuesService;
    private ValueLabelService valueLabelService;
    private ValueImageService valueImageService;
    private LocalizationService localizationService;
    private Listener serviceListener;
    private Composite checkBoxesComposite;

    public CheckBoxGroupPropertyEditorPresentation( final FormComponentPart part, final SwtPresentation parent, final Composite composite, final Orientation orientation )
    {
        super( part, parent, composite );
       
        this.orientation = orientation;
    }

    @Override
   
    protected void createContents( final Composite parent )
    {
        final ElementList<?> list = property();
       
        final ElementType memberType = list.definition().getType();
        final SortedSet<PropertyDef> allMemberProperties = memberType.properties();
       
        if( allMemberProperties.size() == 1 )
        {
            final PropertyDef prop = allMemberProperties.first();
           
            if( prop instanceof ValueProperty )
            {
                this.memberProperty = (ValueProperty) prop;
            }
            else
            {
                throw new IllegalStateException();
            }
        }
        else
        {
            throw new IllegalStateException();
        }

        final Composite mainComposite = createMainComposite( parent );
        mainComposite.setLayout( glspacing( glayout( 2, 0, 0 ), 2 ) );

        final PropertyEditorAssistDecorator decorator = createDecorator( mainComposite );
        decorator.control().setLayoutData( gdvindent( gdvalign( gd(), ( this.orientation == Orientation.HORIZONTAL ? SWT.CENTER : SWT.TOP ) ), ( this.orientation == Orientation.HORIZONTAL ? 0 : 4 ) ) );
       
        this.checkBoxesComposite = new Composite( mainComposite, SWT.NONE );
        this.checkBoxesComposite.setLayoutData( gdvalign( gd(), SWT.CENTER ) );
       
        final RowLayout checkBoxesCompositeLayout = new RowLayout();
        checkBoxesCompositeLayout.type = ( this.orientation == Orientation.HORIZONTAL ? SWT.HORIZONTAL : SWT.VERTICAL );
        checkBoxesCompositeLayout.wrap = false;
        checkBoxesCompositeLayout.marginTop = 0;
        checkBoxesCompositeLayout.marginBottom = 0;
        checkBoxesCompositeLayout.marginLeft = 0;
        checkBoxesCompositeLayout.marginRight = 0;
        checkBoxesCompositeLayout.spacing = ( this.orientation == Orientation.HORIZONTAL ? 10 : 5 );
       
        this.checkBoxesComposite.setLayout( checkBoxesCompositeLayout );
       
        this.serviceListener = new Listener()
        {
            @Override
            public void handle( final Event event )
            {
                refreshCheckBoxes();
            }
        };
       
        this.localizationService = part().definition().adapt( LocalizationService.class );
       
        this.possibleValuesService = list.service( PossibleValuesService.class );
        this.possibleValuesService.attach( this.serviceListener );
       
        this.valueLabelService = this.memberProperty.service( ValueLabelService.class );
        this.valueLabelService.attach( this.serviceListener );
       
        this.valueImageService = this.memberProperty.service( ValueImageService.class );
        this.valueImageService.attach( this.serviceListener );
       
        final Listener modelListener = new FilteredListener<PropertyEvent>()
        {
            @Override
            protected void handleTypedEvent( final PropertyEvent event )
            {
                if( event instanceof PropertyContentEvent || event instanceof PropertyValidationEvent )
                {
                    refreshCheckBoxes();
                }
            }
        };
       
        list.attach( modelListener, this.memberProperty.name() );
       
        addOnDisposeOperation
        (
            new Runnable()
            {
                @Override
                public void run()
                {
                    CheckBoxGroupPropertyEditorPresentation.this.possibleValuesService.detach( CheckBoxGroupPropertyEditorPresentation.this.serviceListener );
                    CheckBoxGroupPropertyEditorPresentation.this.valueLabelService.detach( CheckBoxGroupPropertyEditorPresentation.this.serviceListener );
                    CheckBoxGroupPropertyEditorPresentation.this.valueImageService.detach( CheckBoxGroupPropertyEditorPresentation.this.serviceListener );
                   
                    if( ! list.disposed() )
                    {
                        list.detach( modelListener, CheckBoxGroupPropertyEditorPresentation.this.memberProperty.name() );
                       
                        for( final Element element : list )
                        {
                            final ImageService imageService = element.service( ImageService.class );
                           
                            if( imageService != null )
                            {
                                imageService.detach( CheckBoxGroupPropertyEditorPresentation.this.serviceListener );
                            }
                        }
                    }
                }
            }
        );
       
        refreshCheckBoxes();
    }
   
    private void refreshCheckBoxes()
    {
        final ElementList<?> list = property();
       
        // Build a list of existing check boxes.
       
        final List<Button> checkboxes = new ArrayList<Button>();
       
        for( final Control control : this.checkBoxesComposite.getChildren() )
        {
            checkboxes.add( (Button) control );
        }
       
        // Build a map of value to existing elements.
       
        final Map<String,LinkedList<Element>> valueToElements = new HashMap<String,LinkedList<Element>>();
       
        for( final Element element : list )
        {
            final String value = readMemberProperty( element );
            LinkedList<Element> elements = valueToElements.get( value );
           
            if( elements == null )
            {
                elements = new LinkedList<Element>();
                valueToElements.put( value, elements );
            }
           
            elements.add( element );
        }
       
        // Retrieve the set of possible values.
       
        Set<String> possibleValues;
       
        try
        {
            possibleValues = possibleValuesService.values();
        }
        catch( Exception e )
        {
            Sapphire.service( LoggingService.class ).log( e );
            possibleValues = SetFactory.empty();
        }
       
        // Create or rebase check boxes for all possible values and all elements.
       
        int position = 0;
       
        for( final String value : possibleValues )
        {
            final LinkedList<Element> elements = valueToElements.get( value );
           
            if( elements == null )
            {
                createOrRebaseCheckBox( checkboxes, position, value, null );
                position++;
            }
            else
            {
                for( final Element element : elements )
                {
                    createOrRebaseCheckBox( checkboxes, position, value, element );
                    position++;
                }
               
                valueToElements.remove( value );
            }
        }
       
        for( final Iterator<Map.Entry<String,LinkedList<Element>>> itr = valueToElements.entrySet().iterator(); itr.hasNext(); )
        {
            final Map.Entry<String,LinkedList<Element>> entry = itr.next();
            final String value = entry.getKey();
           
            if( value != null )
            {
                for( final Element element : entry.getValue() )
                {
                    createOrRebaseCheckBox( checkboxes, position, value, element );
                    position++;
                }
               
                itr.remove();
            }
        }

        for( final Map.Entry<String,LinkedList<Element>> entry : valueToElements.entrySet() )
        {
            final String value = entry.getKey();
           
            for( final Element element : entry.getValue() )
            {
                createOrRebaseCheckBox( checkboxes, position, value, element );
                position++;
            }
        }
       
        // Dispose of extra check boxes.
       
        for( int i = position, n = checkboxes.size(); i < n; i++ )
        {
            checkboxes.get( i ).dispose();
        }
       
        // Re-layout everything since the number of check boxes may have changed and their labels may have changed.
       
        layout();
    }
   
    private void createOrRebaseCheckBox( final List<Button> checkboxes, final int position, final String value, final Element element )
    {
        final Button checkbox;
       
        if( position < checkboxes.size() )
        {
            checkbox = checkboxes.get( position );
        }
        else
        {
            checkbox = createCheckBox();
        }
       
        rebaseCheckBox( checkbox, value, element );
    }
   
    private Button createCheckBox()
    {
        final Button checkbox = new Button( this.checkBoxesComposite, SWT.CHECK );
       
        checkbox.addSelectionListener
        (
            new SelectionAdapter()
            {
                @Override
                public void widgetSelected( final SelectionEvent event )
                {
                    final Task task = new Task()
                    {
                        @Override
                        public void run()
                        {
                            if( checkbox.isDisposed() )
                            {
                                return;
                            }
                           
                            final ElementList<?> list = property();
                            final boolean selection = checkbox.getSelection();
                            Element e = (Element) checkbox.getData( "Element" );
                           
                            if( e == null && selection == true )
                            {
                                final Disposable s = list.suspend();
                               
                                try
                                {
                                    e = list.insert();
                                    writeMemberProperty( e, (String) checkbox.getData( "Value" ) );
                                }
                                finally
                                {
                                    s.dispose();
                                }
                            }
                            else if( e != null && selection == false )
                            {
                                list.remove( e );
                            }
                        }
                    };
                   
                    DelayedTasksExecutor.schedule( task );
                }
            }
        );
       
        addControl( checkbox );
       
        this.decorator.addEditorControl( checkbox );
       
        return checkbox;
    }

    private void rebaseCheckBox( final Button checkbox, final String value, final Element element )
    {
        checkbox.setData( "Value", value );
        checkbox.setData( "Element", element );
        checkbox.setSelection( element != null );
       
        String text = null;
       
        if( value == null )
        {
            text = emptyIndicator.text();
        }
        else
        {
            try
            {
                text = this.valueLabelService.provide( value );
            }
            catch( Exception e )
            {
                Sapphire.service( LoggingService.class ).log( e );
            }
           
            if( text == null )
            {
                text = value;
            }
            else if( ! text.equals( value ) )
            {
                text = this.localizationService.transform( text, CapitalizationType.FIRST_WORD_ONLY, false );
            }
        }
       
        checkbox.setText( text );
       
        ImageService elementImageService = (ImageService) checkbox.getData( "ImageService" );
       
        if( elementImageService != null )
        {
            elementImageService.detach( this.serviceListener );
        }
       
        if( element != null )
        {
            elementImageService = element.service( ImageService.class );
            checkbox.setData( "ImageService", elementImageService );
           
            if( elementImageService != null )
            {
                elementImageService.attach( this.serviceListener );
            }
        }
       
        ImageData image = null;
       
        if( elementImageService != null )
        {
            image = elementImageService.image();
        }
        else
        {
            try
            {
                image = this.valueImageService.provide( value );
            }
            catch( Exception e )
            {
                Sapphire.service( LoggingService.class ).log( e );
            }
        }
       
        if( element == null )
        {
            checkbox.setImage( resources().image( image ) );
        }
        else
        {
            checkbox.setImage( resources().image( image, element.property( this.memberProperty ).validation().severity() ) );
        }
    }
   
    private String readMemberProperty( final Element element )
    {
        return element.property( this.memberProperty ).text();
    }
   
    private void writeMemberProperty( final Element element, final String text )
    {
        element.property( this.memberProperty ).write( text, true );
    }
   
    @Override
    protected void handleFocusReceivedEvent()
    {
        for( final Control control : this.checkBoxesComposite.getChildren() )
        {
            control.setFocus();
            break;
        }
    }
   
    public static final class HorizontalFactory extends PossibleValuesListPresentationFactory
    {
        @Override
        protected boolean check( final PropertyEditorPart part )
        {
            final String style = part.definition().getStyle().content();
           
            if( style != null && ( style.equals( "Sapphire.PropertyEditor.CheckBoxGroup" ) || style.equals( "Sapphire.PropertyEditor.CheckBoxGroup.Horizontal" ) ) )
            {
                return super.check( part );
            }
           
            return false;
        }

        @Override
        public PropertyEditorPresentation create( final PropertyEditorPart part, final SwtPresentation parent, final Composite composite )
        {
            if( check( part ) )
            {
                return new CheckBoxGroupPropertyEditorPresentation( part, parent, composite, Orientation.HORIZONTAL );
            }
           
            return null;
        }
    }

    public static final class VerticalFactory extends PossibleValuesListPresentationFactory
    {
        @Override
        protected boolean check( final PropertyEditorPart part )
        {
            final String style = part.definition().getStyle().content();
           
            if( style != null && style.equals( "Sapphire.PropertyEditor.CheckBoxGroup.Vertical" ) )
            {
                return super.check( part );
            }
           
            return false;
        }

        @Override
        public PropertyEditorPresentation create( final PropertyEditorPart part, final SwtPresentation parent, final Composite composite )
        {
            if( check( part ) )
            {
                return new CheckBoxGroupPropertyEditorPresentation( part, parent, composite, Orientation.VERTICAL );
            }
           
            return null;
        }
    }
   
}
TOP

Related Classes of org.eclipse.sapphire.ui.forms.swt.internal.CheckBoxGroupPropertyEditorPresentation$VerticalFactory

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.