Changeset - dabc07eb39e6
[Not reviewed]
default
0 8 0
Jason Maltzen (jmaltzen) - 9 years ago 2015-12-31 05:45:01
jason.maltzen@unsanctioned.net
Add a min ingredients setting during recipe generation to help with extending a set of generated recipes. Add some warning messages if profile creation failed.
8 files changed with 417 insertions and 172 deletions:
0 comments (0 inline, 0 general)
MainWindow.cs
Show inline comments
...
 
@@ -20,24 +20,26 @@
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 
using System.IO;
 
using System.Collections.Generic;
 
using System.Text.RegularExpressions;
 
using Gtk;
 
using DesertPaintLab;
 

	
 
public partial class MainWindow : Gtk.Window
 
{
 
    const string APP_VERSION = "1.1.10";
 

	
 
	bool unsavedData = false;
 
	bool shouldShutDown = false;
 
	string appDataPath;
 
	List<string> profileList = new List<string>();
 
	PlayerProfile profile = null;
 
	PaintColor expectedColor = new PaintColor();
 
	PaintColor reactedColor = new PaintColor();
 
	
 
	int screenWidth = 0;
 
	int screenHeight = 0;
 
	int pixelMultiplier = 1;
 

	
...
 
@@ -75,27 +77,51 @@ public partial class MainWindow : Gtk.Wi
 
		{
 
			if (dir.Name != "template")
 
			{
 
				profileList.Add(dir.Name);
 
			}
 
		}
 

	
 
        reagents[0] = null;
 
        reagents[1] = null;
 
        reagents[2] = null;
 

	
 
        string colorsPath = FileUtils.FindApplicationResourceFile("colors.txt");
 
        if (colorsPath == null)
 
        {
 
            // failed to find colors.txt file
 
            MessageDialog md = new MessageDialog(this, 
 
                DialogFlags.DestroyWithParent,
 
                MessageType.Error, ButtonsType.Close, 
 
                "Failed to find colors.txt file. Please check your installation.");
 
       
 
            md.Run();
 
            md.Destroy();
 
            Application.Quit();
 
        }
 
		Palette.Load(colorsPath);
 

	
 
        string ingredientsPath = FileUtils.FindApplicationResourceFile("ingredients.txt");
 
        if (ingredientsPath == null)
 
        {
 
            // failed to find ingredients.txt file
 
            MessageDialog md = new MessageDialog(this, 
 
                DialogFlags.DestroyWithParent,
 
                MessageType.Error, ButtonsType.Close, 
 
                "Failed to find ingredients.txt file. Please check your installation.");
 
       
 
            md.Run();
 
            md.Destroy();
 
            Application.Quit();
 
        }
 
        ReagentManager.Load(ingredientsPath);
 
		
 
		Build();
 
		
 
		if (unmodifiedSwatch != null)
 
		{
 
			unmodifiedSwatch.Clear();
 
		}
 
		if (reactionSwatch != null)
 
		{
 
			reactionSwatch.Clear();
 
		}
...
 
@@ -258,27 +284,35 @@ public partial class MainWindow : Gtk.Wi
 
					resp = (ResponseType)md.Run();
 
					md.Destroy();
 
					duplicateName = true;
 
					break;	
 
				}
 
			}
 
			
 
			if (!duplicateName)
 
			{
 
				// Set profile name.
 
				SetProfileName(newProfileDialog.ProfileName);
 
				
 
				profile.Initialize();
 
				
 
				newProfileCreated = true;
 
                newProfileCreated = profile.Initialize();
 
                if (!newProfileCreated)
 
                {
 
                    MessageDialog md = new MessageDialog(this, 
 
                        DialogFlags.DestroyWithParent,
 
                        MessageType.Error, ButtonsType.Ok, 
 
                        "Failed to initialize profile: " + profile.LastError);
 
                    resp = (ResponseType)md.Run();
 
                    md.Destroy();
 
                    duplicateName = false;
 
                }
 
			}
 
		}
 
		newProfileDialog.Destroy();
 
		return newProfileCreated;
 
	}
 
	
 
	bool OpenProfile()
 
	{
 
		bool profileSelected = false;
 
		
 
		if (profileList.Count > 0)
 
		{
...
 
@@ -324,28 +358,42 @@ public partial class MainWindow : Gtk.Wi
 
						profileSelected = NewProfile();
 
						if (profileSelected)
 
						{
 
							profile.ImportFromPP(directory);
 
						}
 
					}
 
				}
 
			}
 
		}
 
		
 
		if (profileSelected)
 
		{
 
			profile.Load();
 
			bool ok = profile.Load();
 
            if (ok)
 
            {
 
			PopulateDropDowns();
 
            recipe.Reactions = profile.Reactions;
 
		}
 
            else
 
            {
 
                MessageDialog md = new MessageDialog(this, 
 
                    DialogFlags.DestroyWithParent,
 
                    MessageType.Error, ButtonsType.Ok, 
 
                    "Error loading profile: " + profile.LastError);
 

	
 
                md.Run();
 
                md.Destroy();
 
                profileSelected = false;
 
            }
 
		}
 

	
 
		return profileSelected;
 
	}
 
	
 
	void PopulateDropDowns()
 
	{
 
		ReagentManager.PopulateReagents(ref ingredient1ComboBox);
 
		ReagentManager.PopulateReagents(ref ingredient2ComboBox);
 
		ReagentManager.PopulateReagents(ref ingredient3ComboBox);
 
		
 
		ingredient2ComboBox.Sensitive = false;
 
		ingredient3ComboBox.Sensitive = false;
...
 
@@ -683,59 +731,83 @@ public partial class MainWindow : Gtk.Wi
 
	            "Are you sure you want to lose your changes?");
 
	   
 
			ResponseType resp = (ResponseType)md.Run();
 
			md.Destroy();
 
			if (resp != ResponseType.Ok)
 
			{
 
				return;	
 
			}
 
		}
 
		
 
		if (NewProfile())
 
		{
 
			profile.Load();
 
			bool ok = profile.Load();
 
            if (ok)
 
            {
 
			PopulateDropDowns();
 
            recipe.Reactions = profile.Reactions;
 
		}
 
            else
 
            {
 
                MessageDialog md = new MessageDialog(this, 
 
                    DialogFlags.DestroyWithParent,
 
                    MessageType.Warning, ButtonsType.OkCancel, 
 
                    "Failed to load profile: " + profile.LastError);
 
                md.Run();
 
                md.Destroy();
 
            }
 
		}
 
	}
 
	
 
	protected virtual void OnOpenProfile(object sender, System.EventArgs e)
 
	{
 
		bool profileSelected = false;
 
		SelectProfileDialog selectProfileDialog = new SelectProfileDialog();
 
		selectProfileDialog.ProfileList = profileList;
 
		ResponseType resp = (ResponseType)selectProfileDialog.Run();
 
		selectProfileDialog.Destroy();
 
		if (resp == ResponseType.Ok) // Selected a profile.
 
		{
 
			SetProfileName(selectProfileDialog.SelectedProfile);
 
			profileSelected = true;
 
		}
 
		else if (resp == ResponseType.Accept) // New profile.
 
		{
 
			profileSelected = NewProfile();
 
		}
 
		if (profileSelected)
 
		{
 
			profile.Load();
 
			bool ok = profile.Load();
 
            if (ok)
 
            {
 
			PopulateDropDowns();
 
		}
 
            else
 
            {
 
                MessageDialog md = new MessageDialog(this, 
 
                    DialogFlags.DestroyWithParent,
 
                    MessageType.Warning, ButtonsType.OkCancel, 
 
                    "Failed to load profile: " + profile.LastError);
 
                md.Run();
 
                md.Destroy();
 
            }
 
		}
 
	}
 
	
 
	protected virtual void OnAbout(object sender, System.EventArgs e)
 
	{
 
		AboutDialog aboutDialog = new AboutDialog();
 

	
 
        aboutDialog.ProgramName = "Desert Paint Lab";
 
        aboutDialog.Version = "0.0.1";
 
        aboutDialog.Version = APP_VERSION ;
 
        aboutDialog.Comments = "Desert Paint Lab paint reaction recorder for A Tale in the Desert";
 
        aboutDialog.Authors = new string [] {"Tess Snider", "Jason Maltzen"};
 
        //aboutDialog.Website = "http://www.google.com/";
 
		aboutDialog.Run();
 
		aboutDialog.Destroy();
 
	}
 
	
 
	protected virtual void OnMenuExit (object sender, System.EventArgs e)
 
	{
 
		if (ConfirmedExit())
 
		{
 
			Application.Quit();
...
 
@@ -858,20 +930,32 @@ public partial class MainWindow : Gtk.Wi
 
                resp = (ResponseType)md.Run();
 
                md.Destroy();
 
                if (resp == ResponseType.Ok)
 
                {
 
                    Directory.Delete(profile.Directory, true);
 
                    profile.Import(targetFile);
 
                }
 
            }
 
            else
 
            {
 
                profile.Import(targetFile);
 
            }
 
            profile.Load();
 
            bool ok = profile.Load();
 
            if (ok)
 
            {
 
            PopulateDropDowns();
 
            recipe.Reactions = profile.Reactions;
 
        }
 
            else
 
            {
 
                MessageDialog md = new MessageDialog(this, 
 
                    DialogFlags.DestroyWithParent,
 
                    MessageType.Warning, ButtonsType.OkCancel, 
 
                    "Failed to load imported profile: " + profile.LastError);
 
                md.Run();
 
                md.Destroy();
 
            }
 
        }
 
        fileDialog.Destroy();
 
    }
 
}
 

	
PaintRecipe.cs
Show inline comments
...
 
