#region Copyright
/*
--------------------------------------------------------------------------------
This source file is part of Xenocide
by Project Xenocide Team
For the latest info on Xenocide, see http://www.projectxenocide.com/
This work is licensed under the Creative Commons
Attribution-NonCommercial-ShareAlike 2.5 License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-nc-sa/2.5/
or send a letter to Creative Commons, 543 Howard Street, 5th Floor,
San Francisco, California, 94105, USA.
--------------------------------------------------------------------------------
*/
/*
* @file Frame.cs
* @date Created: 2007/03/04
* @author File creator: David Teviotdale
* @author Credits: none
*/
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using CeGui;
using CeGui.Renderers.Xna;
using ProjectXenocide.Utils;
using Xenocide.Resources;
#endregion
namespace ProjectXenocide.UI.Screens
{
///
/// This is the base class that all screen and dialogs derive from
/// The frame is responsible for:
/// 1. Owning the window that holds all the widgets making the screen or dialog
/// 2. utility functions for creating the widgets
/// Because the CeGui widgets are XNA Components
/// the Frame class does NOT pump Update() and Draw() to the widgets
/// themselves. That's done by the XNA framework
///
public abstract class Frame : IDisposable
{
///
/// Constructor
///
/// ID that CeGui will use to refer to this frame
/// Dimensions of the frame
protected Frame(string ceguiId, System.Drawing.SizeF size)
{
this.ceguiId = ceguiId;
this.screenManager = Xenocide.ScreenManager;
this.size = size;
}
///
/// Constructor
///
/// ID that CeGui will use to refer to this frame
/// The .layout filename used to describe this frame
protected Frame(string ceguiId, string layoutFilename)
{
this.ceguiId = ceguiId;
this.screenManager = Xenocide.ScreenManager;
this.layoutFilename = layoutFilename;
}
///
/// Puts the frame onto the display
///
public virtual void Show()
{
if (layoutFilename == null)
{
rootWidget = ConstructRootWidget();
rootWidget.Size = size;
rootWidget.MinimumSize = size;
}
else
{
rootWidget = WindowManager.Instance.LoadWindowLayout(layoutFilename, this);
rootWidget.MinimumSize = rootWidget.Size;
size = rootWidget.Size;
}
//ToDo: Need to set window to have correct parent
GuiSheet.AddChild(rootWidget);
rootWidget.MetricsMode = CeGui.MetricsMode.Relative;
rootWidget.Position = CalculatePosition();
// now add the other items to the frame
CreateCeguiWidgets();
}
///
/// Determine where to position frame so that it's in center of display
///
/// co-ordinates for top left corner of frame
System.Drawing.PointF CalculatePosition()
{
return new System.Drawing.PointF
(
(1.0f - size.Width) / 2.0f,
(1.0f - size.Height) / 2.0f
);
}
///
/// Implement IDisposable
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Removes the frame from the display
/// Also, completely destroys all the Cegui widgets associated
/// with the frame
///
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
CeGui.WindowManager.Instance.DestroyWindow(rootWidget);
}
rootWidget = null;
}
///
/// Enable/Disable this frame (and it's child widgets)
///
/// true to enable
public void Enable(bool enableFrame)
{
if (enableFrame)
{
rootWidget.Enable();
}
else
{
rootWidget.Disable();
}
}
///
/// populate the fame with the Cegui Widgets
///
protected abstract void CreateCeguiWidgets();
///
/// Load the graphic content of objects in the frame
///
/// content manager that fetches the content
/// the display
public virtual void LoadContent(ContentManager content, GraphicsDevice device)
{
}
///
/// Unload the Scene's graphic content
///
public virtual void UnloadContent()
{
}
///
/// Retreive the Gui Sheet that "hosts" the Form
///
/// The Sheet
protected virtual CeGui.GuiSheet GuiSheet
{
get { return ScreenManager.RootGuiSheet; }
}
///
/// Construct the widget that holds all widgets on this window
///
/// the widget
protected abstract CeGui.Window ConstructRootWidget();
///
/// Put a wigdet at the specified co-ordinates (and size) on this frame
///
/// The widget to place
/// Position on frame for widget's left edge
/// Position on frame for widget's top edge
/// Width of widget (relative to frame)
/// Height of widget (relative to frame)
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods",
Justification = "will throw if widget == null")]
protected void AddWidget(CeGui.Window widget, float left, float top, float width, float height)
{
rootWidget.AddChild(widget);
// ToDo: we're using Position and Size because Top, Left, Width and Height
// properties are currently broken in CeGui
widget.MetricsMode = CeGui.MetricsMode.Relative;
widget.Position = new System.Drawing.PointF(left, top);
widget.Size = new System.Drawing.SizeF(width, height);
}
///
/// Create the specified slider and put it on this frame
///
/// Name of resource string for label to put on button
/// Position on frame for slider's left edge
/// Position on frame for slider's top edge
/// Width of slider (relative to frame)
/// Height of slider (relative to frame)
/// The slider that has been created
public
CeGui.Widgets.Slider
AddSlider(
string resourceName,
float left, float top, float width, float height)
{
string label = XenocideResourceManager.Get(resourceName);
Debug.Assert((!String.IsNullOrEmpty(label)));
CeGui.Widgets.Slider slider = GuiBuilder.CreateSlider(ceguiId + '_' + label);
slider.Text = label;
AddWidget(slider, left, top, width, height);
return slider;
}
///
/// Create the specified checkbox (and text) and put it on this frame
///
/// Name of resource string for label to put on checkbox
/// Position on frame for checkbox left edge
/// Position on frame for checkbox top edge
/// Width of checkbox (relative to frame)
/// Height of checkbox (relative to frame)
/// The checkbox that has been created
public
CeGui.Widgets.Checkbox
AddCheckbox(
string resourceName,
float left, float top, float width, float height)
{
string label = XenocideResourceManager.Get(resourceName);
Debug.Assert((!String.IsNullOrEmpty(label)));
CeGui.Widgets.Checkbox checkbox = GuiBuilder.CreateCheckbox(ceguiId + '_' + label);
checkbox.Text = label;
AddWidget(checkbox, left, top, width, height);
return checkbox;
}
///
/// Create the specified static text and put it on this frame
///
/// Assumes label will be the text
/// Name of resource string for label to put on
/// Position on frame for text's left edge
/// Position on frame for text's top edge
/// Width of text (relative to frame)
/// Height of text (relative to frame)
/// The text that has been created
public
CeGui.Widgets.StaticText
AddStaticText(
string resourceName,
float left, float top, float width, float height)
{
string label = XenocideResourceManager.Get(resourceName);
Debug.Assert((!String.IsNullOrEmpty(label)));
CeGui.Widgets.StaticText statictext = GuiBuilder.CreateText(ceguiId + '_' + label);
statictext.Text = label;
AddWidget(statictext, left, top, width, height);
return statictext;
}
///
/// Create the specified static text and put it on this frame
///
/// We're going to add the text later
/// Position on frame for text's left edge
/// Position on frame for text's top edge
/// Width of text (relative to frame)
/// Height of text (relative to frame)
/// The text that has been created
public
CeGui.Widgets.StaticText
AddStaticText(
float left, float top, float width, float height)
{
CeGui.Widgets.StaticText statictext = GuiBuilder.CreateText(ceguiId + "_StaticText_" + NextId);
AddWidget(statictext, left, top, width, height);
return statictext;
}
///
/// Create the specified button and put it on this frame
///
/// Name of resource string for label to put on button
/// Position on frame for button's left edge
/// Position on frame for button's top edge
/// Width of button (relative to frame)
/// Height of button (relative to frame)
/// The button that has been created
public
CeGui.Widgets.PushButton
AddButton(
string resourceName,
float left, float top, float width, float height)
{
string label = XenocideResourceManager.Get(resourceName);
Debug.Assert((!String.IsNullOrEmpty(label)));
CeGui.Widgets.PushButton button = GuiBuilder.CreateButton(ceguiId + '_' + label);
button.Text = label;
button.Font = CeGui.FontManager.Instance.GetFont("Xeno");
AddWidget(button, left, top, width, height);
button.Clicked += new CeGui.GuiEventHandler(OnPlayButtonSound);
button.MouseEnters += new MouseEventHandler(OnHoverPlaySound);
return button;
}
///
/// Adds a sound to be played for a button.
///
/// The name of the button
/// The sound to play.
public void AddButtonSound(string btnName, string sound)
{
buttonSounds.Add(btnName, sound);
}
///
/// Create the specified button and put it on this frame
///
/// Name of resource string for label to put on button
/// Position on frame for button's left edge
/// Position on frame for button's top edge
/// Width of button (relative to frame)
/// Height of button (relative to frame)
/// Sound to play when button pressed
/// The button that has been created
public
CeGui.Widgets.PushButton
AddButton(
string resourceName,
float left, float top, float width, float height,
string sound)
{
CeGui.Widgets.PushButton button = AddButton(resourceName, left, top, width, height);
buttonSounds.Add(button.Name, sound);
return button;
}
///
/// Create the specified Edit box and put it on this frame
///
/// Name of edit box
/// Position on frame for Edit box's left edge
/// Position on frame for Edit box's top edge
/// Width of Edit box (relative to frame)
/// Height of Edit box (relative to frame)
/// The Edit box that has been created
public
CeGui.Widgets.EditBox
AddEditBox(
string resourceName,
float left, float top, float width, float height)
{
CeGui.Widgets.EditBox editBox = GuiBuilder.CreateEditBox(ceguiId + '_' + resourceName);
AddWidget(editBox, left, top, width, height);
return editBox;
}
///
/// Create the specified image with button events.
///
public
CeGui.Widgets.StaticImage
AddStaticImageButton(
string resourceName,
float left, float top, float width, float height, string imagenormal, string imagepushed, string sound)
{
CeGui.Widgets.StaticImage staticImage = GuiBuilder.CreateImage(ceguiId + '_' + resourceName);
staticImage.MouseClicked += new MouseEventHandler(OnPlayButtonSound);
staticImage.MouseEnters += new MouseEventHandler(ImageHoverOver);
staticImage.MouseLeaves += new MouseEventHandler(ImageHoverLeave);
staticImage.SetImage(ImageSetName, imagenormal);
//set items to dictionary
buttonSounds.Add(staticImage.Name, sound);
imageNames.Add(staticImage.Name, imagenormal);
imageNamesP.Add(staticImage.Name, imagepushed);
AddWidget(staticImage, left, top, width, height);
return staticImage;
}
///
/// Create the specified MultiColumnList and put it on this frame
///
/// Position on frame for MCL's left edge
/// Position on frame for MCL's top edge
/// Width of MCL (relative to frame)
/// Height of MCL (relative to frame)
/// details of columns to add, in form string name, float width
/// The MultiColumnList that has been created
public
CeGui.Widgets.MultiColumnList
AddGrid(
float left, float top, float width, float height, params Object[] args)
{
CeGui.Widgets.MultiColumnList grid = GuiBuilder.CreateGrid(ceguiId + "_multiColumnList_" + NextId);
AddWidget(grid, left, top, width, height);
for (int i = 0; i < args.Length; i += 2)
{
grid.AddColumn((string)args[i], grid.ColumnCount, (float)args[i + 1]);
}
return grid;
}
///
/// Play sound when mouse hovers over button
///
/// unused
/// unused
private void OnHoverPlaySound(object sender, MouseEventArgs e)
{
Xenocide.AudioSystem.PlaySound("Menu\\buttonover.ogg");
}
///
/// Change to hover image and play sound when hover over image "button"
///
/// button
/// unused
void ImageHoverOver(object sender, MouseEventArgs e)
{
CeGui.Widgets.StaticImage imageWidget = sender as CeGui.Widgets.StaticImage;
string label = imageWidget.Name;
imageWidget.SetImage(ImageSetName, imageNamesP[label]);
//play sound
Xenocide.AudioSystem.PlaySound("Menu\\buttonover.ogg");
}
///
/// Replace image with normal image when end hover
///
/// button
/// unused
private void ImageHoverLeave(object sender, MouseEventArgs e)
{
CeGui.Widgets.StaticImage imageWidget = sender as CeGui.Widgets.StaticImage;
string label = imageWidget.Name;
imageWidget.SetImage(ImageSetName, imageNames[label]);
}
///
/// Called to tell the Window prior to destruction to tell it to save any state information
/// needed to reconstruct it's state.
/// Basically, used to get the Geoscape to store the camera's position
/// when we go to a different screen.
///
public virtual void SaveState()
{
}
/// React to user clicking on a button by playing it's sound
/// Button the user clicked
/// Not used
[GuiEvent()]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
public void OnPlayButtonSound(object sender, CeGui.GuiEventArgs e)
{
if (enableButtonSounds)
{
// figure out sound to play, if no sound registered, use default
string sound;
string label = (sender as CeGui.Window).Name;
if (!buttonSounds.TryGetValue(label, out sound))
{
sound = DefaultButtonClickSound;
}
Xenocide.AudioSystem.PlaySound(sound);
}
}
#region Fields
///
/// Play sound when button pressed?
///
public bool EnableButtonSounds { get { return enableButtonSounds; } set { enableButtonSounds = value; } }
/// Make window visible/invisible
public bool Visible { get { return rootWidget.Visible; } set { rootWidget.Visible = value; } }
/// CeGui widget that holds all other widgets in the window
protected CeGui.Window RootWidget { get { return rootWidget; } }
/// CeGui widget that holds all other widgets in the window
private CeGui.Window rootWidget;
/// The identifer (name) that CeGui will use for the root widget
/// RK: There is no other ID you may require from a frame anyways, why not call it Id (and use it widely ;) ).
private string ceguiId;
///
/// The identifer (name) that CeGui will use for the root widget
///
protected string CeguiId { get { return ceguiId; } }
///
/// The ScreenManager
///
private ScreenManager screenManager;
///
/// The ScreenManager
///
protected ScreenManager ScreenManager { get { return screenManager; } }
///
/// The dimensions of the frame (in relative co-ordinates
///
private System.Drawing.SizeF size;
///
/// Helper function to get the GuiBuilder used to create widgets to put on form
///
protected CeGui.GuiBuilder GuiBuilder { get { return ScreenManager.GuiBuilder; } }
///
/// Sound to play when a button is pressed. Format is button ID, sound ID
///
private Dictionary buttonSounds = new Dictionary();
///
/// images when imagebutton is pushed
///
private Dictionary imageNamesP = new Dictionary();
///
/// images when imagebutton is not pushed
///
private Dictionary imageNames = new Dictionary();
///
/// Play sound when button pressed?
///
private bool enableButtonSounds = true;
///
/// Generate a unique (to this form) component to use in widget names
///
private string NextId { get { return Util.ToString(++nextId); } }
///
/// Generate a unique (to this form) component to use in widget names
///
private int nextId;
///
/// Filename of the .layout for this frame
///
private string layoutFilename;
///
/// Default button click sound to play
///
public const String DefaultButtonClickSound = "Menu\\buttonclick1_ok.ogg";
private const String ImageSetName = "TaharezLook";
#endregion Fields
}
}