diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs
new file mode 100644
--- /dev/null
+++ b/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("DesertPaintLab")]
+[assembly: AssemblyDescription("Program to help record pigment lab reactions in ATITD")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Tess Snider")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Tess Snider, 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/DesertPaintLab.csproj b/DesertPaintLab.csproj
new file mode 100644
--- /dev/null
+++ b/DesertPaintLab.csproj
@@ -0,0 +1,78 @@
+
+
+
+ Debug
+ x86
+ 8.0.50727
+ 2.0
+ {1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}
+ WinExe
+ DesertPaintLab
+ DesertPaintLab
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG
+ prompt
+ 4
+ x86
+ false
+ /unsafe
+
+
+ none
+ false
+ bin\Release
+ prompt
+ 4
+ x86
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ gui.stetic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesertPaintLab.sln b/DesertPaintLab.sln
new file mode 100644
--- /dev/null
+++ b/DesertPaintLab.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesertPaintLab", "DesertPaintLab.csproj", "{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x86.ActiveCfg = Debug|x86
+ {1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x86.Build.0 = Debug|x86
+ {1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x86.ActiveCfg = Release|x86
+ {1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = DesertPaintLab.csproj
+ EndGlobalSection
+EndGlobal
diff --git a/FirstRunDialog.cs b/FirstRunDialog.cs
new file mode 100644
--- /dev/null
+++ b/FirstRunDialog.cs
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, Tess Snider
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ 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 System;
+namespace DesertPaintLab
+{
+ public partial class FirstRunDialog : Gtk.Dialog
+ {
+ public FirstRunDialog ()
+ {
+ this.Build ();
+ }
+ }
+}
+
diff --git a/Main.cs b/Main.cs
new file mode 100644
--- /dev/null
+++ b/Main.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, Tess Snider
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ 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 System;
+using Gtk;
+
+namespace DesertPaintLab
+{
+ class MainClass
+ {
+ public static void Main (string[] args)
+ {
+ Application.Init ();
+ MainWindow win = new MainWindow ();
+ if (!win.ShouldShutDown)
+ {
+ win.Show ();
+ Application.Run ();
+ }
+ }
+ }
+}
+
diff --git a/MainWindow.cs b/MainWindow.cs
new file mode 100644
--- /dev/null
+++ b/MainWindow.cs
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 2010, Tess Snider
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ 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 System;
+using System.IO;
+using System.Collections.Generic;
+using Gtk;
+using DesertPaintLab;
+
+public partial class MainWindow : Gtk.Window
+{
+ const int swatchHeight = 24;
+ const int colorBarWidth = 260;
+ const int redBarSpacing = 32;
+ const int greenBarSpacing = 42;
+ const int blueBarSpacing = 52;
+ const int colorTolerance = 2;
+
+
+ bool unsavedData = false;
+ bool shouldShutDown = false;
+ string appDataPath;
+ List profileList = new List();
+ PlayerProfile profile = null;
+ PaintColor expectedColor = new PaintColor();
+ PaintColor reactedColor = new PaintColor();
+
+ int screenWidth = 0;
+ int screenHeight = 0;
+
+ Gdk.Window rootWindow = null;
+ Gdk.Pixbuf screenBuffer = null;
+
+ Reagent reagent1 = null;
+ Reagent reagent2 = null;
+ Reagent reagent3 = null;
+
+
+
+ public bool ShouldShutDown
+ {
+ get
+ {
+ return shouldShutDown;
+ }
+ }
+
+
+ public MainWindow () : base(Gtk.WindowType.Toplevel)
+ {
+ appDataPath = System.IO.Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+ "DesertPaintLab");
+
+ if (!System.IO.Directory.Exists(appDataPath))
+ {
+ System.IO.Directory.CreateDirectory(appDataPath);
+ }
+
+ DirectoryInfo di = new DirectoryInfo(appDataPath);
+ DirectoryInfo[] dirs = di.GetDirectories();
+ foreach (DirectoryInfo dir in dirs)
+ {
+ if (dir.Name != "template")
+ {
+ profileList.Add(dir.Name);
+ }
+ }
+
+ Palette.Load(System.IO.Path.Combine(
+ System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
+ "colors.txt"));
+
+ Build();
+
+ unmodifiedSwatch.Clear();
+ reactionSwatch.Clear();
+
+
+ // get the root window
+ rootWindow = Gdk.Global.DefaultRootWindow;
+
+ // get its width and height
+ rootWindow.GetSize(out screenWidth, out screenHeight);
+
+ screenBuffer = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8,
+ screenWidth, screenHeight);
+
+ if (!OpenProfile())
+ {
+ shouldShutDown = true;
+ }
+ }
+
+ bool ConfirmedExit()
+ {
+ if (unsavedData)
+ {
+ MessageDialog md = new MessageDialog(this,
+ DialogFlags.DestroyWithParent,
+ MessageType.Warning, ButtonsType.OkCancel,
+ "Your last reaction was unsaved." +
+ "Are you sure you want to quit?");
+
+ ResponseType resp = (ResponseType)md.Run();
+ md.Destroy();
+ return (resp == ResponseType.Ok);
+ }
+ return true;
+ }
+
+ void SetProfileName(string name)
+ {
+ profile = new PlayerProfile(name,
+ System.IO.Path.Combine(appDataPath, name));
+
+ statusBar.Push(0, name);
+ }
+
+ bool NewProfile()
+ {
+ bool newProfileCreated = false;
+ bool duplicateName = false;
+ NewProfileDialog newProfileDialog = new NewProfileDialog();
+ ResponseType resp = (ResponseType)newProfileDialog.Run();
+ if (resp == ResponseType.Ok)
+ {
+ // Make sure profile doesn't already exist.
+ foreach (string profileName in profileList)
+ {
+ if (profileName == newProfileDialog.ProfileName)
+ {
+ MessageDialog md = new MessageDialog(this,
+ DialogFlags.DestroyWithParent,
+ MessageType.Error, ButtonsType.Ok,
+ "That profile name already exists.");
+ resp = (ResponseType)md.Run();
+ md.Destroy();
+ duplicateName = true;
+ break;
+ }
+ }
+
+ if (!duplicateName)
+ {
+ // Set profile name.
+ SetProfileName(newProfileDialog.ProfileName);
+
+ profile.Initialize();
+
+ newProfileCreated = true;
+ }
+ }
+ newProfileDialog.Destroy();
+ return newProfileCreated;
+ }
+
+ bool OpenProfile()
+ {
+ bool profileSelected = false;
+
+ if (profileList.Count > 0)
+ {
+ SelectProfileDialog selectProfileDialog = new SelectProfileDialog();
+ selectProfileDialog.ProfileList = profileList;
+ ResponseType resp = (ResponseType)selectProfileDialog.Run();
+ selectProfileDialog.Destroy();
+ string selectedProfile = selectProfileDialog.SelectedProfile;
+ if ((resp == ResponseType.Ok) && (selectedProfile.Length > 0))
+ // Selected a profile.
+ {
+ SetProfileName(selectedProfile);
+ profileSelected = true;
+ }
+ else if (resp == ResponseType.Accept) // New profile.
+ {
+ profileSelected = NewProfile();
+ }
+ }
+ else
+ {
+ FirstRunDialog firstRunDialog = new FirstRunDialog();
+ ResponseType resp = (ResponseType)firstRunDialog.Run();
+ firstRunDialog.Destroy();
+ if (resp == ResponseType.Ok) // New profile
+ {
+ profileSelected = NewProfile();
+ }
+ else if (resp == ResponseType.Accept) // Import
+ {
+ FileChooserDialog fileDialog =
+ new FileChooserDialog("Select reactions.txt file.",
+ this, FileChooserAction.Open,
+ Gtk.Stock.Cancel, ResponseType.Cancel,
+ Gtk.Stock.Open, ResponseType.Accept);
+ resp = (ResponseType)fileDialog.Run();
+ if (resp == ResponseType.Accept)
+ {
+ string fileName = fileDialog.Filename;
+ string directory = fileDialog.CurrentFolder;
+ if (fileName == "reactions.txt")
+ {
+ profileSelected = NewProfile();
+ if (profileSelected)
+ {
+ profile.Import(directory);
+ }
+ }
+ }
+ }
+ }
+
+ if (profileSelected)
+ {
+ profile.Load();
+ PopulateDropDowns();
+ }
+
+ return profileSelected;
+ }
+
+ void PopulateDropDowns()
+ {
+ ReagentManager.PopulateReagents(ref ingredient1ComboBox);
+ ReagentManager.PopulateReagents(ref ingredient2ComboBox);
+ ReagentManager.PopulateReagents(ref ingredient3ComboBox);
+
+ ingredient2ComboBox.Sensitive = false;
+ ingredient3ComboBox.Sensitive = false;
+
+ Gtk.TreeIter iter;
+ ingredient1ComboBox.Model.IterNthChild(out iter, 0);
+ ingredient1ComboBox.SetActiveIter(iter);
+ ingredient2ComboBox.Model.IterNthChild(out iter, 0);
+ ingredient2ComboBox.SetActiveIter(iter);
+ ingredient3ComboBox.Model.IterNthChild(out iter, 0);
+ ingredient3ComboBox.SetActiveIter(iter);
+ }
+
+ protected void SetExpectedColor(byte red, byte green, byte blue)
+ {
+ expectedColor.Red = red;
+ expectedColor.Green = green;
+ expectedColor.Blue = blue;
+ unmodifiedSwatch.Color = expectedColor;
+ }
+
+ protected void SetExpectedColor(PaintColor color)
+ {
+ SetExpectedColor(color.Red, color.Green, color.Blue);
+ }
+
+ protected void UpdateIngredients()
+ {
+ Reaction reaction1, reaction2;
+ TreeIter selectIter;
+ string reagentName;
+ reagent1 = null;
+ reagent2 = null;
+ reagent3 = null;
+
+ int expRedSum = 0;
+ int expGreenSum = 0;
+ int expBlueSum = 0;
+
+ int reactRedSum = 0;
+ int reactGreenSum = 0;
+ int reactBlueSum = 0;
+
+ bool reactionKnown = true;
+
+ int pigmentCount = 0;
+
+ saveButton.Sensitive = false;
+
+ if (ingredient1ComboBox.GetActiveIter(out selectIter))
+ {
+ reagentName = (string)ingredient1ComboBox.Model.GetValue(selectIter, 0);
+ if ((reagentName == null) || (reagentName.Length == 0))
+ {
+ ingredient2ComboBox.Sensitive = false;
+ ingredient3ComboBox.Sensitive = false;
+ unmodifiedSwatch.Clear();
+ captureButton.Sensitive = false;
+ }
+ else
+ {
+ reagent1 = ReagentManager.GetReagent(reagentName);
+ ingredient2ComboBox.Sensitive = true;
+ if (!reagent1.IsCatalyst)
+ {
+ expRedSum = reagent1.Color.Red;
+ expGreenSum = reagent1.Color.Green;
+ expBlueSum = reagent1.Color.Blue;
+ pigmentCount = 1;
+ }
+ if (ingredient2ComboBox.GetActiveIter(out selectIter))
+ {
+ reagentName = (string)ingredient2ComboBox.Model.GetValue(selectIter, 0);
+ if ((reagentName == null) || (reagentName.Length == 0))
+ {
+ ingredient3ComboBox.Sensitive = false;
+ saveButton.Sensitive = false;
+ reactionKnown = false;
+ }
+ else
+ {
+ reagent2 = ReagentManager.GetReagent(reagentName);
+ ingredient3ComboBox.Sensitive = true;
+ captureButton.Sensitive = true;
+ if (!reagent2.IsCatalyst)
+ {
+ expRedSum += reagent2.Color.Red;
+ expGreenSum += reagent2.Color.Green;
+ expBlueSum += reagent2.Color.Blue;
+ pigmentCount++;
+ }
+
+ reaction1 = profile.FindReaction(reagent1, reagent2);
+
+ if (reaction1 != null)
+ {
+ ingredient3ComboBox.Sensitive = true;
+ reactRedSum = reaction1.Red;
+ reactGreenSum = reaction1.Green;
+ reactBlueSum = reaction1.Blue;;
+ }
+ else
+ {
+ reactionKnown = false;
+ ingredient3ComboBox.Sensitive = false;
+ }
+
+ if (ingredient3ComboBox.GetActiveIter(out selectIter))
+ {
+ reagentName = (string)ingredient3ComboBox.Model.GetValue(selectIter, 0);
+ if ((reagentName != null) && (reagentName.Length != 0))
+ {
+ reagent3 = ReagentManager.GetReagent(reagentName);
+
+ if (!reactionKnown)
+ {
+ MessageDialog md = new MessageDialog(this,
+ DialogFlags.DestroyWithParent,
+ MessageType.Error, ButtonsType.Ok,
+ "To do a three-ingredient reaction test, " +
+ "you must first recored the reaction of " +
+ "the first two ingredients.");
+
+ md.Run();
+ md.Destroy();
+ captureButton.Sensitive = false;
+ }
+
+ if (!reagent3.IsCatalyst)
+ {
+ expRedSum += reagent3.Color.Red;
+ expGreenSum += reagent3.Color.Green;
+ expBlueSum += reagent3.Color.Blue;
+ pigmentCount++;
+ }
+
+ reaction1 = profile.FindReaction(reagent1, reagent3);
+ reaction2 = profile.FindReaction(reagent2, reagent3);
+
+ if (reactionKnown && (reaction1 == null) && (reaction2 == null))
+ {
+ MessageDialog md = new MessageDialog(this,
+ DialogFlags.DestroyWithParent,
+ MessageType.Error, ButtonsType.Ok,
+ "To do a three-ingredient reaction test, " +
+ "you must first record the reaction of " +
+ "either the first or second ingredient " +
+ "with the third ingredient.");
+
+ md.Run();
+ md.Destroy();
+ captureButton.Sensitive = false;
+ }
+
+ if (reaction1 != null)
+ {
+ reactRedSum += reaction1.Red;
+ reactGreenSum += reaction1.Green;
+ reactBlueSum += reaction1.Blue;
+ }
+ else
+ {
+ reactionKnown = false;
+ }
+
+ if (reaction2 != null)
+ {
+ reactRedSum += reaction2.Red;
+ reactGreenSum += reaction2.Green;
+ reactBlueSum += reaction2.Blue;
+ }
+ else
+ {
+ reactionKnown = false;
+ }
+ }
+ }
+ }
+ }
+ SetExpectedColor((byte)Math.Round((float)expRedSum / (float)pigmentCount),
+ (byte)Math.Round((float)expGreenSum / (float)pigmentCount),
+ (byte)Math.Round((float)expBlueSum / (float)pigmentCount));
+
+ if (reactionKnown)
+ {
+ reactedColor.Red = (byte)Math.Min(255, Math.Max(0, expectedColor.Red + reactRedSum));
+ reactedColor.Green = (byte)Math.Min(255, Math.Max(0, expectedColor.Green + reactGreenSum));
+ reactedColor.Blue = (byte)Math.Min(255, Math.Max(0, expectedColor.Blue + reactBlueSum));
+ reactionSwatch.Color = reactedColor;
+ }
+ else
+ {
+ reactionSwatch.Clear();
+ }
+ }
+ }
+ }
+
+ protected void OnDeleteEvent(object sender, DeleteEventArgs a)
+ {
+ if (ConfirmedExit())
+ {
+ a.RetVal = true;
+ Application.Quit();
+ }
+ else
+ {
+ a.RetVal = false;
+ }
+ }
+
+ bool IsPapyTexture(byte r, byte g, byte b)
+ {
+ return ((r > 0xD0) && (g > 0xC8) && (b > 0xA0)) &&
+ ((r < 0xF4) && (g < 0xE0) && (b < 0xC4));
+ }
+
+ unsafe bool CaptureReactionColor()
+ {
+ // Take a screenshot.
+ byte r, g, b;
+ int pixelStart, otherPixelStart;
+ bool colorMatch;
+ screenBuffer.GetFromDrawable(rootWindow,
+ rootWindow.Colormap, 0, 0, 0, 0, screenWidth, screenHeight);
+ int stride = screenBuffer.Rowstride;
+ byte* pixBytes = (byte*)screenBuffer.Pixels;
+
+ for (int x = 0; x < screenWidth - colorBarWidth; ++x)
+ {
+ for (int y = 0; y < (screenHeight - 53); ++y)
+ {
+ // Look for the color swatch.
+ pixelStart = (y * stride) + (x * 3);
+ r = pixBytes[pixelStart];
+ g = pixBytes[pixelStart + 1];
+ b = pixBytes[pixelStart + 2];
+
+ // 1.) Check if this is a dark pixel.
+ if ((r < 0x42) && (g < 0x42) && (b <= 0x42))
+ {
+ // 2.) Check the pixel above it,
+ // to see if it's from the papy texture.
+ otherPixelStart = pixelStart - stride;
+ if ((otherPixelStart >= 0) &&
+ IsPapyTexture(pixBytes[otherPixelStart++],
+ pixBytes[otherPixelStart++],
+ pixBytes[otherPixelStart]))
+ {
+ // 3.) Check the pixel below where the swatch should be,
+ // to see if it's also from the papy texture.
+ otherPixelStart = pixelStart + (stride * swatchHeight);
+ if (IsPapyTexture(pixBytes[otherPixelStart++],
+ pixBytes[otherPixelStart++],
+ pixBytes[otherPixelStart]))
+ {
+ // pixBytes[pixelStart] = 0xFF;
+ // pixBytes[pixelStart + 1] = 0x00;
+ // pixBytes[pixelStart + 2] = 0xFF;
+
+ // 4.) Scan the left border of the potential swatch
+ // location.
+ colorMatch = true;
+ for (int i = 1; i < swatchHeight - 2; ++i)
+ {
+ otherPixelStart = pixelStart + (stride * i);
+ if ((Math.Abs(r - pixBytes[otherPixelStart++]) > colorTolerance) ||
+ (Math.Abs(g - pixBytes[otherPixelStart++]) > colorTolerance) ||
+ (Math.Abs(b - pixBytes[otherPixelStart]) > colorTolerance))
+ {
+ colorMatch = false;
+ break;
+ }
+ }
+
+ if (colorMatch)
+ {
+ // WE FOUND THE SWATCH!
+ // Now we know where the color bars are.
+ otherPixelStart = pixelStart + (redBarSpacing * stride);
+ int pixelCount = 0;
+ while ((Math.Abs(pixBytes[otherPixelStart] - 0xA1) < colorTolerance) &&
+ (Math.Abs(pixBytes[otherPixelStart + 1] - 0x04) < colorTolerance) &&
+ (Math.Abs(pixBytes[otherPixelStart + 2] - 0x03) < colorTolerance))
+ {
+ pixelCount++;
+ // pixBytes[otherPixelStart] = 0x00;
+ // pixBytes[otherPixelStart + 1] = 0xFF;
+ // pixBytes[otherPixelStart + 2] = 0xFF;
+ otherPixelStart += 3;
+ }
+
+ reactedColor.Red = (byte)Math.Round((float)pixelCount * 255f / (float)colorBarWidth);
+ otherPixelStart = pixelStart + (greenBarSpacing * stride);
+
+ pixelCount = 0;
+ while ((Math.Abs(pixBytes[otherPixelStart] - 0x04) < colorTolerance) &&
+ (Math.Abs(pixBytes[otherPixelStart + 1] - 0xA1) < colorTolerance) &&
+ (Math.Abs(pixBytes[otherPixelStart + 2] - 0x03) < colorTolerance))
+ {
+ pixelCount++;
+ // pixBytes[otherPixelStart] = 0x00;
+ // pixBytes[otherPixelStart + 1] = 0xFF;
+ // pixBytes[otherPixelStart + 2] = 0xFF;
+ otherPixelStart += 3;
+ }
+
+ reactedColor.Green = (byte)Math.Round((float)pixelCount * 255f / (float)colorBarWidth);
+ otherPixelStart = pixelStart + (blueBarSpacing * stride);
+
+ pixelCount = 0;
+ while ((Math.Abs(pixBytes[otherPixelStart] - 0x04) < colorTolerance) &&
+ (Math.Abs(pixBytes[otherPixelStart + 1] - 0x04) < colorTolerance) &&
+ (Math.Abs(pixBytes[otherPixelStart + 2] - 0xA1) < colorTolerance))
+ {
+ pixelCount++;
+ // pixBytes[otherPixelStart] = 0x00;
+ // pixBytes[otherPixelStart + 1] = 0xFF;
+ // pixBytes[otherPixelStart + 2] = 0xFF;
+ otherPixelStart += 3;
+ }
+
+ reactedColor.Blue = (byte)Math.Round((float)pixelCount * 255f / (float)colorBarWidth);
+
+
+ // screenBuffer.Save("screenshot.png", "png");
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ // screenBuffer.Save("screenshot.png", "png");
+
+ return false;
+
+ }
+
+ protected virtual void OnCaptureButton(object sender, System.EventArgs e)
+ {
+ if (CaptureReactionColor())
+ {
+ string warning = "";
+ if (reactedColor.Red == 0)
+ {
+ warning = warning + "\nRed is too low.";
+ }
+ if (reactedColor.Green == 0)
+ {
+ warning = warning + "\nGreen is too low.";
+ }
+ if (reactedColor.Blue == 0)
+ {
+ warning = warning + "\nBlue is too low.";
+ }
+ if (reactedColor.Red == 255)
+ {
+ warning = warning + "\nRed is too low.";
+ }
+ if (reactedColor.Green == 255)
+ {
+ warning = warning + "\nGreen is too low.";
+ }
+ if (reactedColor.Blue == 255)
+ {
+ warning = warning + "\nBlue is too low.";
+ }
+
+ if (warning.Length != 0)
+ {
+ MessageDialog md = new MessageDialog(this,
+ DialogFlags.DestroyWithParent,
+ MessageType.Error, ButtonsType.Ok,
+ "Reaction clipped. You will need to do a " +
+ "3-way reaction to test this pair. Details: " +
+ warning);
+
+ md.Run();
+ md.Destroy();
+ }
+ else
+ {
+ this.reactionSwatch.Color = reactedColor;
+ saveButton.Sensitive = true;
+ }
+ }
+ else
+ {
+ MessageDialog md = new MessageDialog(this,
+ DialogFlags.DestroyWithParent,
+ MessageType.Error, ButtonsType.Ok,
+ "Pigment Lab dialog box NOT FOUND. Please ensure " +
+ "that there is an unobstructed view of the dialog " +
+ "when you press the Capture button.");
+
+ md.Run();
+ md.Destroy();
+ }
+ }
+
+ protected virtual void OnSaveButton(object sender, System.EventArgs e)
+ {
+ int r, g, b;
+ if (reagent3 != null)
+ {
+ // A 3-reagent reaction.
+ Reaction reaction1 = profile.FindReaction(reagent1, reagent2);
+ Reaction reaction2 = profile.FindReaction(reagent1, reagent3);
+ Reaction reaction3 = profile.FindReaction(reagent2, reagent3);
+
+ r = reactedColor.Red - expectedColor.Red;
+ g = reactedColor.Green - expectedColor.Green;
+ b = reactedColor.Blue - expectedColor.Blue;
+
+ if (reaction2 == null)
+ {
+ r = r - reaction1.Red - reaction3.Red;
+ g = g - reaction1.Green - reaction3.Green;
+ b = b - reaction1.Blue - reaction3.Blue;
+ profile.SetReaction(reagent1, reagent3, new Reaction(r, g, b));
+ profile.Save();
+ saveButton.Sensitive = false;
+ }
+ else if (reaction3 == null)
+ {
+ r = r - reaction1.Red - reaction2.Red;
+ g = g - reaction1.Green - reaction2.Green;
+ b = b - reaction1.Blue - reaction2.Blue;
+ profile.SetReaction(reagent2, reagent3, new Reaction(r, g, b));
+ profile.Save();
+ saveButton.Sensitive = false;
+ }
+ }
+ else if ((reagent1 != null) && (reagent2 != null))
+ {
+ // A 2-reagent reaction.
+ r = reactedColor.Red - expectedColor.Red;
+ g = reactedColor.Green - expectedColor.Green;
+ b = reactedColor.Blue - expectedColor.Blue;
+ profile.SetReaction(reagent1, reagent2, new Reaction(r, g, b));
+ profile.Save();
+ saveButton.Sensitive = false;
+ }
+ }
+
+ protected virtual void OnChangedIngredient1(object sender, System.EventArgs e)
+ {
+ UpdateIngredients();
+ }
+
+ protected virtual void OnChangedIngredient2(object sender, System.EventArgs e)
+ {
+ UpdateIngredients();
+ }
+
+ protected virtual void OnChangedIngredient3(object sender, System.EventArgs e)
+ {
+ UpdateIngredients();
+
+ }
+
+ protected virtual void OnNewProfile(object sender, System.EventArgs e)
+ {
+ if (unsavedData)
+ {
+ MessageDialog md = new MessageDialog(this,
+ DialogFlags.DestroyWithParent,
+ MessageType.Warning, ButtonsType.OkCancel,
+ "Your last reaction was unsaved." +
+ "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();
+ PopulateDropDowns();
+ }
+ }
+
+ 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();
+ PopulateDropDowns();
+ }
+ }
+
+ protected virtual void OnAbout(object sender, System.EventArgs e)
+ {
+ AboutDialog aboutDialog = new AboutDialog();
+ aboutDialog.Run();
+ aboutDialog.Destroy();
+ }
+
+ protected virtual void OnMenuExit (object sender, System.EventArgs e)
+ {
+ if (ConfirmedExit())
+ {
+ Application.Quit();
+ }
+ }
+
+ protected virtual void OnExport(object sender, System.EventArgs e)
+ {
+ FileChooserDialog fileDialog =
+ new FileChooserDialog("Select destination file.",
+ this, FileChooserAction.Save,
+ Gtk.Stock.Cancel, ResponseType.Cancel,
+ Gtk.Stock.Save, ResponseType.Accept);
+ ResponseType resp = (ResponseType)fileDialog.Run();
+ if (resp == ResponseType.Accept)
+ {
+ string fileName = fileDialog.Filename;
+ string directory = fileDialog.CurrentFolder;
+ profile.Export(System.IO.Path.Combine(directory, fileName));
+ }
+ fileDialog.Destroy();
+ }
+
+ protected virtual void RunSimulator(object sender, System.EventArgs e)
+ {
+ SimulatorWindow win = new SimulatorWindow(profile);
+ win.Show();
+ }
+
+
+
+
+}
+
diff --git a/NewProfileDialog.cs b/NewProfileDialog.cs
new file mode 100644
--- /dev/null
+++ b/NewProfileDialog.cs
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010, Tess Snider
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ 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 System;
+namespace DesertPaintLab
+{
+ public partial class NewProfileDialog : Gtk.Dialog
+ {
+ public string ProfileName
+ {
+ get
+ {
+ return profileNameEntry.Text;
+ }
+ }
+
+ public NewProfileDialog ()
+ {
+ this.Build ();
+ }
+
+
+ }
+}
+
diff --git a/PaintColor.cs b/PaintColor.cs
new file mode 100644
--- /dev/null
+++ b/PaintColor.cs
@@ -0,0 +1,108 @@
+using System;
+namespace DesertPaintLab
+{
+ public class PaintColor
+ {
+ byte red;
+ byte green;
+ byte blue;
+
+ string name;
+
+ public byte Red
+ {
+ get
+ {
+ return red;
+ }
+ set
+ {
+ red = value;
+ }
+ }
+
+ public byte Blue
+ {
+ get
+ {
+ return blue;
+ }
+ set
+ {
+ blue = value;
+ }
+ }
+
+ public byte Green
+ {
+ get
+ {
+ return green;
+ }
+ set
+ {
+ green = value;
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return name;
+ }
+ set
+ {
+ name = value;
+ }
+ }
+
+ public PaintColor()
+ {
+ name = "Undefined";
+ red = 0;
+ green = 0;
+ blue = 0;
+ }
+
+ public PaintColor(string name, string hexRed, string hexGreen, string hexBlue)
+ {
+ this.name = name;
+ red = (byte)System.Int32.Parse(hexRed,
+ System.Globalization.NumberStyles.AllowHexSpecifier);
+ green = (byte)System.Int32.Parse(hexGreen,
+ System.Globalization.NumberStyles.AllowHexSpecifier);
+ blue = (byte)System.Int32.Parse(hexBlue,
+ System.Globalization.NumberStyles.AllowHexSpecifier);
+ }
+
+ public PaintColor(byte red, byte green, byte blue)
+ {
+ name = "Undefined";
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ }
+
+ public int GetDistanceSquared(PaintColor otherColor)
+ {
+ return (int)(Math.Pow(this.red - otherColor.red, 2) +
+ Math.Pow(this.green - otherColor.green, 2) +
+ Math.Pow(this.blue - otherColor.blue, 2));
+ }
+
+ public void Clear()
+ {
+ red = 0;
+ green = 0;
+ blue = 0;
+ }
+
+ public override string ToString()
+ {
+ return "[" + name + ", " + red + ", " + green + ", " + blue + "]";
+ }
+
+ }
+}
+
diff --git a/PaintSwatch.cs b/PaintSwatch.cs
new file mode 100644
--- /dev/null
+++ b/PaintSwatch.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace DesertPaintLab
+{
+ [System.ComponentModel.ToolboxItem(true)]
+ public partial class PaintSwatch : Gtk.Bin
+ {
+ PaintColor color;
+
+ public PaintColor Color
+ {
+ get
+ {
+ return color;
+ }
+
+ set
+ {
+ color.Red = value.Red;
+ color.Green = value.Green;
+ color.Blue = value.Blue;
+ colorBox.ModifyBg(Gtk.StateType.Normal, new Gdk.Color(color.Red, color.Green, color.Blue));
+ rgbLabel.Text = color.Red.ToString() + ", " +
+ color.Green.ToString() + ", " +
+ color.Blue.ToString();
+ colorNameLabel.Text = Palette.FindNearest(color);
+ }
+
+ }
+
+ public PaintSwatch ()
+ {
+ color = new PaintColor();
+ this.Build ();
+ }
+
+ public void Clear()
+ {
+ color.Clear();
+ colorBox.ModifyBg(Gtk.StateType.Normal, new Gdk.Color(color.Red, color.Green, color.Blue));
+ rgbLabel.Text = "???, ???, ???";
+ colorNameLabel.Text = "Unknown";
+ }
+
+ }
+}
+
diff --git a/Palette.cs b/Palette.cs
new file mode 100644
--- /dev/null
+++ b/Palette.cs
@@ -0,0 +1,56 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace DesertPaintLab
+{
+ public class Palette
+ {
+ static List colors = new List();
+ static Regex colorEntry = new Regex(@"\#(?\w\w)(?\w\w)(?\w\w)\s*(?\w+)");
+
+
+ public Palette ()
+ {
+
+ }
+
+ public static void Load(string file)
+ {
+ string line;
+ Match match;
+ using (StreamReader reader = new StreamReader(file))
+ {
+ while ((line = reader.ReadLine()) != null)
+ {
+ match = colorEntry.Match(line);
+ if (match.Success)
+ {
+ colors.Add(new PaintColor(match.Groups["name"].Value,
+ match.Groups["red"].Value,
+ match.Groups["green"].Value,
+ match.Groups["blue"].Value));
+ }
+ }
+ }
+ }
+
+ public static string FindNearest(PaintColor color)
+ {
+ int bestDistSq = int.MaxValue;
+ PaintColor bestColor = null;
+ foreach (PaintColor paintColor in colors)
+ {
+ int distSq = paintColor.GetDistanceSquared(color);
+ if (distSq < bestDistSq)
+ {
+ bestDistSq = distSq;
+ bestColor = paintColor;
+ }
+ }
+ return bestColor.Name;
+ }
+ }
+}
+
diff --git a/PlayerProfile.cs b/PlayerProfile.cs
new file mode 100644
--- /dev/null
+++ b/PlayerProfile.cs
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2010, Tess Snider
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ 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 System;
+using System.IO;
+using System.Collections.Generic;
+
+namespace DesertPaintLab
+{
+ public class PlayerProfile
+ {
+ string name;
+ string directory;
+ string reactFile;
+
+ SortedDictionary> reactions =
+ new SortedDictionary>();
+
+ public PlayerProfile(string name, string directory)
+ {
+ this.name = name;
+ this.directory = directory;
+ this.reactFile = System.IO.Path.Combine(directory, "dp_reactions.txt");
+ }
+
+ public void Initialize()
+ {
+ // Create new directory.
+ System.IO.Directory.CreateDirectory(directory);
+
+ // Copy template files into new directory.
+ string templatePath = System.IO.Path.Combine(
+ System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
+ "template");
+
+ 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);
+ }
+ }
+
+ 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] != "//"))
+ {
+ // Write reaction.
+ writer.Write(tokens[0] + " " + tokens[2] + " ");
+ switch (tokens[4])
+ {
+ case "W":
+ writer.WriteLine(tokens[6] + " " + tokens[6] + " " + tokens[6]);
+ break;
+ case "R":
+ writer.WriteLine(tokens[6] + " 0 0");
+ break;
+ case "G":
+ writer.WriteLine("0 " + tokens[6] + " 0");
+ break;
+ case "B":
+ writer.WriteLine("0 0 " + tokens[6]);
+ break;
+ }
+
+ // Write reverse reaction.
+ writer.Write(tokens[2] + " " + tokens[0] + " ");
+ switch (tokens[4])
+ {
+ case "W":
+ writer.WriteLine(tokens[8] + " " + tokens[8] + " " + tokens[8]);
+ break;
+ case "R":
+ writer.WriteLine(tokens[8] + " 0 0");
+ break;
+ case "G":
+ writer.WriteLine("0 " + tokens[8] + " 0");
+ break;
+ case "B":
+ writer.WriteLine("0 0 " + tokens[8]);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public bool SaveToPP(string ppFile)
+ {
+ Reaction reaction1, reaction2;
+ SortedDictionary secondReagentDict;
+ using (StreamWriter writer = new StreamWriter(ppFile))
+ {
+ foreach (KeyValuePair> firstPair in reactions)
+ {
+ foreach (KeyValuePair secondPair in firstPair.Value)
+ {
+ reaction1 = secondPair.Value;
+ if ((reaction1 != null) && !reaction1.Exported)
+ {
+ reaction2 = null;
+ reactions.TryGetValue(secondPair.Key, out secondReagentDict);
+ if (secondReagentDict != null)
+ {
+ secondReagentDict.TryGetValue(firstPair.Key, out reaction2);
+ }
+ if (reaction2 != null)
+ {
+ writer.Write(firstPair.Key + " | " + secondPair.Key + " | ");
+ if ((Math.Abs(reaction1.Red) > Math.Abs(reaction1.Green)) ||
+ (Math.Abs(reaction2.Red) > Math.Abs(reaction2.Green)))
+ {
+ writer.WriteLine("R | " + reaction1.Red + " | " + reaction2.Red);
+ }
+ else if ((Math.Abs(reaction1.Green) > Math.Abs(reaction1.Red)) ||
+ (Math.Abs(reaction2.Green) > Math.Abs(reaction2.Red)))
+ {
+ writer.WriteLine("G | " + reaction1.Green + " | " + reaction2.Green);
+ }
+ else if ((Math.Abs(reaction1.Blue) > Math.Abs(reaction1.Red)) ||
+ (Math.Abs(reaction2.Blue) > Math.Abs(reaction2.Red)))
+ {
+ writer.WriteLine("B | " + reaction1.Blue + " | " + reaction2.Blue);
+ }
+ else
+ {
+ writer.WriteLine("W | " + reaction1.Red + " | " + reaction2.Red);
+ }
+ reaction1.Exported = true;
+ reaction2.Exported = true;
+ }
+ }
+ }
+ }
+ }
+
+ // Clear Exported flags.
+ foreach (KeyValuePair> firstPair in reactions)
+ {
+ foreach (KeyValuePair secondPair in firstPair.Value)
+ {
+ if (secondPair.Value != null)
+ {
+ secondPair.Value.Exported = false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public void Import(string importDir)
+ {
+ // Convert old file.
+ ConvertFromPP(
+ System.IO.Path.Combine(importDir, "reactions.txt"),
+ reactFile);
+ try
+ {
+ // If there is an ingredients file, move it in.
+ System.IO.File.Copy(
+ System.IO.Path.Combine(importDir, "ingredients.txt"),
+ System.IO.Path.Combine(directory, "ingredients.txt"),
+ true);
+ }
+ catch (Exception)
+ {
+ // If there is no ingredients file, we don't really care.
+ }
+ }
+
+ public void Export(string file)
+ {
+ SaveToPP(file);
+ }
+
+ public void Load()
+ {
+ string line;
+ SortedDictionary dict;
+ reactions.Clear();
+ ReagentManager.Load(System.IO.Path.Combine(directory, "ingredients.txt"));
+ ReagentManager.InitializeReactions(ref reactions);
+ using (StreamReader reader = new StreamReader(reactFile))
+ {
+ while ((line = reader.ReadLine()) != null)
+ {
+ string[] tokens = line.Split(null);
+ reactions.TryGetValue(tokens[0], out dict);
+ dict[tokens[1]] = new Reaction(int.Parse(tokens[2]), int.Parse(tokens[3]), int.Parse(tokens[4]));
+ }
+ }
+ }
+
+ public void Save()
+ {
+ Reaction reaction;
+ using (StreamWriter writer = new StreamWriter(reactFile, false))
+ {
+ foreach (KeyValuePair> firstPair in reactions)
+ {
+ foreach (KeyValuePair secondPair in firstPair.Value)
+ {
+ reaction = secondPair.Value;
+
+ if (reaction != null)
+ {
+ writer.WriteLine(firstPair.Key + " " + secondPair.Key + " " +
+ reaction.Red + " " + reaction.Green + " " + reaction.Blue);
+ }
+ }
+ }
+ }
+ }
+
+ public Reaction FindReaction(Reagent reagent1, Reagent reagent2)
+ {
+ SortedDictionary secondReagentDict = null;
+ Reaction reaction = null;
+ reactions.TryGetValue(reagent1.Name, out secondReagentDict);
+ if (secondReagentDict != null)
+ {
+ secondReagentDict.TryGetValue(reagent2.Name, out reaction);
+ }
+ return reaction;
+ }
+
+ public void SetReaction(Reagent reagent1, Reagent reagent2, Reaction reaction)
+ {
+ SortedDictionary secondReagentDict = null;
+ reactions.TryGetValue(reagent1.Name, out secondReagentDict);
+ if (secondReagentDict != null)
+ {
+ secondReagentDict[reagent2.Name] = reaction;
+ }
+ }
+ }
+}
+
diff --git a/Reaction.cs b/Reaction.cs
new file mode 100644
--- /dev/null
+++ b/Reaction.cs
@@ -0,0 +1,61 @@
+using System;
+namespace DesertPaintLab
+{
+ public class Reaction
+ {
+ int red = 0;
+ int green = 0;
+ int blue = 0;
+ bool exported = false;
+
+ public int Red
+ {
+ get
+ {
+ return red;
+ }
+ }
+
+ public int Green
+ {
+ get
+ {
+ return green;
+ }
+ }
+
+ public int Blue
+ {
+ get
+ {
+ return blue;
+ }
+ }
+
+ public bool Exported
+ {
+ get
+ {
+ return exported;
+ }
+ set
+ {
+ exported = value;
+ }
+ }
+
+ public Reaction(int r, int g, int b)
+ {
+ red = r;
+ green = g;
+ blue = b;
+ }
+
+ public override string ToString()
+ {
+ return "[" + red + ", " + green + ", " + blue + "]";
+ }
+
+ }
+}
+
diff --git a/Reagent.cs b/Reagent.cs
new file mode 100644
--- /dev/null
+++ b/Reagent.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace DesertPaintLab
+{
+ public class Reagent
+ {
+ string name;
+ bool isCatalyst = false;
+ PaintColor color;
+
+ public bool IsCatalyst
+ {
+ get
+ {
+ return isCatalyst;
+ }
+ }
+
+ public PaintColor Color
+ {
+ get
+ {
+ return color;
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return name;
+ }
+ }
+
+ public Reagent(string name)
+ {
+ this.name = name;
+ isCatalyst = true;
+ }
+
+ public Reagent(string name, byte red, byte green, byte blue)
+ {
+ color = new PaintColor(red, green, blue);
+ this.name = name;
+ }
+
+ public override string ToString()
+ {
+ if (isCatalyst)
+ {
+ return "[" + name + ", catalyst]";
+ }
+ else
+ {
+ return "[" + name + ", " + color.ToString() + "]";
+ }
+ }
+
+
+ }
+}
+
diff --git a/ReagentManager.cs b/ReagentManager.cs
new file mode 100644
--- /dev/null
+++ b/ReagentManager.cs
@@ -0,0 +1,128 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace DesertPaintLab
+{
+ public class ReagentManager
+ {
+ static Regex reagentRegex = new Regex(@"(?\w+)\s*\|\s*(?\d+),\s*(?\d+),\s*(?\d+).*");
+ static Regex catalystRegex = new Regex(@"(?\w+)\s*\|\s*catalyst");
+
+ static SortedDictionary reagents = new SortedDictionary();
+
+ static Gtk.ListStore nameStore = new Gtk.ListStore(typeof(string));
+
+ static public Gtk.ListStore NameListModel
+ {
+ get
+ {
+ return nameStore;
+ }
+ }
+
+ public ReagentManager ()
+ {
+
+ }
+
+ public static void Load(string file)
+ {
+ Match match;
+ string line;
+ reagents.Clear();
+ using (StreamReader reader = new StreamReader(file))
+ {
+ while ((line = reader.ReadLine()) != null)
+ {
+ match = reagentRegex.Match(line);
+ if (match.Success)
+ {
+ string name = match.Groups["name"].Value;
+ reagents.Add(name,
+ new Reagent(name,
+ byte.Parse(match.Groups["red"].Value),
+ byte.Parse(match.Groups["green"].Value),
+ byte.Parse(match.Groups["blue"].Value)));
+ nameStore.AppendValues(name);
+ }
+ else
+ {
+ match = catalystRegex.Match(line);
+ if (match.Success)
+ {
+ string name = match.Groups["name"].Value;
+ reagents.Add(name, new Reagent(name));
+ nameStore.AppendValues(name);
+ }
+ }
+ }
+ }
+ }
+
+ public static void InitializeReactions(ref SortedDictionary> reactions)
+ {
+ foreach (KeyValuePair pair1 in reagents)
+ {
+ SortedDictionary dict = new SortedDictionary();
+ foreach (KeyValuePair pair2 in reagents)
+ {
+ if (pair1.Key != pair2.Key)
+ {
+ dict.Add(pair2.Key, null);
+ }
+ }
+ reactions.Add(pair1.Key, dict);
+ }
+ }
+
+ public static void PopulateReagents(ref Gtk.ComboBox comboBox)
+ {
+ comboBox.Clear();
+
+ Gtk.CellRendererText cell = new Gtk.CellRendererText();
+ comboBox.PackStart(cell, false);
+ comboBox.AddAttribute(cell, "text", 0);
+ Gtk.ListStore store = new Gtk.ListStore(typeof(string));
+ comboBox.Model = store;
+
+ store.AppendValues("");
+ foreach (KeyValuePair pair in reagents)
+ {
+ store.AppendValues(pair.Key);
+ }
+ }
+
+ /*
+ public static void PopulatePigments(ref Gtk.ComboBox comboBox)
+ {
+ comboBox.Clear();
+
+ Gtk.CellRendererText cell = new Gtk.CellRendererText();
+ comboBox.PackStart(cell, false);
+ comboBox.AddAttribute(cell, "text", 0);
+ Gtk.ListStore store = new Gtk.ListStore(typeof(string));
+ comboBox.Model = store;
+
+ store.AppendValues("");
+ foreach (KeyValuePair pair in reagents)
+ {
+ if (!pair.Value.IsCatalyst)
+ {
+ store.AppendValues(pair.Key);
+ }
+ }
+ }
+ */
+
+ public static Reagent GetReagent(string reagentName)
+ {
+ Reagent returnVal;
+ reagents.TryGetValue(reagentName, out returnVal);
+ return returnVal;
+ }
+ }
+
+}
+
diff --git a/SelectProfileDialog.cs b/SelectProfileDialog.cs
new file mode 100644
--- /dev/null
+++ b/SelectProfileDialog.cs
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2010, Tess Snider
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ 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 System;
+using System.Collections.Generic;
+
+namespace DesertPaintLab
+{
+ public partial class SelectProfileDialog : Gtk.Dialog
+ {
+ List profileList = null;
+ Gtk.ListStore profileStore = new Gtk.ListStore(typeof(string));
+ string selectedProfile;
+
+ public int ProfileCount
+ {
+ get
+ {
+ return profileList.Count;
+ }
+ }
+
+ public List ProfileList
+ {
+ get
+ {
+ return profileList;
+ }
+ set
+ {
+ profileList = value;
+ profileStore.Clear();
+ foreach (string name in profileList)
+ {
+ profileStore.AppendValues(name);
+ }
+ }
+ }
+
+ public string SelectedProfile
+ {
+ get
+ {
+ return selectedProfile;
+ }
+ }
+
+ public SelectProfileDialog()
+ {
+ this.Build();
+
+ Gtk.TreeViewColumn nameColumn = new Gtk.TreeViewColumn();
+ Gtk.CellRendererText nameColumnCell = new Gtk.CellRendererText();
+ nameColumn.PackStart(nameColumnCell, true);
+ nameColumn.Title = "Name";
+ profileListView.AppendColumn(nameColumn);
+ nameColumn.AddAttribute(nameColumnCell, "text", 0);
+
+ profileListView.Model = profileStore;
+ }
+
+ protected virtual void OnCursorChanged(object sender, System.EventArgs e)
+ {
+ Gtk.TreeModel model;
+ Gtk.TreeIter iter;
+
+ Gtk.TreeSelection selection = profileListView.Selection;
+ if ((selection != null) && selection.GetSelected(out model, out iter))
+ {
+ selectedProfile = model.GetValue(iter, 0).ToString();
+ }
+ else
+ {
+ selectedProfile = "";
+ }
+ }
+
+ }
+}
+
diff --git a/SimWindow.cs b/SimWindow.cs
new file mode 100644
--- /dev/null
+++ b/SimWindow.cs
@@ -0,0 +1,12 @@
+using System;
+namespace DesertPaintLab
+{
+ public partial class SimWindow : Gtk.Window
+ {
+ public SimWindow () : base(Gtk.WindowType.Toplevel)
+ {
+ this.Build ();
+ }
+ }
+}
+
diff --git a/SimulatorWindow.cs b/SimulatorWindow.cs
new file mode 100644
--- /dev/null
+++ b/SimulatorWindow.cs
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2010, Tess Snider
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ 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 System;
+using System.Collections.Generic;
+
+namespace DesertPaintLab
+{
+ public partial class SimulatorWindow : Gtk.Window
+ {
+ PlayerProfile profile;
+ Gtk.ListStore recipeData = new Gtk.ListStore(typeof(string), typeof(int));
+
+ public SimulatorWindow(PlayerProfile profile) : base(Gtk.WindowType.Toplevel)
+ {
+ this.profile = profile;
+ this.Build ();
+
+ Gtk.TreeViewColumn reagentColumn = new Gtk.TreeViewColumn();
+ Gtk.CellRendererText reagentColumnCell = new Gtk.CellRendererText();
+ reagentColumn.PackStart(reagentColumnCell, true);
+ reagentColumn.Title = "Ingredient";
+
+ reagentListView.AppendColumn(reagentColumn);
+ reagentColumn.AddAttribute(reagentColumnCell, "text", 0);
+
+ reagentListView.Model = ReagentManager.NameListModel;
+
+ Gtk.TreeViewColumn additiveColumn = new Gtk.TreeViewColumn();
+ Gtk.CellRendererText additiveColumnCell = new Gtk.CellRendererText();
+ additiveColumn.PackStart(additiveColumnCell, true);
+ additiveColumn.Title = "Ingredient";
+
+ recipeView.AppendColumn(additiveColumn);
+ additiveColumn.AddAttribute(additiveColumnCell, "text", 0);
+
+ Gtk.TreeViewColumn qtyColumn = new Gtk.TreeViewColumn();
+ Gtk.CellRendererText qtyColumnCell = new Gtk.CellRendererText();
+ qtyColumnCell.Editable = true;
+ qtyColumnCell.Edited += OnQtyEdited;
+ qtyColumn.PackStart(qtyColumnCell, true);
+ qtyColumn.Title = "Qty";
+
+ recipeView.AppendColumn(qtyColumn);
+ qtyColumn.AddAttribute(qtyColumnCell, "text", 1);
+
+ recipeView.Model = recipeData;
+
+ recipeData.RowChanged += OnRecipeChanged;
+ recipeData.RowDeleted += OnRecipeChanged;
+ recipeData.RowInserted += OnRecipeChanged;
+ recipeData.RowsReordered += OnRecipeChanged;
+
+ }
+
+ protected virtual void OnAddReagent(object sender, System.EventArgs e)
+ {
+ Gtk.TreeModel model;
+ Gtk.TreeIter iter;
+
+ Gtk.TreeSelection selection = reagentListView.Selection;
+ if ((selection != null) && selection.GetSelected(out model, out iter))
+ {
+ recipeData.AppendValues(model.GetValue(iter, 0).ToString(), 1);
+
+ recipeData.IterNthChild(out iter, recipeView.Children.Length - 1);
+
+ selection = recipeView.Selection;
+ selection.SelectIter(iter);
+ }
+ }
+
+ protected void OnQtyEdited(object sender, Gtk.EditedArgs args)
+ {
+ Gtk.TreeIter iter;
+ recipeData.GetIter(out iter, new Gtk.TreePath(args.Path));
+
+ int oldValue = (int)recipeData.GetValue(iter, 1);
+
+ try
+ {
+ recipeData.SetValue(iter, 1, int.Parse(args.NewText));
+ UpdateRecipeColor();
+ }
+ catch (Exception)
+ {
+ recipeData.SetValue(iter, 1, oldValue);
+ }
+ }
+
+ protected void OnRecipeChanged(object sender, GLib.SignalArgs args)
+ {
+ UpdateRecipeColor();
+ }
+
+ void UpdateRecipeColor()
+ {
+ if (recipeView.Children.Length == 0)
+ {
+ paintSwatch.Clear();
+ }
+
+ Reaction reaction;
+ Gtk.TreeIter iter;
+ string reagentName;
+ int qty;
+ PaintColor color = null;
+ Reagent reagent = null;
+
+ int baseRedSum = 0;
+ int baseGreenSum = 0;
+ int baseBlueSum = 0;
+
+ int reactRedSum = 0;
+ int reactGreenSum = 0;
+ int reactBlueSum = 0;
+
+ int pigmentCount = 0;
+
+ SortedDictionary reagentSet = new SortedDictionary();
+ List reagents = new List();
+
+ recipeData.GetIterFirst(out iter);
+
+ do
+ {
+ reagentName = (string) recipeData.GetValue(iter, 0);
+
+ if (reagentName == null)
+ {
+ continue;
+ }
+
+ qty = (int)recipeData.GetValue(iter, 1);
+ reagent = ReagentManager.GetReagent(reagentName);
+ if (!reagent.IsCatalyst)
+ {
+ color = reagent.Color;
+ baseRedSum += qty * color.Red;
+ baseGreenSum += qty * color.Green;
+ baseBlueSum += qty * color.Blue;
+ pigmentCount += qty;
+ }
+ if (!reagentSet.ContainsKey(reagentName) && reagentSet.Count <= 4)
+ {
+ reagentSet[reagentName] = true;
+ // Run reactions.
+ foreach (Reagent otherReagent in reagents)
+ {
+ reaction = profile.FindReaction(otherReagent, reagent);
+ if (reaction != null)
+ {
+ reactRedSum += reaction.Red;
+ reactGreenSum += reaction.Green;
+ reactBlueSum += reaction.Blue;
+ }
+ }
+ reagents.Add(reagent);
+ }
+
+ }
+ while (recipeData.IterNext(ref iter));
+
+ paintSwatch.Color = new PaintColor(
+ CalculateColor(baseRedSum, pigmentCount, reactRedSum),
+ CalculateColor(baseGreenSum, pigmentCount, reactGreenSum),
+ CalculateColor(baseBlueSum, pigmentCount, reactBlueSum));
+ }
+
+ byte CalculateColor(int baseSum, int pigmentCount, int reactSum)
+ {
+ return (byte)Math.Max(Math.Min(Math.Round((((float)baseSum / (float)pigmentCount) + (float)reactSum)), 255), 0);
+ }
+
+ protected virtual void OnIncrementReagent (object sender, System.EventArgs e)
+ {
+ Gtk.TreeModel model;
+ Gtk.TreeIter iter;
+
+ Gtk.TreeSelection selection = recipeView.Selection;
+ if ((selection != null) && selection.GetSelected(out model, out iter))
+ {
+ int oldValue = (int)recipeData.GetValue(iter, 1);
+ recipeData.SetValue(iter, 1, oldValue + 1);
+ }
+
+ }
+
+ protected virtual void OnDecrementReagent (object sender, System.EventArgs e)
+ {
+ Gtk.TreeModel model;
+ Gtk.TreeIter iter;
+
+ Gtk.TreeSelection selection = recipeView.Selection;
+ if ((selection != null) && selection.GetSelected(out model, out iter))
+ {
+ int oldValue = (int)recipeData.GetValue(iter, 1);
+ if (oldValue == 1)
+ {
+ recipeData.Remove(ref iter);
+ }
+ else
+ {
+ recipeData.SetValue(iter, 1, oldValue - 1);
+ }
+ }
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/bin/Debug/DesertPaintLab/colors.txt b/bin/Debug/DesertPaintLab/colors.txt
new file mode 100644
--- /dev/null
+++ b/bin/Debug/DesertPaintLab/colors.txt
@@ -0,0 +1,142 @@
+#F0F8FF AliceBlue
+#FAEBD7 AntiqueWhite
+#00FFFF Aqua
+#7FFFD4 Aquamarine
+#F0FFFF Azure
+#F5F5DC Beige
+#FFE4C4 Bisque
+#010101 Black
+#FFEBCD BlanchedAlmond
+#0000FF Blue
+#8A2BE2 BlueViolet
+#A52A2A Brown
+#DEB887 Burlywood
+#5F9EA0 CadetBlue
+#E07020 Carrot
+#7FFF00 Chartreuse
+#D2691E Chocolate
+#FF7F50 Coral
+#6495ED CornflowerBlue
+#FFF8DC Cornsilk
+#DC143C Crimson
+#00008B DarkBlue
+#008B8B DarkCyan
+#B8860B DarkGoldenrod
+#A9A9A9 DarkGray
+#006400 DarkGreen
+#BDB76B DarkKhaki
+#8B008B DarkMagenta
+#556B2F DarkOliveGreen
+#FF8C00 DarkOrange
+#9932CC DarkOrchid
+#8B0000 DarkRed
+#E9967A DarkSalmon
+#8FBC8F DarkSeaGreen
+#483D8B DarkSlateBlue
+#2F4F4F DarkSlateGray
+#00CED1 DarkTurquoise
+#9400D3 DarkViolet
+#FF1493 DeepPink
+#00BFFF DeepSkyBlue
+#696969 DimGray
+#1E90FF DodgerBlue
+#D19275 Feldspar
+#B22222 FireBrick
+#FFFAF0 FloralWhite
+#228B22 ForestGreen
+#FF00FF Fuchsia
+#DCDCDC Gainsboro
+#F8F8FF GhostWhite
+#FFD700 Gold
+#DAA520 Goldenrod
+#808080 Gray
+#008000 Green
+#ADFF2F GreenYellow
+#F0FFF0 Honeydew
+#FF69B4 HotPink
+#CD5C5C IndianRed
+#4B0082 Indigo
+#FFFFF0 Ivory
+#F0E68C Khaki
+#E6E6FA Lavender
+#FFF0F5 LavenderBlush
+#7CFC00 LawnGreen
+#FFFACD LemonChiffon
+#ADD8E6 LightBlue
+#F08080 LightCoral
+#E0FFFF LightCyan
+#FAFAD2 LightGoldenrodYellow
+#90EE90 LightGreen
+#D3D3D3 LightGrey
+#FFB6C1 LightPink
+#FFA07A LightSalmon
+#20B2AA LightSeaGreen
+#87CEFA LightSkyBlue
+#8470FF LightSlateBlue
+#778899 LightSlateGray
+#B0C4DE LightSteelBlue
+#FFFFE0 LightYellow
+#00FF00 Lime
+#32CD32 LimeGreen
+#FAF0E6 Linen
+#800000 Maroon
+#66CDAA MediumAquamarine
+#0000CD MediumBlue
+#BA55D3 MediumOrchid
+#9370DB MediumPurple
+#3CB371 MediumSeaGreen
+#7B68EE MediumSlateBlue
+#00FA9A MediumSpringGreen
+#48D1CC MediumTurquoise
+#C71585 MediumVioletRed
+#191970 MidnightBlue
+#F5FFFA MintCream
+#FFE4E1 MistyRose
+#FFE4B5 Moccasin
+#FFDEAD NavajoWhite
+#000080 Navy
+#FDF5E6 OldLace
+#808000 Olive
+#6B8E23 OliveDrab
+#FFA500 Orange
+#FF4500 OrangeRed
+#DA70D6 Orchid
+#EEE8AA PaleGoldenrod
+#98FB98 PaleGreen
+#AFEEEE PaleTurquoise
+#DB7093 PaleVioletRed
+#FFEFD5 PapayaWhip
+#FFDAB9 PeachPuff
+#CD853F Peru
+#FFC0CB Pink
+#DDA0DD Plum
+#B0E0E6 PowderBlue
+#800080 Purple
+#FF0000 Red
+#BC8F8F RosyBrown
+#4169E1 RoyalBlue
+#8B4513 SaddleBrown
+#FA8072 Salmon
+#F4A460 SandyBrown
+#2E8B57 SeaGreen
+#FFF5EE Seashell
+#A0522D Sienna
+#C0C0C0 Silver
+#87CEEB SkyBlue
+#6A5ACD SlateBlue
+#708090 SlateGray
+#FFFAFA Snow
+#00FF7F SpringGreen
+#4682B4 SteelBlue
+#D2B48C Tan
+#008080 Teal
+#D8BFD8 Thistle
+#FF6347 Tomato
+#40E0D0 Turquoise
+#EE82EE Violet
+#D02090 VioletRed
+#F5DEB3 Wheat
+#FFFFFF White
+#F5F5F5 WhiteSmoke
+#FFFF00 Yellow
+#9ACD32 YellowGreen
\ No newline at end of file
diff --git a/bin/Debug/DesertPaintLab/template/dp_reactions.txt b/bin/Debug/DesertPaintLab/template/dp_reactions.txt
new file mode 100644
--- /dev/null
+++ b/bin/Debug/DesertPaintLab/template/dp_reactions.txt
@@ -0,0 +1,1 @@
+
\ No newline at end of file
diff --git a/bin/Debug/DesertPaintLab/template/ingredients.txt b/bin/Debug/DesertPaintLab/template/ingredients.txt
new file mode 100644
--- /dev/null
+++ b/bin/Debug/DesertPaintLab/template/ingredients.txt
@@ -0,0 +1,21 @@
+// Ingredients are in the form:
+// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)
+//
+// It is recommended to only change the cost value
+// It is not recommended to set many of the ingredients above 10 per paint
+
+Cabbage | 128, 64, 144 | 8 | Y | bulk | 10
+Clay | 128, 96, 32 | 4 | Y | bulk | 20
+Carrot | 224, 112, 32 | 10 | Y | bulk | 10
+Copper | 64, 192, 192 | 30 | Y | normal | 8
+Iron | 96, 48, 32 | 30 | Y | normal | 8
+Lead | 80, 80, 96 | 50 | Y | normal | 6
+RedSand | 144, 16, 24 | 10 | Y | bulk | 20
+Silver | 16, 16, 32 | 50 | N | normal | 6
+ToadSkin | 48, 96, 48 | 500 | N | normal | 4
+DeadTongue | 112, 64, 64 | 500 | N | normal | 4
+EarthLight | 128, 240, 224 | 10000 | N | normal | 4
+Lime | catalyst | 20 | Y | normal | 1
+Sulfur | catalyst | 10 | Y | normal | 1
+Potash | catalyst | 50 | Y | normal | 1
+Saltpeter | catalyst | 10 | Y | normal | 1
\ No newline at end of file
diff --git a/bin/Debug/colors.txt b/bin/Debug/colors.txt
new file mode 100644
--- /dev/null
+++ b/bin/Debug/colors.txt
@@ -0,0 +1,142 @@
+#F0F8FF AliceBlue
+#FAEBD7 AntiqueWhite
+#00FFFF Aqua
+#7FFFD4 Aquamarine
+#F0FFFF Azure
+#F5F5DC Beige
+#FFE4C4 Bisque
+#010101 Black
+#FFEBCD BlanchedAlmond
+#0000FF Blue
+#8A2BE2 BlueViolet
+#A52A2A Brown
+#DEB887 Burlywood
+#5F9EA0 CadetBlue
+#E07020 Carrot
+#7FFF00 Chartreuse
+#D2691E Chocolate
+#FF7F50 Coral
+#6495ED CornflowerBlue
+#FFF8DC Cornsilk
+#DC143C Crimson
+#00008B DarkBlue
+#008B8B DarkCyan
+#B8860B DarkGoldenrod
+#A9A9A9 DarkGray
+#006400 DarkGreen
+#BDB76B DarkKhaki
+#8B008B DarkMagenta
+#556B2F DarkOliveGreen
+#FF8C00 DarkOrange
+#9932CC DarkOrchid
+#8B0000 DarkRed
+#E9967A DarkSalmon
+#8FBC8F DarkSeaGreen
+#483D8B DarkSlateBlue
+#2F4F4F DarkSlateGray
+#00CED1 DarkTurquoise
+#9400D3 DarkViolet
+#FF1493 DeepPink
+#00BFFF DeepSkyBlue
+#696969 DimGray
+#1E90FF DodgerBlue
+#D19275 Feldspar
+#B22222 FireBrick
+#FFFAF0 FloralWhite
+#228B22 ForestGreen
+#FF00FF Fuchsia
+#DCDCDC Gainsboro
+#F8F8FF GhostWhite
+#FFD700 Gold
+#DAA520 Goldenrod
+#808080 Gray
+#008000 Green
+#ADFF2F GreenYellow
+#F0FFF0 Honeydew
+#FF69B4 HotPink
+#CD5C5C IndianRed
+#4B0082 Indigo
+#FFFFF0 Ivory
+#F0E68C Khaki
+#E6E6FA Lavender
+#FFF0F5 LavenderBlush
+#7CFC00 LawnGreen
+#FFFACD LemonChiffon
+#ADD8E6 LightBlue
+#F08080 LightCoral
+#E0FFFF LightCyan
+#FAFAD2 LightGoldenrodYellow
+#90EE90 LightGreen
+#D3D3D3 LightGrey
+#FFB6C1 LightPink
+#FFA07A LightSalmon
+#20B2AA LightSeaGreen
+#87CEFA LightSkyBlue
+#8470FF LightSlateBlue
+#778899 LightSlateGray
+#B0C4DE LightSteelBlue
+#FFFFE0 LightYellow
+#00FF00 Lime
+#32CD32 LimeGreen
+#FAF0E6 Linen
+#800000 Maroon
+#66CDAA MediumAquamarine
+#0000CD MediumBlue
+#BA55D3 MediumOrchid
+#9370DB MediumPurple
+#3CB371 MediumSeaGreen
+#7B68EE MediumSlateBlue
+#00FA9A MediumSpringGreen
+#48D1CC MediumTurquoise
+#C71585 MediumVioletRed
+#191970 MidnightBlue
+#F5FFFA MintCream
+#FFE4E1 MistyRose
+#FFE4B5 Moccasin
+#FFDEAD NavajoWhite
+#000080 Navy
+#FDF5E6 OldLace
+#808000 Olive
+#6B8E23 OliveDrab
+#FFA500 Orange
+#FF4500 OrangeRed
+#DA70D6 Orchid
+#EEE8AA PaleGoldenrod
+#98FB98 PaleGreen
+#AFEEEE PaleTurquoise
+#DB7093 PaleVioletRed
+#FFEFD5 PapayaWhip
+#FFDAB9 PeachPuff
+#CD853F Peru
+#FFC0CB Pink
+#DDA0DD Plum
+#B0E0E6 PowderBlue
+#800080 Purple
+#FF0000 Red
+#BC8F8F RosyBrown
+#4169E1 RoyalBlue
+#8B4513 SaddleBrown
+#FA8072 Salmon
+#F4A460 SandyBrown
+#2E8B57 SeaGreen
+#FFF5EE Seashell
+#A0522D Sienna
+#C0C0C0 Silver
+#87CEEB SkyBlue
+#6A5ACD SlateBlue
+#708090 SlateGray
+#FFFAFA Snow
+#00FF7F SpringGreen
+#4682B4 SteelBlue
+#D2B48C Tan
+#008080 Teal
+#D8BFD8 Thistle
+#FF6347 Tomato
+#40E0D0 Turquoise
+#EE82EE Violet
+#D02090 VioletRed
+#F5DEB3 Wheat
+#FFFFFF White
+#F5F5F5 WhiteSmoke
+#FFFF00 Yellow
+#9ACD32 YellowGreen
\ No newline at end of file
diff --git a/bin/Debug/template/dp_reactions.txt b/bin/Debug/template/dp_reactions.txt
new file mode 100644
--- /dev/null
+++ b/bin/Debug/template/dp_reactions.txt
@@ -0,0 +1,1 @@
+
\ No newline at end of file
diff --git a/bin/Debug/template/ingredients.txt b/bin/Debug/template/ingredients.txt
new file mode 100644
--- /dev/null
+++ b/bin/Debug/template/ingredients.txt
@@ -0,0 +1,21 @@
+// Ingredients are in the form:
+// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)
+//
+// It is recommended to only change the cost value
+// It is not recommended to set many of the ingredients above 10 per paint
+
+Cabbage | 128, 64, 144 | 8 | Y | bulk | 10
+Clay | 128, 96, 32 | 4 | Y | bulk | 20
+Carrot | 224, 112, 32 | 10 | Y | bulk | 10
+Copper | 64, 192, 192 | 30 | Y | normal | 8
+Iron | 96, 48, 32 | 30 | Y | normal | 8
+Lead | 80, 80, 96 | 50 | Y | normal | 6
+RedSand | 144, 16, 24 | 10 | Y | bulk | 20
+Silver | 16, 16, 32 | 50 | N | normal | 6
+ToadSkin | 48, 96, 48 | 500 | N | normal | 4
+DeadTongue | 112, 64, 64 | 500 | N | normal | 4
+EarthLight | 128, 240, 224 | 10000 | N | normal | 4
+Lime | catalyst | 20 | Y | normal | 1
+Sulfur | catalyst | 10 | Y | normal | 1
+Potash | catalyst | 50 | Y | normal | 1
+Saltpeter | catalyst | 10 | Y | normal | 1
\ No newline at end of file
diff --git a/gtk-gui/DesertPaintLab.FirstRunDialog.cs b/gtk-gui/DesertPaintLab.FirstRunDialog.cs
new file mode 100644
--- /dev/null
+++ b/gtk-gui/DesertPaintLab.FirstRunDialog.cs
@@ -0,0 +1,86 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace DesertPaintLab
+{
+ public partial class FirstRunDialog
+ {
+ private global::Gtk.Label label2;
+
+ private global::Gtk.Button buttonCancel;
+
+ private global::Gtk.Button buttonImport;
+
+ private global::Gtk.Button buttonNew;
+
+ protected virtual void Build ()
+ {
+ global::Stetic.Gui.Initialize (this);
+ // Widget DesertPaintLab.FirstRunDialog
+ this.Name = "DesertPaintLab.FirstRunDialog";
+ this.Title = global::Mono.Unix.Catalog.GetString ("Set Up Profile");
+ this.WindowPosition = ((global::Gtk.WindowPosition)(4));
+ this.Modal = true;
+ this.AllowShrink = true;
+ // Internal child DesertPaintLab.FirstRunDialog.VBox
+ global::Gtk.VBox w1 = this.VBox;
+ w1.Name = "dialog1_VBox";
+ w1.BorderWidth = ((uint)(2));
+ // Container child dialog1_VBox.Gtk.Box+BoxChild
+ this.label2 = new global::Gtk.Label ();
+ this.label2.Name = "label2";
+ this.label2.LabelProp = global::Mono.Unix.Catalog.GetString ("Since this is your first time using this program, you need a new profile.\n\nYou ca" + "n either import an existing PracticalPaint reactions.txt file, or you can start " + "a new profile from scratch.");
+ this.label2.Wrap = true;
+ w1.Add (this.label2);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(w1[this.label2]));
+ w2.Position = 0;
+ w2.Padding = ((uint)(5));
+ // Internal child DesertPaintLab.FirstRunDialog.ActionArea
+ global::Gtk.HButtonBox w3 = this.ActionArea;
+ w3.Name = "dialog1_ActionArea";
+ w3.Spacing = 10;
+ w3.BorderWidth = ((uint)(5));
+ w3.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4));
+ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+ this.buttonCancel = new global::Gtk.Button ();
+ this.buttonCancel.CanDefault = true;
+ this.buttonCancel.CanFocus = true;
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.UseStock = true;
+ this.buttonCancel.UseUnderline = true;
+ this.buttonCancel.Label = "gtk-cancel";
+ this.AddActionWidget (this.buttonCancel, -6);
+ global::Gtk.ButtonBox.ButtonBoxChild w4 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w3[this.buttonCancel]));
+ w4.Expand = false;
+ w4.Fill = false;
+ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+ this.buttonImport = new global::Gtk.Button ();
+ this.buttonImport.CanDefault = true;
+ this.buttonImport.CanFocus = true;
+ this.buttonImport.Name = "buttonImport";
+ this.buttonImport.UseUnderline = true;
+ this.buttonImport.Label = global::Mono.Unix.Catalog.GetString ("Import reactions.txt");
+ this.AddActionWidget (this.buttonImport, -3);
+ global::Gtk.ButtonBox.ButtonBoxChild w5 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w3[this.buttonImport]));
+ w5.Position = 1;
+ w5.Expand = false;
+ w5.Fill = false;
+ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+ this.buttonNew = new global::Gtk.Button ();
+ this.buttonNew.CanFocus = true;
+ this.buttonNew.Name = "buttonNew";
+ this.buttonNew.UseUnderline = true;
+ this.buttonNew.Label = global::Mono.Unix.Catalog.GetString ("New Profile");
+ this.AddActionWidget (this.buttonNew, -5);
+ global::Gtk.ButtonBox.ButtonBoxChild w6 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w3[this.buttonNew]));
+ w6.Position = 2;
+ w6.Expand = false;
+ w6.Fill = false;
+ if ((this.Child != null)) {
+ this.Child.ShowAll ();
+ }
+ this.DefaultWidth = 416;
+ this.DefaultHeight = 189;
+ this.Show ();
+ }
+ }
+}
diff --git a/gtk-gui/DesertPaintLab.NewProfileDialog.cs b/gtk-gui/DesertPaintLab.NewProfileDialog.cs
new file mode 100644
--- /dev/null
+++ b/gtk-gui/DesertPaintLab.NewProfileDialog.cs
@@ -0,0 +1,86 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace DesertPaintLab
+{
+ public partial class NewProfileDialog
+ {
+ private global::Gtk.Label label1;
+
+ private global::Gtk.Entry profileNameEntry;
+
+ private global::Gtk.Button buttonCancel;
+
+ private global::Gtk.Button buttonOk;
+
+ protected virtual void Build ()
+ {
+ global::Stetic.Gui.Initialize (this);
+ // Widget DesertPaintLab.NewProfileDialog
+ this.Name = "DesertPaintLab.NewProfileDialog";
+ this.Title = global::Mono.Unix.Catalog.GetString ("New Profile");
+ this.WindowPosition = ((global::Gtk.WindowPosition)(4));
+ this.BorderWidth = ((uint)(5));
+ // Internal child DesertPaintLab.NewProfileDialog.VBox
+ global::Gtk.VBox w1 = this.VBox;
+ w1.Name = "dialog1_VBox";
+ w1.Spacing = 10;
+ w1.BorderWidth = ((uint)(9));
+ // Container child dialog1_VBox.Gtk.Box+BoxChild
+ this.label1 = new global::Gtk.Label ();
+ this.label1.Name = "label1";
+ this.label1.LabelProp = global::Mono.Unix.Catalog.GetString ("Name your new profile:");
+ w1.Add (this.label1);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(w1[this.label1]));
+ w2.Position = 0;
+ w2.Expand = false;
+ w2.Fill = false;
+ // Container child dialog1_VBox.Gtk.Box+BoxChild
+ this.profileNameEntry = new global::Gtk.Entry ();
+ this.profileNameEntry.CanFocus = true;
+ this.profileNameEntry.Name = "profileNameEntry";
+ this.profileNameEntry.IsEditable = true;
+ w1.Add (this.profileNameEntry);
+ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(w1[this.profileNameEntry]));
+ w3.Position = 1;
+ w3.Expand = false;
+ w3.Fill = false;
+ // Internal child DesertPaintLab.NewProfileDialog.ActionArea
+ global::Gtk.HButtonBox w4 = this.ActionArea;
+ w4.Name = "dialog1_ActionArea";
+ w4.Spacing = 10;
+ w4.BorderWidth = ((uint)(5));
+ w4.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4));
+ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+ this.buttonCancel = new global::Gtk.Button ();
+ this.buttonCancel.CanDefault = true;
+ this.buttonCancel.CanFocus = true;
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.UseStock = true;
+ this.buttonCancel.UseUnderline = true;
+ this.buttonCancel.Label = "gtk-cancel";
+ this.AddActionWidget (this.buttonCancel, -6);
+ global::Gtk.ButtonBox.ButtonBoxChild w5 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w4[this.buttonCancel]));
+ w5.Expand = false;
+ w5.Fill = false;
+ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+ this.buttonOk = new global::Gtk.Button ();
+ this.buttonOk.CanDefault = true;
+ this.buttonOk.CanFocus = true;
+ this.buttonOk.Name = "buttonOk";
+ this.buttonOk.UseStock = true;
+ this.buttonOk.UseUnderline = true;
+ this.buttonOk.Label = "gtk-ok";
+ this.AddActionWidget (this.buttonOk, -5);
+ global::Gtk.ButtonBox.ButtonBoxChild w6 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w4[this.buttonOk]));
+ w6.Position = 1;
+ w6.Expand = false;
+ w6.Fill = false;
+ if ((this.Child != null)) {
+ this.Child.ShowAll ();
+ }
+ this.DefaultWidth = 318;
+ this.DefaultHeight = 177;
+ this.Show ();
+ }
+ }
+}
diff --git a/gtk-gui/DesertPaintLab.PaintSwatch.cs b/gtk-gui/DesertPaintLab.PaintSwatch.cs
new file mode 100644
--- /dev/null
+++ b/gtk-gui/DesertPaintLab.PaintSwatch.cs
@@ -0,0 +1,56 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace DesertPaintLab
+{
+ public partial class PaintSwatch
+ {
+ private global::Gtk.VBox vbox1;
+
+ private global::Gtk.Label colorNameLabel;
+
+ private global::Gtk.DrawingArea colorBox;
+
+ private global::Gtk.Label rgbLabel;
+
+ protected virtual void Build ()
+ {
+ global::Stetic.Gui.Initialize (this);
+ // Widget DesertPaintLab.PaintSwatch
+ global::Stetic.BinContainer.Attach (this);
+ this.Name = "DesertPaintLab.PaintSwatch";
+ // Container child DesertPaintLab.PaintSwatch.Gtk.Container+ContainerChild
+ this.vbox1 = new global::Gtk.VBox ();
+ this.vbox1.Name = "vbox1";
+ this.vbox1.Spacing = 6;
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.colorNameLabel = new global::Gtk.Label ();
+ this.colorNameLabel.Name = "colorNameLabel";
+ this.colorNameLabel.LabelProp = global::Mono.Unix.Catalog.GetString ("Unknown");
+ this.vbox1.Add (this.colorNameLabel);
+ global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox1[this.colorNameLabel]));
+ w1.Position = 0;
+ w1.Expand = false;
+ w1.Fill = false;
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.colorBox = new global::Gtk.DrawingArea ();
+ this.colorBox.Name = "colorBox";
+ this.vbox1.Add (this.colorBox);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.vbox1[this.colorBox]));
+ w2.Position = 1;
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.rgbLabel = new global::Gtk.Label ();
+ this.rgbLabel.Name = "rgbLabel";
+ this.rgbLabel.LabelProp = global::Mono.Unix.Catalog.GetString ("???, ???, ???");
+ this.vbox1.Add (this.rgbLabel);
+ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.vbox1[this.rgbLabel]));
+ w3.Position = 2;
+ w3.Expand = false;
+ w3.Fill = false;
+ this.Add (this.vbox1);
+ if ((this.Child != null)) {
+ this.Child.ShowAll ();
+ }
+ this.Hide ();
+ }
+ }
+}
diff --git a/gtk-gui/DesertPaintLab.SelectProfileDialog.cs b/gtk-gui/DesertPaintLab.SelectProfileDialog.cs
new file mode 100644
--- /dev/null
+++ b/gtk-gui/DesertPaintLab.SelectProfileDialog.cs
@@ -0,0 +1,99 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace DesertPaintLab
+{
+ public partial class SelectProfileDialog
+ {
+ private global::Gtk.Label label3;
+
+ private global::Gtk.TreeView profileListView;
+
+ private global::Gtk.Button buttonCancel;
+
+ private global::Gtk.Button button56;
+
+ private global::Gtk.Button buttonOk;
+
+ protected virtual void Build ()
+ {
+ global::Stetic.Gui.Initialize (this);
+ // Widget DesertPaintLab.SelectProfileDialog
+ this.Name = "DesertPaintLab.SelectProfileDialog";
+ this.Title = global::Mono.Unix.Catalog.GetString ("Open Profile");
+ this.WindowPosition = ((global::Gtk.WindowPosition)(4));
+ this.Modal = true;
+ this.BorderWidth = ((uint)(5));
+ // Internal child DesertPaintLab.SelectProfileDialog.VBox
+ global::Gtk.VBox w1 = this.VBox;
+ w1.Name = "dialog1_VBox";
+ w1.Spacing = 10;
+ w1.BorderWidth = ((uint)(2));
+ // Container child dialog1_VBox.Gtk.Box+BoxChild
+ this.label3 = new global::Gtk.Label ();
+ this.label3.Name = "label3";
+ this.label3.LabelProp = global::Mono.Unix.Catalog.GetString ("Select the profile you would like to open:");
+ w1.Add (this.label3);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(w1[this.label3]));
+ w2.Position = 0;
+ w2.Expand = false;
+ w2.Fill = false;
+ // Container child dialog1_VBox.Gtk.Box+BoxChild
+ this.profileListView = new global::Gtk.TreeView ();
+ this.profileListView.CanFocus = true;
+ this.profileListView.Name = "profileListView";
+ this.profileListView.EnableSearch = false;
+ w1.Add (this.profileListView);
+ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(w1[this.profileListView]));
+ w3.Position = 1;
+ // Internal child DesertPaintLab.SelectProfileDialog.ActionArea
+ global::Gtk.HButtonBox w4 = this.ActionArea;
+ w4.Name = "dialog1_ActionArea";
+ w4.Spacing = 10;
+ w4.BorderWidth = ((uint)(5));
+ w4.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4));
+ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+ this.buttonCancel = new global::Gtk.Button ();
+ this.buttonCancel.CanDefault = true;
+ this.buttonCancel.CanFocus = true;
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.UseStock = true;
+ this.buttonCancel.UseUnderline = true;
+ this.buttonCancel.Label = "gtk-cancel";
+ this.AddActionWidget (this.buttonCancel, -6);
+ global::Gtk.ButtonBox.ButtonBoxChild w5 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w4[this.buttonCancel]));
+ w5.Expand = false;
+ w5.Fill = false;
+ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+ this.button56 = new global::Gtk.Button ();
+ this.button56.CanFocus = true;
+ this.button56.Name = "button56";
+ this.button56.UseUnderline = true;
+ this.button56.Label = global::Mono.Unix.Catalog.GetString ("New Profile");
+ this.AddActionWidget (this.button56, -3);
+ global::Gtk.ButtonBox.ButtonBoxChild w6 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w4[this.button56]));
+ w6.Position = 1;
+ w6.Expand = false;
+ w6.Fill = false;
+ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+ this.buttonOk = new global::Gtk.Button ();
+ this.buttonOk.CanDefault = true;
+ this.buttonOk.CanFocus = true;
+ this.buttonOk.Name = "buttonOk";
+ this.buttonOk.UseStock = true;
+ this.buttonOk.UseUnderline = true;
+ this.buttonOk.Label = "gtk-ok";
+ this.AddActionWidget (this.buttonOk, -5);
+ global::Gtk.ButtonBox.ButtonBoxChild w7 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w4[this.buttonOk]));
+ w7.Position = 2;
+ w7.Expand = false;
+ w7.Fill = false;
+ if ((this.Child != null)) {
+ this.Child.ShowAll ();
+ }
+ this.DefaultWidth = 400;
+ this.DefaultHeight = 288;
+ this.Show ();
+ this.profileListView.CursorChanged += new global::System.EventHandler (this.OnCursorChanged);
+ }
+ }
+}
diff --git a/gtk-gui/DesertPaintLab.SimulatorWindow.cs b/gtk-gui/DesertPaintLab.SimulatorWindow.cs
new file mode 100644
--- /dev/null
+++ b/gtk-gui/DesertPaintLab.SimulatorWindow.cs
@@ -0,0 +1,189 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace DesertPaintLab
+{
+ public partial class SimulatorWindow
+ {
+ private global::Gtk.HBox hbox1;
+
+ private global::Gtk.ScrolledWindow GtkScrolledWindow;
+
+ private global::Gtk.TreeView reagentListView;
+
+ private global::Gtk.VBox vbox162;
+
+ private global::Gtk.Alignment alignment1;
+
+ private global::Gtk.Button addReagentButton;
+
+ private global::Gtk.Image addReagentButtonImage;
+
+ private global::Gtk.Alignment alignment3;
+
+ private global::Gtk.ScrolledWindow GtkScrolledWindow1;
+
+ private global::Gtk.TreeView recipeView;
+
+ private global::Gtk.VBox vbox3;
+
+ private global::Gtk.Alignment alignment2;
+
+ private global::Gtk.Button button65;
+
+ private global::Gtk.Image image1;
+
+ private global::Gtk.Button button66;
+
+ private global::Gtk.Image image2;
+
+ private global::Gtk.Alignment alignment4;
+
+ private global::DesertPaintLab.PaintSwatch paintSwatch;
+
+ protected virtual void Build ()
+ {
+ global::Stetic.Gui.Initialize (this);
+ // Widget DesertPaintLab.SimulatorWindow
+ this.Name = "DesertPaintLab.SimulatorWindow";
+ this.Title = global::Mono.Unix.Catalog.GetString ("Simulator");
+ this.WindowPosition = ((global::Gtk.WindowPosition)(4));
+ // Container child DesertPaintLab.SimulatorWindow.Gtk.Container+ContainerChild
+ this.hbox1 = new global::Gtk.HBox ();
+ this.hbox1.Name = "hbox1";
+ this.hbox1.Spacing = 6;
+ this.hbox1.BorderWidth = ((uint)(12));
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.GtkScrolledWindow = new global::Gtk.ScrolledWindow ();
+ this.GtkScrolledWindow.Name = "GtkScrolledWindow";
+ this.GtkScrolledWindow.ShadowType = ((global::Gtk.ShadowType)(1));
+ // Container child GtkScrolledWindow.Gtk.Container+ContainerChild
+ this.reagentListView = new global::Gtk.TreeView ();
+ this.reagentListView.CanFocus = true;
+ this.reagentListView.Name = "reagentListView";
+ this.GtkScrolledWindow.Add (this.reagentListView);
+ this.hbox1.Add (this.GtkScrolledWindow);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.GtkScrolledWindow]));
+ w2.Position = 0;
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.vbox162 = new global::Gtk.VBox ();
+ this.vbox162.Name = "vbox162";
+ this.vbox162.Spacing = 6;
+ // Container child vbox162.Gtk.Box+BoxChild
+ this.alignment1 = new global::Gtk.Alignment (0.5f, 0.5f, 1f, 1f);
+ this.alignment1.Name = "alignment1";
+ this.vbox162.Add (this.alignment1);
+ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.vbox162[this.alignment1]));
+ w3.Position = 0;
+ // Container child vbox162.Gtk.Box+BoxChild
+ this.addReagentButton = new global::Gtk.Button ();
+ this.addReagentButton.CanFocus = true;
+ this.addReagentButton.Name = "addReagentButton";
+ // Container child addReagentButton.Gtk.Container+ContainerChild
+ this.addReagentButtonImage = new global::Gtk.Image ();
+ this.addReagentButtonImage.Name = "addReagentButtonImage";
+ this.addReagentButtonImage.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-go-forward", global::Gtk.IconSize.Menu);
+ this.addReagentButton.Add (this.addReagentButtonImage);
+ this.addReagentButton.Label = null;
+ this.vbox162.Add (this.addReagentButton);
+ global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox162[this.addReagentButton]));
+ w5.Position = 1;
+ w5.Expand = false;
+ w5.Fill = false;
+ // Container child vbox162.Gtk.Box+BoxChild
+ this.alignment3 = new global::Gtk.Alignment (0.5f, 0.5f, 1f, 1f);
+ this.alignment3.Name = "alignment3";
+ this.vbox162.Add (this.alignment3);
+ global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox162[this.alignment3]));
+ w6.Position = 2;
+ this.hbox1.Add (this.vbox162);
+ global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.vbox162]));
+ w7.Position = 1;
+ w7.Expand = false;
+ w7.Fill = false;
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.GtkScrolledWindow1 = new global::Gtk.ScrolledWindow ();
+ this.GtkScrolledWindow1.WidthRequest = 0;
+ this.GtkScrolledWindow1.Name = "GtkScrolledWindow1";
+ this.GtkScrolledWindow1.ShadowType = ((global::Gtk.ShadowType)(1));
+ // Container child GtkScrolledWindow1.Gtk.Container+ContainerChild
+ this.recipeView = new global::Gtk.TreeView ();
+ this.recipeView.CanFocus = true;
+ this.recipeView.Name = "recipeView";
+ this.recipeView.EnableSearch = false;
+ this.recipeView.Reorderable = true;
+ this.GtkScrolledWindow1.Add (this.recipeView);
+ this.hbox1.Add (this.GtkScrolledWindow1);
+ global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.GtkScrolledWindow1]));
+ w9.Position = 2;
+ // 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.alignment2 = new global::Gtk.Alignment (0.5f, 0.5f, 1f, 1f);
+ this.alignment2.Name = "alignment2";
+ this.vbox3.Add (this.alignment2);
+ global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.alignment2]));
+ w10.Position = 0;
+ // Container child vbox3.Gtk.Box+BoxChild
+ this.button65 = new global::Gtk.Button ();
+ this.button65.CanFocus = true;
+ this.button65.Name = "button65";
+ // Container child button65.Gtk.Container+ContainerChild
+ this.image1 = new global::Gtk.Image ();
+ this.image1.Name = "image1";
+ this.image1.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-add", global::Gtk.IconSize.Menu);
+ this.button65.Add (this.image1);
+ this.button65.Label = null;
+ this.vbox3.Add (this.button65);
+ global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.button65]));
+ w12.Position = 1;
+ w12.Expand = false;
+ w12.Fill = false;
+ // Container child vbox3.Gtk.Box+BoxChild
+ this.button66 = new global::Gtk.Button ();
+ this.button66.CanFocus = true;
+ this.button66.Name = "button66";
+ // Container child button66.Gtk.Container+ContainerChild
+ this.image2 = new global::Gtk.Image ();
+ this.image2.Name = "image2";
+ this.image2.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-remove", global::Gtk.IconSize.Menu);
+ this.button66.Add (this.image2);
+ this.button66.Label = null;
+ this.vbox3.Add (this.button66);
+ global::Gtk.Box.BoxChild w14 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.button66]));
+ w14.Position = 2;
+ w14.Expand = false;
+ w14.Fill = false;
+ // Container child vbox3.Gtk.Box+BoxChild
+ this.alignment4 = new global::Gtk.Alignment (0.5f, 0.5f, 1f, 1f);
+ this.alignment4.Name = "alignment4";
+ this.vbox3.Add (this.alignment4);
+ global::Gtk.Box.BoxChild w15 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.alignment4]));
+ w15.Position = 3;
+ this.hbox1.Add (this.vbox3);
+ global::Gtk.Box.BoxChild w16 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.vbox3]));
+ w16.Position = 3;
+ w16.Expand = false;
+ w16.Fill = false;
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.paintSwatch = new global::DesertPaintLab.PaintSwatch ();
+ this.paintSwatch.WidthRequest = 200;
+ this.paintSwatch.Events = ((global::Gdk.EventMask)(256));
+ this.paintSwatch.Name = "paintSwatch";
+ this.hbox1.Add (this.paintSwatch);
+ global::Gtk.Box.BoxChild w17 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.paintSwatch]));
+ w17.Position = 4;
+ this.Add (this.hbox1);
+ if ((this.Child != null)) {
+ this.Child.ShowAll ();
+ }
+ this.DefaultWidth = 804;
+ this.DefaultHeight = 390;
+ this.Show ();
+ this.addReagentButton.Clicked += new global::System.EventHandler (this.OnAddReagent);
+ this.button65.Clicked += new global::System.EventHandler (this.OnIncrementReagent);
+ this.button66.Clicked += new global::System.EventHandler (this.OnDecrementReagent);
+ }
+ }
+}
diff --git a/gtk-gui/MainWindow.cs b/gtk-gui/MainWindow.cs
new file mode 100644
--- /dev/null
+++ b/gtk-gui/MainWindow.cs
@@ -0,0 +1,362 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+
+public partial class MainWindow
+{
+ private global::Gtk.UIManager UIManager;
+
+ private global::Gtk.Action FileAction;
+
+ private global::Gtk.Action HelpAction;
+
+ private global::Gtk.Action AboutAction;
+
+ private global::Gtk.Action NewProfileAction;
+
+ private global::Gtk.Action OpenProfileAction;
+
+ private global::Gtk.Action ExitAction;
+
+ private global::Gtk.Action ExportForPracticalPaintAction;
+
+ private global::Gtk.Action WindowAction;
+
+ private global::Gtk.Action RunSimulatorAction;
+
+ private global::Gtk.VBox vbox1;
+
+ private global::Gtk.MenuBar menubar1;
+
+ private global::Gtk.HBox hbox1;
+
+ private global::Gtk.Frame frame2;
+
+ private global::Gtk.Alignment GtkAlignment;
+
+ private global::Gtk.VBox vbox3;
+
+ private global::Gtk.HBox hbox6;
+
+ private global::Gtk.Label label4;
+
+ private global::Gtk.ComboBox ingredient1ComboBox;
+
+ private global::Gtk.HBox hbox7;
+
+ private global::Gtk.Label label5;
+
+ private global::Gtk.ComboBox ingredient2ComboBox;
+
+ private global::Gtk.HBox hbox8;
+
+ private global::Gtk.Label label6;
+
+ private global::Gtk.ComboBox ingredient3ComboBox;
+
+ private global::Gtk.Label GtkLabel2;
+
+ private global::Gtk.Frame frame3;
+
+ private global::Gtk.Alignment GtkAlignment1;
+
+ private global::Gtk.VBox vbox4;
+
+ private global::DesertPaintLab.PaintSwatch unmodifiedSwatch;
+
+ private global::Gtk.Button captureButton;
+
+ private global::Gtk.Label GtkLabel25;
+
+ private global::Gtk.Frame frame4;
+
+ private global::Gtk.Alignment GtkAlignment2;
+
+ private global::Gtk.VBox vbox5;
+
+ private global::DesertPaintLab.PaintSwatch reactionSwatch;
+
+ private global::Gtk.Button saveButton;
+
+ private global::Gtk.Label GtkLabel26;
+
+ private global::Gtk.Statusbar statusBar;
+
+ protected virtual void Build ()
+ {
+ global::Stetic.Gui.Initialize (this);
+ // Widget MainWindow
+ this.UIManager = new global::Gtk.UIManager ();
+ global::Gtk.ActionGroup w1 = new global::Gtk.ActionGroup ("Default");
+ this.FileAction = new global::Gtk.Action ("FileAction", global::Mono.Unix.Catalog.GetString ("_File"), null, null);
+ this.FileAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("_File");
+ w1.Add (this.FileAction, "f");
+ this.HelpAction = new global::Gtk.Action ("HelpAction", global::Mono.Unix.Catalog.GetString ("_Help"), null, null);
+ this.HelpAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("_Help");
+ w1.Add (this.HelpAction, "a");
+ this.AboutAction = new global::Gtk.Action ("AboutAction", global::Mono.Unix.Catalog.GetString ("_About..."), null, null);
+ this.AboutAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("_About...");
+ w1.Add (this.AboutAction, "a");
+ this.NewProfileAction = new global::Gtk.Action ("NewProfileAction", global::Mono.Unix.Catalog.GetString ("_New Profile..."), null, null);
+ this.NewProfileAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("_New Profile...");
+ w1.Add (this.NewProfileAction, "n");
+ this.OpenProfileAction = new global::Gtk.Action ("OpenProfileAction", global::Mono.Unix.Catalog.GetString ("_Open Profile..."), null, null);
+ this.OpenProfileAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("_Open Profile...");
+ w1.Add (this.OpenProfileAction, "o");
+ this.ExitAction = new global::Gtk.Action ("ExitAction", global::Mono.Unix.Catalog.GetString ("E_xit"), null, null);
+ this.ExitAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("E_xit");
+ w1.Add (this.ExitAction, "x");
+ this.ExportForPracticalPaintAction = new global::Gtk.Action ("ExportForPracticalPaintAction", global::Mono.Unix.Catalog.GetString ("Export for _PracticalPaint..."), null, null);
+ this.ExportForPracticalPaintAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("Export for _PracticalPaint...");
+ w1.Add (this.ExportForPracticalPaintAction, null);
+ this.WindowAction = new global::Gtk.Action ("WindowAction", global::Mono.Unix.Catalog.GetString ("_Window"), null, null);
+ this.WindowAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("_Window");
+ w1.Add (this.WindowAction, null);
+ this.RunSimulatorAction = new global::Gtk.Action ("RunSimulatorAction", global::Mono.Unix.Catalog.GetString ("_Run Simulator"), null, null);
+ this.RunSimulatorAction.ShortLabel = global::Mono.Unix.Catalog.GetString ("_Run Simulator");
+ w1.Add (this.RunSimulatorAction, null);
+ this.UIManager.InsertActionGroup (w1, 0);
+ this.AddAccelGroup (this.UIManager.AccelGroup);
+ this.Name = "MainWindow";
+ this.Title = global::Mono.Unix.Catalog.GetString ("Desert Paint Lab");
+ this.WindowPosition = ((global::Gtk.WindowPosition)(4));
+ // Container child MainWindow.Gtk.Container+ContainerChild
+ this.vbox1 = new global::Gtk.VBox ();
+ this.vbox1.Name = "vbox1";
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.UIManager.AddUiFromString (@"");
+ this.menubar1 = ((global::Gtk.MenuBar)(this.UIManager.GetWidget ("/menubar1")));
+ this.menubar1.Name = "menubar1";
+ this.vbox1.Add (this.menubar1);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.vbox1[this.menubar1]));
+ w2.Position = 0;
+ w2.Expand = false;
+ w2.Fill = false;
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.hbox1 = new global::Gtk.HBox ();
+ this.hbox1.Name = "hbox1";
+ this.hbox1.Spacing = 6;
+ this.hbox1.BorderWidth = ((uint)(4));
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.frame2 = new global::Gtk.Frame ();
+ this.frame2.Name = "frame2";
+ this.frame2.BorderWidth = ((uint)(4));
+ // Container child frame2.Gtk.Container+ContainerChild
+ this.GtkAlignment = new global::Gtk.Alignment (0f, 0f, 1f, 1f);
+ this.GtkAlignment.Name = "GtkAlignment";
+ this.GtkAlignment.LeftPadding = ((uint)(6));
+ this.GtkAlignment.RightPadding = ((uint)(6));
+ // Container child GtkAlignment.Gtk.Container+ContainerChild
+ this.vbox3 = new global::Gtk.VBox ();
+ this.vbox3.Name = "vbox3";
+ this.vbox3.Homogeneous = true;
+ this.vbox3.Spacing = 6;
+ // Container child vbox3.Gtk.Box+BoxChild
+ this.hbox6 = new global::Gtk.HBox ();
+ this.hbox6.Name = "hbox6";
+ this.hbox6.Spacing = 6;
+ // Container child hbox6.Gtk.Box+BoxChild
+ this.label4 = new global::Gtk.Label ();
+ this.label4.Name = "label4";
+ this.label4.LabelProp = global::Mono.Unix.Catalog.GetString ("Ingredient 1:");
+ this.hbox6.Add (this.label4);
+ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox6[this.label4]));
+ w3.Position = 0;
+ w3.Expand = false;
+ w3.Fill = false;
+ // Container child hbox6.Gtk.Box+BoxChild
+ this.ingredient1ComboBox = global::Gtk.ComboBox.NewText ();
+ this.ingredient1ComboBox.Name = "ingredient1ComboBox";
+ this.hbox6.Add (this.ingredient1ComboBox);
+ global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox6[this.ingredient1ComboBox]));
+ w4.Position = 1;
+ this.vbox3.Add (this.hbox6);
+ global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.hbox6]));
+ w5.Position = 0;
+ w5.Expand = false;
+ w5.Fill = false;
+ // Container child vbox3.Gtk.Box+BoxChild
+ this.hbox7 = new global::Gtk.HBox ();
+ this.hbox7.Name = "hbox7";
+ this.hbox7.Spacing = 6;
+ // Container child hbox7.Gtk.Box+BoxChild
+ this.label5 = new global::Gtk.Label ();
+ this.label5.Name = "label5";
+ this.label5.LabelProp = global::Mono.Unix.Catalog.GetString ("Ingredient 2:");
+ this.hbox7.Add (this.label5);
+ global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.hbox7[this.label5]));
+ w6.Position = 0;
+ w6.Expand = false;
+ w6.Fill = false;
+ // Container child hbox7.Gtk.Box+BoxChild
+ this.ingredient2ComboBox = global::Gtk.ComboBox.NewText ();
+ this.ingredient2ComboBox.Name = "ingredient2ComboBox";
+ this.hbox7.Add (this.ingredient2ComboBox);
+ global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.hbox7[this.ingredient2ComboBox]));
+ w7.Position = 1;
+ this.vbox3.Add (this.hbox7);
+ global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.hbox7]));
+ w8.Position = 1;
+ w8.Expand = false;
+ w8.Fill = false;
+ // Container child vbox3.Gtk.Box+BoxChild
+ this.hbox8 = new global::Gtk.HBox ();
+ this.hbox8.Name = "hbox8";
+ this.hbox8.Spacing = 6;
+ // Container child hbox8.Gtk.Box+BoxChild
+ this.label6 = new global::Gtk.Label ();
+ this.label6.Name = "label6";
+ this.label6.LabelProp = global::Mono.Unix.Catalog.GetString ("Ingredient 3:");
+ this.hbox8.Add (this.label6);
+ global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.hbox8[this.label6]));
+ w9.Position = 0;
+ w9.Expand = false;
+ w9.Fill = false;
+ // Container child hbox8.Gtk.Box+BoxChild
+ this.ingredient3ComboBox = global::Gtk.ComboBox.NewText ();
+ this.ingredient3ComboBox.Name = "ingredient3ComboBox";
+ this.hbox8.Add (this.ingredient3ComboBox);
+ global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.hbox8[this.ingredient3ComboBox]));
+ w10.Position = 1;
+ this.vbox3.Add (this.hbox8);
+ global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.vbox3[this.hbox8]));
+ w11.Position = 2;
+ w11.Expand = false;
+ w11.Fill = false;
+ this.GtkAlignment.Add (this.vbox3);
+ this.frame2.Add (this.GtkAlignment);
+ this.GtkLabel2 = new global::Gtk.Label ();
+ this.GtkLabel2.Name = "GtkLabel2";
+ this.GtkLabel2.LabelProp = global::Mono.Unix.Catalog.GetString ("Select Ingredients");
+ this.GtkLabel2.UseMarkup = true;
+ this.frame2.LabelWidget = this.GtkLabel2;
+ this.hbox1.Add (this.frame2);
+ global::Gtk.Box.BoxChild w14 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.frame2]));
+ w14.Position = 0;
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.frame3 = new global::Gtk.Frame ();
+ this.frame3.Name = "frame3";
+ this.frame3.BorderWidth = ((uint)(4));
+ // Container child frame3.Gtk.Container+ContainerChild
+ this.GtkAlignment1 = new global::Gtk.Alignment (0f, 0f, 1f, 1f);
+ this.GtkAlignment1.Name = "GtkAlignment1";
+ this.GtkAlignment1.LeftPadding = ((uint)(5));
+ this.GtkAlignment1.TopPadding = ((uint)(5));
+ this.GtkAlignment1.RightPadding = ((uint)(5));
+ this.GtkAlignment1.BottomPadding = ((uint)(6));
+ // Container child GtkAlignment1.Gtk.Container+ContainerChild
+ this.vbox4 = new global::Gtk.VBox ();
+ this.vbox4.WidthRequest = 120;
+ this.vbox4.Name = "vbox4";
+ this.vbox4.Spacing = 6;
+ // Container child vbox4.Gtk.Box+BoxChild
+ this.unmodifiedSwatch = new global::DesertPaintLab.PaintSwatch ();
+ this.unmodifiedSwatch.Events = ((global::Gdk.EventMask)(256));
+ this.unmodifiedSwatch.Name = "unmodifiedSwatch";
+ this.vbox4.Add (this.unmodifiedSwatch);
+ global::Gtk.Box.BoxChild w15 = ((global::Gtk.Box.BoxChild)(this.vbox4[this.unmodifiedSwatch]));
+ w15.Position = 0;
+ // Container child vbox4.Gtk.Box+BoxChild
+ this.captureButton = new global::Gtk.Button ();
+ this.captureButton.WidthRequest = 100;
+ this.captureButton.CanFocus = true;
+ this.captureButton.Name = "captureButton";
+ this.captureButton.UseUnderline = true;
+ this.captureButton.Label = global::Mono.Unix.Catalog.GetString ("Capture");
+ this.vbox4.Add (this.captureButton);
+ global::Gtk.Box.BoxChild w16 = ((global::Gtk.Box.BoxChild)(this.vbox4[this.captureButton]));
+ w16.Position = 1;
+ w16.Expand = false;
+ w16.Fill = false;
+ this.GtkAlignment1.Add (this.vbox4);
+ this.frame3.Add (this.GtkAlignment1);
+ this.GtkLabel25 = new global::Gtk.Label ();
+ this.GtkLabel25.Name = "GtkLabel25";
+ this.GtkLabel25.LabelProp = global::Mono.Unix.Catalog.GetString ("Unmodified");
+ this.GtkLabel25.UseMarkup = true;
+ this.frame3.LabelWidget = this.GtkLabel25;
+ this.hbox1.Add (this.frame3);
+ global::Gtk.Box.BoxChild w19 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.frame3]));
+ w19.Position = 1;
+ w19.Expand = false;
+ w19.Fill = false;
+ // Container child hbox1.Gtk.Box+BoxChild
+ this.frame4 = new global::Gtk.Frame ();
+ this.frame4.Name = "frame4";
+ this.frame4.BorderWidth = ((uint)(4));
+ // Container child frame4.Gtk.Container+ContainerChild
+ this.GtkAlignment2 = new global::Gtk.Alignment (0f, 0f, 1f, 1f);
+ this.GtkAlignment2.WidthRequest = 130;
+ this.GtkAlignment2.Name = "GtkAlignment2";
+ this.GtkAlignment2.LeftPadding = ((uint)(5));
+ this.GtkAlignment2.TopPadding = ((uint)(5));
+ this.GtkAlignment2.RightPadding = ((uint)(5));
+ this.GtkAlignment2.BottomPadding = ((uint)(6));
+ // Container child GtkAlignment2.Gtk.Container+ContainerChild
+ this.vbox5 = new global::Gtk.VBox ();
+ this.vbox5.WidthRequest = 120;
+ this.vbox5.Name = "vbox5";
+ this.vbox5.Spacing = 6;
+ // Container child vbox5.Gtk.Box+BoxChild
+ this.reactionSwatch = new global::DesertPaintLab.PaintSwatch ();
+ this.reactionSwatch.Events = ((global::Gdk.EventMask)(256));
+ this.reactionSwatch.Name = "reactionSwatch";
+ this.vbox5.Add (this.reactionSwatch);
+ global::Gtk.Box.BoxChild w20 = ((global::Gtk.Box.BoxChild)(this.vbox5[this.reactionSwatch]));
+ w20.Position = 0;
+ // Container child vbox5.Gtk.Box+BoxChild
+ this.saveButton = new global::Gtk.Button ();
+ this.saveButton.WidthRequest = 100;
+ this.saveButton.CanFocus = true;
+ this.saveButton.Name = "saveButton";
+ this.saveButton.UseUnderline = true;
+ this.saveButton.Label = global::Mono.Unix.Catalog.GetString ("Record");
+ this.vbox5.Add (this.saveButton);
+ global::Gtk.Box.BoxChild w21 = ((global::Gtk.Box.BoxChild)(this.vbox5[this.saveButton]));
+ w21.Position = 1;
+ w21.Expand = false;
+ w21.Fill = false;
+ this.GtkAlignment2.Add (this.vbox5);
+ this.frame4.Add (this.GtkAlignment2);
+ this.GtkLabel26 = new global::Gtk.Label ();
+ this.GtkLabel26.Name = "GtkLabel26";
+ this.GtkLabel26.LabelProp = global::Mono.Unix.Catalog.GetString ("Reaction");
+ this.GtkLabel26.UseMarkup = true;
+ this.frame4.LabelWidget = this.GtkLabel26;
+ this.hbox1.Add (this.frame4);
+ global::Gtk.Box.BoxChild w24 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.frame4]));
+ w24.Position = 2;
+ w24.Expand = false;
+ w24.Fill = false;
+ this.vbox1.Add (this.hbox1);
+ global::Gtk.Box.BoxChild w25 = ((global::Gtk.Box.BoxChild)(this.vbox1[this.hbox1]));
+ w25.Position = 1;
+ // Container child vbox1.Gtk.Box+BoxChild
+ this.statusBar = new global::Gtk.Statusbar ();
+ this.statusBar.Name = "statusBar";
+ this.statusBar.Spacing = 6;
+ this.vbox1.Add (this.statusBar);
+ global::Gtk.Box.BoxChild w26 = ((global::Gtk.Box.BoxChild)(this.vbox1[this.statusBar]));
+ w26.Position = 2;
+ w26.Expand = false;
+ w26.Fill = false;
+ this.Add (this.vbox1);
+ if ((this.Child != null)) {
+ this.Child.ShowAll ();
+ }
+ this.DefaultWidth = 629;
+ this.DefaultHeight = 265;
+ this.Show ();
+ this.DeleteEvent += new global::Gtk.DeleteEventHandler (this.OnDeleteEvent);
+ this.AboutAction.Activated += new global::System.EventHandler (this.OnAbout);
+ this.NewProfileAction.Activated += new global::System.EventHandler (this.OnNewProfile);
+ this.OpenProfileAction.Activated += new global::System.EventHandler (this.OnOpenProfile);
+ this.ExitAction.Activated += new global::System.EventHandler (this.OnMenuExit);
+ this.ExportForPracticalPaintAction.Activated += new global::System.EventHandler (this.OnExport);
+ this.RunSimulatorAction.Activated += new global::System.EventHandler (this.RunSimulator);
+ this.ingredient1ComboBox.Changed += new global::System.EventHandler (this.OnChangedIngredient1);
+ this.ingredient2ComboBox.Changed += new global::System.EventHandler (this.OnChangedIngredient2);
+ this.ingredient3ComboBox.Changed += new global::System.EventHandler (this.OnChangedIngredient3);
+ this.captureButton.Clicked += new global::System.EventHandler (this.OnCaptureButton);
+ this.saveButton.Clicked += new global::System.EventHandler (this.OnSaveButton);
+ }
+}
diff --git a/gtk-gui/generated.cs b/gtk-gui/generated.cs
new file mode 100644
--- /dev/null
+++ b/gtk-gui/generated.cs
@@ -0,0 +1,116 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace Stetic
+{
+ internal class Gui
+ {
+ private static bool initialized;
+
+ static internal void Initialize (Gtk.Widget iconRenderer)
+ {
+ if ((Stetic.Gui.initialized == false)) {
+ Stetic.Gui.initialized = true;
+ }
+ }
+ }
+
+ internal class BinContainer
+ {
+ private Gtk.Widget child;
+
+ private Gtk.UIManager uimanager;
+
+ public static BinContainer Attach (Gtk.Bin bin)
+ {
+ BinContainer bc = new BinContainer ();
+ bin.SizeRequested += new Gtk.SizeRequestedHandler (bc.OnSizeRequested);
+ bin.SizeAllocated += new Gtk.SizeAllocatedHandler (bc.OnSizeAllocated);
+ bin.Added += new Gtk.AddedHandler (bc.OnAdded);
+ return bc;
+ }
+
+ private void OnSizeRequested (object sender, Gtk.SizeRequestedArgs args)
+ {
+ if ((this.child != null)) {
+ args.Requisition = this.child.SizeRequest ();
+ }
+ }
+
+ private void OnSizeAllocated (object sender, Gtk.SizeAllocatedArgs args)
+ {
+ if ((this.child != null)) {
+ this.child.Allocation = args.Allocation;
+ }
+ }
+
+ private void OnAdded (object sender, Gtk.AddedArgs args)
+ {
+ this.child = args.Widget;
+ }
+
+ public void SetUiManager (Gtk.UIManager uim)
+ {
+ this.uimanager = uim;
+ this.child.Realized += new System.EventHandler (this.OnRealized);
+ }
+
+ private void OnRealized (object sender, System.EventArgs args)
+ {
+ if ((this.uimanager != null)) {
+ Gtk.Widget w;
+ w = this.child.Toplevel;
+ if (((w != null) && typeof(Gtk.Window).IsInstanceOfType (w))) {
+ ((Gtk.Window)(w)).AddAccelGroup (this.uimanager.AccelGroup);
+ this.uimanager = null;
+ }
+ }
+ }
+ }
+
+ internal class IconLoader
+ {
+ public static Gdk.Pixbuf LoadIcon (Gtk.Widget widget, string name, Gtk.IconSize size)
+ {
+ Gdk.Pixbuf res = widget.RenderIcon (name, size, null);
+ if ((res != null)) {
+ return res;
+ } else {
+ int sz;
+ int sy;
+ global::Gtk.Icon.SizeLookup (size, out sz, out sy);
+ try {
+ return Gtk.IconTheme.Default.LoadIcon (name, sz, 0);
+ } catch (System.Exception) {
+ if ((name != "gtk-missing-image")) {
+ return Stetic.IconLoader.LoadIcon (widget, "gtk-missing-image", size);
+ } else {
+ Gdk.Pixmap pmap = new Gdk.Pixmap (Gdk.Screen.Default.RootWindow, sz, sz);
+ Gdk.GC gc = new Gdk.GC (pmap);
+ gc.RgbFgColor = new Gdk.Color (255, 255, 255);
+ pmap.DrawRectangle (gc, true, 0, 0, sz, sz);
+ gc.RgbFgColor = new Gdk.Color (0, 0, 0);
+ pmap.DrawRectangle (gc, false, 0, 0, (sz - 1), (sz - 1));
+ gc.SetLineAttributes (3, Gdk.LineStyle.Solid, Gdk.CapStyle.Round, Gdk.JoinStyle.Round);
+ gc.RgbFgColor = new Gdk.Color (255, 0, 0);
+ pmap.DrawLine (gc, (sz / 4), (sz / 4), ((sz - 1) - (sz / 4)), ((sz - 1) - (sz / 4)));
+ pmap.DrawLine (gc, ((sz - 1) - (sz / 4)), (sz / 4), (sz / 4), ((sz - 1) - (sz / 4)));
+ return Gdk.Pixbuf.FromDrawable (pmap, pmap.Colormap, 0, 0, 0, 0, sz, sz);
+ }
+ }
+ }
+ }
+ }
+
+ internal class ActionGroups
+ {
+ public static Gtk.ActionGroup GetActionGroup (System.Type type)
+ {
+ return Stetic.ActionGroups.GetActionGroup (type.FullName);
+ }
+
+ public static Gtk.ActionGroup GetActionGroup (string name)
+ {
+ return null;
+ }
+ }
+}
diff --git a/gtk-gui/gui.stetic b/gtk-gui/gui.stetic
new file mode 100644
--- /dev/null
+++ b/gtk-gui/gui.stetic
@@ -0,0 +1,908 @@
+
+
+
+ ..
+ 2.12
+
+
+
+
+
+
+
+
+ Action
+ <Alt>f
+ _File
+ _File
+
+
+ Action
+ <Alt>a
+ _Help
+ _Help
+
+
+ Action
+ <Alt>a
+ _About...
+ _About...
+
+
+
+ Action
+ <Alt>n
+ _New Profile...
+ _New Profile...
+
+
+
+ Action
+ <Alt>o
+ _Open Profile...
+ _Open Profile...
+
+
+
+ Action
+ <Alt>x
+ E_xit
+ E_xit
+
+
+
+ Action
+ Export for _PracticalPaint...
+ Export for _PracticalPaint...
+
+
+
+ Action
+ _Window
+ _Window
+
+
+ Action
+ _Run Simulator
+ _Run Simulator
+
+
+
+
+ Desert Paint Lab
+ CenterOnParent
+
+
+
+
+
+
+
+ 0
+ True
+ False
+ False
+
+
+
+
+
+ 6
+ 4
+
+
+
+ 4
+
+
+
+ 0
+ 0
+ 6
+ 6
+
+
+
+ True
+ 6
+
+
+
+ 6
+
+
+
+ Ingredient 1:
+
+
+ 0
+ True
+ False
+ False
+
+
+
+
+
+ True
+
+
+
+
+ 1
+ False
+
+
+
+
+ 0
+ True
+ False
+ False
+
+
+
+
+
+ 6
+
+
+
+ Ingredient 2:
+
+
+ 0
+ True
+ False
+ False
+
+
+
+
+
+ True
+
+
+
+
+ 1
+ False
+
+
+
+
+ 1
+ True
+ False
+ False
+
+
+
+
+
+ 6
+
+
+
+ Ingredient 3:
+
+
+ 0
+ True
+ False
+ False
+
+
+
+
+
+ True
+
+
+
+
+ 1
+ False
+
+
+
+
+ 2
+ True
+ False
+ False
+
+
+
+
+
+
+
+
+
+ <b>Select Ingredients</b>
+ True
+
+
+ label_item
+
+
+
+
+ 0
+ False
+
+
+
+
+
+ 4
+
+
+
+ 0
+ 0
+ 5
+ 5
+ 5
+ 6
+
+
+
+ 120
+ 6
+
+
+
+ ButtonPressMask
+
+
+ 0
+ True
+
+
+
+
+
+ 100
+ True
+ TextOnly
+ Capture
+ True
+
+
+
+ 1
+ True
+ False
+ False
+
+
+
+
+
+
+
+
+
+ <b>Unmodified</b>
+ True
+
+
+ label_item
+
+
+
+
+ 1
+ True
+ False
+ False
+
+
+
+
+
+ 4
+
+
+
+ 130
+ 0
+ 0
+ 5
+ 5
+ 5
+ 6
+
+
+
+ 120
+ 6
+
+
+
+ ButtonPressMask
+
+
+ 0
+ True
+
+
+
+
+
+ 100
+ True
+ TextOnly
+ Record
+ True
+
+
+
+ 1
+ True
+ False
+ False
+
+
+
+
+
+
+
+
+
+ <b>Reaction</b>
+ True
+
+
+ label_item
+
+
+
+
+ 2
+ True
+ False
+ False
+
+
+
+
+ 1
+ False
+
+
+
+
+
+ 6
+
+
+ 2
+ True
+ False
+ False
+
+
+
+
+
+
+
+ Set Up Profile
+ CenterOnParent
+ True
+ True
+ 3
+ False
+
+
+
+ 2
+
+
+
+ Since this is your first time using this program, you need a new profile.
+
+You can either import an existing PracticalPaint reactions.txt file, or you can start a new profile from scratch.
+ True
+
+
+ 0
+ False
+ 5
+
+
+
+
+
+
+
+ 10
+ 5
+ 3
+ End
+
+
+
+ True
+ True
+ True
+ StockItem
+ gtk-cancel
+ -6
+ gtk-cancel
+
+
+ False
+ False
+
+
+
+
+
+ True
+ True
+ TextOnly
+ Import reactions.txt
+ True
+ -3
+
+
+ 1
+ False
+ False
+
+
+
+
+
+ True
+ TextOnly
+ New Profile
+ True
+ -5
+
+
+ 2
+ False
+ False
+
+
+
+
+
+
+
+ Open Profile
+ CenterOnParent
+ True
+ 5
+ 3
+ False
+
+
+
+ 10
+ 2
+
+
+
+ Select the profile you would like to open:
+
+
+ 0
+ True
+ False
+ False
+
+
+
+
+
+ True
+ False
+
+
+
+ 1
+ True
+
+
+
+
+
+
+
+ 10
+ 5
+ 3
+ End
+
+
+
+ True
+ True
+ True
+ StockItem
+ gtk-cancel
+ -6
+ gtk-cancel
+
+
+ False
+ False
+
+
+
+
+
+ True
+ TextOnly
+ New Profile
+ True
+ -3
+
+
+ 1
+ False
+ False
+
+
+
+
+
+ True
+ True
+ True
+ StockItem
+ gtk-ok
+ -5
+ gtk-ok
+
+
+ 2
+ False
+ False
+
+
+
+
+
+
+
+ New Profile
+ CenterOnParent
+ 5
+ 2
+ False
+
+
+
+ 10
+ 9
+
+
+
+ Name your new profile:
+
+
+ 0
+ True
+ False
+ False
+
+
+
+
+
+ True
+ True
+
+
+ 1
+ True
+ False
+ False
+
+
+
+
+
+
+
+ 10
+ 5
+ 2
+ End
+
+
+
+ True
+ True
+ True
+ StockItem
+ gtk-cancel
+ -6
+ gtk-cancel
+
+
+ False
+ False
+
+
+
+
+
+ True
+ True
+ True
+ StockItem
+ gtk-ok
+ -5
+ gtk-ok
+
+
+ 1
+ False
+ False
+
+
+
+
+
+
+
+ False
+
+
+
+ 6
+
+
+
+ Unknown
+
+
+ 0
+ True
+ False
+ False
+
+
+
+
+
+
+
+ 1
+ True
+
+
+
+
+
+ ???, ???, ???
+
+
+ 2
+ True
+ False
+ False
+
+
+
+
+
+
+
+ Simulator
+ CenterOnParent
+
+
+
+ 6
+ 12
+
+
+
+ In
+
+
+
+ True
+ True
+
+
+
+
+ 0
+ True
+
+
+
+
+
+ 6
+
+
+
+
+
+
+
+
+ 0
+ True
+
+
+
+
+
+ True
+ Custom
+
+
+
+
+ stock:gtk-go-forward Menu
+
+
+
+
+ 1
+ True
+ False
+ False
+
+
+
+
+
+
+
+
+
+
+ 2
+ True
+
+
+
+
+ 1
+ True
+ False
+ False
+
+
+
+
+
+ 0
+ In
+
+
+
+ True
+ True
+ False
+ True
+
+
+
+
+ 2
+ True
+
+
+
+
+
+ 6
+
+
+
+
+
+
+
+
+ 0
+ True
+
+
+
+
+
+ True
+ Custom
+
+
+
+
+ stock:gtk-add Menu
+
+
+
+
+ 1
+ True
+ False
+ False
+
+
+
+
+
+ True
+ Custom
+
+
+
+
+ stock:gtk-remove Menu
+
+
+
+
+ 2
+ True
+ False
+ False
+
+
+
+
+
+
+
+
+
+
+ 3
+ True
+
+
+
+
+ 3
+ True
+ False
+ False
+
+
+
+
+
+ 200
+ ButtonPressMask
+
+
+ 4
+ False
+
+
+
+
+
+
\ No newline at end of file