@@ -196,25 +196,28 @@ namespace DesertPaintLab
 
            reagents.Add(reagentName);
 
        }
 

	
 
        public void Clear()
 
        {
 
            reagents.Clear();
 
            recipe.Clear();
 
        }
 

	
 
        byte CalculateColor(int baseSum, uint pigmentCount, int reactSum)
 
        {
 
            // Changed to Math.Floor from Math.Round, since Round appears to be incorrect.
 
            return (byte)Math.Max(Math.Min(Math.Floor((((float)baseSum / (float)pigmentCount) + (float)reactSum)), 255), 0);
 
            return (byte)Math.Max(
 
                Math.Min(Math.Floor((((float)baseSum / (float)pigmentCount) + (float)reactSum)), 
 
                        255),
 
                 0);
 
        }
 

	
 
        // Compute the color including reactions based on the player's profile
 
        private void ComputeReactedColor()
 
        {
 
            RGB baseRGB;
 
            baseRGB.r = 0;
 
            baseRGB.g = 0;
 
            baseRGB.b = 0;
 
            RGB reactionColor;
 
            reactionColor.r = 0;
 
            reactionColor.g = 0;
PlayerProfile.cs
Show inline comments
...
 
@@ -11,24 +11,25 @@
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using Gtk;
 
using System;
 
using System.IO;
 
using System.IO.Compression;
 
using System.Collections.Generic;
 
using System.Text.RegularExpressions;
 

 
namespace DesertPaintLab
 
{
 
	public class PlayerProfile
 
	{
 
		string name;
 
		string directory;
...
 
@@ -44,24 +45,26 @@ namespace DesertPaintLab
 
		//	new SortedDictionary<string, SortedDictionary<string, Reaction>>();
 
        SortedDictionary<string, PaintRecipe> recipes;
 

 
        static PlayerProfile current = null;
 

 
        static PlayerProfile Current
 
        {
 
            get {
 
                return current;
 
            }
 
        }
 
		
 
        public string LastError { get; private set; }
 
		
 
		public PlayerProfile(string name, string directory)
 
		{
 
			this.name = name;
 
			this.directory = directory;
 
			this.reactFile = System.IO.Path.Combine(directory, "dp_reactions.txt");
 
            this.reagentFile = System.IO.Path.Combine(directory, "ingredients.txt");
 
            this.recipes = new SortedDictionary<string, PaintRecipe>();
 
            foreach (PaintColor color in Palette.Colors)
 
            {
 
                this.recipes.Add(color.Name, new PaintRecipe());
 
            }
 
		}
...
 
@@ -100,45 +103,53 @@ namespace DesertPaintLab
 
                int count = 0;
 
                foreach (PaintRecipe recipe in this.recipes.Values)
 
                {
 
                    if (recipe.IsValid)
 
                    {
 
                        ++count;
 
                    }
 
                }
 
                return count;
 
            }
 
        }
 
		
 
		public void Initialize()
 
		public bool Initialize()
 
		{
 
			// Create new directory.
 
			System.IO.Directory.CreateDirectory(directory);
 
				
 
			// Copy template files into new directory.
 
			string templatePath = FileUtils.FindApplicationResourceDirectory("template");
 
			
 
            if (!System.IO.Directory.Exists(templatePath))
 
            {
 
                LastError = "Failed to find profile template folder.";
 
                return false;
 
            }
 

 
			DirectoryInfo di = new DirectoryInfo(templatePath);
 
			FileInfo[] templateFiles = di.GetFiles();
 

 
			foreach (FileInfo file in templateFiles)
 
			{
 
				System.IO.File.Copy(file.FullName,
 
					System.IO.Path.Combine(directory, file.Name), true);					
 
                string destFile = System.IO.Path.Combine(directory, file.Name);
 
				System.IO.File.Copy(file.FullName, destFile, true);
 
                if (!File.Exists(destFile))
 
                {
 
                    LastError = "Failed to copy template file " + file.Name + ".";
 
                    return false;
 
			}
 
		}
 
            return true;
 
		}
 
		
 
		public void ConvertFromPP(string ppFile, string dpFile)
 
		{
 
			string line;
 
			using (StreamReader reader = new StreamReader(ppFile))
 
			{
 
				using (StreamWriter writer = new StreamWriter(dpFile))
 
				{
 
					while ((line = reader.ReadLine()) != null) 
 
                	{
 
						string[] tokens = line.Split(null);
 
						if ((tokens.Length > 0) && (tokens[0] != "//"))
...
 
@@ -282,40 +293,54 @@ namespace DesertPaintLab
 
		}
 
		
 
        public void Import(string file)
 
        {
 
            ZipFile.ExtractToDirectory(file, directory);
 
        }
 

 
		public void Export(string file)
 
		{
 
            ZipFile.CreateFromDirectory(directory, file);
 
		}
 
		
 
		public void Load()
 
		public bool Load()
 
		{
 
			string line;
 
			reactions.Clear();
 
            if (File.Exists(reagentFile))
 
            {
 
			ReagentManager.LoadProfileReagents(reagentFile);
 
            }
 
            else
 
            {
 
                LastError = "Failed to find profile reagents file.";
 
                return false;
 
            }
 
			ReagentManager.InitializeReactions(ref reactions);
 
            if (!File.Exists(reactFile))
 
            {
 
                LastError = "Failed to find profile reactions file.";
 
                return false;
 
            }
 
			using (StreamReader reader = new StreamReader(reactFile))
 
			{
 
				while ((line = reader.ReadLine()) != null) 
 
               	{
 
					string[] tokens = line.Split(null);
 
                    Reagent reagent1 = ReagentManager.GetReagent(tokens[0]);
 
                    Reagent reagent2 = ReagentManager.GetReagent(tokens[1]);
 
					reactions.Set(reagent1, reagent2, new Reaction(int.Parse(tokens[2]), int.Parse(tokens[3]), int.Parse(tokens[4])));
 
				}
 
			}
 
            return true;
 
		}
 
		
 
		public void Save()
 
		{
 
			Reaction reaction;
 
			using (StreamWriter writer = new StreamWriter(reactFile, false))
 
			{
 
                foreach (string reagentName1 in ReagentManager.Names)
 
                {
 
                    // TODO: could be more efficient by only iterating over the names after reagent1
 
                    foreach (string reagentName2 in ReagentManager.Names)
 
                    {
RecipeGenerator.cs
Show inline comments
...
 
@@ -57,24 +57,25 @@ namespace DesertPaintLab
 

	
 
    public class RecipeGenerator
 
    {
 
        public enum SearchType {
 
            DEPTH_FIRST,
 
            BREADTH_FIRST
 
        };
 

	
 
        public SearchType Mode { get; set; }
 

	
 
        public uint MaxQuantity { get; private set; } // maximum number of total ingredients
 
        public uint MaxReagents { get; private set; } // maximum number of reagents to use in the recipe
 
        public uint MinReagents { get; private set; } // minimum number of reagents to use in the recipe
 
        public uint FullQuantityDepth { get; private set; } // at or equal this number of reagents, ignore ingredient settings for max quantity
 
        public uint FullQuantity { get; private set; }  // The max number of a reagent to use at full quantity
 

	
 
        ReactionSet reactions;
 
        bool running = false;
 

	
 
        int runningThreads = 0;
 
        
 
        SortedDictionary<string, uint> recipeCosts = new SortedDictionary<string, uint>();
 
        SortedDictionary<string, PaintRecipe> recipes = new SortedDictionary<string, PaintRecipe>();
 

	
 
        uint totalReagents;
...
 
@@ -97,24 +98,27 @@ namespace DesertPaintLab
 
        public event EventHandler Progress;
 
        public event EventHandler<NewRecipeEventArgs> NewRecipe;
 

	
 
        public RecipeGenerator(ReactionSet reactions)
 
        {
 
            Mode = SearchType.BREADTH_FIRST;
 
            this.reactions = reactions;
 
            foreach (PaintColor color in Palette.Colors)
 
            {
 
                recipes.Add(color.Name, new PaintRecipe());
 
                recipeCosts.Add(color.Name, uint.MaxValue);
 
            }
 
            MinReagents = 1;
 
            MaxReagents = 5;
 
            MaxQuantity = 20;
 
        }
 

	
 
        public SortedDictionary<string, PaintRecipe> Recipes
 
        {
 
            get
 
            {
 
                return recipes;
 
            }
 
        }
 

	
 
        public ulong RecipeCount
 
        {
...
 
@@ -170,33 +174,34 @@ namespace DesertPaintLab
 

	
 
        private void InitSortedReagents()
 
        {
 
            costSortedReagents.Clear();
 
            foreach (string name in ReagentManager.Names)
 
            {
 
                Reagent reagent = ReagentManager.GetReagent(name);
 
                costSortedReagents.Add(reagent);
 
            }
 
            costSortedReagents.Sort(new ReagentCostSort());
 
        }
 

	
 
        public void BeginRecipeGeneration(uint maxQuantity, uint maxReagents, uint fullQuantityDepth, uint fullQuantity)
 
        public void BeginRecipeGeneration(uint maxQuantity, uint minReagents, uint maxReagents, uint fullQuantityDepth, uint fullQuantity)
 
        {
 
            if (running)
 
            {
 
                // Already running - don't start again
 
                return;
 
            }
 

	
 
            this.MaxQuantity = maxQuantity;
 
            this.MinReagents = minReagents;
 
            this.MaxReagents = maxReagents;
 
            this.FullQuantity = fullQuantity;
 
            this.FullQuantityDepth = fullQuantityDepth;
 

	
 
            // first, sort reagents by cost.
 
            InitSortedReagents();
 

	
 
            totalReagents = (uint)costSortedReagents.Count;
 

	
 
            // Pre-populate recipes list with:
 
            // 1) 1-ingredient recipes @ 10db for all enabled ingredients with a count >= 10
 
            // 2) any previously-generated recipes
...
 
@@ -208,48 +213,50 @@ namespace DesertPaintLab
 
                if (reagent.Enabled)
 
                {
 
                    if (!reagent.IsCatalyst && ((reagent.RecipeMax >= 10) || ((FullQuantityDepth > 0) && (FullQuantity >= 10))))
 
                    {
 
                        recipe.Clear();
 
                        recipe.AddReagent(reagent.Name, 10);
 
                        AddCheapestRecipe(recipe);
 
                    }
 
                    ++enabledReagentCount;
 
                }
 
            }
 
            this.MaxReagents = (uint)Math.Min(enabledReagentCount, this.MaxReagents);
 
            this.MinReagents = (uint)Math.Min(this.MinReagents, this.MaxReagents);
 

	
 
            while (!searchQueue.IsEmpty)
 
            {
 
                RecipeSearchNode node;
 
                searchQueue.TryDequeue(out node);
 
            }
 
            for (uint reagentIdx = 0; reagentIdx < costSortedReagents.Count; ++reagentIdx)
 
            {
 
                if (costSortedReagents[(int)reagentIdx].Enabled)
 
                {
 
                    RecipeSearchNode initialNode = new RecipeSearchNode(costSortedReagents, reagentIdx);
 
                    initialNode.FullQuantity = FullQuantity;
 
                    initialNode.FullQuantityDepth = FullQuantityDepth;
 
                    initialNode.MaxQuantity = maxQuantity;
 
                    initialNode.MinReagents = minReagents;
 
                    initialNode.MaxReagents = maxReagents;
 
                    searchQueue.Enqueue(initialNode);
 
                }
 
            }
 

	
 
            recipeCount = 0;
 

	
 
            if (log != null)
 
            {
 
                log.WriteLine("Begin recipe generation: MaxQuantity={0} MaxReagents={1} FullQuantity={2} FullQuantityDepth={3}", MaxQuantity, MaxReagents, FullQuantity, FullQuantityDepth);
 
                log.WriteLine("Begin recipe generation: MaxQuantity={0} MinReagents={1} MaxReagents={2} FullQuantity={3} FullQuantityDepth={4}", MaxQuantity, MinReagents, MaxReagents, FullQuantity, FullQuantityDepth);
 
            }
 
            
 
            // start worker threads to do the actual work
 
            ResumeRecipeGeneration();
 
        }
 

	
 
        public void ResumeRecipeGeneration()
 
        {
 
            if (running)
 
            {
 
                // Already running - don't start again
 
                return;
...
 
@@ -284,24 +291,25 @@ namespace DesertPaintLab
 
        }
 

	
 
        public bool SaveState(string file)
 
        {
 
            if (running)
 
            {
 
                // can't save state while running
 
                return false;
 
            }
 

	
 
            using (StreamWriter writer = new StreamWriter(file, false))
 
            {
 
                writer.WriteLine("MinReagents: {0}", MinReagents);
 
                writer.WriteLine("MaxReagents: {0}", MaxReagents);
 
                writer.WriteLine("FullQuantityDepth: {0}", FullQuantityDepth);
 
                writer.WriteLine("FullQuantity: {0}", FullQuantity);
 
                writer.WriteLine("TotalReagents: {0}", totalReagents);
 
                writer.WriteLine("RecipeCount: {0}", recipeCount);
 
                writer.WriteLine("SearchType: {0}", Mode.ToString());
 
                foreach (KeyValuePair<string, PaintRecipe> pair in recipes)
 
                {
 
                    PaintRecipe recipe = pair.Value;
 
                    string colorName = Palette.FindNearest(recipe.ReactedColor);
 
                    writer.WriteLine("BeginRecipe: {0}", colorName);
 
                    foreach (PaintRecipe.RecipeIngredient ingredient in recipe.Ingredients)
...
 
@@ -336,26 +344,31 @@ namespace DesertPaintLab
 
            Match match;
 
            string line;
 
            using (StreamReader reader = new StreamReader(file, false))
 
            {
 
                while (success && ((line = reader.ReadLine()) != null))
 
                {
 
                    match = keyValueRegex.Match(line);
 
                    if (match.Success)
 
                    {
 
                        string value = match.Groups["value"].Value;
 
                        switch(match.Groups["key"].Value)
 
                        {
 
                            case "MinReagents":
 
                                MinReagents = uint.Parse(value);
 
                                MaxReagents = (uint)Math.Max(this.MinReagents, this.MaxReagents);
 
                                break;
 
                            case "MaxReagents":
 
                                MaxReagents = uint.Parse(value);
 
                                MinReagents = (uint)Math.Min(this.MinReagents, this.MaxReagents);
 
                                break;
 
                            case "FullQuantityDepth":
 
                                FullQuantityDepth = uint.Parse(value);
 
                                break;
 
                            case "FullQuantity":
 
                                FullQuantity = uint.Parse(value);
 
                                break;
 
                            case "TotalReagents":
 
                                totalReagents = uint.Parse(value);
 
                                break;
 
                            case "RecipeCount":
 
                                if (!ulong.TryParse(value, out recipeCount))
...
 
@@ -392,24 +405,25 @@ namespace DesertPaintLab
 
                                    {
 
                                        success = false;
 
                                    }
 
                                }
 
                                break;
 
                            case "SearchNodes":
 
                                int nodeCount = int.Parse(match.Groups["value"].Value);
 
                                for (int i = 0; i < nodeCount; ++i)
 
                                {
 
                                    RecipeSearchNode node = new RecipeSearchNode(costSortedReagents);
 
                                    node.FullQuantity = FullQuantity;
 
                                    node.FullQuantityDepth = FullQuantityDepth;
 
                                    node.MinReagents = MinReagents;
 
                                    node.MaxReagents = MaxReagents;
 
                                    node.MaxQuantity = MaxQuantity;
 
                                    success = success && node.LoadState(reader);
 
                                    if (success)
 
                                    {
 
                                        searchQueue.Enqueue(node);
 
                                    }
 
                                }
 
                                break;
 
                            case "SearchType":
 
                                Mode = (SearchType)Enum.Parse(typeof(SearchType), match.Groups["value"].Value);
 
                                break;
...
 
@@ -581,44 +595,44 @@ namespace DesertPaintLab
 
            if (NextRecipeSize(node))
 
            {
 
                //System.Console.WriteLine("Found next recipe size {0}", node.CurrentTargetQuantity);
 
                return true;
 
            }
 

	
 
            // Search for next ingredient combo - all quantity combos for previous were searched
 
            //System.Console.WriteLine("Finding next ingredient combo");
 
            do
 
            {
 
                if (!node.AddNextReagent())
 
                {
 
                    while ((node.ReagentCount > node.InitialCount) && (node.LastReagent == (totalReagents-1)))
 
                    while ((node.ReagentCount > node.MinReagents) && (node.LastReagent == (totalReagents-1)))
 
                    {
 
                        node.RemoveLastReagent();
 
                    }
 
                    if (node.ReagentCount == node.InitialCount)
 
                    if (node.ReagentCount == node.MinReagents)
 
                    {
 
                        // done
 
                        return false;
 
                    }
 
                    uint nextReagent = node.NextFreeReagent(node.LastReagent);
 
                    while ((node.ReagentCount > node.InitialCount) && (nextReagent >= totalReagents))
 
                    while ((node.ReagentCount > node.MinReagents) && (nextReagent >= totalReagents))
 
                    {
 
                        // No more reagents to try at this level
 
                        node.RemoveLastReagent();
 
                        if (node.ReagentCount > node.InitialCount)
 
                        if (node.ReagentCount > node.MinReagents)
 
                        {
 
                            nextReagent = node.NextFreeReagent(node.LastReagent);
 
                        }
 
                    }
 
                    if (node.ReagentCount == node.InitialCount)
 
                    if (node.ReagentCount == node.MinReagents)
 
                    {
 
                        // done
 
                        return false;
 
                    }
 
                    node.ReplaceLastReagent(nextReagent);
 
                }
 
            } while (node.MaxQuantity < (10 + node.CatalystCount));
 
            node.InitForQuantity(node.MaxQuantity);
 

	
 
            //string outStr = "{0} : {1} : ";
 
            //for (int i = 0; i < currentReagents.Count; ++i)
 
            //{
...
 
@@ -672,78 +686,78 @@ namespace DesertPaintLab
 
            // next reagent in last position
 
            // if at end, pop reagent
 
            //Console.WriteLine("Finding new recipe after quantity {0}/{1} used {2}", newQuantity, node.MaxQuantity, node.UsedQuantity);
 
            node.InitForQuantity(10+node.CatalystCount); // reset quantity
 
            int currentDepth = node.ReagentCount;
 
            bool recipeFound = false;
 
            uint nextReagent;
 
            do {
 
                //Console.WriteLine("Current depth: {0}/{1}", currentDepth, node.MaxReagents);
 
                do {
 
                    recipeFound = false;
 
                    // back out until we find a node that can be incremented
 
                    if (currentDepth > node.InitialCount)
 
                    if (currentDepth > node.MinReagents)
 
                    {
 
                        while (node.ReagentCount > node.InitialCount)
 
                        while (node.ReagentCount > node.MinReagents)
 
                        {
 
                            if (node.LastReagent < (totalReagents - 1))
 
                            {
 
                                nextReagent = node.NextFreeReagent(node.LastReagent);
 
                                if (nextReagent < totalReagents)
 
                                {
 
                                    //Console.WriteLine("Replace last reagent with {0}", nextReagent);
 
                                    node.ReplaceLastReagent(nextReagent);
 
                                    break;
 
                                }
 
                                else
 
                                {
 
                                    // shouldn't happen
 
                                    //Console.WriteLine("No available reagents at depth {0}!", node.ReagentCount);
 
                                    node.RemoveLastReagent();
 
                                    if (node.ReagentCount == node.InitialCount)
 
                                    if (node.ReagentCount == node.MinReagents)
 
                                    {
 
                                        // just popped the last reagent at the top level
 
                                        ++currentDepth;
 
                                        if (log != null) { lock(log) { log.WriteLine("Increased depth to {0}/{1}", currentDepth, node.MaxReagents); } }
 
                                    }
 
                                }
 
                            }
 
                            else
 
                            {
 
                                //Console.WriteLine("Pop last reagent");
 
                                node.RemoveLastReagent();
 
                                if (node.ReagentCount == node.InitialCount)
 
                                if (node.ReagentCount == node.MinReagents)
 
                                {
 
                                    // just popped the last reagent at the top level
 
                                    ++currentDepth;
 
                                    if (log != null) { lock(log) { log.WriteLine("Increased depth to {0}/{1} [pop last reagent at top level]", currentDepth, node.MaxReagents); } }
 
                                }
 
                            }
 
                        }
 
                        // fill in the nodes up to the current depth
 
                        if (node.ReagentCount >= node.InitialCount)
 
                        if (node.ReagentCount >= node.MinReagents)
 
                        {
 
                            recipeFound = true;
 
                            while (node.ReagentCount < currentDepth)
 
                            {
 
                                if (! node.AddNextReagent())
 
                                {
 
                                    if (log != null) { lock(log) { log.WriteLine("Failed to reagent {0}/{1}", node.ReagentCount+1, currentDepth); } }
 
                                    recipeFound = false;
 
                                }
 
                            }
 
                        }
 
                    }
 
                    //Console.WriteLine("Catalysts: {0} Reagents: {1} Initial: {2}", node.CatalystCount, node.ReagentCount, node.InitialCount);
 
                } while ((node.CatalystCount >= node.ReagentCount) && (node.ReagentCount >= node.InitialCount)); // make sure to skip all-catalyst combinations
 
                    //Console.WriteLine("Catalysts: {0} Reagents: {1} Min: {2}", node.CatalystCount, node.ReagentCount, node.MinReagents);
 
                } while ((node.CatalystCount >= node.ReagentCount) && (node.ReagentCount >= node.MinReagents)); // make sure to skip all-catalyst combinations
 
                if (recipeFound)
 
                {
 
                    break;
 
                }
 
                else
 
                {
 
                    ++currentDepth;
 
                    if (log != null) { lock(log) { log.WriteLine("Increased depth to {0}/{1} [no recipe]", currentDepth, node.MaxReagents); } }
 
                }
 
            } while (currentDepth <= node.MaxReagents);
 
            if (recipeFound)
 
            {
RecipeGeneratorWindow.cs
Show inline comments
...
 
@@ -60,31 +60,33 @@ namespace DesertPaintLab
 
        Gtk.ThreadNotify notifyProgress;
 
        Gtk.ThreadNotify notifyNewRecipe;
 

	
 
        ConcurrentQueue<PaintRecipe> pendingNewRecipes = new ConcurrentQueue<PaintRecipe>();
 

	
 
        Gtk.ListStore reagentListStore;
 
        // end reagent view
 

	
 
        public RecipeGeneratorWindow(PlayerProfile profile) : base(Gtk.WindowType.Toplevel)
 
        {
 
            this.profile = profile;
 
            this.Build();
 
            minIngredientsSpinButton.Value = 1; // TODO: read/save profile info
 
            maxIngredientsSpinButton.Value = 5; // TODO: read/save profile info
 
            maxRecipeSpinButton.Value = 20; // TODO: read/save profile info
 
            fullQuantitySpinButton.Value = 20; // TODO: read/save profile info
 
            fullQuantityDepthSpinButton.Value = 4; // TODO: read/save profile info
 

	
 
            fullQuantityDepthSpinButton.SetRange(0, ReagentManager.Names.Count);
 
            maxIngredientsSpinButton.SetRange(0, ReagentManager.Names.Count);
 
            maxIngredientsSpinButton.SetRange(1, ReagentManager.Names.Count);
 
            minIngredientsSpinButton.SetRange(1, ReagentManager.Names.Count);
 

	
 

	
 
            Gtk.TreeViewColumn recipeColorColumn = new Gtk.TreeViewColumn();
 
            Gtk.CellRendererText recipeColumnCell = new Gtk.CellRendererText();
 
            recipeColorColumn.PackStart(recipeColumnCell, true);       
 
            recipeColorColumn.Title = "Color";
 

	
 
            recipeList.AppendColumn(recipeColorColumn);
 
            recipeColorColumn.AddAttribute(recipeColumnCell, "text", 0);
 

	
 
            colorStore.Clear();
 

	
...
 
@@ -203,50 +205,67 @@ namespace DesertPaintLab
 
            reagentListView.Sensitive = true;
 

	
 
            reagentListView.AppendColumn(reagentEnabledColumn);
 
            reagentListView.AppendColumn(reagentNameColumn);
 
            reagentListView.AppendColumn(reagentCostColumn);
 
            reagentListView.AppendColumn(reagentMaxColumn);
 

	
 
            reagentListView.
 
            
 
            ShowAll();
 
        }
 

	
 
        protected void OnMinIngredientsChanged(object sender, EventArgs e)
 
        {
 
            Gtk.SpinButton button = (Gtk.SpinButton) sender;
 
            if (button.ValueAsInt > maxIngredientsSpinButton.ValueAsInt)
 
            {
 
                maxIngredientsSpinButton.Value = button.ValueAsInt;
 
            }
 
            maxIngredientsSpinButton.SetRange(button.ValueAsInt, maxIngredientsSpinButton.Adjustment.Upper);
 
        }
 

	
 
        protected void OnMaxIngredientsChanged(object sender, EventArgs e)
 
        {
 
            Gtk.SpinButton button = (Gtk.SpinButton) sender;
 
            if (button.ValueAsInt < minIngredientsSpinButton.ValueAsInt)
 
            {
 
                minIngredientsSpinButton.Value = button.ValueAsInt;
 
            }
 
            minIngredientsSpinButton.SetRange(1, button.ValueAsInt);
 
            // TODO: save profile setting
 
            // TODO: no longer permit resume
 
        }
 

	
 
        protected void OnMaxRecipeChanged(object sender, EventArgs e)
 
        {
 
            // TODO: save profile setting
 
            // TODO: no longer permit resume
 
        }
 

	
 
        protected void OnFullQuantityDepthChanged(object sender, EventArgs e)
 
        {
 
            // TODO: save profile setting
 
            // TODO: no longer permit resume
 
        }
 

	
 
        protected void OnFullQuantityChanged(object sender, EventArgs e)
 
        {
 
            // TODO: save profile setting
 
            // TODO: no longer permit resume
 
        }
 

	
 
        protected void OnBegin(object sender, EventArgs e)
 
        {
 
            minIngredientsSpinButton.Sensitive = false;
 
            maxIngredientsSpinButton.Sensitive = false;
 
            ExportToWikiAction.Sensitive = false;
 
            IngredientsAction.Sensitive = false;
 
            maxRecipeSpinButton.Sensitive = false;
 
            beginButton.Sensitive = false; // TODO: change to "pause"?
 
            stopResumeButton.Sensitive = true;
 
            fullQuantitySpinButton.Sensitive = false;
 
            fullQuantityDepthSpinButton.Sensitive = false;
 
            reagentListView.Sensitive = false;
 

	
 
            countLabel.Text = String.Format("{0} / {1}", profile.RecipeCount, Palette.Count);
 

	
...
 
@@ -267,43 +286,44 @@ namespace DesertPaintLab
 

	
 
            lastProgressUpdate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
 
            lastStatusUpdate = lastProgressUpdate;
 

	
 
            lastProfileSave = lastProgressUpdate;
 
            lastCheckpoint = lastProgressUpdate;
 

	
 
            running = true;
 
            canceling = false;
 
            pauseForCheckpoint = false;
 
            stopResumeButton.Label = "Pause";
 

	
 
            generator.BeginRecipeGeneration((uint)maxRecipeSpinButton.ValueAsInt, (uint)maxIngredientsSpinButton.ValueAsInt, (uint)fullQuantityDepthSpinButton.ValueAsInt, (uint)fullQuantitySpinButton.ValueAsInt);
 
            generator.BeginRecipeGeneration((uint)maxRecipeSpinButton.ValueAsInt, (uint)minIngredientsSpinButton.Value, (uint)maxIngredientsSpinButton.ValueAsInt, (uint)fullQuantityDepthSpinButton.ValueAsInt, (uint)fullQuantitySpinButton.ValueAsInt);
 
        }
 

	
 
        protected void OnStopResume(object sender, EventArgs e)
 
        {
 
            if (generator != null)
 
            {
 
                if (running)
 
                {
 
                    canceling = true;
 
                    pauseForCheckpoint = false;
 
                    generator.Stop();
 
                }
 
                else
 
                {
 
                    // Resume previous run
 
                    ExportToWikiAction.Sensitive = false;
 
                    IngredientsAction.Sensitive = false;
 
                    reagentListView.Sensitive = false;
 
                    minIngredientsSpinButton.Sensitive = false;
 
                    maxIngredientsSpinButton.Sensitive = false;
 
                    maxRecipeSpinButton.Sensitive = false;
 
                    beginButton.Sensitive = false;
 
                    stopResumeButton.Sensitive = true;
 
                    fullQuantitySpinButton.Sensitive = false;
 
                    fullQuantityDepthSpinButton.Sensitive = false;
 
                    reagentListView.Sensitive = false;
 

	
 
                    lastProgressUpdate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
 
                    lastStatusUpdate = lastProgressUpdate;
 
                    lastProfileSave = lastProgressUpdate;
 
                    lastCheckpoint = lastProgressUpdate;
...
 
@@ -325,24 +345,25 @@ namespace DesertPaintLab
 
            {
 
                pauseForCheckpoint = false;
 
                generator.SaveState(System.IO.Path.Combine(profile.Directory, STATE_FILE));
 
                generator.ResumeRecipeGeneration();
 
            }
 
            else
 
            {
 
                running = false;
 
                beginButton.Sensitive = true;
 
                ExportToWikiAction.Sensitive = true;
 
                IngredientsAction.Sensitive = true;
 
                stopResumeButton.Sensitive = false;
 
                minIngredientsSpinButton.Sensitive = true;
 
                maxIngredientsSpinButton.Sensitive = true;
 
                maxRecipeSpinButton.Sensitive = true;
 
                fullQuantitySpinButton.Sensitive = true;
 
                fullQuantityDepthSpinButton.Sensitive = true;
 
                reagentListView.Sensitive = true;
 
                //generator = null; // don't. Hang on to generator for resume.
 
                profile.SaveRecipes();
 
                if (canceling)
 
                {
 
                    generator.SaveState(System.IO.Path.Combine(profile.Directory, STATE_FILE));
 
                    stopResumeButton.Label = "Resume";
 
                    stopResumeButton.Sensitive = true;
RecipeSearchNode.cs
Show inline comments
...
 
@@ -54,31 +54,31 @@ namespace DesertPaintLab
 
        public PaintRecipe TestRecipe
 
        {
 
            get
 
            {
 
                return testRecipe;
 
            }
 
            set
 
            {
 
                testRecipe = value;
 
            }
 
        }
 

	
 
        public int InitialCount { get; private set; }
 
        public uint CurrentTargetQuantity { get; set; }
 
        public uint MaxQuantity { get; set; }
 
        public uint UsedQuantity { get; private set; }
 
        public uint CatalystCount { get; set; }
 
        public uint FullQuantityDepth { get; set; }
 
        public uint FullQuantity { get; set; }
 
        public uint MinReagents { get; set; }
 

	
 
        uint maxReagents;
 
        public uint MaxReagents
 
        {
 
            get
 
            {
 
                return maxReagents;
 
            }
 
            set
 
            {
 
                maxReagents = value;
 
                currentWeights = new uint[maxReagents];
...
 
@@ -115,69 +115,69 @@ namespace DesertPaintLab
 
            reagentInUse = new bool[costSortedReagents.Count];
 
            for (uint reagentIdx = 0; reagentIdx < costSortedReagents.Count; ++reagentIdx)
 
            {
 
                reagentInUse[reagentIdx] = false;
 
            }
 
            foreach (uint reagentIdx in this.reagents)
 
            {
 
                if (reagentIdx != INVALID_REAGENT)
 
                {
 
                    reagentInUse[reagentIdx] = true;
 
                }
 
            }
 
            InitialCount = nextReagentPos;
 
            MinReagents = (uint)nextReagentPos;
 
            MaxReagents = (uint)nextReagentPos; // better set this later!
 
            UsedQuantity = 0;
 
        }
 

	
 
        // top-level search
 
        public RecipeSearchNode(List<Reagent> costSortedReagents, uint startReagent)
 
        {
 
            this.costSortedReagents = new List<Reagent>(costSortedReagents);
 
            this.reagents = new uint[costSortedReagents.Count];
 
            INVALID_REAGENT = (uint)costSortedReagents.Count;
 
            nextReagentPos = 0;
 
            for (int i = 0; i < reagents.Length; ++i)
 
            {
 
                this.reagents[i] = INVALID_REAGENT;
 
            }
 
            reagentInUse = new bool[costSortedReagents.Count];
 
            for (uint reagentIdx = 0; reagentIdx < costSortedReagents.Count; ++reagentIdx)
 
            {
 
                reagentInUse[reagentIdx] = false;
 
            }
 
            this.reagents[nextReagentPos++] = NextFreeReagent(startReagent);
 
            //Console.WriteLine("Added reagent {0} at pos {1}", this.reagents[nextReagentPos-1], nextReagentPos-1);
 
            InitialCount = 1; // don't iterate up beyond the start reagent
 
            MinReagents = 1; // don't iterate up beyond the start reagent
 
            MaxReagents = 1;
 
            UsedQuantity = 0;
 
        }
 

	
 
        public RecipeSearchNode(List<Reagent> costSortedReagents)
 
        {
 
            this.costSortedReagents = costSortedReagents;
 
            this.reagents = new uint[costSortedReagents.Count];
 
            INVALID_REAGENT = (uint)costSortedReagents.Count;
 
            nextReagentPos = 0;
 
            for (int i = 0; i < reagents.Length; ++i)
 
            {
 
                this.reagents[i] = INVALID_REAGENT;
 
            }
 
            reagentInUse = new bool[costSortedReagents.Count];
 
            for (uint reagentIdx = 0; reagentIdx < costSortedReagents.Count; ++reagentIdx)
 
            {
 
                reagentInUse[reagentIdx] = false;
 
            }
 
            this.reagents[nextReagentPos++] = NextFreeReagent(0);
 
            InitialCount = 0;
 
            MinReagents = 0;
 
            MaxReagents = 1;
 
            UsedQuantity = 0;
 
        }
 

	
 
        public Reagent Reagent(int idx)
 
        {
 
            return costSortedReagents[(int)reagents[idx]];
 
        }
 

	
 
        public uint LastReagent
 
        {
 
            get
...
 
@@ -291,39 +291,39 @@ namespace DesertPaintLab
 
        }
 

	
 
        public void SetWeight(int idx, uint quantity)
 
        {
 
            UsedQuantity -= currentWeights[idx];
 
            currentWeights[idx] = quantity;
 
            UsedQuantity += quantity;
 
        }
 

	
 
        public void SaveState(StreamWriter writer)
 
        {
 
            writer.WriteLine("---SearchNode---");
 
            writer.WriteLine("MinReagents: {0}", MinReagents);
 
            writer.WriteLine("MaxReagents: {0}", MaxReagents);
 
            writer.WriteLine("Reagents: {0}", nextReagentPos);
 
            for (int i = 0; i < nextReagentPos; ++i)
 
            {
 
                uint idx = reagents[i];
 
                uint weight = currentWeights[i];
 
                writer.WriteLine("Reagent: {0},{1},{2}", idx, reagentInUse[idx] ? 1 : 0, weight);
 
            }
 
            // pulled from parent: List<Reagent> costSortedReagents;
 
            // new on construct: PaintRecipe testRecipe = null;
 
            writer.WriteLine("CurrentTargetQuantity: {0}", CurrentTargetQuantity);
 
            writer.WriteLine("MaxQuantity: {0}", MaxQuantity);
 
            writer.WriteLine("UsedQuantity: {0}", UsedQuantity);
 
            writer.WriteLine("CatalystCount: {0}", CatalystCount);
 
            writer.WriteLine("InitialCount: {0}", InitialCount);
 
            writer.WriteLine("FullQuantity: {0}", FullQuantity);
 
            writer.WriteLine("FullQuantityDepth: {0}", FullQuantityDepth);
 
            writer.WriteLine("---EndNode---");
 
            
 
        }
 

	
 
        static Regex keyValueRegex = new Regex(@"(\w+)\:\s*(.*)\s*$");
 
        static Regex reagentPartsRegex = new Regex(@"(?<id>\d+),(?<inUse>\d+),(?<weight>\d+)");
 
        public bool LoadState(StreamReader reader)
 
        {
 
            string line = reader.ReadLine();
 
            if (!line.Equals("---SearchNode---"))
...
 
@@ -383,46 +383,52 @@ namespace DesertPaintLab
 
                        case "CurrentTargetQuantity":
 
                            {
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                CurrentTargetQuantity = value;
 
                            }
 
                            break;
 
                        case "MaxQuantity":
 
                            {
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                MaxQuantity = value;
 
                            }
 
                            break;
 
                        case "MinReagents":
 
                            {
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                MinReagents = value;
 
                            }
 
                            break;
 
                        case "MaxReagents":
 
                            {
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                MaxReagents = value;
 
                            }
 
                            break;
 
                        case "UsedQuantity":
 
                            {
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                UsedQuantity = value;
 
                            }
 
                            break;
 
                        case "CatalystCount":
 
                            {
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                CatalystCount = value;
 
                            }
 
                            break;
 
                        case "InitialCount":
 
                            {
 
                                int value = int.Parse(match.Groups[2].Value);
 
                                InitialCount = value;
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                MinReagents = value;
 
                            }
 
                            break;
 
                        case "FullQuantity":
 
                            {
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                FullQuantity = value;
 
                            }
 
                            break;
 
                        case "FullQuantityDepth":
 
                            {
 
                                uint value = uint.Parse(match.Groups[2].Value);
 
                                FullQuantityDepth = value;
gtk-gui/DesertPaintLab.RecipeGeneratorWindow.cs
Show inline comments
...
 
@@ -17,24 +17,30 @@ namespace DesertPaintLab
 
		private global::Gtk.Action CopyToClipboardAction;
 
		
 
		private global::Gtk.VBox vbox2;
 
		
 
		private global::Gtk.MenuBar menubar1;
 
		
 
		private global::Gtk.HBox hbox1;
 
		
 
		private global::Gtk.VBox vbox8;
 
		
 
		private global::Gtk.HBox hbox2;
 
		
 
		private global::Gtk.SpinButton minIngredientsSpinButton;
 
		
 
		private global::Gtk.Label label1;
 
		
 
		private global::Gtk.HBox hbox7;
 
		
 
		private global::Gtk.SpinButton maxIngredientsSpinButton;
 
		
 
		private global::Gtk.Label label3;
 
		
 
		private global::Gtk.HSeparator hseparator3;
 
		
 
		private global::Gtk.HBox hbox4;
 
		
 
		private global::Gtk.SpinButton maxRecipeSpinButton;
 
		
 
		private global::Gtk.Label label4;
 
		
...
 
@@ -144,166 +150,201 @@ namespace DesertPaintLab
 
			this.hbox1 = new global::Gtk.HBox ();
 
			this.hbox1.Name = "hbox1";
 
			this.hbox1.Spacing = 6;
 
			// Container child hbox1.Gtk.Box+BoxChild
 
			this.vbox8 = new global::Gtk.VBox ();
 
			this.vbox8.Name = "vbox8";
 
			this.vbox8.Spacing = 6;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hbox2 = new global::Gtk.HBox ();
 
			this.hbox2.Name = "hbox2";
 
			this.hbox2.Spacing = 6;
 
			// Container child hbox2.Gtk.Box+BoxChild
 
			this.maxIngredientsSpinButton = new global::Gtk.SpinButton (0, 14, 1);
 
			this.maxIngredientsSpinButton.CanFocus = true;
 
			this.maxIngredientsSpinButton.Name = "maxIngredientsSpinButton";
 
			this.maxIngredientsSpinButton.Adjustment.PageIncrement = 10;
 
			this.maxIngredientsSpinButton.ClimbRate = 1;
 
			this.maxIngredientsSpinButton.Numeric = true;
 
			this.hbox2.Add (this.maxIngredientsSpinButton);
 
			global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.maxIngredientsSpinButton]));
 
			this.minIngredientsSpinButton = new global::Gtk.SpinButton (1, 14, 1);
 
			this.minIngredientsSpinButton.CanFocus = true;
 
			this.minIngredientsSpinButton.Name = "minIngredientsSpinButton";
 
			this.minIngredientsSpinButton.Adjustment.PageIncrement = 10;
 
			this.minIngredientsSpinButton.ClimbRate = 1;
 
			this.minIngredientsSpinButton.Numeric = true;
 
			this.minIngredientsSpinButton.Value = 1;
 
			this.hbox2.Add (this.minIngredientsSpinButton);
 
			global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.minIngredientsSpinButton]));
 
			w3.Position = 0;
 
			w3.Expand = false;
 
			w3.Fill = false;
 
			// Container child hbox2.Gtk.Box+BoxChild
 
			this.label3 = new global::Gtk.Label ();
 
			this.label3.Name = "label3";
 
			this.label3.LabelProp = "Maximum Ingredients";
 
			this.hbox2.Add (this.label3);
 
			global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.label3]));
 
			this.label1 = new global::Gtk.Label ();
 
			this.label1.Name = "label1";
 
			this.label1.LabelProp = "Minimum Ingredients";
 
			this.hbox2.Add (this.label1);
 
			global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.label1]));
 
			w4.Position = 1;
 
			w4.Expand = false;
 
			w4.Fill = false;
 
			this.vbox8.Add (this.hbox2);
 
			global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hbox2]));
 
			w5.Position = 0;
 
			w5.Expand = false;
 
			w5.Fill = false;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hbox7 = new global::Gtk.HBox ();
 
			this.hbox7.Name = "hbox7";
 
			this.hbox7.Spacing = 6;
 
			// Container child hbox7.Gtk.Box+BoxChild
 
			this.maxIngredientsSpinButton = new global::Gtk.SpinButton (1, 14, 1);
 
			this.maxIngredientsSpinButton.CanFocus = true;
 
			this.maxIngredientsSpinButton.Name = "maxIngredientsSpinButton";
 
			this.maxIngredientsSpinButton.Adjustment.PageIncrement = 10;
 
			this.maxIngredientsSpinButton.ClimbRate = 1;
 
			this.maxIngredientsSpinButton.Numeric = true;
 
			this.maxIngredientsSpinButton.Value = 5;
 
			this.hbox7.Add (this.maxIngredientsSpinButton);
 
			global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.hbox7 [this.maxIngredientsSpinButton]));
 
			w6.Position = 0;
 
			w6.Expand = false;
 
			w6.Fill = false;
 
			// Container child hbox7.Gtk.Box+BoxChild
 
			this.label3 = new global::Gtk.Label ();
 
			this.label3.Name = "label3";
 
			this.label3.LabelProp = "Maximum Ingredients";
 
			this.hbox7.Add (this.label3);
 
			global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.hbox7 [this.label3]));
 
			w7.Position = 1;
 
			w7.Expand = false;
 
			w7.Fill = false;
 
			this.vbox8.Add (this.hbox7);
 
			global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hbox7]));
 
			w8.Position = 1;
 
			w8.Expand = false;
 
			w8.Fill = false;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hseparator3 = new global::Gtk.HSeparator ();
 
			this.hseparator3.Name = "hseparator3";
 
			this.vbox8.Add (this.hseparator3);
 
			global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hseparator3]));
 
			w6.Position = 1;
 
			w6.Expand = false;
 
			w6.Fill = false;
 
			global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hseparator3]));
 
			w9.Position = 2;
 
			w9.Expand = false;
 
			w9.Fill = false;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hbox4 = new global::Gtk.HBox ();
 
			this.hbox4.Name = "hbox4";
 
			this.hbox4.Spacing = 6;
 
			// Container child hbox4.Gtk.Box+BoxChild
 
			this.maxRecipeSpinButton = new global::Gtk.SpinButton (0, 100, 1);
 
			this.maxRecipeSpinButton = new global::Gtk.SpinButton (10, 100, 1);
 
			this.maxRecipeSpinButton.CanFocus = true;
 
			this.maxRecipeSpinButton.Name = "maxRecipeSpinButton";
 
			this.maxRecipeSpinButton.Adjustment.PageIncrement = 10;
 
			this.maxRecipeSpinButton.ClimbRate = 1;
 
			this.maxRecipeSpinButton.Numeric = true;
 
			this.maxRecipeSpinButton.Value = 14;
 
			this.hbox4.Add (this.maxRecipeSpinButton);
 
			global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.hbox4 [this.maxRecipeSpinButton]));
 
			w7.Position = 0;
 
			w7.Expand = false;
 
			w7.Fill = false;
 
			global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.hbox4 [this.maxRecipeSpinButton]));
 
			w10.Position = 0;
 
			w10.Expand = false;
 
			w10.Fill = false;
 
			// Container child hbox4.Gtk.Box+BoxChild
 
			this.label4 = new global::Gtk.Label ();
 
			this.label4.Name = "label4";
 
			this.label4.LabelProp = "Max Total Quantity";
 
			this.label4.UseMarkup = true;
 
			this.label4.Wrap = true;
 
			this.hbox4.Add (this.label4);
 
			global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.hbox4 [this.label4]));
 
			w8.Position = 1;
 
			w8.Expand = false;
 
			w8.Fill = false;
 
			global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.hbox4 [this.label4]));
 
			w11.Position = 1;
 
			w11.Expand = false;
 
			w11.Fill = false;
 
			this.vbox8.Add (this.hbox4);
 
			global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hbox4]));
 
			w9.Position = 2;
 
			w9.Expand = false;
 
			w9.Fill = false;
 
			global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hbox4]));
 
			w12.Position = 3;
 
			w12.Expand = false;
 
			w12.Fill = false;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hseparator4 = new global::Gtk.HSeparator ();
 
			this.hseparator4.Name = "hseparator4";
 
			this.vbox8.Add (this.hseparator4);
 
			global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hseparator4]));
 
			w10.Position = 3;
 
			w10.Expand = false;
 
			w10.Fill = false;
 
			w10.Padding = ((uint)(8));
 
			global::Gtk.Box.BoxChild w13 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hseparator4]));
 
			w13.Position = 4;
 
			w13.Expand = false;
 
			w13.Fill = false;
 
			w13.Padding = ((uint)(8));
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hbox5 = new global::Gtk.HBox ();
 
			this.hbox5.Name = "hbox5";
 
			this.hbox5.Spacing = 6;
 
			// Container child hbox5.Gtk.Box+BoxChild
 
			this.fullQuantityDepthSpinButton = new global::Gtk.SpinButton (0, 15, 1);
 
			this.fullQuantityDepthSpinButton.CanFocus = true;
 
			this.fullQuantityDepthSpinButton.Name = "fullQuantityDepthSpinButton";
 
			this.fullQuantityDepthSpinButton.Adjustment.PageIncrement = 10;
 
			this.fullQuantityDepthSpinButton.ClimbRate = 1;
 
			this.fullQuantityDepthSpinButton.Numeric = true;
 
			this.fullQuantityDepthSpinButton.Value = 4;
 
			this.hbox5.Add (this.fullQuantityDepthSpinButton);
 
			global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.hbox5 [this.fullQuantityDepthSpinButton]));
 
			w11.Position = 0;
 
			w11.Expand = false;
 
			w11.Fill = false;
 
			global::Gtk.Box.BoxChild w14 = ((global::Gtk.Box.BoxChild)(this.hbox5 [this.fullQuantityDepthSpinButton]));
 
			w14.Position = 0;
 
			w14.Expand = false;
 
			w14.Fill = false;
 
			// Container child hbox5.Gtk.Box+BoxChild
 
			this.label8 = new global::Gtk.Label ();
 
			this.label8.Name = "label8";
 
			this.label8.LabelProp = "Full Quantity Depth";
 
			this.hbox5.Add (this.label8);
 
			global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(this.hbox5 [this.label8]));
 
			w12.Position = 1;
 
			w12.Expand = false;
 
			w12.Fill = false;
 
			global::Gtk.Box.BoxChild w15 = ((global::Gtk.Box.BoxChild)(this.hbox5 [this.label8]));
 
			w15.Position = 1;
 
			w15.Expand = false;
 
			w15.Fill = false;
 
			this.vbox8.Add (this.hbox5);
 
			global::Gtk.Box.BoxChild w13 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hbox5]));
 
			w13.Position = 4;
 
			w13.Expand = false;
 
			w13.Fill = false;
 
			global::Gtk.Box.BoxChild w16 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hbox5]));
 
			w16.Position = 5;
 
			w16.Expand = false;
 
			w16.Fill = false;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hseparator5 = new global::Gtk.HSeparator ();
 
			this.hseparator5.Name = "hseparator5";
 
			this.vbox8.Add (this.hseparator5);
 
			global::Gtk.Box.BoxChild w14 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hseparator5]));
 
			w14.Position = 5;
 
			w14.Expand = false;
 
			w14.Fill = false;
 
			global::Gtk.Box.BoxChild w17 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hseparator5]));
 
			w17.Position = 6;
 
			w17.Expand = false;
 
			w17.Fill = false;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hbox6 = new global::Gtk.HBox ();
 
			this.hbox6.Name = "hbox6";
 
			this.hbox6.Spacing = 6;
 
			// Container child hbox6.Gtk.Box+BoxChild
 
			this.fullQuantitySpinButton = new global::Gtk.SpinButton (0, 30, 1);
 
			this.fullQuantitySpinButton.CanFocus = true;
 
			this.fullQuantitySpinButton.Name = "fullQuantitySpinButton";
 
			this.fullQuantitySpinButton.Adjustment.PageIncrement = 10;
 
			this.fullQuantitySpinButton.ClimbRate = 1;
 
			this.fullQuantitySpinButton.Numeric = true;
 
			this.fullQuantitySpinButton.Value = 20;
 
			this.hbox6.Add (this.fullQuantitySpinButton);
 
			global::Gtk.Box.BoxChild w15 = ((global::Gtk.Box.BoxChild)(this.hbox6 [this.fullQuantitySpinButton]));
 
			w15.Position = 0;
 
			w15.Expand = false;
 
			w15.Fill = false;
 
			global::Gtk.Box.BoxChild w18 = ((global::Gtk.Box.BoxChild)(this.hbox6 [this.fullQuantitySpinButton]));
 
			w18.Position = 0;
 
			w18.Expand = false;
 
			w18.Fill = false;
 
			// Container child hbox6.Gtk.Box+BoxChild
 
			this.label9 = new global::Gtk.Label ();
 
			this.label9.Name = "label9";
 
			this.label9.LabelProp = "FullQuantity";
 
			this.hbox6.Add (this.label9);
 
			global::Gtk.Box.BoxChild w16 = ((global::Gtk.Box.BoxChild)(this.hbox6 [this.label9]));
 
			w16.Position = 1;
 
			w16.Expand = false;
 
			w16.Fill = false;
 
			global::Gtk.Box.BoxChild w19 = ((global::Gtk.Box.BoxChild)(this.hbox6 [this.label9]));
 
			w19.Position = 1;
 
			w19.Expand = false;
 
			w19.Fill = false;
 
			this.vbox8.Add (this.hbox6);
 
			global::Gtk.Box.BoxChild w17 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hbox6]));
 
			w17.Position = 6;
 
			w17.Expand = false;
 
			w17.Fill = false;
 
			global::Gtk.Box.BoxChild w20 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hbox6]));
 
			w20.Position = 7;
 
			w20.Expand = false;
 
			w20.Fill = false;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.frame3 = new global::Gtk.Frame ();
 
			this.frame3.Name = "frame3";
 
			this.frame3.ShadowType = ((global::Gtk.ShadowType)(0));
 
			// Container child frame3.Gtk.Container+ContainerChild
 
			this.GtkAlignment1 = new global::Gtk.Alignment (0F, 0F, 1F, 1F);
 
			this.GtkAlignment1.Name = "GtkAlignment1";
 
			this.GtkAlignment1.LeftPadding = ((uint)(12));
 
			// Container child GtkAlignment1.Gtk.Container+ContainerChild
 
			this.scrolledwindow2 = new global::Gtk.ScrolledWindow ();
 
			this.scrolledwindow2.CanFocus = true;
 
			this.scrolledwindow2.Name = "scrolledwindow2";
