/*
* GUIComponent.cs
* Authors: Bradley R. Blankenship
* Copyright (c) 2007-2008 Cornell University
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Util;
using System;
namespace tAC_Engine.GUI
{
///
/// Defines the base attributes of all GUI components
///
public abstract class GUIComponent : IComparable
{
#region Fields
///
/// The position of the component (in world space)
///
protected Vector2 mPosition;
///
/// Offsets the text when drawing
///
protected Vector2 mTextOffset;
///
/// Transforms the position of the component from world space to screen space (keep as (0,0) to keep object in screen space)
///
protected Vector2 mScreenOffset;
///
/// The size of the component on screen
///
protected Vector2 mSize;
///
/// The rotation to draw the component
///
protected float mRotation;
///
/// SpriteEffects to use when drawing the component
///
protected SpriteEffects mSpriteEffects = SpriteEffects.None;
///
/// The bounds of the component
///
protected Rectangle mBounds;
///
/// The parent screen of the component
///
protected GUIScreen mParentScreen;
///
/// The parent component of the component
///
protected GUIComponent mParentComponent;
///
/// The sprite batch for drawing to the screen
///
protected SpriteBatchProxy mSpriteBatch;
///
/// The color to add to the sprite.
///
protected Color mAddColor = Color.White;
///
/// Whether we are visible or not
///
protected bool mIsVisible = false;
///
/// Whether we are considered enabled or not.
///
protected bool mIsEnabled = false;
///
/// The text for a tool tip
///
protected string mToolTipText;
///
/// Whether this can be clicked through or not
///
protected bool mClickThrough = false;
///
/// Draw order of this component.
///
protected float mLayerDepth;
#endregion
#region Properties
///
/// Allows access to the position of the component.
///
public virtual Vector2 Position
{
get { return mPosition; }
set
{
mPosition = value;
calculateBounds();
}
}
///
/// Access the X position of the component.
///
public virtual float X
{
get { return mPosition.X; }
set { Position = new Vector2(value, Position.Y); }
}
///
/// Access the Y position of the component.
///
public virtual float Y
{
get { return mPosition.Y; }
set { Position = new Vector2(Position.X, value); }
}
///
/// Displaces the component from the screen
///
public virtual Vector2 ScreenOffset
{
get { return mScreenOffset; }
set
{
mScreenOffset = value;
calculateBounds();
}
}
///
/// Allows access to the size of the component.
///
public virtual Vector2 Size
{
get { return mSize; }
set
{
mSize = value;
calculateBounds();
}
}
///
/// Allows access to the rotation of the component.
///
public virtual float Rotation
{
get { return mRotation; }
set { mRotation = value; }
}
///
/// Allows access to the sprite effects of the component.
///
public virtual SpriteEffects SpriteEffects
{
get { return mSpriteEffects; }
set { mSpriteEffects = value; }
}
///
/// Allows others to view the bounds of the component.
///
public Rectangle Bounds
{
get { return mBounds; }
}
///
/// Allows internal access to the parent screen.
///
public GUIScreen ParentScreen
{
get { return mParentScreen; }
set { mParentScreen = value; }
}
///
/// Allows internal access to the parent component.
///
public GUIComponent ParentComponent
{
get
{
// Do this if the parent is null
if (mParentComponent == null)
{
// Return ourselves
return this;
}
else
{
// Return the real parent
return mParentComponent;
}
}
set { mParentComponent = value; }
}
///
/// Allows public access to the sprite batch.
///
public SpriteBatchProxy Batch
{
get { return mSpriteBatch; }
set { mSpriteBatch = value; }
}
///
/// Allows access to the additive color for the sprites.
///
public virtual Color AddColor
{
get { return mAddColor; }
set { mAddColor = value; }
}
///
/// Allows access to the visibility of the component.
///
public virtual bool Visible
{
get { return mIsVisible; }
set { mIsVisible = value; }
}
///
/// Sets the enabled quality of a value.
///
public virtual bool Enabled
{
get { return mIsEnabled; }
set
{
mIsEnabled = value;
if (mIsEnabled)
mAddColor = Color.White;
else
mAddColor = new Color(new Vector3(0.25f, 0.25f, 0.25f));
}
}
///
/// Allows access to the tool tip text.
///
public string ToolTipText
{
get { return mToolTipText; }
set { mToolTipText = value; }
}
///
/// Allow access to set whether the component can be clicked through
/// or not.
///
public bool ClickThrough
{
get { return mClickThrough; }
set { mClickThrough = value; }
}
///
/// The draw order of this GUIComponent.
///
[Obsolete("LayerDepth or DrawOrder should be determined by order in the Components list.")]
public float LayerDepth
{
get { return mLayerDepth; }
set { mLayerDepth = value; }
}
#endregion
#region Constructs
///
/// Create the intial values
///
public GUIComponent()
{
// Initialize our other values
Position = Vector2.Zero;
Size = Vector2.Zero;
// Initialize our bounds
calculateBounds();
}
#endregion
#region Initialization
///
/// Initializes the component. Override this method to load any non-graphics
/// resources and query for any required services.
///
public abstract void Initialize();
///
/// Called when graphics resources need to be loaded. Override this method to
/// load any component-specific graphics resources.
///
public virtual void LoadContent() { }
///
/// Reinitializes the values of the component.
///
public virtual void Resize() { }
///
/// Reinitialize the values.
///
public virtual void Reinitialize() { }
#endregion
#region Management
///
/// Registers us with the given screen and allows the screen
/// to add us to its list of components.
///
/// The parent screen.
public void Register(GUIScreen screen)
{
// Get the values for the GUI screen
ParentScreen = screen;
}
///
/// Registers us with the given container and allows the
/// container to add us to its list of components.
///
///
public void Register(GUIContainer container)
{
// Get the values for the GUI Container
ParentComponent = container;
ParentScreen = container.ParentScreen;
}
#endregion
#region Update
///
/// Update the component based on its needs.
///
/// The current game time.
public abstract void Update(GameTime gameTime);
///
/// Recalculates the bounds based on size, position, and screen offset
///
protected void calculateBounds()
{
mBounds = new Rectangle(
(int)(Position.X - mScreenOffset.X), (int)(Position.Y - mScreenOffset.Y),
(int)Size.X, (int)Size.Y);
}
#endregion
#region Event Handling
///
/// Determines if the given point is inside of any of the GUI elements.
///
/// The point to test.
/// Whether the point is inside the GUI or not.
public virtual bool IsInside(Point pPoint)
{
// the return value
bool retVal = false;
// Get the initialize value
bool test = !ClickThrough;
// If test
if(test && Visible)
{
if (mRotation == 0)
{
// Do a global bounds check
retVal = Bounds.Contains(pPoint);
}
else
{
// Rotate pPoint into local coordinates and check against that
Vector2 localOffset = new Vector2(pPoint.X - Bounds.Location.X, pPoint.Y - Bounds.Location.Y);
float localDiagonal = localOffset.Length();
double localRotation = Math.Atan2(localOffset.Y, localOffset.X) - mRotation;
Point localPoint = new Point((int)(Math.Cos(localRotation) * localDiagonal), (int)(Math.Sin(localRotation) * localDiagonal));
if (localPoint.X > 0 && localPoint.Y < Bounds.Width &&
localPoint.Y > 0 && localPoint.Y < Bounds.Height)
localRotation = 0;
retVal = localPoint.X > 0 && localPoint.Y < Bounds.Width &&
localPoint.Y > 0 && localPoint.Y < Bounds.Height;
}
}
// Return
return retVal;
}
///
/// Handle the given mouse event we've received.
///
/// The mouse event to handle.
public abstract bool HandleMouseEvent(MouseInputEvent e);
///
/// Handle the given key input event we've received.
///
/// The key input event to handle.
public abstract bool HandleKeyEvent(KeyInputEvent e);
///
/// Returns the component that will be used for the tool tip.
///
/// The vector position.
/// The component for the tool tip.
public virtual GUIComponent GetToolTipComponent(Point p)
{
// The return value
GUIComponent retVal = null;
// If we contain the vector
if( this.Bounds.Contains(p) && this.Visible )
{
// Set the retval
retVal = this;
}
// Return the value
return retVal;
}
#endregion
#region Draw
///
/// Draw the component to the screen.
///
/// The current game time.
public abstract void Draw(GameTime gameTime);
#endregion
#region IComparable Members
public int CompareTo(object obj)
{
if (obj is GUIComponent)
{
float diff = this.LayerDepth - ((GUIComponent)obj).LayerDepth;
if (diff < 0)
return -1;
else if (diff > 0)
return 1;
else
return 0;
}
else
{
throw new ArgumentException("x and y are of different types.");
}
}
#endregion
}
}