diff --git a/DesertPaintLab.csproj b/DesertPaintLab.csproj --- a/DesertPaintLab.csproj +++ b/DesertPaintLab.csproj @@ -8,6 +8,7 @@ DesertPaintLab DesertPaintLab v4.5 + false publish\ true Disk @@ -18,9 +19,9 @@ false false true + true 0 1.0.0.%2a - false false true @@ -82,6 +83,7 @@ + diff --git a/InterfaceSize.cs b/InterfaceSize.cs new file mode 100644 --- /dev/null +++ b/InterfaceSize.cs @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, Jason Maltzen + + 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. +*/ + +namespace DesertPaintLab +{ + public enum InterfaceSize + { + Tiny = 0, + Small = 1, + Medium = 2, + Large = 3, + Huge = 4 + } +} \ No newline at end of file diff --git a/MainWindow.cs b/MainWindow.cs --- a/MainWindow.cs +++ b/MainWindow.cs @@ -31,152 +31,128 @@ public partial class MainWindow : Gtk.Wi { const string APP_VERSION = "1.7.15"; - bool unsavedData = false; - bool shouldShutDown = false; - List profileList = new List(); - PlayerProfile profile = null; - - Gdk.Window rootWindow = null; - Gdk.Pixbuf screenBuffer = null; + bool unsavedData = false; + bool shouldShutDown = false; + List profileList = new List(); + PlayerProfile profile = null; + + Gdk.Window rootWindow = null; + Gdk.Pixbuf screenBuffer = null; // views RecipeGeneratorView generatorView; SimulatorView simulatorView; CaptureView captureView; - public bool ShouldShutDown - { - get - { - return shouldShutDown; - } - } - - public MainWindow () : base(Gtk.WindowType.Toplevel) - { + private ReactionStatusWindow _reactionStatusWindow; + + public bool ShouldShutDown + { + get + { + return shouldShutDown; + } + } + + public MainWindow() : base(Gtk.WindowType.Toplevel) + { string appDataPath = FileUtils.AppDataPath; - 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); - } - } + 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); + } + } string colorsPath = FileUtils.FindApplicationResourceFile("colors.txt"); if (colorsPath == null) { // failed to find colors.txt file - MessageDialog md = new MessageDialog(this, + MessageDialog md = new MessageDialog(this, DialogFlags.DestroyWithParent, - MessageType.Error, ButtonsType.Close, + MessageType.Error, ButtonsType.Close, "Failed to find colors.txt file. Please check your installation."); - + md.Run(); md.Destroy(); Application.Quit(); } - Palette.Load(colorsPath); + Palette.Load(colorsPath); string ingredientsPath = FileUtils.FindApplicationResourceFile("ingredients.txt"); if (ingredientsPath == null) { // failed to find ingredients.txt file - MessageDialog md = new MessageDialog(this, + MessageDialog md = new MessageDialog(this, DialogFlags.DestroyWithParent, - MessageType.Error, ButtonsType.Close, + MessageType.Error, ButtonsType.Close, "Failed to find ingredients.txt file. Please check your installation."); - + md.Run(); md.Destroy(); Application.Quit(); } ReagentManager.Load(ingredientsPath); - - Build(); - - // get the root window - rootWindow = Gdk.Global.DefaultRootWindow; + + Build(); - // get its width and height - int detectedScreenWidth; - int detectedScreenHeight; - rootWindow.GetSize(out detectedScreenWidth, out detectedScreenHeight); - int screenWidth = detectedScreenWidth; - int screenHeight = detectedScreenHeight; - int pixelMultiplier = 1; + // get the root window + rootWindow = Gdk.Global.DefaultRootWindow; - if ( DesertPaintLab.AppSettings.Load() == true ) - { - DesertPaintLab.AppSettings.Get("ScreenWidth", out screenWidth); - DesertPaintLab.AppSettings.Get("ScreenHeight", out screenHeight); - DesertPaintLab.AppSettings.Get("PixelMultiplier", out pixelMultiplier); - } + // get its width and height + DesertPaintLab.AppSettings.Load(); + + ShowPreferencesDialog(); bool enableDebugMenu; DesertPaintLab.AppSettings.Get("EnableDebugMenu", out enableDebugMenu); this.DebugAction.Visible = enableDebugMenu; - ScreenCheckDialog screenCheckDialog = new ScreenCheckDialog(); - // TODO: screenCheckDialog.DetectedWidth = detectedScreenWidth; - // TODO: screenCheckDialog.DetectedHeight = detectedScreenHeight; - screenCheckDialog.ScreenWidth = screenWidth; - screenCheckDialog.ScreenHeight = screenHeight; - screenCheckDialog.GamePixelWidth = pixelMultiplier; - ResponseType resp = (ResponseType)screenCheckDialog.Run(); - screenWidth = screenCheckDialog.ScreenWidth; - screenHeight = screenCheckDialog.ScreenHeight; - pixelMultiplier = screenCheckDialog.GamePixelWidth; - screenCheckDialog.Destroy(); + ReactionRecorder.Instance.OnReactionRecorded += OnReactionRecorded; + + if (!OpenProfile()) + { + shouldShutDown = true; + } - DesertPaintLab.AppSettings.Set("ScreenWidth", screenWidth); - DesertPaintLab.AppSettings.Set("ScreenHeight", screenHeight); - DesertPaintLab.AppSettings.Set("PixelMultiplier", pixelMultiplier); - DesertPaintLab.AppSettings.Save(); - - screenBuffer = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8, screenWidth, screenHeight); - - ReactionRecorder.Instance.SetPixelMultiplier(pixelMultiplier); - - if (!OpenProfile()) - { - shouldShutDown = true; - } + if (!shouldShutDown) + { + captureView = new CaptureView(profile, screenBuffer); + generatorView = new RecipeGeneratorView(profile); + generatorView.SetStatus += OnStatusUpdate; + generatorView.Started += OnGeneratorRunning; + generatorView.Stopped += OnGeneratorStopped; + simulatorView = new SimulatorView(profile); - captureView = new CaptureView(profile, screenBuffer); - generatorView = new RecipeGeneratorView(profile); - generatorView.SetStatus += OnStatusUpdate; - generatorView.Started += OnGeneratorRunning; - generatorView.Stopped += OnGeneratorStopped; - simulatorView = new SimulatorView(profile); - - contentContainer.Add(captureView); - captureView.Show(); - } + contentContainer.Add(captureView); + captureView.Show(); + } + } - 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; - } + 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; + } protected void OnStatusUpdate(object sender, EventArgs args) { @@ -205,17 +181,17 @@ public partial class MainWindow : Gtk.Wi captureView.EnableRecord(); } } - - void SetProfileName(string name) - { - profile = new PlayerProfile(name, + + void SetProfileName(string name) + { + profile = new PlayerProfile(name, System.IO.Path.Combine(FileUtils.AppDataPath, name)); - } + } void ProfileChanged() { statusBar.Push(0, "Profile: " + profile.Name); - Title = "Desert Paint Lab - " + profile.Name; + Title = "Desert Paint Lab - " + profile.Name; if (generatorView != null) { @@ -230,112 +206,112 @@ public partial class MainWindow : Gtk.Wi captureView.Profile = profile; } } - - 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.Equals(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); - + + 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.Equals(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); + newProfileCreated = profile.Initialize(); if (!newProfileCreated) { - MessageDialog md = new MessageDialog(this, + MessageDialog md = new MessageDialog(this, DialogFlags.DestroyWithParent, - MessageType.Error, ButtonsType.Ok, + MessageType.Error, ButtonsType.Ok, "Failed to initialize profile: " + profile.LastError); resp = (ResponseType)md.Run(); md.Destroy(); duplicateName = false; } ProfileChanged(); - } - } - 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.ImportFromPP(directory); - } - } - } - } - } - - if (profileSelected) - { - bool ok = profile.Load(); + } + } + 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.ImportFromPP(directory); + } + } + } + } + } + + if (profileSelected) + { + bool ok = profile.Load(); if (ok) { @@ -343,33 +319,33 @@ public partial class MainWindow : Gtk.Wi } else { - MessageDialog md = new MessageDialog(this, + MessageDialog md = new MessageDialog(this, DialogFlags.DestroyWithParent, - MessageType.Error, ButtonsType.Ok, + MessageType.Error, ButtonsType.Ok, "Error loading profile: " + profile.LastError); md.Run(); md.Destroy(); profileSelected = false; } - } + } + + return profileSelected; + } - return profileSelected; - } - - protected void OnDeleteEvent(object sender, DeleteEventArgs a) - { - if (ConfirmedExit()) - { - a.RetVal = true; - Application.Quit(); - } - else - { - a.RetVal = false; - } - } - + protected void OnDeleteEvent(object sender, DeleteEventArgs a) + { + if (ConfirmedExit()) + { + a.RetVal = true; + Application.Quit(); + } + else + { + a.RetVal = false; + } + } + protected virtual void OnDebugScreenshot(object sender, System.EventArgs e) { int screenWidth, screenHeight; @@ -389,120 +365,135 @@ public partial class MainWindow : Gtk.Wi screenBuffer.Save(filename, "png"); } - 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()) - { - bool ok = profile.Load(); + 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()) + { + bool ok = profile.Load(); + if (ok) + { + ProfileChanged(); + } + else + { + MessageDialog md = new MessageDialog(this, + DialogFlags.DestroyWithParent, + MessageType.Warning, ButtonsType.OkCancel, + "Failed to load profile: " + profile.LastError); + md.Run(); + md.Destroy(); + } + } + } + + protected virtual void OnOpenProfile(object sender, System.EventArgs e) + { + bool profileSelected = false; + SelectProfileDialog selectProfileDialog = new SelectProfileDialog(); + selectProfileDialog.ProfileList = profileList; + ResponseType resp = (ResponseType)selectProfileDialog.Run(); + selectProfileDialog.Destroy(); + if (resp == ResponseType.Ok) // Selected a profile. + { + SetProfileName(selectProfileDialog.SelectedProfile); + profileSelected = true; + } + else if (resp == ResponseType.Accept) // New profile. + { + profileSelected = NewProfile(); + } + if (profileSelected) + { + bool ok = profile.Load(); if (ok) { ProfileChanged(); } else { - MessageDialog md = new MessageDialog(this, + MessageDialog md = new MessageDialog(this, DialogFlags.DestroyWithParent, - MessageType.Warning, ButtonsType.OkCancel, - "Failed to load profile: " + profile.LastError); - md.Run(); - md.Destroy(); - } - } - } - - protected virtual void OnOpenProfile(object sender, System.EventArgs e) - { - bool profileSelected = false; - SelectProfileDialog selectProfileDialog = new SelectProfileDialog(); - selectProfileDialog.ProfileList = profileList; - ResponseType resp = (ResponseType)selectProfileDialog.Run(); - selectProfileDialog.Destroy(); - if (resp == ResponseType.Ok) // Selected a profile. - { - SetProfileName(selectProfileDialog.SelectedProfile); - profileSelected = true; - } - else if (resp == ResponseType.Accept) // New profile. - { - profileSelected = NewProfile(); - } - if (profileSelected) - { - bool ok = profile.Load(); - if (ok) - { - ProfileChanged(); - } - else - { - MessageDialog md = new MessageDialog(this, - DialogFlags.DestroyWithParent, - MessageType.Warning, ButtonsType.OkCancel, + MessageType.Warning, ButtonsType.OkCancel, "Failed to load profile: " + profile.LastError); md.Run(); md.Destroy(); } - } - } - - protected virtual void OnAbout(object sender, System.EventArgs e) - { - AboutDialog aboutDialog = new AboutDialog(); + } + } + + protected virtual void OnAbout(object sender, System.EventArgs e) + { + AboutDialog aboutDialog = new AboutDialog(); aboutDialog.ProgramName = "Desert Paint Lab"; - aboutDialog.Version = APP_VERSION ; + aboutDialog.Version = APP_VERSION; aboutDialog.Comments = "Desert Paint Lab paint reaction recorder for A Tale in the Desert"; - aboutDialog.Authors = new string [] {"Tess Snider", "Jason Maltzen"}; + aboutDialog.Authors = new string[] { "Tess Snider", "Jason Maltzen" }; //aboutDialog.Website = "http://www.google.com/"; - aboutDialog.Run(); - aboutDialog.Destroy(); - } - - protected virtual void OnMenuExit (object sender, System.EventArgs e) - { - if (ConfirmedExit()) - { - Application.Quit(); - } - } - - protected virtual void OnExportToPracticalPaint(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.SaveToPP(System.IO.Path.Combine(directory, fileName)); - } - fileDialog.Destroy(); - } + aboutDialog.Run(); + aboutDialog.Destroy(); + } + + protected virtual void OnMenuExit(object sender, System.EventArgs e) + { + if (ConfirmedExit()) + { + Application.Quit(); + } + } + + protected virtual void OnExportToPracticalPaint(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.SaveToPP(System.IO.Path.Combine(directory, fileName)); + } + fileDialog.Destroy(); + } + + protected void OnReactionRecorded(Reagent reagent1, Reagent reagent2, Reaction reaction) + { + if (_reactionStatusWindow != null) + { + _reactionStatusWindow.RefreshReactions(); + } + } + + protected void OnReactionStatusDestroyed(object o, EventArgs args) + { + _reactionStatusWindow = null; + } protected void OnShowReactionStatus(object sender, EventArgs e) { - ReactionStatusWindow win = new ReactionStatusWindow(profile); - win.Show(); + if (_reactionStatusWindow != null) return; // already open + _reactionStatusWindow = new ReactionStatusWindow(profile); + _reactionStatusWindow.Destroyed += new EventHandler(OnReactionStatusDestroyed); + _reactionStatusWindow.Show(); } protected void OnExportProfile(object sender, EventArgs e) @@ -521,12 +512,12 @@ public partial class MainWindow : Gtk.Wi if (File.Exists(targetFile)) { // prompt to overwrite - MessageDialog md = new MessageDialog(this, + MessageDialog md = new MessageDialog(this, DialogFlags.DestroyWithParent, - MessageType.Warning, ButtonsType.OkCancel, + MessageType.Warning, ButtonsType.OkCancel, "Overwrite file at " + targetFile + "?"); - + resp = (ResponseType)md.Run(); md.Destroy(); if (resp == ResponseType.Ok) @@ -563,12 +554,12 @@ public partial class MainWindow : Gtk.Wi if (Directory.Exists(profile.Directory)) { // prompt to overwrite - MessageDialog md = new MessageDialog(this, + MessageDialog md = new MessageDialog(this, DialogFlags.DestroyWithParent, - MessageType.Warning, ButtonsType.OkCancel, + MessageType.Warning, ButtonsType.OkCancel, "Overwrite profile '" + profile.Name + "'?"); - + resp = (ResponseType)md.Run(); md.Destroy(); if (resp == ResponseType.Ok) @@ -588,9 +579,9 @@ public partial class MainWindow : Gtk.Wi } else { - MessageDialog md = new MessageDialog(this, + MessageDialog md = new MessageDialog(this, DialogFlags.DestroyWithParent, - MessageType.Warning, ButtonsType.OkCancel, + MessageType.Warning, ButtonsType.OkCancel, "Failed to load imported profile: " + profile.LastError); md.Run(); md.Destroy(); @@ -721,5 +712,65 @@ public partial class MainWindow : Gtk.Wi OpenProfileAction.Sensitive = true; ImportProfileAction.Sensitive = true; } + + protected void ShowPreferencesDialog() + { + int detectedScreenWidth; + int detectedScreenHeight; + rootWindow.GetSize(out detectedScreenWidth, out detectedScreenHeight); + int screenWidth = detectedScreenWidth; + int screenHeight = detectedScreenHeight; + int pixelMultiplier = 1; + int interfaceSizeIndex = (int)(InterfaceSize.Small); + + DesertPaintLab.AppSettings.Get("ScreenWidth", out screenWidth); + DesertPaintLab.AppSettings.Get("ScreenHeight", out screenHeight); + DesertPaintLab.AppSettings.Get("PixelMultiplier", out pixelMultiplier); + DesertPaintLab.AppSettings.Get("InterfaceSize", out interfaceSizeIndex); + InterfaceSize interfaceSize = (InterfaceSize)interfaceSizeIndex; + + ScreenCheckDialog screenCheckDialog = new ScreenCheckDialog(); + screenCheckDialog.DetectedScreenWidth = detectedScreenWidth; + screenCheckDialog.DetectedScreenHeight = detectedScreenHeight; + screenCheckDialog.ScreenWidth = screenWidth; + screenCheckDialog.ScreenHeight = screenHeight; + screenCheckDialog.GamePixelWidth = pixelMultiplier; + screenCheckDialog.InterfaceSize = interfaceSize; + + ResponseType resp = (ResponseType)screenCheckDialog.Run(); + + screenWidth = screenCheckDialog.ScreenWidth; + screenHeight = screenCheckDialog.ScreenHeight; + pixelMultiplier = screenCheckDialog.GamePixelWidth; + interfaceSize = screenCheckDialog.InterfaceSize; + screenCheckDialog.Destroy(); + + DesertPaintLab.AppSettings.Set("ScreenWidth", screenWidth); + DesertPaintLab.AppSettings.Set("ScreenHeight", screenHeight); + DesertPaintLab.AppSettings.Set("PixelMultiplier", pixelMultiplier); + DesertPaintLab.AppSettings.Set("InterfaceSize", (int)interfaceSize); + DesertPaintLab.AppSettings.Save(); + + screenBuffer = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8, screenWidth, screenHeight); + + ReactionRecorder.Instance.SetPixelMultiplier(pixelMultiplier); + ReactionRecorder.Instance.SetInterfaceSize(interfaceSize); + } + + protected void OnPreferences(object sender, EventArgs e) + { + ShowPreferencesDialog(); + + int screenWidth = 1920; + int screenHeight = 1080; + int pixelMultiplier = 1; + int interfaceSizeIndex = (int)(InterfaceSize.Small); + + DesertPaintLab.AppSettings.Get("ScreenWidth", out screenWidth); + DesertPaintLab.AppSettings.Get("ScreenHeight", out screenHeight); + DesertPaintLab.AppSettings.Get("PixelMultiplier", out pixelMultiplier); + DesertPaintLab.AppSettings.Get("InterfaceSize", out interfaceSizeIndex); + + captureView.ScreenBuffer = screenBuffer; + } } - diff --git a/PlayerProfile.cs b/PlayerProfile.cs --- a/PlayerProfile.cs +++ b/PlayerProfile.cs @@ -516,7 +516,7 @@ namespace DesertPaintLab using (writer) { writer.WriteLine("{| class='wikitable sortable' border=\"1\" style=\"background-color:#DEB887;\""); - writer.WriteLine("! Color !! Recipe !! Verified"); + writer.WriteLine("! Color !! Recipe !! Missing Reactions? || Verified"); foreach (PaintColor color in Palette.Colors) { writer.WriteLine("|-"); @@ -547,10 +547,16 @@ namespace DesertPaintLab } colorLine += " || "; - if (recipe.CheckMissingReactions(ref missing) == false) + if (recipe.CheckMissingReactions(ref missing) == true) { colorLine += "Y"; } + else + { + colorLine += "N"; + } + + colorLine += " || N"; writer.WriteLine(colorLine); } writer.WriteLine("|}"); diff --git a/ReactionRecorder.cs b/ReactionRecorder.cs --- a/ReactionRecorder.cs +++ b/ReactionRecorder.cs @@ -28,29 +28,104 @@ namespace DesertPaintLab // ReactionRecorder - business logic for recording paint reactions public class ReactionRecorder { + public delegate void CaptureProgressHandler(int x, int y); + public CaptureProgressHandler OnCaptureProgress; + const int COLOR_TOLERANCE = 3; - const int DEFAULT_SWATCH_HEIGHT = 24; // including top and bottom borders - const int DEFAULT_SWATCH_WIDTH = 260; - const int DEFAULT_COLOR_BAR_WIDTH = 306; - const int DEFAULT_RED_BAR_SPACING = 32; - const int DEFAULT_GREEN_BAR_SPACING = 42; - const int DEFAULT_BLUE_BAR_SPACING = 52; - - const int DEFAULT_SWATCH_TEST_WIDTH = 26; // width to test on ends of swatch (10% on either end) + const InterfaceSize DEFAULT_INTERFACE_SIZE = InterfaceSize.Small; - int swatchHeight = DEFAULT_SWATCH_HEIGHT; - int swatchWidth = DEFAULT_SWATCH_WIDTH; - int swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH; - int colorBarWidth = DEFAULT_COLOR_BAR_WIDTH; - int redBarSpacing = DEFAULT_RED_BAR_SPACING; - int greenBarSpacing = DEFAULT_GREEN_BAR_SPACING; - int blueBarSpacing = DEFAULT_BLUE_BAR_SPACING; + public static readonly int[] SWATCH_HEIGHT = + { + 24, // tiny + 24, // small + 24, // medium + 24, // large + 24 // huge + }; + public static readonly int[] SWATCH_WIDTH = + { + 260, // tiny + 260, // small + 260, // medium + 274, // large + 304 // huge + }; + public static readonly int[] COLOR_BAR_WIDTH = + { + 306, // tiny + 306, // small + 306, // medium + 320, // large + 350 // huge + }; + public static readonly int[] RED_BAR_SPACING = + { + 32, // tiny + 32, // small + 32, // medium + 32, // large + 32 // huge + }; + public static readonly int[] GREEN_BAR_SPACING = + { + 42, // tiny + 42, // small + 42, // medium + 42, // large + 42 // huge + }; + public static readonly int[] BLUE_BAR_SPACING = + { + 52, // tiny + 52, // small + 52, // medium + 52, // large + 52 // huge + }; + // width to test on ends of swatch (10% on either end) + public static readonly int[] SWATCH_TEST_WIDTH = + { + 26, // tiny + 26, // small + 26, // medium + 28, // large + 31 // huge + }; + + int swatchHeight = SWATCH_HEIGHT[(int)DEFAULT_INTERFACE_SIZE]; + int swatchWidth = SWATCH_WIDTH[(int)DEFAULT_INTERFACE_SIZE]; + int swatchTestWidth = SWATCH_TEST_WIDTH[(int)DEFAULT_INTERFACE_SIZE]; + int colorBarWidth = COLOR_BAR_WIDTH[(int)DEFAULT_INTERFACE_SIZE]; + int redBarSpacing = RED_BAR_SPACING[(int)DEFAULT_INTERFACE_SIZE]; + int greenBarSpacing = GREEN_BAR_SPACING[(int)DEFAULT_INTERFACE_SIZE]; + int blueBarSpacing = BLUE_BAR_SPACING[(int)DEFAULT_INTERFACE_SIZE]; + + public int SwatchHeight { get { return swatchHeight; } } + public int SwatchWidth { get { return swatchWidth; } } + public int ColorBarWidth { get { return colorBarWidth; } } + public int RedBarSpacing { get { return redBarSpacing; } } + public int GreenBarSpacing { get { return greenBarSpacing; } } + public int BlueBarSpacing { get { return blueBarSpacing; } } + + // Current Status + public bool IsCaptured { get; private set; } + public int X { get; private set; } + public int Y { get; private set; } + public int ScreenWidth { get; private set; } + public int ScreenHeight { get; private set; } + public PaintColor RecordedColor { get; private set; } + public int RedBarX { get; private set; } + public int RedBarY { get; private set; } + int pixelMultiplier = 1; + InterfaceSize interfaceSize; bool firstRun = true; int lastSwatchX = -1; int lastSwatchY = -1; + public int SwatchX { get { return lastSwatchX; } } + public int SwatchY { get { return lastSwatchY; } } private static ReactionRecorder _instance; public static ReactionRecorder Instance @@ -64,44 +139,55 @@ namespace DesertPaintLab } } - private StreamWriter _log; - public StreamWriter Log - { - set - { - _log = value; - } - } + public StreamWriter Log { get; set; } private void WriteLog(string format, params object[] args) { - if (_log != null) + if (Log != null) { - _log.WriteLine(format, args); + Log.WriteLine(format, args); } } + public delegate void ReactionRecordedHandler(Reagent reagent1, Reagent reagent2, Reaction reaction); + public ReactionRecordedHandler OnReactionRecorded; + public ReactionRecorder() { - this.pixelMultiplier = 1; - swatchHeight = DEFAULT_SWATCH_HEIGHT * pixelMultiplier; - swatchWidth = DEFAULT_SWATCH_WIDTH * pixelMultiplier; - colorBarWidth = DEFAULT_COLOR_BAR_WIDTH * pixelMultiplier; - redBarSpacing = DEFAULT_RED_BAR_SPACING * pixelMultiplier; - greenBarSpacing = DEFAULT_GREEN_BAR_SPACING * pixelMultiplier; - blueBarSpacing = DEFAULT_BLUE_BAR_SPACING * pixelMultiplier; - swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH * pixelMultiplier; + pixelMultiplier = 1; + interfaceSize = DEFAULT_INTERFACE_SIZE; + swatchHeight = SWATCH_HEIGHT[(int)interfaceSize] * pixelMultiplier; + swatchWidth = SWATCH_WIDTH[(int)interfaceSize] * pixelMultiplier; + colorBarWidth = COLOR_BAR_WIDTH[(int)interfaceSize] * pixelMultiplier; + redBarSpacing = RED_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + greenBarSpacing = GREEN_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + blueBarSpacing = BLUE_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + swatchTestWidth = SWATCH_TEST_WIDTH[(int)interfaceSize] * pixelMultiplier; } public ReactionRecorder(int pixelMultiplier) { this.pixelMultiplier = pixelMultiplier; - swatchHeight = DEFAULT_SWATCH_HEIGHT * pixelMultiplier; - swatchWidth = DEFAULT_SWATCH_WIDTH * pixelMultiplier; - colorBarWidth = DEFAULT_COLOR_BAR_WIDTH * pixelMultiplier; - redBarSpacing = DEFAULT_RED_BAR_SPACING * pixelMultiplier; - greenBarSpacing = DEFAULT_GREEN_BAR_SPACING * pixelMultiplier; - blueBarSpacing = DEFAULT_BLUE_BAR_SPACING * pixelMultiplier; - swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH * pixelMultiplier; + this.interfaceSize = DEFAULT_INTERFACE_SIZE; + swatchHeight = SWATCH_HEIGHT[(int)interfaceSize] * pixelMultiplier; + swatchWidth = SWATCH_WIDTH[(int)interfaceSize] * pixelMultiplier; + colorBarWidth = COLOR_BAR_WIDTH[(int)interfaceSize] * pixelMultiplier; + redBarSpacing = RED_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + greenBarSpacing = GREEN_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + blueBarSpacing = BLUE_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + swatchTestWidth = SWATCH_TEST_WIDTH[(int)interfaceSize] * pixelMultiplier; + } + + public ReactionRecorder(int pixelMultiplier, InterfaceSize interfaceSize) + { + this.pixelMultiplier = pixelMultiplier; + this.interfaceSize = interfaceSize; + swatchHeight = SWATCH_HEIGHT[(int)interfaceSize] * pixelMultiplier; + swatchWidth = SWATCH_WIDTH[(int)interfaceSize] * pixelMultiplier; + colorBarWidth = COLOR_BAR_WIDTH[(int)interfaceSize] * pixelMultiplier; + redBarSpacing = RED_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + greenBarSpacing = GREEN_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + blueBarSpacing = BLUE_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + swatchTestWidth = SWATCH_TEST_WIDTH[(int)interfaceSize] * pixelMultiplier; } private static bool IsPapyTexture(byte r, byte g, byte b) @@ -115,14 +201,28 @@ namespace DesertPaintLab public void SetPixelMultiplier(int pixelMultiplier) { - swatchHeight = DEFAULT_SWATCH_HEIGHT * pixelMultiplier; - swatchWidth = DEFAULT_SWATCH_WIDTH * pixelMultiplier; - colorBarWidth = DEFAULT_COLOR_BAR_WIDTH * pixelMultiplier; - redBarSpacing = DEFAULT_RED_BAR_SPACING * pixelMultiplier; - greenBarSpacing = DEFAULT_GREEN_BAR_SPACING * pixelMultiplier; - blueBarSpacing = DEFAULT_BLUE_BAR_SPACING * pixelMultiplier; - swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH * pixelMultiplier; this.pixelMultiplier = pixelMultiplier; + + swatchHeight = SWATCH_HEIGHT[(int)interfaceSize] * pixelMultiplier; + swatchWidth = SWATCH_WIDTH[(int)interfaceSize] * pixelMultiplier; + colorBarWidth = COLOR_BAR_WIDTH[(int)interfaceSize] * pixelMultiplier; + redBarSpacing = RED_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + greenBarSpacing = GREEN_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + blueBarSpacing = BLUE_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + swatchTestWidth = SWATCH_TEST_WIDTH[(int)interfaceSize] * pixelMultiplier; + } + + public void SetInterfaceSize(InterfaceSize interfaceSize) + { + this.interfaceSize = interfaceSize; + + swatchHeight = SWATCH_HEIGHT[(int)interfaceSize] * pixelMultiplier; + swatchWidth = SWATCH_WIDTH[(int)interfaceSize] * pixelMultiplier; + colorBarWidth = COLOR_BAR_WIDTH[(int)interfaceSize] * pixelMultiplier; + redBarSpacing = RED_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + greenBarSpacing = GREEN_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + blueBarSpacing = BLUE_BAR_SPACING[(int)interfaceSize] * pixelMultiplier; + swatchTestWidth = SWATCH_TEST_WIDTH[(int)interfaceSize] * pixelMultiplier; } unsafe private void ColorAt(byte *pixBytes, int x, int y, int stride, out byte r, out byte g, out byte b) @@ -299,18 +399,19 @@ namespace DesertPaintLab // WE FOUND THE SWATCH! // Now we know where the color bars are. redPixelStart = pixelStart + (redBarSpacing * stride); + int redPixel = redPixelStart; int redPixelCount = 0; - while ((pixBytes[redPixelStart] > 0x9F) && - (pixBytes[redPixelStart + 1] < 0x62) && - (pixBytes[redPixelStart + 2] < 0x62)) + while ((pixBytes[redPixel] > 0x9F) && + (pixBytes[redPixel + 1] < 0x62) && + (pixBytes[redPixel + 2] < 0x62)) { redPixelCount++; - // pixBytes[redPixelStart] = 0x00; - // pixBytes[redPixelStart + 1] = 0xFF; - // pixBytes[redPixelStart + 2] = 0xFF; - redPixelStart += 3; + // pixBytes[redPixel] = 0x00; + // pixBytes[redPixel + 1] = 0xFF; + // pixBytes[redPixel + 2] = 0xFF; + redPixel += 3; } - WriteLog("Color {0}, {1}, {2} is no longer red at {3},{4}", pixBytes[redPixelStart], pixBytes[redPixelStart + 1], pixBytes[redPixelStart + 2], (redPixelStart % stride)/3, redPixelStart / stride); + WriteLog("Color {0}, {1}, {2} is no longer red at {3},{4}", pixBytes[redPixel], pixBytes[redPixel + 1], pixBytes[redPixel + 2], (redPixel % stride)/3, redPixel / stride); reactedColor.Red = (byte)Math.Round((float)redPixelCount * 255f / (float)colorBarWidth); int greenPixelStart = pixelStart + (greenBarSpacing * stride); @@ -326,7 +427,7 @@ namespace DesertPaintLab // pixBytes[greenPixelStart + 2] = 0xFF; greenPixelStart += 3; } - WriteLog("Color {0}, {1}, {2} is no longer green at pixel offset {3},{4}", pixBytes[greenPixelStart], pixBytes[greenPixelStart + 1], pixBytes[greenPixelStart + 2], (greenPixelStart % stride)/3, redPixelStart / stride); + WriteLog("Color {0}, {1}, {2} is no longer green at pixel offset {3},{4}", pixBytes[greenPixelStart], pixBytes[greenPixelStart + 1], pixBytes[greenPixelStart + 2], (greenPixelStart % stride)/3, greenPixelStart / stride); reactedColor.Green = (byte)Math.Round((float)greenPixelCount * 255f / (float)colorBarWidth); int bluePixelStart = pixelStart + (blueBarSpacing * stride); @@ -352,13 +453,23 @@ namespace DesertPaintLab return false; } - unsafe public bool CaptureReaction(byte* pixBytes, int screenshotWidth, int screenshotHeight, int stride, ref PaintColor reactedColor, ref int redPixelStart) + unsafe public bool CaptureReaction(byte* pixBytes, int screenshotWidth, int screenshotHeight, int stride) { + PaintColor reactedColor = new PaintColor(); + int redPixelStart = 0; + ScreenWidth = screenshotWidth; + ScreenHeight = screenshotHeight; + + IsCaptured = false; if (!firstRun) { // If this is not the first run, let's check the last location, to see if the UI is still there. if (TestPosition(lastSwatchX, lastSwatchY, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart)) { + IsCaptured = true; + RedBarX = (redPixelStart % stride) / 3; + RedBarY = redPixelStart / stride; + RecordedColor = reactedColor; return true; } else @@ -367,17 +478,22 @@ namespace DesertPaintLab } } - for (int x = 0; x < screenshotWidth - colorBarWidth; ++x) + for (X = 0; X < screenshotWidth - colorBarWidth; ++X) { - for (int y = 0; y < (screenshotHeight - (blueBarSpacing + 1) /*53*/); ++y) + for (int Y = 0; Y < (screenshotHeight - (blueBarSpacing + 10) /*53*/); ++Y) { - if (TestPosition(x, y, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart)) + if (TestPosition(X, Y, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart)) { - lastSwatchX = x; - lastSwatchY = y; + RedBarX = (redPixelStart % stride) / 3; + RedBarY = redPixelStart / stride; + RecordedColor = reactedColor; + lastSwatchX = X; + lastSwatchY = Y; firstRun = false; + IsCaptured = true; return true; } + OnCaptureProgress?.Invoke(X, Y); } } return false; @@ -403,19 +519,23 @@ namespace DesertPaintLab r = r - reaction1.Red - reaction3.Red; g = g - reaction1.Green - reaction3.Green; b = b - reaction1.Blue - reaction3.Blue; - profile.SetReaction(reagents[0], reagents[2], new Reaction(r, g, b)); + Reaction reaction = new Reaction(r, g, b); + profile.SetReaction(reagents[0], reagents[2], reaction); profile.Save(); saved = true; + OnReactionRecorded?.Invoke(reagents[0], reagents[2], reaction); } else if (reaction3 == null) { r = r - reaction1.Red - reaction2.Red; g = g - reaction1.Green - reaction2.Green; b = b - reaction1.Blue - reaction2.Blue; - profile.SetReaction(reagents[1], reagents[2], new Reaction(r, g, b)); + Reaction reaction = new Reaction(r, g, b); + profile.SetReaction(reagents[1], reagents[2], reaction); profile.Save(); saved = true; - } + OnReactionRecorded?.Invoke(reagents[1], reagents[2], reaction); + } } else if ((reagents[0] != null) && (reagents[1] != null)) { @@ -423,9 +543,11 @@ namespace DesertPaintLab r = reactedColor.Red - expectedColor.Red; g = reactedColor.Green - expectedColor.Green; b = reactedColor.Blue - expectedColor.Blue; - profile.SetReaction(reagents[0], reagents[1], new Reaction(r, g, b)); + Reaction reaction = new Reaction(r, g, b); + profile.SetReaction(reagents[0], reagents[1], reaction); profile.Save(); saved = true; + OnReactionRecorded?.Invoke(reagents[0], reagents[1], reaction); } return saved; } diff --git a/ReactionStatusWindow.cs b/ReactionStatusWindow.cs --- a/ReactionStatusWindow.cs +++ b/ReactionStatusWindow.cs @@ -4,15 +4,19 @@ namespace DesertPaintLab { public partial class ReactionStatusWindow : Gtk.Window { - //PlayerProfile profile; + PlayerProfile _profile; + + Gtk.ListStore reagentListStore; public ReactionStatusWindow(PlayerProfile profile) : base(Gtk.WindowType.Toplevel) { - //this.profile = profile; + _profile = profile; this.Build(); //Gtk.CellRendererText reagentColumnCell = new Gtk.CellRendererText(); + SetupReagentList(); + int count = 0; foreach (string name1 in ReagentManager.Names) { @@ -49,6 +53,119 @@ namespace DesertPaintLab } ShowAll(); } + + public void RefreshReactions() + { + while (resultbox.Children.Length > 0) + { + Gtk.Widget child = resultbox.Children[0]; + resultbox.Remove(child); + } + int count = 0; + foreach (string name1 in ReagentManager.Names) + { + Reagent reagent1 = ReagentManager.GetReagent(name1); + foreach (string name2 in ReagentManager.Names) + { + if (name1.Equals(name2)) + { + continue; + } + Reagent reagent2 = ReagentManager.GetReagent(name2); + if (!reagent1.Enabled || !reagent2.Enabled) continue; + Reaction reaction = _profile.FindReaction(reagent1, reagent2); + if (reaction == null) + { + if (count == 0) + { + Gtk.Label header = new Gtk.Label("Missing Reactions:"); + resultbox.PackStart(header, false, false, 0); + Gtk.HSeparator sep = new Gtk.HSeparator(); + resultbox.PackStart(sep, false, false, 0); + } + Gtk.Label label = new Gtk.Label(name1 + " + " + name2); + resultbox.PackStart(label, false, false, 0); + + ++count; + } + } + } + + if (count == 0) + { + Gtk.Label header = new Gtk.Label("All reactions recorded!"); + resultbox.PackStart(header, false, false, 0); + } + ShowAll(); + } + + private void OnReagentToggled(object o, Gtk.ToggledArgs args) + { + Gtk.TreeIter iter; + reagentListStore.GetIter(out iter, new Gtk.TreePath(args.Path)); + + Reagent reagent = (Reagent)reagentListStore.GetValue(iter, 0); + reagent.Enabled = !reagent.Enabled; + // TODO: SaveReagentSettings(); + RefreshReactions(); + } + + // Reagent view handling + private void RenderReagentToggle(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) + { + Reagent reagent = (Reagent)model.GetValue(iter, 0); + Gtk.CellRendererToggle toggle = (cell as Gtk.CellRendererToggle); + toggle.Active = reagent.Enabled; + toggle.Activatable = !reagent.IsCatalyst; + toggle.Mode = reagent.IsCatalyst ? Gtk.CellRendererMode.Inert : Gtk.CellRendererMode.Activatable; + } + + void SetupReagentList() + { + // initialize reagent list + reagentListStore = new Gtk.ListStore(typeof(Reagent), typeof(string), typeof(Reagent), typeof(Reagent)); + foreach (string reagentName in ReagentManager.Names) + { + Reagent reagent = ReagentManager.GetReagent(reagentName); + reagentListStore.AppendValues(reagent, reagentName); // , reagent, reagent); + } + + // Add the columns to the TreeView + Gtk.TreeViewColumn reagentEnabledColumn = new Gtk.TreeViewColumn(); + reagentEnabledColumn.Title = "Enabled"; + Gtk.CellRendererToggle reagentEnabledCell = new Gtk.CellRendererToggle(); + reagentEnabledCell.Activatable = true; + reagentEnabledCell.Sensitive = true; + reagentEnabledCell.Mode = Gtk.CellRendererMode.Activatable; + reagentEnabledCell.Visible = true; + reagentEnabledCell.Toggled += new Gtk.ToggledHandler(OnReagentToggled); + reagentEnabledColumn.PackStart(reagentEnabledCell, true); + //reagentEnabledColumn.AddAttribute(reagentEnabledCell, "active", 0); + + Gtk.TreeViewColumn reagentNameColumn = new Gtk.TreeViewColumn(); + reagentNameColumn.Title = "Ingredient"; + Gtk.CellRendererText reagentNameCell = new Gtk.CellRendererText(); + reagentNameCell.Mode = Gtk.CellRendererMode.Inert; + reagentNameColumn.PackStart(reagentNameCell, true); + reagentNameColumn.AddAttribute(reagentNameCell, "text", 1); + reagentNameColumn.Expand = true; + + reagentListStore = new Gtk.ListStore(typeof(Reagent), typeof(string), typeof(Reagent), typeof(Reagent)); + foreach (string reagentName in ReagentManager.Names) + { + Reagent reagent = ReagentManager.GetReagent(reagentName); + reagentListStore.AppendValues(reagent, reagentName); // , reagent, reagent); + } + + reagentEnabledColumn.SetCellDataFunc(reagentEnabledCell, new Gtk.TreeCellDataFunc(RenderReagentToggle)); + + // Assign the model to the TreeView + reagentListView.Model = reagentListStore; + reagentListView.Sensitive = true; + + reagentListView.AppendColumn(reagentEnabledColumn); + reagentListView.AppendColumn(reagentNameColumn); + } } } diff --git a/ScreenCheckDialog.cs b/ScreenCheckDialog.cs --- a/ScreenCheckDialog.cs +++ b/ScreenCheckDialog.cs @@ -50,7 +50,35 @@ namespace DesertPaintLab } } - public int GamePixelWidth + private int _detectedScreenWidth; + private int _detectedScreenHeight; + public int DetectedScreenWidth + { + get + { + return _detectedScreenWidth; + } + set + { + _detectedScreenWidth = value; + detectedResolutionLabel.Text = string.Format("Detected: {0} x {1}", _detectedScreenWidth, _detectedScreenHeight); + } + } + + public int DetectedScreenHeight + { + get + { + return _detectedScreenHeight; + } + set + { + _detectedScreenHeight = value; + detectedResolutionLabel.Text = string.Format("Detected: {0} x {1}", _detectedScreenWidth, _detectedScreenHeight); + } + } + + public int GamePixelWidth { get { @@ -62,6 +90,21 @@ namespace DesertPaintLab } } + public InterfaceSize InterfaceSize + { + get + { + InterfaceSize result = (InterfaceSize)interfaceSizeComboBox.Active; + return result; + } + set + { + Gtk.TreeIter iter; + interfaceSizeComboBox.Model.IterNthChild(out iter, (int)value); + interfaceSizeComboBox.SetActiveIter(iter); + } + } + public ScreenCheckDialog () { this.Build (); diff --git a/UI/CaptureView.cs b/UI/CaptureView.cs --- a/UI/CaptureView.cs +++ b/UI/CaptureView.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Threading; namespace DesertPaintLab { @@ -17,6 +18,9 @@ namespace DesertPaintLab Gdk.Pixbuf screenBuffer = null; + Gtk.ThreadNotify notifyCaptureProgress; + Gtk.ThreadNotify notifyCaptureComplete; + bool recordEnabled = true; bool isCaptured = false; @@ -44,6 +48,18 @@ namespace DesertPaintLab recipe.Reactions = profile.Reactions; } + public Gdk.Pixbuf ScreenBuffer + { + get { return screenBuffer; } + set { + if (screenBuffer != null) + { + // TODO: free it up? + } + screenBuffer = value; + } + } + public PlayerProfile Profile { set { @@ -244,26 +260,19 @@ namespace DesertPaintLab } } - unsafe bool CaptureReactionColor() + unsafe void BeginCapture() { - // Take a screenshot. - int screenWidth, screenHeight; - bool debugScreenshot = false; + captureButton.Sensitive = false; + ingredient1ComboBox.Sensitive = false; + ingredient2ComboBox.Sensitive = false; + ingredient3ComboBox.Sensitive = false; + clearReactionButton.Sensitive = false; + + progressBar.Show(); + recordButton.Hide(); + bool enableDebugMenu = false; - Gdk.Window rootWindow = Gdk.Global.DefaultRootWindow; - DesertPaintLab.AppSettings.Get("ScreenWidth", out screenWidth); - DesertPaintLab.AppSettings.Get("ScreenHeight", out screenHeight); DesertPaintLab.AppSettings.Get("EnableDebugMenu", out enableDebugMenu); - DesertPaintLab.AppSettings.Get("DebugScreenshot", out debugScreenshot); - Gdk.Image rootImage = rootWindow.GetImage(0, 0, screenWidth, screenHeight); - screenBuffer.GetFromImage(rootImage, rootImage.Colormap, 0, 0, 0, 0, screenWidth, screenHeight); - rootImage.Unref(); - System.GC.Collect(); // really, clean up now - //screenBuffer.GetFromDrawable(rootWindow, - // rootWindow.Colormap, 0, 0, 0, 0, screenWidth, screenHeight); - int stride = screenBuffer.Rowstride; - byte* pixBytes = (byte*)screenBuffer.Pixels; - int redPixelStart = -1; StreamWriter log = null; if (enableDebugMenu) @@ -272,13 +281,64 @@ namespace DesertPaintLab log = new StreamWriter(logfile); ReactionRecorder.Instance.Log = log; } - isCaptured = ReactionRecorder.Instance.CaptureReaction(pixBytes, screenWidth, screenHeight, stride, ref reactedColor, ref redPixelStart); + + if (notifyCaptureProgress == null) + { + notifyCaptureProgress = new Gtk.ThreadNotify(new Gtk.ReadyEvent(NotifyCaptureProgress)); + notifyCaptureComplete = new Gtk.ThreadNotify(new Gtk.ReadyEvent(NotifyCaptureComplete)); + } + + this.reactionSwatch.Color = new PaintColor("Searching", "00", "00", "00"); + + Thread thr = new Thread(new ThreadStart(this.CaptureReactionThread)); + thr.Priority = ThreadPriority.AboveNormal; + thr.Start(); + //OnCaptureComplete(isCaptured, reactedColor, screenWidth, screenHeight, stride, redPixelStart); + } + + unsafe private void CaptureReactionThread() + { + byte* pixBytes = (byte*)screenBuffer.Pixels; + + ReactionRecorder.Instance.OnCaptureProgress += OnCaptureProgress; + ReactionRecorder.Instance.CaptureReaction(pixBytes, screenBuffer.Width, screenBuffer.Height, screenBuffer.Rowstride); + ReactionRecorder.Instance.OnCaptureProgress -= OnCaptureProgress; + + notifyCaptureComplete.WakeupMain(); + } + + private void OnCaptureProgress(int x, int y) + { + notifyCaptureProgress.WakeupMain(); + } + + private void NotifyCaptureProgress() + { + // TODO: progress bar + //ReactionRecorder.Instance.X; + //ReactionRecorder.Instance.Y; + progressBar.Fraction = ((double)(ReactionRecorder.Instance.X) / (double)(ReactionRecorder.Instance.ScreenWidth - ReactionRecorder.Instance.ColorBarWidth)); + } + + void OnCaptureComplete(bool isCaptured, PaintColor reactedColor, int swatchX, int swatchY) + { + int screenWidth = screenBuffer.Width; + int screenHeight = screenBuffer.Height; + int stride = screenBuffer.Rowstride; + + StreamWriter log = ReactionRecorder.Instance.Log; if (log != null) { log.Flush(); log.Close(); log = null; + ReactionRecorder.Instance.Log = null; } + + bool enableDebugMenu = false; + DesertPaintLab.AppSettings.Get("EnableDebugMenu", out enableDebugMenu); + bool debugScreenshot = false; + DesertPaintLab.AppSettings.Get("DebugScreenshot", out debugScreenshot); if (enableDebugMenu && debugScreenshot) { if (!isCaptured) @@ -291,27 +351,27 @@ namespace DesertPaintLab else { // record the swatch that was captured - // convert to pixel offset instead of byte - int redPixelStartX = (redPixelStart % stride) / 3; - int redPixelStartY = (redPixelStart / stride); // write out the screenshot string screenshotDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); string filename = FileUtils.FindNumberedFile("DesertPaintLab_Colormatch", "png", screenshotDir); - int captureAreaWidth = Math.Min(64, screenWidth - redPixelStartX + 64); - int captureAreaHeight = Math.Min(64, screenHeight - redPixelStartY + 64); - Gdk.Pixbuf outPixBuf = new Gdk.Pixbuf(screenBuffer, Math.Max(0, redPixelStartX - 32), Math.Max(0, redPixelStartY - 32), captureAreaWidth, captureAreaHeight); + int x = swatchX - 16; + int captureAreaWidth = ReactionRecorder.Instance.ColorBarWidth + 32; + captureAreaWidth = Math.Min(screenWidth - x, captureAreaWidth); + int y = swatchY - 16; + int captureAreaHeight = ReactionRecorder.Instance.BlueBarSpacing + 42; + captureAreaHeight = Math.Min(screenHeight - y, captureAreaHeight); + + Gdk.Pixbuf outPixBuf = new Gdk.Pixbuf(screenBuffer, Math.Max(0, x), Math.Max(0, y), + captureAreaWidth, captureAreaHeight); + //Gdk.Pixbuf outPixBuf = new Gdk.Pixbuf(screenBuffer, Math.Max(0, redPixelStartX), Math.Max(0, redPixelStartY), + // ReactionRecorder.Instance.ColorBarWidth, ReactionRecorder.Instance.GreenBarSpacing - ReactionRecorder.Instance.RedBarSpacing); //screenBuffer.Save(filename, "png"); outPixBuf.Save(filename, "png"); } } //screenBuffer.Save("screenshot.png", "png"); - - return isCaptured; - } - protected virtual void OnCapture(object sender, System.EventArgs e) - { - if (CaptureReactionColor()) + if (isCaptured) { string warning = ""; if (reactedColor.Red == 0) @@ -320,11 +380,11 @@ namespace DesertPaintLab } if (reactedColor.Green == 0) { - warning = warning + "\nGreen is too low."; + warning = warning + "\nGreen is too low."; } if (reactedColor.Blue == 0) { - warning = warning + "\nBlue is too low."; + warning = warning + "\nBlue is too low."; } if (reactedColor.Red == 255) { @@ -332,23 +392,23 @@ namespace DesertPaintLab } if (reactedColor.Green == 255) { - warning = warning + "\nGreen is too high."; + warning = warning + "\nGreen is too high."; } if (reactedColor.Blue == 255) { - warning = warning + "\nBlue is too high."; + warning = warning + "\nBlue is too high."; } - + if (warning.Length != 0) { isCaptured = true; - Gtk.MessageDialog md = new Gtk.MessageDialog((Gtk.Window)Toplevel, + Gtk.MessageDialog md = new Gtk.MessageDialog((Gtk.Window)Toplevel, Gtk.DialogFlags.DestroyWithParent, - Gtk.MessageType.Error, Gtk.ButtonsType.Ok, + Gtk.MessageType.Error, Gtk.ButtonsType.Ok, "Reaction clipped. You will need to do a " + "3-way reaction to test this pair. Details: " + warning); - + md.Run(); md.Destroy(); } @@ -357,20 +417,59 @@ namespace DesertPaintLab this.reactionSwatch.Color = reactedColor; recordButton.Sensitive = recordEnabled; } + + captureButton.Sensitive = false; } else { - Gtk.MessageDialog md = new Gtk.MessageDialog((Gtk.Window)Toplevel, + Gtk.MessageDialog md = new Gtk.MessageDialog((Gtk.Window)Toplevel, Gtk.DialogFlags.DestroyWithParent, - Gtk.MessageType.Error, Gtk.ButtonsType.Ok, + Gtk.MessageType.Error, Gtk.ButtonsType.Ok, "Pigment Lab dialog box NOT FOUND. Please ensure " + "that there is an unobstructed view of the dialog " + "and that your interface size is set to 'small' " + "when you press the Capture button."); - + md.Run(); - md.Destroy(); + md.Destroy(); } + + progressBar.Hide(); + recordButton.Show(); + + ingredient1ComboBox.Sensitive = true; + ingredient2ComboBox.Sensitive = true; + ingredient3ComboBox.Sensitive = false; + UpdateIngredients(); + } + + private void NotifyCaptureComplete() + { + OnCaptureComplete( + ReactionRecorder.Instance.IsCaptured, + ReactionRecorder.Instance.RecordedColor, + ReactionRecorder.Instance.SwatchX, + ReactionRecorder.Instance.SwatchY); + } + + unsafe void CaptureReactionColor() + { + // Take a screenshot. + int screenWidth, screenHeight; + Gdk.Window rootWindow = Gdk.Global.DefaultRootWindow; + DesertPaintLab.AppSettings.Get("ScreenWidth", out screenWidth); + DesertPaintLab.AppSettings.Get("ScreenHeight", out screenHeight); + Gdk.Image rootImage = rootWindow.GetImage(0, 0, screenWidth, screenHeight); + screenBuffer.GetFromImage(rootImage, rootImage.Colormap, 0, 0, 0, 0, screenWidth, screenHeight); + rootImage.Unref(); + System.GC.Collect(); // really, clean up now + + BeginCapture(); + } + + protected virtual void OnCapture(object sender, System.EventArgs e) + { + CaptureReactionColor(); } protected virtual void OnRecord(object sender, System.EventArgs e) @@ -394,7 +493,6 @@ namespace DesertPaintLab protected virtual void OnChangedIngredient3(object sender, System.EventArgs e) { UpdateIngredients(); - } protected void OnClearReaction(object sender, EventArgs e) diff --git a/gtk-gui/DesertPaintLab.CaptureView.cs b/gtk-gui/DesertPaintLab.CaptureView.cs --- a/gtk-gui/DesertPaintLab.CaptureView.cs +++ b/gtk-gui/DesertPaintLab.CaptureView.cs @@ -58,7 +58,9 @@ namespace DesertPaintLab private global::Gtk.Label reactionLabel; - protected virtual void Build () + private global::Gtk.ProgressBar progressBar; + + protected virtual void Build () { global::Stetic.Gui.Initialize (this); // Widget DesertPaintLab.CaptureView @@ -251,15 +253,25 @@ namespace DesertPaintLab this.vbox4.Add (this.reactionSwatch); global::Gtk.Box.BoxChild w19 = ((global::Gtk.Box.BoxChild)(this.vbox4 [this.reactionSwatch])); w19.Position = 0; - // Container child vbox4.Gtk.Box+BoxChild - this.recordButton = new global::Gtk.Button (); + + this.progressBar = new global::Gtk.ProgressBar(); + this.progressBar.Name = "progressBar"; + this.vbox4.Add(this.progressBar); + global::Gtk.Box.BoxChild wProgress = ((global::Gtk.Box.BoxChild)(this.vbox4[this.progressBar])); + wProgress.PackType = ((global::Gtk.PackType)(1)); + wProgress.Position = 1; + wProgress.Expand = false; + wProgress.Fill = false; + + // Container child vbox4.Gtk.Box+BoxChild + this.recordButton = new global::Gtk.Button (); this.recordButton.CanFocus = true; this.recordButton.Name = "recordButton"; this.recordButton.UseUnderline = true; this.recordButton.Label = "Record"; this.vbox4.Add (this.recordButton); global::Gtk.Box.BoxChild w20 = ((global::Gtk.Box.BoxChild)(this.vbox4 [this.recordButton])); - w20.Position = 1; + w20.Position = 2; w20.Expand = false; w20.Fill = false; this.GtkAlignment2.Add (this.vbox4); @@ -272,7 +284,7 @@ namespace DesertPaintLab this.reactedColorFrame.LabelWidget = this.reactionLabel; this.hbox1.Add (this.reactedColorFrame); global::Gtk.Box.BoxChild w23 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.reactedColorFrame])); - w23.Position = 2; + w23.Position = 3; w23.Expand = false; w23.Fill = false; this.Add (this.hbox1); @@ -280,7 +292,8 @@ namespace DesertPaintLab this.Child.ShowAll (); } this.clearReactionButton.Hide (); - this.Hide (); + this.progressBar.Hide(); + this.Hide (); 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); diff --git a/gtk-gui/DesertPaintLab.ReactionStatusWindow.cs b/gtk-gui/DesertPaintLab.ReactionStatusWindow.cs --- a/gtk-gui/DesertPaintLab.ReactionStatusWindow.cs +++ b/gtk-gui/DesertPaintLab.ReactionStatusWindow.cs @@ -4,7 +4,19 @@ namespace DesertPaintLab { public partial class ReactionStatusWindow { - private global::Gtk.ScrolledWindow scroller; + private global::Gtk.HBox hbox1; + + private global::Gtk.Frame ingredientFrame; + private global::Gtk.Alignment ingredientAlignment; + + private global::Gtk.ScrolledWindow scrolledwindow2; + + private global::Gtk.TreeView reagentListView; + + private global::Gtk.Label GtkLabel4; + + + private global::Gtk.ScrolledWindow scroller; private global::Gtk.VBox resultbox; @@ -15,8 +27,48 @@ namespace DesertPaintLab this.Name = "DesertPaintLab.ReactionStatusWindow"; this.Title = "Reaction Status"; this.WindowPosition = ((global::Gtk.WindowPosition)(4)); - // Container child DesertPaintLab.ReactionStatusWindow.Gtk.Container+ContainerChild - this.scroller = new global::Gtk.ScrolledWindow (); + + this.hbox1 = new global::Gtk.HBox(); + this.hbox1.Name = "hbox1"; + this.hbox1.Spacing = 6; + + // Reagent list + // Container child vbox8.Gtk.Box+BoxChild + this.ingredientFrame = new global::Gtk.Frame(); + this.ingredientFrame.Name = "frame3"; + this.ingredientFrame.ShadowType = ((global::Gtk.ShadowType)(0)); + // Container child ingredientFrame.Gtk.Container+ContainerChild + this.ingredientAlignment = new global::Gtk.Alignment(0F, 0F, 1F, 1F); + this.ingredientAlignment.Name = "GtkAlignment1"; + this.ingredientAlignment.LeftPadding = ((uint)(12)); + // Container child GtkAlignment1.Gtk.Container+ContainerChild + this.scrolledwindow2 = new global::Gtk.ScrolledWindow(); + this.scrolledwindow2.CanFocus = true; + this.scrolledwindow2.Name = "scrolledwindow2"; + this.scrolledwindow2.ShadowType = ((global::Gtk.ShadowType)(1)); + // Container child scrolledwindow2.Gtk.Container+ContainerChild + this.reagentListView = new global::Gtk.TreeView(); + this.reagentListView.WidthRequest = 240; + this.reagentListView.CanFocus = true; + this.reagentListView.Name = "reagentListView"; + this.scrolledwindow2.Add(this.reagentListView); + this.ingredientAlignment.Add(this.scrolledwindow2); + this.ingredientFrame.Add(this.ingredientAlignment); + this.GtkLabel4 = new global::Gtk.Label(); + this.GtkLabel4.Name = "GtkLabel4"; + this.GtkLabel4.LabelProp = "Ingredients"; + this.GtkLabel4.UseMarkup = true; + this.ingredientFrame.LabelWidget = this.GtkLabel4; + this.hbox1.Add(this.ingredientFrame); + global::Gtk.Box.BoxChild w0 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.ingredientFrame])); + w0.Expand = false; + w0.Fill = true; + w0.Position = 0; + + + // Container child DesertPaintLab.ReactionStatusWindow.Gtk.Container+ContainerChild + this.scroller = new global::Gtk.ScrolledWindow (); + this.scroller.WidthRequest = 300; this.scroller.CanFocus = true; this.scroller.Name = "scroller"; this.scroller.ShadowType = ((global::Gtk.ShadowType)(1)); @@ -29,8 +81,15 @@ namespace DesertPaintLab this.resultbox.Spacing = 6; w1.Add (this.resultbox); this.scroller.Add (w1); - this.Add (this.scroller); - if ((this.Child != null)) { + this.hbox1.Add(this.scroller); + global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.scroller])); + w2.Expand = true; + w2.Fill = true; + w2.Position = 1; + + this.Add(this.hbox1); + + if ((this.Child != null)) { this.Child.ShowAll (); } this.DefaultWidth = 400; diff --git a/gtk-gui/DesertPaintLab.RecipeGeneratorView.cs b/gtk-gui/DesertPaintLab.RecipeGeneratorView.cs --- a/gtk-gui/DesertPaintLab.RecipeGeneratorView.cs +++ b/gtk-gui/DesertPaintLab.RecipeGeneratorView.cs @@ -190,7 +190,7 @@ namespace DesertPaintLab this.checkButtonRibbon = new global::Gtk.CheckButton (); this.checkButtonRibbon.CanFocus = true; this.checkButtonRibbon.Name = "checkButtonRibbon"; - this.checkButtonRibbon.Label = "Ribbon Recipes"; + this.checkButtonRibbon.Label = "Silk Ribbon Recipes"; this.checkButtonRibbon.DrawIndicator = true; this.checkButtonRibbon.UseUnderline = true; this.vbox8.Add (this.checkButtonRibbon); diff --git a/gtk-gui/DesertPaintLab.ScreenCheckDialog.cs b/gtk-gui/DesertPaintLab.ScreenCheckDialog.cs --- a/gtk-gui/DesertPaintLab.ScreenCheckDialog.cs +++ b/gtk-gui/DesertPaintLab.ScreenCheckDialog.cs @@ -9,8 +9,10 @@ namespace DesertPaintLab private global::Gtk.HBox hbox1; private global::Gtk.Label label1; - - private global::Gtk.Entry screenWidthEntry; + + private global::Gtk.Label detectedResolutionLabel; + + private global::Gtk.Entry screenWidthEntry; private global::Gtk.Entry screenHeightEntry; @@ -19,8 +21,14 @@ namespace DesertPaintLab private global::Gtk.Label label2; private global::Gtk.Entry gamePixelWidthEntry; - - private global::Gtk.Button buttonOk; + + private global::Gtk.HBox hbox3; + + private global::Gtk.Label interfaceSizeLlabel; + + private global::Gtk.ComboBox interfaceSizeComboBox; + + private global::Gtk.Button buttonOk; protected virtual void Build () { @@ -39,8 +47,9 @@ namespace DesertPaintLab this.vbox2.Name = "vbox2"; this.vbox2.Spacing = 20; this.vbox2.BorderWidth = ((uint)(20)); - // Container child vbox2.Gtk.Box+BoxChild - this.hbox1 = new global::Gtk.HBox (); + + // Container child vbox2.Gtk.Box+BoxChild + this.hbox1 = new global::Gtk.HBox (); this.hbox1.Name = "hbox1"; this.hbox1.Spacing = 20; this.hbox1.BorderWidth = ((uint)(10)); @@ -49,10 +58,10 @@ namespace DesertPaintLab this.label1.Name = "label1"; this.label1.LabelProp = "Screen Resolution"; this.hbox1.Add (this.label1); - global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.label1])); - w2.Position = 0; - w2.Expand = false; - w2.Fill = false; + global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.label1])); + w2.Position = 0; + w2.Expand = false; + w2.Fill = false; // Container child hbox1.Gtk.Box+BoxChild this.screenWidthEntry = new global::Gtk.Entry (); this.screenWidthEntry.WidthRequest = 50; @@ -78,8 +87,19 @@ namespace DesertPaintLab w5.Position = 0; w5.Expand = false; w5.Fill = false; - // Container child vbox2.Gtk.Box+BoxChild - this.hbox2 = new global::Gtk.HBox (); + + // Container child vbox2.Gtk.Box+BoxChild + this.detectedResolutionLabel = new global::Gtk.Label(); + this.detectedResolutionLabel.Name = "detectedResolutionLabel"; + this.detectedResolutionLabel.LabelProp = "Detected Screen Resolution: ??"; + this.vbox2.Add(this.detectedResolutionLabel); + global::Gtk.Box.BoxChild wDR = ((global::Gtk.Box.BoxChild)(this.vbox2[this.detectedResolutionLabel])); + wDR.Position = 1; + wDR.Expand = false; + wDR.Fill = false; + + // Container child vbox2.Gtk.Box+BoxChild + this.hbox2 = new global::Gtk.HBox (); this.hbox2.Name = "hbox2"; this.hbox2.Spacing = 20; this.hbox2.BorderWidth = ((uint)(10)); @@ -106,12 +126,56 @@ namespace DesertPaintLab w7.Fill = false; this.vbox2.Add (this.hbox2); global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.hbox2])); - w8.Position = 1; + w8.Position = 2; w8.Expand = false; w8.Fill = false; - w1.Add (this.vbox2); + + // Container child vbox2.Gtk.Box+BoxChild + this.hbox3 = new global::Gtk.HBox(); + this.hbox3.Name = "hbox3"; + this.hbox3.Spacing = 20; + this.hbox3.BorderWidth = ((uint)(10)); + // Container child hbox3.Gtk.Box+BoxChild + this.interfaceSizeLlabel = new global::Gtk.Label(); + this.interfaceSizeLlabel.Name = "interfaceSizeLabel"; + this.interfaceSizeLlabel.LabelProp = "Interface Size"; + this.hbox3.Add(this.interfaceSizeLlabel); + global::Gtk.Box.BoxChild interfaceSizeContainer = ((global::Gtk.Box.BoxChild)(this.hbox3[this.interfaceSizeLlabel])); + interfaceSizeContainer.Position = 0; + interfaceSizeContainer.Expand = false; + interfaceSizeContainer.Fill = false; + // Container child hbox2.Gtk.Box+BoxChild + this.interfaceSizeComboBox = global::Gtk.ComboBox.NewText(); + this.interfaceSizeComboBox.Name = "interfaceSizeComboBox"; + this.hbox3.Add(this.interfaceSizeComboBox); + global::Gtk.Box.BoxChild wInterfaceSize = ((global::Gtk.Box.BoxChild)(this.hbox2[this.interfaceSizeComboBox])); + wInterfaceSize.Position = 1; + this.vbox2.Add(this.hbox3); + global::Gtk.Box.BoxChild wInterfaceSizeBox = ((global::Gtk.Box.BoxChild)(this.vbox2[this.hbox3])); + wInterfaceSizeBox.Position = 0; + wInterfaceSizeBox.Expand = false; + wInterfaceSizeBox.Fill = false; + + // Fill interface size box + interfaceSizeComboBox.Clear(); + + Gtk.CellRendererText cell = new Gtk.CellRendererText(); + interfaceSizeComboBox.PackStart(cell, false); + interfaceSizeComboBox.AddAttribute(cell, "text", 0); + Gtk.ListStore store = new Gtk.ListStore(typeof(string)); + interfaceSizeComboBox.Model = store; + store.AppendValues("Tiny"); + store.AppendValues("Small"); + store.AppendValues("Medium"); + store.AppendValues("Large"); + store.AppendValues("Huge"); + Gtk.TreeIter iter; + interfaceSizeComboBox.Model.IterNthChild(out iter, 1); + interfaceSizeComboBox.SetActiveIter(iter); + + w1.Add (this.vbox2); global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(w1 [this.vbox2])); - w9.Position = 0; + w9.Position = 3; // Internal child DesertPaintLab.ScreenCheckDialog.ActionArea global::Gtk.HButtonBox w10 = this.ActionArea; w10.Name = "dialog1_ActionArea"; @@ -130,7 +194,8 @@ namespace DesertPaintLab global::Gtk.ButtonBox.ButtonBoxChild w11 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w10 [this.buttonOk])); w11.Expand = false; w11.Fill = false; - if ((this.Child != null)) { + + if ((this.Child != null)) { this.Child.ShowAll (); } this.DefaultWidth = 378; diff --git a/gtk-gui/MainWindow.cs b/gtk-gui/MainWindow.cs --- a/gtk-gui/MainWindow.cs +++ b/gtk-gui/MainWindow.cs @@ -44,8 +44,10 @@ public partial class MainWindow private global::Gtk.Action ExportProfileAction; private global::Gtk.Action ExportForPracticalPaintAction; - - private global::Gtk.VBox vbox1; + + private global::Gtk.Action PreferencesAction; + + private global::Gtk.VBox vbox1; private global::Gtk.MenuBar menu; @@ -122,7 +124,10 @@ public partial class MainWindow this.ExportForPracticalPaintAction = new global::Gtk.Action ("ExportForPracticalPaintAction", "Export for PracticalPaint", null, null); this.ExportForPracticalPaintAction.ShortLabel = "Export for PracticalPaint"; w1.Add (this.ExportForPracticalPaintAction, null); - this.UIManager.InsertActionGroup (w1, 0); + this.PreferencesAction = new global::Gtk.Action("PreferencesAction", "Preferences", null, null); + this.PreferencesAction.ShortLabel = "Preferences"; + w1.Add(this.PreferencesAction, null); + this.UIManager.InsertActionGroup (w1, 0); this.AddAccelGroup (this.UIManager.AccelGroup); this.Name = "MainWindow"; this.Title = "Desert Paint Lab"; @@ -131,7 +136,7 @@ public partial class MainWindow this.vbox1 = new global::Gtk.VBox (); this.vbox1.Name = "vbox1"; // Container child vbox1.Gtk.Box+BoxChild - this.UIManager.AddUiFromString (""); + this.UIManager.AddUiFromString (""); this.menu = ((global::Gtk.MenuBar)(this.UIManager.GetWidget ("/menu"))); this.menu.Name = "menu"; this.vbox1.Add (this.menu); @@ -180,5 +185,6 @@ public partial class MainWindow this.ImportProfileAction.Activated += new global::System.EventHandler (this.OnImportProfile); this.ExportProfileAction.Activated += new global::System.EventHandler (this.OnExportProfile); this.ExportForPracticalPaintAction.Activated += new global::System.EventHandler (this.OnExportToPracticalPaint); + this.PreferencesAction.Activated += new global::System.EventHandler(this.OnPreferences); } } diff --git a/gtk-gui/gui.stetic b/gtk-gui/gui.stetic --- a/gtk-gui/gui.stetic +++ b/gtk-gui/gui.stetic @@ -638,6 +638,18 @@ You can either import an existing Practi + + + Detected Resolution + + + 0 + True + False + False + + + @@ -1258,7 +1270,7 @@ You can either import an existing Practi True - Ribbon Recipes + Silk Ribbon Recipes True True True