diff --git a/Programs/GridProxyGUI/GridProxyGUI.csproj b/Programs/GridProxyGUI/GridProxyGUI.csproj index 2436b8f4..b3b08437 100755 --- a/Programs/GridProxyGUI/GridProxyGUI.csproj +++ b/Programs/GridProxyGUI/GridProxyGUI.csproj @@ -94,6 +94,7 @@ + diff --git a/Programs/GridProxyGUI/MainWindow.cs b/Programs/GridProxyGUI/MainWindow.cs index 6dadc208..72030c7d 100755 --- a/Programs/GridProxyGUI/MainWindow.cs +++ b/Programs/GridProxyGUI/MainWindow.cs @@ -1,8 +1,8 @@ +using GridProxyGUI; using System; using System.Collections.Generic; using System.Collections.Concurrent; using Gtk; -using GridProxyGUI; using OpenMetaverse.Packets; using Logger = OpenMetaverse.Logger; using System.Timers; @@ -35,11 +35,12 @@ public partial class MainWindow : Gtk.Window : base(Gtk.WindowType.Toplevel) { Build(); + LoadSavedSettings(); + ProxyLogger.Init(); ProxyLogger.OnLogLine += new ProxyLogger.Log(Logger_OnLogLine); tabsMain.Page = 0; - mainSplit.Position = 600; string font; if (PlatformDetection.IsMac) @@ -322,17 +323,47 @@ public partial class MainWindow : Gtk.Window plugins.Store.Clear(); } - protected void OnDeleteEvent(object sender, DeleteEventArgs a) + void LoadSavedSettings() + { + if (Options.Instance.ContainsKey("main_split_pos")) + { + mainSplit.Position = Options.Instance["main_split_pos"]; + mainSplit.PositionSet = true; + } + if (Options.Instance.ContainsKey("main_width")) + { + Resize(Options.Instance["main_width"], Options.Instance["main_height"]); + Move(Options.Instance["main_x"], Options.Instance["main_y"]); + } + } + + void OnQuit() { StopProxy(); + Options.Instance["main_split_pos"] = mainSplit.Position; + int x, y; + + GetSize(out x, out y); ; + Options.Instance["main_width"] = x; + Options.Instance["main_height"] = y; + + GetPosition(out x, out y); + Options.Instance["main_x"] = x; + Options.Instance["main_y"] = y; + + Options.Instance.Save(); Application.Quit(); + } + + protected void OnDeleteEvent(object sender, DeleteEventArgs a) + { + OnQuit(); a.RetVal = true; } protected void OnExitActionActivated(object sender, EventArgs e) { - StopProxy(); - Application.Quit(); + OnQuit(); } protected void OnBtnStartClicked(object sender, EventArgs e) @@ -671,4 +702,5 @@ public partial class MainWindow : Gtk.Window plugins.LoadPlugin(proxy.Proxy); } -} \ No newline at end of file + +} diff --git a/Programs/GridProxyGUI/Options.cs b/Programs/GridProxyGUI/Options.cs new file mode 100755 index 00000000..ba3b4199 --- /dev/null +++ b/Programs/GridProxyGUI/Options.cs @@ -0,0 +1,256 @@ +// +// Radegast Metaverse Client +// Copyright (c) 2009-2013, Radegast Development Team +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the application "Radegast", nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// $Id$ +// +using System; +using System.Collections.Generic; +using System.Collections; +using System.IO; +using System.Xml; +using System.Threading; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace GridProxyGUI +{ + public class Options : IDictionary + { + string SettingsFile; + OSDMap SettingsData; + Timer SaveTimer; + int SaveDelay = 10000; + + public delegate void SettingChangedCallback(object sender, SettingsEventArgs e); + public event SettingChangedCallback OnSettingChanged; + + static Options instance; + public static Options Instance + { + get + { + if (instance == null) + { + throw new NullReferenceException("Using instance of setting without call to CreateInstance() first"); + } + return instance; + } + } + + public Options(string fileName) + { + Init(fileName); + } + + public static void CreateInstance(string fileName) + { + instance = new Options(fileName); + } + + public void Init(string fileName) + { + SettingsFile = fileName; + + try + { + string xml = File.ReadAllText(SettingsFile); + SettingsData = (OSDMap)OSDParser.DeserializeLLSDXml(xml); + } + catch + { + Logger.DebugLog("Failed openning setting file: " + fileName); + SettingsData = new OSDMap(); + Save(); + } + + SaveTimer = new Timer((state) => Save(), this, Timeout.Infinite, Timeout.Infinite); + } + + public void SaveDelayed() + { + SaveTimer.Change(SaveDelay, Timeout.Infinite); + } + + public void Save() + { + try + { + File.WriteAllText(SettingsFile, SerializeLLSDXmlStringFormated(SettingsData)); + } + catch (Exception ex) + { + Logger.Log("Failed saving settings", Helpers.LogLevel.Warning, ex); + } + } + + public static string SerializeLLSDXmlStringFormated(OSD data) + { + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter writer = new XmlTextWriter(sw)) + { + writer.Formatting = Formatting.Indented; + writer.Indentation = 4; + writer.IndentChar = ' '; + + writer.WriteStartElement(String.Empty, "llsd", String.Empty); + OSDParser.SerializeLLSDXmlElement(writer, data); + writer.WriteEndElement(); + + writer.Close(); + + return sw.ToString(); + } + } + } + + private void FireEvent(string key, OSD val) + { + if (OnSettingChanged != null) + { + try { OnSettingChanged(this, new SettingsEventArgs(key, val)); } + catch (Exception) { } + } + } + + #region IDictionary Implementation + + public int Count { get { return SettingsData.Count; } } + public bool IsReadOnly { get { return false; } } + public ICollection Keys { get { return SettingsData.Keys; } } + public ICollection Values { get { return SettingsData.Values; } } + public OSD this[string key] + { + get + { + return SettingsData[key]; + } + set + { + if (string.IsNullOrEmpty(key)) + { + Logger.DebugLog("Warning: trying to set an emprty setting: " + Environment.StackTrace.ToString()); + } + else + { + SettingsData[key] = value; + FireEvent(key, value); + SaveDelayed(); + } + } + } + + public bool ContainsKey(string key) + { + return SettingsData.ContainsKey(key); + } + + public void Add(string key, OSD llsd) + { + SettingsData.Add(key, llsd); + FireEvent(key, llsd); + SaveDelayed(); + } + + public void Add(KeyValuePair kvp) + { + SettingsData.Add(kvp.Key, kvp.Value); + FireEvent(kvp.Key, kvp.Value); + SaveDelayed(); + } + + public bool Remove(string key) + { + bool ret = SettingsData.Remove(key); + FireEvent(key, null); + SaveDelayed(); + return ret; + } + + public bool TryGetValue(string key, out OSD llsd) + { + return SettingsData.TryGetValue(key, out llsd); + } + + public void Clear() + { + SettingsData.Clear(); + SaveDelayed(); + } + + public bool Contains(KeyValuePair kvp) + { + // This is a bizarre function... we don't really implement it + // properly, hopefully no one wants to use it + return SettingsData.ContainsKey(kvp.Key); + } + + public void CopyTo(KeyValuePair[] array, int index) + { + throw new NotImplementedException(); + } + + public bool Remove(KeyValuePair kvp) + { + bool ret = SettingsData.Remove(kvp.Key); + FireEvent(kvp.Key, null); + SaveDelayed(); + return ret; + } + + public System.Collections.IDictionaryEnumerator GetEnumerator() + { + return SettingsData.GetEnumerator(); + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + return null; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return SettingsData.GetEnumerator(); + } + + #endregion IDictionary Implementation + + } + + public class SettingsEventArgs : EventArgs + { + public string Key = string.Empty; + public OSD Value = new OSD(); + + public SettingsEventArgs(string key, OSD val) + { + Key = key; + Value = val; + } + } +} diff --git a/Programs/GridProxyGUI/Program.cs b/Programs/GridProxyGUI/Program.cs index fa143bb7..ad00bf26 100644 --- a/Programs/GridProxyGUI/Program.cs +++ b/Programs/GridProxyGUI/Program.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Diagnostics; using Gtk; @@ -10,6 +11,7 @@ namespace GridProxyGUI { try { + InitLogging(); StartGtkApp(); } catch (Exception ex) @@ -29,6 +31,28 @@ namespace GridProxyGUI win.Show(); Application.Run(); } + + static bool InitLogging() + { + try + { + string userDir = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), "GridProxyGUI"); + + if (!Directory.Exists(userDir)) + { + Directory.CreateDirectory(userDir); + } + + string settingsFile = Path.Combine(userDir, "Settings.xml"); + Options.CreateInstance(settingsFile); + + return true; + } + catch + { + return false; + } + } } public static class NativeApi @@ -62,7 +86,7 @@ namespace GridProxyGUI } else { - LinuxMessageBox(title, msg + @" foo ""bar"" baz", "error"); + LinuxMessageBox(title, msg, "error"); } Environment.Exit(exitCode); diff --git a/Programs/GridProxyGUI/gtk-gui/MainWindow.cs b/Programs/GridProxyGUI/gtk-gui/MainWindow.cs index 7888798a..00ed789b 100755 --- a/Programs/GridProxyGUI/gtk-gui/MainWindow.cs +++ b/Programs/GridProxyGUI/gtk-gui/MainWindow.cs @@ -240,7 +240,7 @@ public partial class MainWindow this.mainSplit = new global::Gtk.HPaned (); this.mainSplit.CanFocus = true; this.mainSplit.Name = "mainSplit"; - this.mainSplit.Position = 500; + this.mainSplit.Position = 600; // Container child mainSplit.Gtk.Paned+PanedChild this.vboxSessions = new global::Gtk.VBox (); this.vboxSessions.Name = "vboxSessions"; diff --git a/Programs/GridProxyGUI/gtk-gui/gui.stetic b/Programs/GridProxyGUI/gtk-gui/gui.stetic index 3a09ab84..cb77c84e 100644 --- a/Programs/GridProxyGUI/gtk-gui/gui.stetic +++ b/Programs/GridProxyGUI/gtk-gui/gui.stetic @@ -222,7 +222,7 @@ http://login.orgrid.org/ True - 500 + 600