...
 
@@ -313,54 +354,54 @@ namespace DesertPaintLab
 
			this.reagentListView.WidthRequest = 300;
 
			this.reagentListView.CanFocus = true;
 
			this.reagentListView.Name = "reagentListView";
 
			this.scrolledwindow2.Add (this.reagentListView);
 
			this.GtkAlignment1.Add (this.scrolledwindow2);
 
			this.frame3.Add (this.GtkAlignment1);
 
			this.GtkLabel4 = new global::Gtk.Label ();
 
			this.GtkLabel4.Name = "GtkLabel4";
 
			this.GtkLabel4.LabelProp = "<b>Ingredients</b>";
 
			this.GtkLabel4.UseMarkup = true;
 
			this.frame3.LabelWidget = this.GtkLabel4;
 
			this.vbox8.Add (this.frame3);
 
			global::Gtk.Box.BoxChild w21 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.frame3]));
 
			w21.PackType = ((global::Gtk.PackType)(1));
 
			w21.Position = 7;
 
			global::Gtk.Box.BoxChild w24 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.frame3]));
 
			w24.PackType = ((global::Gtk.PackType)(1));
 
			w24.Position = 8;
 
			// Container child vbox8.Gtk.Box+BoxChild
 
			this.hseparator6 = new global::Gtk.HSeparator ();
 
			this.hseparator6.Name = "hseparator6";
 
			this.vbox8.Add (this.hseparator6);
 
			global::Gtk.Box.BoxChild w22 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hseparator6]));
 
			w22.PackType = ((global::Gtk.PackType)(1));
 
			w22.Position = 8;
 
			w22.Expand = false;
 
			w22.Fill = false;
 
			global::Gtk.Box.BoxChild w25 = ((global::Gtk.Box.BoxChild)(this.vbox8 [this.hseparator6]));
 
			w25.PackType = ((global::Gtk.PackType)(1));
 
			w25.Position = 9;
 
			w25.Expand = false;
 
			w25.Fill = false;
 
			this.hbox1.Add (this.vbox8);
 
			global::Gtk.Box.BoxChild w23 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.vbox8]));
 
			w23.Position = 0;
 
			w23.Expand = false;
 
			w23.Fill = false;
 
			global::Gtk.Box.BoxChild w26 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.vbox8]));
 
			w26.Position = 0;
 
			w26.Expand = false;
 
			w26.Fill = false;
 
			// Container child hbox1.Gtk.Box+BoxChild
 
			this.GtkScrolledWindow1 = new global::Gtk.ScrolledWindow ();
 
			this.GtkScrolledWindow1.Name = "GtkScrolledWindow1";
 
			this.GtkScrolledWindow1.ShadowType = ((global::Gtk.ShadowType)(1));
 
			// Container child GtkScrolledWindow1.Gtk.Container+ContainerChild
 
			this.recipeList = new global::Gtk.TreeView ();
 
			this.recipeList.WidthRequest = 300;
 
			this.recipeList.CanFocus = true;
 
			this.recipeList.Name = "recipeList";
 
			this.GtkScrolledWindow1.Add (this.recipeList);
 
			this.hbox1.Add (this.GtkScrolledWindow1);
 
			global::Gtk.Box.BoxChild w25 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.GtkScrolledWindow1]));
 
			w25.Position = 1;
 
			global::Gtk.Box.BoxChild w28 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.GtkScrolledWindow1]));
 
			w28.Position = 1;
 
			// Container child hbox1.Gtk.Box+BoxChild
 
			this.vbox3 = new global::Gtk.VBox ();
 
			this.vbox3.Name = "vbox3";
 
			this.vbox3.Spacing = 6;
 
			// Container child vbox3.Gtk.Box+BoxChild
 
			this.frame2 = new global::Gtk.Frame ();
 
			this.frame2.WidthRequest = 200;
 
			this.frame2.HeightRequest = 200;
 
			this.frame2.Name = "frame2";
 
			this.frame2.ShadowType = ((global::Gtk.ShadowType)(0));
 
			// Container child frame2.Gtk.Container+ContainerChild
 
			this.GtkScrolledWindow = new global::Gtk.ScrolledWindow ();
