All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.metsci.glimpse.layout.GlimpseAxisLayout1D Maven / Gradle / Ivy

There is a newer version: 4.0.0
Show newest version
/*
 * Copyright (c) 2016, Metron, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Metron, Inc. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL METRON, INC. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.metsci.glimpse.layout;

import java.util.Collection;

import com.metsci.glimpse.axis.Axis1D;
import com.metsci.glimpse.axis.Axis2D;
import com.metsci.glimpse.axis.AxisNotSetException;
import com.metsci.glimpse.axis.factory.AxisFactory1D;
import com.metsci.glimpse.axis.factory.AxisFactory2D;
import com.metsci.glimpse.axis.factory.DefaultAxisFactory1D;
import com.metsci.glimpse.context.GlimpseBounds;
import com.metsci.glimpse.context.GlimpseContext;
import com.metsci.glimpse.context.GlimpseTarget;
import com.metsci.glimpse.context.GlimpseTargetStack;
import com.metsci.glimpse.layout.matcher.TargetStackMatcher;

/**
 * A GlimpseLayout which can provide axes to its child
 * {@link com.metsci.glimpse.painter.base.GlimpsePainter}s.
 * GlimpseAxisLayout1D is often used for displaying timelines
 * or plot axes where dimensions only matter along one
 * orientation (the other orientation is measured simply
 * in pixel space). This is contrasted with
 * {@link GlimpseAxisLayout2D} where both horizontal and
 * verical coordinates of the GlimpseLayout have associated
 * {@link com.metsci.glimpse.axis.Axis1D} axes.
 *
 * @author ulman
 */
public abstract class GlimpseAxisLayout1D extends GlimpseLayout
{
    protected GlimpseLayoutCache cache;
    protected Axis1D axis;
    protected AxisFactory1D factory;

    public GlimpseAxisLayout1D( GlimpseLayout parent, String name, Axis1D axis )
    {
        super( parent, name );

        this.axis = axis;
        this.cache = new GlimpseLayoutCache( );
    }

    public GlimpseAxisLayout1D( GlimpseLayout parent, Axis1D axis )
    {
        this( parent, null, axis );
    }

    public GlimpseAxisLayout1D( String name, Axis1D axis )
    {
        this( null, name, axis );
    }

    public GlimpseAxisLayout1D( Axis1D axis )
    {
        this( null, null, axis );
    }

    public GlimpseAxisLayout1D( GlimpseLayout parent, String name )
    {
        this( parent, name, null );
    }

    public GlimpseAxisLayout1D( GlimpseLayout parent )
    {
        this( parent, null, null );
    }

    public GlimpseAxisLayout1D( )
    {
        this( null, null, null );
    }

    @Override
    protected void preLayout( GlimpseTargetStack stack, GlimpseBounds bounds )
    {
        Axis1D contextAxis = getAxis( stack );

        if ( contextAxis == null ) throw new AxisNotSetException( stack );

        contextAxis.setSizePixels( getSize( bounds ) );
    }

    public abstract boolean isHorizontal( );

    protected abstract Axis1D getAxis( Axis2D axis );

    protected abstract int getSize( GlimpseBounds bounds );

    public synchronized void clearCache( )
    {
        // remove parent links for all the cached axes then clear the cache
        for ( Axis1D axis : this.cache.getValues( ) )
        {
            axis.setParent( null );
        }
        this.cache.clear( );

        // descend recursively clearing caches
        // stop if a child has its' axis explicitly set
        // (because it is not using its' parent's axes)
        for ( GlimpseTarget target : getTargetChildren( ) )
        {
            if ( target instanceof GlimpseAxisLayout1D )
            {
                GlimpseAxisLayout1D layout = ( GlimpseAxisLayout1D ) target;
                if ( !layout.isAxisSet( ) )
                {
                    layout.clearCache( );
                }
            }
        }
    }

    public void setAxis( Axis1D axis )
    {
        // set the axis for all contexts, reset the cache
        this.clearCache( );
        this.axis = axis;
    }

    public synchronized void setAxis( GlimpseTargetStack stack, Axis1D axis )
    {
        this.cache.setValue( stack, axis );
    }

