/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* 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 the 'Xith3D Project Group' 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.ui.hud.widgets;
import java.util.ArrayList;
import org.jagatoo.input.devices.components.MouseButton;
import org.openmali.vecmath2.Colorf;
import org.openmali.vecmath2.Point2f;
import org.openmali.vecmath2.Tuple2f;
import org.xith3d.loop.UpdatingThread.TimingMode;
import org.xith3d.loop.opscheduler.impl.ScheduledOperationImpl;
import org.xith3d.scenegraph.Texture2DCanvas;
import org.xith3d.ui.hud.HUD;
import org.xith3d.ui.hud.base.Widget;
import org.xith3d.ui.hud.listeners.QuadDividerListener;
import org.xith3d.ui.hud.listeners.WidgetLocationListener;
import org.xith3d.ui.hud.utils.HUDPickResult;
import org.xith3d.ui.hud.utils.HUDPickResult.HUDPickReason;
/**
* The QuadDivider is used to resize four Widgets in
* north-west, north-east, south-west and south-east.
*
* @author Marvin Froehlich (aka Qudus)
*/
public class QuadDivider extends Widget
{
public static final float DIVIDER_WIDTH = 10f;
public static enum QuadPanels
{
UPPER_LEFT,
UPPER_RIGHT,
LOWER_LEFT,
LOWER_RIGHT,
;
}
private class EventEngine extends ScheduledOperationImpl implements WidgetLocationListener
{
private boolean eventBlocked = false;
public void onWidgetDragStarted( Widget widget )
{
}
public void onWidgetDragStopped( Widget widget )
{
}
public void onWidgetLocationChanged( Widget widget, float oldLeft, float oldTop, float newLeft, float newTop )
{
if ( eventBlocked )
return;
eventBlocked = true;
if ( ( widget == horizontalDivider ) && ( widget.getLeft() != 0f ) )
widget.setLocation( 0f, widget.getTop() );
if ( ( widget == verticalDivider ) && ( widget.getTop() != 0f ) )
widget.setLocation( widget.getLeft(), 0f );
eventBlocked = false;
final HUD hud = QuadDivider.this.getHUD();
if ( hud != null )
{
hud.getOperationScheduler().scheduleOperation( this );
}
}
public void update( long gameTime, long frameTime, TimingMode timingMode )
{
updatePanelSizes();
for ( int i = 0; i < listeners.size(); i++ )
{
listeners.get( i ).onDividerResized( QuadDivider.this, leftWidth, rightWidth, topHeight, bottomHeight );
}
}
public EventEngine()
{
super( false );
}
}
private Colorf earlyDivColor;
private float earlyVertDivLeft = -1f;
private float earlyHorizDivTop = -1f;
private Image horizontalDivider;
private Image verticalDivider;
private EventEngine eventEngine = new EventEngine();
private float leftWidth = -1f;
private float rightWidth = -1f;
private float topHeight = -1f;
private float bottomHeight = -1f;
private float rightLeft = -1f;
private float bottomTop = -1f;
private final ArrayList< QuadDividerListener > listeners = new ArrayList< QuadDividerListener >( 1 );
protected void updatePanelSizes()
{
final float horizDivTop;
final float vertDivLeft;
if ( isInitialized() )
{
horizDivTop = horizontalDivider.getTop();
vertDivLeft = verticalDivider.getLeft();
}
else
{
if ( earlyHorizDivTop < 0f )
horizDivTop = ( getHeight() / 2f ) - ( DIVIDER_WIDTH / 2f );
else
horizDivTop = earlyHorizDivTop;
if ( earlyVertDivLeft < 0f )
vertDivLeft = ( getWidth() / 2f ) - ( DIVIDER_WIDTH / 2f );
else
vertDivLeft = earlyVertDivLeft;
}
leftWidth = vertDivLeft;
rightWidth = getWidth() - ( vertDivLeft + DIVIDER_WIDTH );
topHeight = horizDivTop;
bottomHeight = getHeight() - ( horizDivTop + DIVIDER_WIDTH );
rightLeft = vertDivLeft + DIVIDER_WIDTH;
bottomTop = horizDivTop + DIVIDER_WIDTH;
}
public void setDividerColor( Colorf color )
{
if ( isInitialized() )
{
horizontalDivider.setColor( color );
verticalDivider.setColor( color );
}
else
{
earlyDivColor = color;
}
}
/**
* Sets the left-position of the vertical diviver.
*
* @param vertLeft
*/
public void setVerticalDividerLeft( float vertLeft )
{
if ( !isInitialized() )
{
earlyVertDivLeft = vertLeft;
}
else
{
verticalDivider.setLocation( vertLeft, 0f );
}
updatePanelSizes();
}
/**
* Sets the top-position of the horizontal divider.
*
* @param horizTop
*/
public void setHorizontalDividerTop( float horizTop )
{
if ( !isInitialized() )
{
earlyHorizDivTop = horizTop;
}
else
{
horizontalDivider.setLocation( 0f, horizTop );
}
updatePanelSizes();
}
/**
* @return the width of the left-hand panels.
*/
public final float getLeftWidth()
{
return ( leftWidth );
}
/**
* @return the width of the right-hand panels.
*/
public final float getRightWidth()
{
return ( rightWidth );
}
/**
* @return the height of the top panels.
*/
public final float getTopHeight()
{
return ( topHeight );
}
/**
* @return the height of the bottom panels.
*/
public final float getBottomHeight()
{
return ( bottomHeight );
}
/**
* @return the left-position of the right-hand panels.
*/
public final float getRightLeft()
{
return ( rightLeft );
}
/**
* @return the top-position of the bottom panels.
*/
public final float getBottomTop()
{
return ( bottomTop );
}
/**
* Returns a constant indicating the "panel" under the mouse cursor.
*
* @param canvasX
* @param canvasY
*
* @return the "panel". (or null, if the widget has not yet been initialized or the mouse is not over one of the panels)
*/
public QuadPanels getPanelUnderMouse( int canvasX, int canvasY )
{
if ( getHUD() == null )
return ( null );
Point2f p = Point2f.fromPool();
getLocationPixels2HUD_( canvasX, canvasY, p );
QuadPanels qp = null;
if ( ( p.getX() >= 0f ) && ( p.getX() <= getLeftWidth() ) )
{
if ( ( p.getY() >= 0f ) && ( p.getY() <= getTopHeight() ) )
{
qp = QuadPanels.UPPER_LEFT;
}
else if ( ( p.getY() >= getBottomTop() ) && ( p.getY() <= getHeight() ) )
{
qp = QuadPanels.LOWER_LEFT;
}
}
else if ( ( p.getX() >= getRightLeft() ) && ( p.getX() <= getWidth() ) )
{
if ( ( p.getY() >= 0f ) && ( p.getY() <= getTopHeight() ) )
{
qp = QuadPanels.UPPER_RIGHT;
}
else if ( ( p.getY() >= getBottomTop() ) && ( p.getY() <= getHeight() ) )
{
qp = QuadPanels.LOWER_RIGHT;
}
}
Point2f.toPool( p );
return ( qp );
}
/**
* Adds a new QuadDividerListener.
*
* @param l
*/
public void addQuadDividerListener( QuadDividerListener l )
{
listeners.add( l );
}
/**
* Removes a QuadDividerListener.
*
* @param l
*/
public void removeQuadDividerListener( QuadDividerListener l )
{
listeners.remove( l );
}
/**
* {@inheritDoc}
*/
@Override
public HUDPickResult pick( int canvasX, int canvasY, HUDPickReason pickReason, MouseButton button, long when, long meta, int flags )
{
final Tuple2f locP = Tuple2f.fromPool();
getLocationPixels2HUD_( canvasX, canvasY, locP );
float pickXHUD = locP.getX();
float pickYHUD = locP.getY();
Tuple2f.toPool( locP );
getWidgetAssembler().pick( canvasX, canvasY, pickXHUD, pickYHUD, pickReason, button, when, meta, flags );
return ( null );
}
@Override
protected void drawWidget( Texture2DCanvas texCanvas, int offsetX, int offsetY, int width, int height, boolean drawsSelf )
{
texCanvas.getImage().clear( Colorf.BLACK_TRANSPARENT );
}
/**
* {@inheritDoc}
*/
@Override
protected void init()
{
this.horizontalDivider = new Image( getWidth(), DIVIDER_WIDTH, earlyDivColor );
this.verticalDivider = new Image( DIVIDER_WIDTH, getHeight(), earlyDivColor );
earlyDivColor = null;
horizontalDivider.setDraggable( true );
verticalDivider.setDraggable( true );
horizontalDivider.addLocationListener( eventEngine );
verticalDivider.addLocationListener( eventEngine );
if ( earlyHorizDivTop < 0f )
earlyHorizDivTop = ( getHeight() / 2f ) - ( DIVIDER_WIDTH / 2f );
if ( earlyVertDivLeft < 0f )
earlyVertDivLeft = ( getWidth() / 2f ) - ( DIVIDER_WIDTH / 2f );
getWidgetAssembler().addWidget( horizontalDivider, 0f, earlyHorizDivTop );
getWidgetAssembler().addWidget( verticalDivider, earlyVertDivLeft, 0f );
updatePanelSizes();
}
public QuadDivider( float width, float height, Colorf dividerColor )
{
super( true, true, width, height );
this.setFocussable( false );
earlyDivColor = dividerColor;
updatePanelSizes();
}
public QuadDivider( float width, float height )
{
this( width, height, Colorf.PINK );
}
}