#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 } }