...
 
@@ -369,135 +410,136 @@ namespace DesertPaintLab
 
			// Container child GtkScrolledWindow.Gtk.Container+ContainerChild
 
			this.recipeIngredientsView = new global::Gtk.TreeView ();
 
			this.recipeIngredientsView.CanFocus = true;
 
			this.recipeIngredientsView.Name = "recipeIngredientsView";
 
			this.GtkScrolledWindow.Add (this.recipeIngredientsView);
 
			this.frame2.Add (this.GtkScrolledWindow);
 
			this.recipeLabel = new global::Gtk.Label ();
 
			this.recipeLabel.Name = "recipeLabel";
 
			this.recipeLabel.LabelProp = "<b>Recipe</b>";
 
			this.recipeLabel.UseMarkup = true;
 
			this.frame2.LabelWidget = this.recipeLabel;
 
			this.vbox3.Add (this.frame2);
 
			global::Gtk.Box.BoxChild w28 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.frame2]));
 
			w28.Position = 0;
 
			global::Gtk.Box.BoxChild w31 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.frame2]));
 
			w31.Position = 0;
 
			// Container child vbox3.Gtk.Box+BoxChild
 
			this.button919 = new global::Gtk.Button ();
 
			this.button919.CanFocus = true;
 
			this.button919.Name = "button919";
 
			this.button919.UseUnderline = true;
 
			this.button919.Label = "Copy";
 
			this.vbox3.Add (this.button919);
 
			global::Gtk.Box.BoxChild w29 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.button919]));
 
			w29.Position = 1;
 
			w29.Expand = false;
 
			w29.Fill = false;
 
			global::Gtk.Box.BoxChild w32 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.button919]));
 
			w32.Position = 1;
 
			w32.Expand = false;
 
			w32.Fill = false;
 
			// Container child vbox3.Gtk.Box+BoxChild
 
			this.paintSwatch = new global::DesertPaintLab.PaintSwatch ();
 
			this.paintSwatch.HeightRequest = 200;
 
			this.paintSwatch.Events = ((global::Gdk.EventMask)(256));
 
			this.paintSwatch.Name = "paintSwatch";
 
			this.vbox3.Add (this.paintSwatch);
 
			global::Gtk.Box.BoxChild w30 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.paintSwatch]));
 
			w30.Position = 2;
 
			global::Gtk.Box.BoxChild w33 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.paintSwatch]));
 
			w33.Position = 2;
 
			this.hbox1.Add (this.vbox3);
 
			global::Gtk.Box.BoxChild w31 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.vbox3]));
 
			w31.Position = 2;
 
			w31.Expand = false;
 
			w31.Fill = false;
 
			global::Gtk.Box.BoxChild w34 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.vbox3]));
 
			w34.Position = 2;
 
			w34.Expand = false;
 
			w34.Fill = false;
 
			this.vbox2.Add (this.hbox1);
 
			global::Gtk.Box.BoxChild w32 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.hbox1]));
 
			w32.Position = 1;
 
			global::Gtk.Box.BoxChild w35 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.hbox1]));
 
			w35.Position = 1;
 
			// Container child vbox2.Gtk.Box+BoxChild
 
			this.hbox3 = new global::Gtk.HBox ();
 
			this.hbox3.Name = "hbox3";
 
			this.hbox3.Spacing = 6;
 
			// Container child hbox3.Gtk.Box+BoxChild
 
			this.hseparator2 = new global::Gtk.HSeparator ();
 
			this.hseparator2.Name = "hseparator2";
 
			this.hbox3.Add (this.hseparator2);
 
			global::Gtk.Box.BoxChild w33 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.hseparator2]));
 
			w33.Position = 0;
 
			global::Gtk.Box.BoxChild w36 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.hseparator2]));
 
			w36.Position = 0;
 
			// Container child hbox3.Gtk.Box+BoxChild
 
			this.stopResumeButton = new global::Gtk.Button ();
 
			this.stopResumeButton.Sensitive = false;
 
			this.stopResumeButton.CanFocus = true;
 
			this.stopResumeButton.Name = "stopResumeButton";
 
			this.stopResumeButton.UseUnderline = true;
 
			this.stopResumeButton.Label = "Stop";
 
			this.hbox3.Add (this.stopResumeButton);
 
			global::Gtk.Box.BoxChild w34 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.stopResumeButton]));
 
			w34.Position = 1;
 
			w34.Expand = false;
 
			w34.Fill = false;
 
			w34.Padding = ((uint)(20));
 
			global::Gtk.Box.BoxChild w37 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.stopResumeButton]));
 
			w37.Position = 1;
 
			w37.Expand = false;
 
			w37.Fill = false;
 
			w37.Padding = ((uint)(20));
 
			// Container child hbox3.Gtk.Box+BoxChild
 
			this.countLabel = new global::Gtk.Label ();
 
			this.countLabel.Name = "countLabel";
 
			this.countLabel.LabelProp = "0/192";
 
			this.hbox3.Add (this.countLabel);
 
			global::Gtk.Box.BoxChild w35 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.countLabel]));
 
			w35.Position = 2;
 
			w35.Expand = false;
 
			w35.Fill = false;
 
			w35.Padding = ((uint)(40));
 
			global::Gtk.Box.BoxChild w38 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.countLabel]));
 
			w38.Position = 2;
 
			w38.Expand = false;
 
			w38.Fill = false;
 
			w38.Padding = ((uint)(40));
 
			// Container child hbox3.Gtk.Box+BoxChild
 
			this.beginButton = new global::Gtk.Button ();
 
			this.beginButton.CanFocus = true;
 
			this.beginButton.Name = "beginButton";
 
			this.beginButton.UseUnderline = true;
 
			this.beginButton.Label = "Begin";
 
			this.hbox3.Add (this.beginButton);
 
			global::Gtk.Box.BoxChild w36 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.beginButton]));
 
			w36.Position = 3;
 
			w36.Expand = false;
 
			w36.Fill = false;
 
			w36.Padding = ((uint)(20));
 
			global::Gtk.Box.BoxChild w39 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.beginButton]));
 
			w39.Position = 3;
 
			w39.Expand = false;
 
			w39.Fill = false;
 
			w39.Padding = ((uint)(20));
 
			// Container child hbox3.Gtk.Box+BoxChild
 
			this.hseparator1 = new global::Gtk.HSeparator ();
 
			this.hseparator1.Name = "hseparator1";
 
			this.hbox3.Add (this.hseparator1);
 
			global::Gtk.Box.BoxChild w37 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.hseparator1]));
 
			w37.Position = 4;
 
			global::Gtk.Box.BoxChild w40 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.hseparator1]));
 
			w40.Position = 4;
 
			this.vbox2.Add (this.hbox3);
 
			global::Gtk.Box.BoxChild w38 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.hbox3]));
 
			w38.Position = 2;
 
			w38.Expand = false;
 
			w38.Fill = false;
 
			global::Gtk.Box.BoxChild w41 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.hbox3]));
 
			w41.Position = 2;
 
			w41.Expand = false;
 
			w41.Fill = false;
 
			// Container child vbox2.Gtk.Box+BoxChild
 
			this.statusLabel = new global::Gtk.Label ();
 
			this.statusLabel.Name = "statusLabel";
 
			this.vbox2.Add (this.statusLabel);
 
			global::Gtk.Box.BoxChild w39 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.statusLabel]));
 
			w39.PackType = ((global::Gtk.PackType)(1));
 
			w39.Position = 3;
 
			w39.Expand = false;
 
			w39.Fill = false;
 
			global::Gtk.Box.BoxChild w42 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.statusLabel]));
 
			w42.PackType = ((global::Gtk.PackType)(1));
 
			w42.Position = 3;
 
			w42.Expand = false;
 
			w42.Fill = false;
 
			// Container child vbox2.Gtk.Box+BoxChild
 
			this.progressBar = new global::Gtk.ProgressBar ();
 
			this.progressBar.Name = "progressBar";
 
			this.vbox2.Add (this.progressBar);
 
			global::Gtk.Box.BoxChild w40 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.progressBar]));
 
			w40.PackType = ((global::Gtk.PackType)(1));
 
			w40.Position = 4;
 
			w40.Expand = false;
 
			w40.Fill = false;
 
			global::Gtk.Box.BoxChild w43 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.progressBar]));
 
			w43.PackType = ((global::Gtk.PackType)(1));
 
			w43.Position = 4;
 
			w43.Expand = false;
 
			w43.Fill = false;
 
			this.Add (this.vbox2);
 
			if ((this.Child != null)) {
 
				this.Child.ShowAll ();
 
			}
 
			this.DefaultWidth = 887;
 
			this.DefaultHeight = 577;
 
			this.Show ();
 
			this.ExportToWikiAction.Activated += new global::System.EventHandler (this.OnExportToWiki);
 
			this.IngredientsAction.Activated += new global::System.EventHandler (this.OnShowIngredients);
 
			this.CopyToClipboardAction.Activated += new global::System.EventHandler (this.OnCopyRecipeListToClipboard);
 
			this.minIngredientsSpinButton.ValueChanged += new global::System.EventHandler (this.OnMinIngredientsChanged);
 
			this.maxIngredientsSpinButton.ValueChanged += new global::System.EventHandler (this.OnMaxIngredientsChanged);
 
			this.maxRecipeSpinButton.ValueChanged += new global::System.EventHandler (this.OnMaxRecipeChanged);
 
			this.fullQuantityDepthSpinButton.ValueChanged += new global::System.EventHandler (this.OnFullQuantityDepthChanged);
 
			this.fullQuantitySpinButton.ValueChanged += new global::System.EventHandler (this.OnFullQuantityChanged);
 
			this.button919.Clicked += new global::System.EventHandler (this.OnCopyRecipeToClipboard);
 
			this.stopResumeButton.Clicked += new global::System.EventHandler (this.OnStopResume);
 
			this.beginButton.Clicked += new global::System.EventHandler (this.OnBegin);
 
		}
 
	}
 
}
gtk-gui/gui.stetic
Show inline comments
 
<?xml version="1.0" encoding="utf-8"?>
 
<stetic-interface>
 
  <configuration>
 
    <images-root-path>..</images-root-path>
 
    <target-gtk-version>2.12</target-gtk-version>
 
  </configuration>
 
  <import>
 
    <widget-library name="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <widget-library name="../bin/Release/DesertPaintLab.exe" internal="true" />
 
    <widget-library name="../bin/Debug/DesertPaintLab.exe" internal="true" />
 
  </import>
 
  <widget class="Gtk.Window" id="MainWindow" design-size="629 265">
 
    <action-group name="Default">
 
      <action id="FileAction">
 
        <property name="Type">Action</property>
 
        <property name="Accelerator">&lt;Alt&gt;f</property>
 
        <property name="Label" translatable="yes">_File</property>
 
        <property name="ShortLabel" translatable="yes">_File</property>
 
      </action>
 
      <action id="HelpAction">
 
        <property name="Type">Action</property>
 
        <property name="Accelerator">&lt;Alt&gt;a</property>
...
 
@@ -1187,25 +1187,25 @@ You can either import an existing Practi
 
    </action-group>
 
    <property name="MemberName" />
 
    <property name="Title" translatable="yes">Recipe Generator</property>
 
    <property name="WindowPosition">CenterOnParent</property>
 
    <child>
 
      <widget class="Gtk.VBox" id="vbox2">
 
        <property name="MemberName" />
 
        <property name="Spacing">6</property>
 
        <property name="BorderWidth">8</property>
 
        <child>
 
          <widget class="Gtk.MenuBar" id="menubar1">
 
            <property name="MemberName" />
 
            <node name="__gtksharp_64_Stetic_Editor_ActionMenuBar" type="Menubar">
 
            <node name="menubar1" type="Menubar">
 
              <node type="Menu" action="ExportAction">
 
                <node type="Menuitem" action="ExportToWikiAction" />
 
                <node type="Menuitem" action="CopyToClipboardAction" />
 
              </node>
 
            </node>
 
          </widget>
 
          <packing>
 
            <property name="Position">0</property>
 
            <property name="AutoSize">True</property>
 
            <property name="Expand">False</property>
 
            <property name="Fill">False</property>
 
          </packing>
...
 
@@ -1214,85 +1214,133 @@ You can either import an existing Practi
 
          <widget class="Gtk.HBox" id="hbox1">
 
            <property name="MemberName" />
 
            <property name="Spacing">6</property>
 
            <child>
 
              <widget class="Gtk.VBox" id="vbox8">
 
                <property name="MemberName" />
 
                <property name="Spacing">6</property>
 
                <child>
 
                  <widget class="Gtk.HBox" id="hbox2">
 
                    <property name="MemberName" />
 
                    <property name="Spacing">6</property>
 
                    <child>
 
                      <widget class="Gtk.SpinButton" id="maxIngredientsSpinButton">
 
                      <widget class="Gtk.SpinButton" id="minIngredientsSpinButton">
 
                        <property name="MemberName" />
 
                        <property name="CanFocus">True</property>
 
                        <property name="Lower">1</property>
 
                        <property name="Upper">14</property>
 
                        <property name="PageIncrement">10</property>
 
                        <property name="StepIncrement">1</property>
 
                        <property name="ClimbRate">1</property>
 
                        <property name="Numeric">True</property>
 
                        <property name="Value">1</property>
 
                        <signal name="ValueChanged" handler="OnMinIngredientsChanged" />
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">0</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                    <child>
 
                      <widget class="Gtk.Label" id="label1">
 
                        <property name="MemberName" />
 
                        <property name="LabelProp" translatable="yes">Minimum Ingredients</property>
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">1</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                  </widget>
 
                  <packing>
 
                    <property name="Position">0</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.HBox" id="hbox7">
 
                    <property name="MemberName" />
 
                    <property name="Spacing">6</property>
 
                    <child>
 
                      <widget class="Gtk.SpinButton" id="maxIngredientsSpinButton">
 
                        <property name="MemberName" />
 
                        <property name="CanFocus">True</property>
 
                        <property name="Lower">1</property>
 
                        <property name="Upper">14</property>
 
                        <property name="PageIncrement">10</property>
 
                        <property name="StepIncrement">1</property>
 
                        <property name="ClimbRate">1</property>
 
                        <property name="Numeric">True</property>
 
                        <property name="Value">5</property>
 
                        <signal name="ValueChanged" handler="OnMaxIngredientsChanged" after="yes" />
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">0</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                    <child>
 
                      <widget class="Gtk.Label" id="label3">
 
                        <property name="MemberName" />
 
                        <property name="LabelProp" translatable="yes">Maximum Ingredients</property>
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">1</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                  </widget>
 
                  <packing>
 
                    <property name="Position">0</property>
 
                    <property name="Position">1</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.HSeparator" id="hseparator3">
 
                    <property name="MemberName" />
 
                  </widget>
 
                  <packing>
 
                    <property name="Position">1</property>
 
                    <property name="Position">2</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.HBox" id="hbox4">
 
                    <property name="MemberName" />
 
                    <property name="Spacing">6</property>
 
                    <child>
 
                      <widget class="Gtk.SpinButton" id="maxRecipeSpinButton">
 
                        <property name="MemberName" />
 
                        <property name="CanFocus">True</property>
 
                        <property name="Lower">10</property>
 
                        <property name="Upper">100</property>
 
                        <property name="PageIncrement">10</property>
 
                        <property name="StepIncrement">1</property>
 
                        <property name="ClimbRate">1</property>
 
                        <property name="Numeric">True</property>
 
                        <property name="Value">14</property>
 
                        <signal name="ValueChanged" handler="OnMaxRecipeChanged" after="yes" />
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">0</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                    <child>
 
                      <widget class="Gtk.Label" id="label4">
 
                        <property name="MemberName" />
...
 
@@ -1300,132 +1348,134 @@ You can either import an existing Practi
 
                        <property name="UseMarkup">True</property>
 
                        <property name="Wrap">True</property>
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">1</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                  </widget>
 
                  <packing>
 
                    <property name="Position">2</property>
 
                    <property name="Position">3</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.HSeparator" id="hseparator4">
 
                    <property name="MemberName" />
 
                  </widget>
 
                  <packing>
 
                    <property name="Position">3</property>
 
                    <property name="Position">4</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                    <property name="Padding">8</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.HBox" id="hbox5">
 
                    <property name="MemberName" />
 
                    <property name="Spacing">6</property>
 
                    <child>
 
                      <widget class="Gtk.SpinButton" id="fullQuantityDepthSpinButton">
 
                        <property name="MemberName" />
 
                        <property name="CanFocus">True</property>
 
                        <property name="Upper">15</property>
 
                        <property name="PageIncrement">10</property>
 
                        <property name="StepIncrement">1</property>
 
                        <property name="ClimbRate">1</property>
 
                        <property name="Numeric">True</property>
 
                        <property name="Value">4</property>
 
                        <signal name="ValueChanged" handler="OnFullQuantityDepthChanged" after="yes" />
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">0</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                    <child>
 
                      <widget class="Gtk.Label" id="label8">
 
                        <property name="MemberName" />
 
                        <property name="LabelProp" translatable="yes">Full Quantity Depth</property>
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">1</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                  </widget>
 
                  <packing>
 
                    <property name="Position">4</property>
 
                    <property name="Position">5</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.HSeparator" id="hseparator5">
 
                    <property name="MemberName" />
 
                  </widget>
 
                  <packing>
 
                    <property name="Position">5</property>
 
                    <property name="Position">6</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.HBox" id="hbox6">
 
                    <property name="MemberName" />
 
                    <property name="Spacing">6</property>
 
                    <child>
 
                      <widget class="Gtk.SpinButton" id="fullQuantitySpinButton">
 
                        <property name="MemberName" />
 
                        <property name="CanFocus">True</property>
 
                        <property name="Upper">30</property>
 
                        <property name="PageIncrement">10</property>
 
                        <property name="StepIncrement">1</property>
 
                        <property name="ClimbRate">1</property>
 
                        <property name="Numeric">True</property>
 
                        <property name="Value">20</property>
 
                        <signal name="ValueChanged" handler="OnFullQuantityChanged" />
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">0</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                    <child>
 
                      <widget class="Gtk.Label" id="label9">
 
                        <property name="MemberName" />
 
                        <property name="LabelProp" translatable="yes">FullQuantity</property>
 
                      </widget>
 
                      <packing>
 
                        <property name="Position">1</property>
 
                        <property name="AutoSize">True</property>
 
                        <property name="Expand">False</property>
 
                        <property name="Fill">False</property>
 
                      </packing>
 
                    </child>
 
                  </widget>
 
                  <packing>
 
                    <property name="Position">6</property>
 
                    <property name="Position">7</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.Frame" id="frame3">
 
                    <property name="MemberName" />
 
                    <property name="ShadowType">None</property>
 
                    <child>
 
                      <widget class="Gtk.Alignment" id="GtkAlignment1">
 
                        <property name="MemberName" />
...
 
@@ -1452,35 +1502,35 @@ You can either import an existing Practi
 
                      <widget class="Gtk.Label" id="GtkLabel4">
 
                        <property name="MemberName" />
 
                        <property name="LabelProp" translatable="yes">&lt;b&gt;Ingredients&lt;/b&gt;</property>
 
                        <property name="UseMarkup">True</property>
 
                      </widget>
 
                      <packing>
 
                        <property name="type">label_item</property>
 
                      </packing>
 
                    </child>
 
                  </widget>
 
                  <packing>
 
                    <property name="PackType">End</property>
 
                    <property name="Position">7</property>
 
                    <property name="Position">8</property>
 
                    <property name="AutoSize">True</property>
 
                  </packing>
 
                </child>
 
                <child>
 
                  <widget class="Gtk.HSeparator" id="hseparator6">
 
                    <property name="MemberName" />
 
                  </widget>
 
                  <packing>
 
                    <property name="PackType">End</property>
 
                    <property name="Position">8</property>
 
                    <property name="Position">9</property>
 
                    <property name="AutoSize">True</property>
 
                    <property name="Expand">False</property>
 
                    <property name="Fill">False</property>
 
                  </packing>
 
                </child>
 
              </widget>
 
              <packing>
 
                <property name="Position">0</property>
 
                <property name="AutoSize">True</property>
 
                <property name="Expand">False</property>
 
                <property name="Fill">False</property>
 
              </packing>
0 comments (0 inline, 0 general)