    public synchronized void setAxis( GlimpseContext context, Axis1D axis )
    {
        this.cache.setValue( context, axis );
    }

    public AxisFactory1D getAxisFactory( )
    {
        return this.factory;
    }

    public void setAxisFactory( AxisFactory1D factory )
    {
        this.factory = factory;
    }

    public boolean isAxisSet( )
    {
        return this.axis != null;
    }

    public boolean isAxisFactorySet( )
    {
        return this.factory != null;
    }

    public Axis1D getAxis( )
    {
        return this.axis;
    }

    public Axis1D getAxis( GlimpseContext context )
    {
        return getAxis( context.getTargetStack( ) );
    }

    // search up through the stack until a layout with an axis is found
    // then retrieve or create a version of that axis for the current stack and return it
    public synchronized Axis1D getAxis( GlimpseTargetStack stack )
    {
        if ( !stack.getTarget( ).equals( this ) )
        {
            throw new AxisNotSetException( String.format( "GlimpseAxisLayout1D %s is not on top of GlimpseTargetStack %s. Cannot provide Axis1D", getName( ), stack ) );
        }

        AxisFactory1D factory = getAxisFactory0( stack );

        for ( GlimpseTarget target : stack.getTargetList( ) )
        {
            if ( target instanceof GlimpseAxisLayout2D )
            {
                GlimpseAxisLayout2D layout = ( GlimpseAxisLayout2D ) target;
                if ( layout.isAxisSet( ) )
                {
                    return getCachedAxis0( getAxis( layout.getAxis( ) ), factory, stack );
                }
            }
            else if ( target instanceof GlimpseAxisLayout1D )
            {
                GlimpseAxisLayout1D layout = ( GlimpseAxisLayout1D ) target;
                if ( layout.isAxisSet( ) )
                {
                    return getCachedAxis0( layout.getAxis( ), factory, stack );
                }
            }
        }

        return null;
    }

    public synchronized Collection getAxis( TargetStackMatcher matcher )
    {
        return this.cache.getMatching( matcher );
    }

    protected AxisFactory1D getAxisFactory0( GlimpseTargetStack stack )
    {
        for ( GlimpseTarget target : stack.getTargetList( ) )
        {
            if ( target instanceof GlimpseAxisLayout2D )
            {
                GlimpseAxisLayout2D layout = ( GlimpseAxisLayout2D ) target;
                if ( layout.isAxisFactorySet( ) )
                {
                    AxisFactory2D factory = layout.getAxisFactory( );
                    return isHorizontal( ) ? factory.getAxisFactoryX( stack ) : factory.getAxisFactoryY( stack );
                }
            }
            else if ( target instanceof GlimpseAxisLayout1D )
            {
                GlimpseAxisLayout1D layout = ( GlimpseAxisLayout1D ) target;
                if ( layout.isAxisFactorySet( ) )
                {
                    return layout.getAxisFactory( );
                }
            }
        }

        return null;
    }

    // retrieve an axis for the given stack from the cache if it exists
    // otherwise, create an axis using the given parent_axis and factory and store it in the cache
    protected Axis1D getCachedAxis0( Axis1D parent_axis, AxisFactory1D factory, GlimpseTargetStack stack )
    {
        Axis1D newAxis = cache.getValueNoBoundsCheck( stack );

        if ( newAxis == null )
        {
            newAxis = getNewAxis0( parent_axis, factory, stack );
            newAxis.setSizePixels( getSize( stack.getBounds( ) ) );
            cache.setValue( stack, newAxis );
        }

        return newAxis;
    }

    protected Axis1D getCachedAxis0( Axis1D parent_axis, AxisFactory1D factory, GlimpseContext context )
    {
        return getCachedAxis0( parent_axis, factory, context.getTargetStack( ) );
    }

    protected Axis1D getNewAxis0( Axis1D parent_axis, AxisFactory1D factory, GlimpseTargetStack stack )
    {
        if ( factory != null )
        {
            return factory.newAxis( stack, parent_axis );
        }
        else
        {
            return DefaultAxisFactory1D.newAxis( parent_axis );
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy