view Widgets/UnitDisplayWidget.cs @ 91:986fc923c0fa

Fixes #331: Equipment buttons should be disabled when options aren't available * Edit was already handled via UnitEquipmentUtil call * Added enabling/disabling for Add via extracted methods on AddEquipmentUIControl
author IBBoard <dev@ibboard.co.uk>
date Fri, 31 Dec 2010 11:36:06 +0000
parents 68804784bf6f
children 58779fcd0166
line wrap: on
line source

// This file (UnitDisplayWidget.cs) is a part of the IBBoard.WarFoundry.GTK project and is copyright 2008, 2009 IBBoard.
//
// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
using System;
using Gtk;
using IBBoard.Commands;
using IBBoard.GtkSharp;
using IBBoard.Lang;
using IBBoard.WarFoundry.API;
using IBBoard.WarFoundry.API.Commands;
using IBBoard.WarFoundry.API.Objects;
using IBBoard.WarFoundry.API.Util;
using IBBoard.WarFoundry.GUI.GTK.UIControl;
using log4net;
using WFObjects = IBBoard.WarFoundry.API.Objects;
using System.Collections.Generic;

namespace IBBoard.WarFoundry.GUI.GTK.Widgets
{
	[System.ComponentModel.Category("WarFoundry GTK# GUI")]
	[System.ComponentModel.ToolboxItem(true)]
	public partial class UnitDisplayWidget : Gtk.Bin
	{
		private static ILog log = LogManager.GetLogger (typeof (UnitDisplayWidget));
		private WFObjects.Unit unit;
		private CommandStack stack;
		private Dictionary<string, NodeView> statsViews = new Dictionary<string, NodeView> ();

		public UnitDisplayWidget (WFObjects.Unit sourceUnit, CommandStack commandStack)
		{
			this.Build ();
			stack = commandStack;
			unit = sourceUnit;
			unitName.Text = unit.Name;
			unitSize.Value = unit.Size;
			int maxSize = (unit.UnitType.MaxSize == WarFoundryCore.INFINITY ? int.MaxValue : unit.UnitType.MaxSize);
			int minSize = unit.UnitType.MinSize;
			unitSize.SetRange (minSize, maxSize);
			unitSize.Sensitive = (maxSize != minSize);
			notesView.Buffer.Text = unit.UnitType.Notes;
			unit.NameChanged += UnitNameChanged;
			unit.UnitSizeChanged += UnitSizeChanged;
			unit.UnitEquipmentAmountChanged += HandleUnitUnitEquipmentAmountChanged;
			equipmentList.Selection.Changed += HandleEquipmentListSelectionChanged;
			SetAbilities ();
			SetStats ();
			SetWeapons ();
			SetAddButtonEnabledState();
		}

		private void HandleEquipmentListSelectionChanged (object sender, EventArgs e)
		{
			SetButtonsEnabledState ();	
		}

		private void SetButtonsEnabledState ()
		{			
			UnitEquipmentItem equipItem = GetSelectedEquipmentItem ();
			bttnReplaceEquipment.Sensitive = (equipItem != null && equipItem.HasAlternatives ());
			bttnEditEquipment.Sensitive = (UnitEquipmentUtil.CanEditEquipmentAmount (unit, equipItem));
			bttnRemoveEquipment.Sensitive = (equipItem != null && !equipItem.IsRequired);
		}

		private void SetAddButtonEnabledState()
		{
			bttnAddEquipment.Sensitive = AddEquipmentUIControl.HasEquipmentToAdd(unit);
		}

		private UnitEquipmentItem GetSelectedEquipmentItem ()
		{
			return (UnitEquipmentItem)TreeUtils.GetSelectedItem (equipmentList);
		}

		private void SetAbilities ()
		{
			CellRendererText renderer = new CellRendererText ();
			abilitiesList.AppendColumn ("", renderer, new TreeCellDataFunc (RenderAbility));
			
			ListStore model = new ListStore (typeof (Ability));
			
			foreach (Ability ability in unit.UnitType.GetRequiredAbilities ()) {
				model.AppendValues (ability);
			}
			
			abilitiesList.Model = model;
		}

		public void RenderAbility (TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
		{
			object o = model.GetValue (iter, 0);
			
			if (o is Ability) {
				Ability ability = (Ability)o;
				(cell as CellRendererText).Text = ability.Name;
			}			
						
		}

		private void SetStats ()
		{
			Stat[][] stats = unit.UnitStatsArraysWithName;
			string[] statsIDs = unit.UnitStatsArrayIDs;
			int statsCount = stats.Length;
			log.DebugFormat ("Unit {0} has {1} stats arrays", unit.UnitType.Name, statsCount);

			for (int i = 0; i < statsCount; i++) {
				NodeView statsGrid = GetStatsView (statsIDs [i]);
				TreeStore model = (TreeStore)statsGrid.Model;
				log.DebugFormat ("Adding row to data table for {0}", statsIDs [i]);
				log.DebugFormat ("TreeStore supports {0} columns", model.NColumns);
				model.AppendValues ((object)stats [i]);
			}
		}

		private NodeView GetStatsView (string statsID)
		{
			NodeView statsView;

			if (statsViews.ContainsKey (statsID)) {
				statsView = DictionaryUtils.GetValue (statsViews, statsID);
			} else {
				statsView = CreateStatsView (statsID);
				statsViews [statsID] = statsView;
			}

			return statsView;
		}

		private NodeView CreateStatsView (string statsID)
		{
			log.DebugFormat ("Create NodeView for stats ID {0}", statsID);
			SystemStats sysStats = unit.Race.GameSystem.GetSystemStatsForID (statsID);
			StatSlot[] sysStatSlots = sysStats.StatSlots;
			int statsCount = sysStatSlots.Length;
			NodeView statsGrid = CreateNodeView ();
			CellRendererText renderer = new CellRendererText ();
			statsGrid.AppendColumn (Translation.GetTranslation ("UnitNameColumn", "Unit Type", null), renderer, RenderUnitStat);

			for (int i = 0; i < statsCount; i++) {
				StatSlot stat = sysStatSlots [i];
				string slotName = stat.Name;
				statsGrid.AppendColumn (slotName, renderer, RenderUnitStat);
			}
			
			statsGrid.Model = new TreeStore (typeof (Stat[]));
			return statsGrid;
		}

		private NodeView CreateNodeView ()
		{
			NodeView nodeView = new NodeView ();
			statsRepeatBox.Add (nodeView);
			return nodeView;
		}

		private void RenderUnitStat (TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
		{
			object o = model.GetValue (iter, 0);
			
			if (o is Stat[]) {
				Stat[] stats = (Stat[])o;
				(cell as CellRendererText).Text = stats [GetStatColumnIndex (column)].SlotValueString;
			}
		}

		private int GetStatColumnIndex (TreeViewColumn column)
		{
			int idx = -1;
			TreeViewColumn[] cols = ((TreeView)column.TreeView).Columns;
			int colCount = cols.Length;
			
			for (int i = 0; i < colCount; i++) {
				if (cols [i] == column) {
					idx = i;
					break;
				}
			}
			
			return idx;
		}

		private void SetWeapons ()
		{
			CellRendererText renderer = new CellRendererText ();
			equipmentList.AppendColumn ("", renderer, new TreeCellDataFunc (RenderEquipmentLine));
			
			ListStore model = new ListStore (typeof (UnitEquipmentItem));
			
			foreach (UnitEquipmentItem item in unit.GetEquipment ()) {
				model.AppendValues (item);
			}
			
			equipmentList.Model = model;
		}

		public void RenderEquipmentLine (TreeViewColumn column, CellRenderer cell, TreeModel model, TreeIter iter)
		{
			object o = model.GetValue (iter, 0);
			
			if (o is UnitEquipmentItem) {
				UnitEquipmentItem item = (UnitEquipmentItem)o;
				(cell as CellRendererText).Text = GetUnitEquipmentText (item);
			}			
						
		}

		private string GetUnitEquipmentText (UnitEquipmentItem item)
		{
			string translation = "";

			if (item.Cost == 0) {
				translation = Translation.GetTranslation ("equipmentAmountWithZeroCost", "{0} ({1} - free)", item.Name, GetAmountString (item));
			} else {
				translation = Translation.GetTranslation ("equipmentAmountWithCost", "{0} ({1} at {2}pts each)", item.Name, GetAmountString (item), item.Cost);
			}

			return translation;
		}

		private string GetAmountString (UnitEquipmentItem item)
		{
			double amount = UnitEquipmentUtil.GetEquipmentAmount (unit, item);
			string amountString = "";
			
			if (UnitEquipmentUtil.GetEquipmentAmountIsRatio (unit, item)) {
				int number = UnitEquipmentUtil.GetEquipmentAmountTaken (unit, item);
				
				if (amount == 100) {
					amountString = Translation.GetTranslation ("equipmentChoiceAmountAll", "all ({1})", amount, number);
				} else {
					amountString = Translation.GetTranslation ("equipmentChoiceAmountPercentage", "{0}% ({1})", amount, number);
				}
			} else {
				amountString = Translation.GetTranslation ("equipmentChoiceAmountNumber", "{0}", amount);
			}
			
			return amountString;
		}

		public WFObjects.Unit Unit {
			get { return unit; }
		}

		private void UnitNameChanged (WarFoundryObject obj, string oldValue, string newValue)
		{
			unitName.Text = newValue;
		}

		private void UnitSizeChanged (WarFoundryObject obj, int oldValue, int newValue)
		{
			unitSize.Value = newValue;
		}

		private void HandleUnitUnitEquipmentAmountChanged (WarFoundryObject obj, double oldValue, double newValue)
		{
			if (oldValue == 0)
			{
				((ListStore)equipmentList.Model).AppendValues(obj);
			}
			else
			{
				if (newValue == 0)
				{
					TreeIter treeIter = TreeUtils.GetItemIter(equipmentList, obj);
					((ListStore)equipmentList.Model).Remove(ref treeIter);
				}
			}

			SetAddButtonEnabledState();
			equipmentList.QueueDraw();
		}

		protected virtual void OnUnitSizeFocusOut (object o, Gtk.FocusOutEventArgs args)
		{
			SetNewUnitSize ();
		}

		[GLib.ConnectBefore ()]

		protected virtual void OnUnitSizeKeyPress (object o, Gtk.KeyPressEventArgs args)
		{
			if (args.Event.Key == Gdk.Key.Return || args.Event.Key == Gdk.Key.KP_Enter) {
				SetNewUnitSize ();
			}
		}

		private void SetNewUnitSize ()
		{
			if (unitSize.Value != unit.Size) {
				SetUnitSizeCommand cmd = new SetUnitSizeCommand (unit, (int)Math.Round (unitSize.Value));
				stack.Execute (cmd);
			}
		}

		protected virtual void OnUnitNameFocusOut (object o, Gtk.FocusOutEventArgs args)
		{
			SetNewUnitName ();
		}

		[GLib.ConnectBefore ()]

		protected virtual void OnUnitNameKeyPress (object o, Gtk.KeyPressEventArgs args)
		{
			if (args.Event.Key == Gdk.Key.Return || args.Event.Key == Gdk.Key.KP_Enter) {
				SetNewUnitName ();
			}
		}

		private void SetNewUnitName ()
		{
			if (unitName.Text != unit.Name) {
				SetNameCommand cmd = new SetNameCommand (unit, unitName.Text);
				stack.Execute (cmd);
			}
		}

		private void OnBttnAddEquipmentClicked (object sender, System.EventArgs e)
		{
			AddEquipment ();
		}

		private void AddEquipment ()
		{
			AddEquipmentUIControl addEquipment = new AddEquipmentUIControl (unit, stack);
			addEquipment.Show ();
		}

		protected virtual void HandleRemoveButtonActivated (object sender, System.EventArgs e)
		{
			UnitEquipmentItem item = GetSelectedEquipmentItem ();
			log.Debug ("Remove " + item);
				
			if (item != null) {
				SetUnitEquipmentNumericAmountCommand cmd = new SetUnitEquipmentNumericAmountCommand (unit, item, 0);
				stack.Execute (cmd);
			}
		}		

		protected virtual void HandleEditButtonClicked (object sender, System.EventArgs e)
		{
			UnitEquipmentItem item = GetSelectedEquipmentItem ();
			log.Debug ("Edit " + item);
			
			if (item != null) {
				EditEquipmentUIControl editEquipment = new EditEquipmentUIControl (unit, item, stack);
				editEquipment.Show ();
			}
		}

		protected virtual void HandleReplaceButtonClicked (object sender, System.EventArgs e)
		{
			UnitEquipmentItem item = GetSelectedEquipmentItem ();
			log.Debug ("Replace " + item);
				
			if (item != null) {
				ReplaceEquipmentUIControl addEquipment = new ReplaceEquipmentUIControl (unit, item, stack);
				addEquipment.Show ();
			}
		}		
	}
}