Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono-addins.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Nordan <rpvn@robpvn.net>2013-10-11 16:35:04 +0400
committerRobert Nordan <rpvn@robpvn.net>2013-10-11 16:35:04 +0400
commitf10aa40291c3daf2a32d614f0bdbba1b529b543a (patch)
tree7b3c19f630c72f8afe051966e1505d792470f92e /Mono.Addins.GuiGtk3/Mono.Addins.Gui
parent0aa5fb5f949dcb8c13a2c6c0fc58b5aa7e06a634 (diff)
Add new GTK UI project
Currently have stubs for all UI elements, but not connected up
Diffstat (limited to 'Mono.Addins.GuiGtk3/Mono.Addins.Gui')
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInfoView.cs471
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInstaller.cs25
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInstallerDialog.cs186
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinManagerDialog.cs573
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinManagerWindow.cs75
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinTreeWidget.cs572
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/ErrorDialog.cs104
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/HeaderBox.cs196
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/HoverImageButton.cs265
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/HslColor.cs164
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/InstallDialog.cs288
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/InstallMonitor.cs133
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/ManageSitesDialog.cs179
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/NewSiteDialog.cs124
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/ProgressDialog.cs120
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/SearchEntry.cs130
-rw-r--r--Mono.Addins.GuiGtk3/Mono.Addins.Gui/Services.cs152
17 files changed, 3757 insertions, 0 deletions
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInfoView.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInfoView.cs
new file mode 100644
index 0000000..f58f246
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInfoView.cs
@@ -0,0 +1,471 @@
+//
+// AddinInfoView.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+//
+// 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 Mono.Addins.Setup;
+using System.Text;
+using Mono.Unix;
+using System.Linq;
+using UI = Gtk.Builder.ObjectAttribute;
+using Gtk;
+
+namespace Mono.Addins.GuiGtk3
+{
+ [System.ComponentModel.ToolboxItem(true)]
+ class AddinInfoView : Gtk.Bin
+ {
+ //From UI files
+ [UI] EventBox eboxButs;
+ [UI] Label labelName;
+ [UI] Label labelDesc;
+ [UI] Button urlButton;
+ [UI] HBox boxTitle;
+ [UI] EventBox boxHeader;
+ [UI] HBox headerBox;
+ [UI] Button btnDisable;
+ [UI] Button btnInstall;
+ [UI] Button btnUninstall;
+ [UI] Button btnUpdate;
+ [UI] Label labelHeader;
+ [UI] Image imageHeader;
+ [UI] Label labelVersion;
+ [UI] EventBox ebox;
+ [UI] EventBox ebox2;
+ [UI] VBox vboxDesc;
+ [UI] ScrolledWindow scrolledwindow;
+
+ List<AddinRepositoryEntry> selectedEntry = new List<AddinRepositoryEntry> ();
+ List<Addin> selectedAddin = new List<Addin> ();
+ SetupService service;
+ HeaderBox topHeaderBox;
+ List<Gtk.Widget> previewImages = new List<Gtk.Widget> ();
+ ImageContainer titleIcon;
+ int titleWidth;
+ string infoUrl;
+
+ public event EventHandler InstallClicked;
+ public event EventHandler UninstallClicked;
+ public event EventHandler UpdateClicked;
+ public event EventHandler EnableDisableClicked;
+
+ public AddinInfoView ()
+ {
+ this.Build ();
+ AllowInstall = true;
+ titleWidth = labelName.SizeRequest ().Width;
+
+ HeaderBox hb = new HeaderBox (1,1,1,1);
+ hb.Show ();
+ hb.Replace (this);
+
+ hb = new HeaderBox (1,0,0,0);
+ hb.SetPadding (6,6,6,6);
+ hb.Show ();
+ hb.GradientBackround = true;
+ hb.Replace (eboxButs);
+
+ hb = new HeaderBox (0,1,0,0);
+ hb.SetPadding (6,6,6,6);
+ hb.Show ();
+ hb.GradientBackround = true;
+ hb.Replace (boxHeader);
+ topHeaderBox = hb;
+ }
+
+ public void Init (SetupService service)
+ {
+ this.service = service;
+ }
+
+ public bool AllowInstall { get; set; }
+
+ public List<AddinRepositoryEntry> SelectedEntries {
+ get {
+ return this.selectedEntry;
+ }
+ }
+
+ public List<Addin> SelectedAddins {
+ get {
+ return this.selectedAddin;
+ }
+ }
+
+ public void ShowAddins (object[] data)
+ {
+ selectedEntry.Clear ();
+ selectedAddin.Clear ();
+ eboxButs.Visible = true;
+ topHeaderBox.Hide ();
+ urlButton.Hide ();
+
+ if (titleIcon != null) {
+ boxTitle.Remove (titleIcon);
+ titleIcon.Destroy ();
+ titleIcon = null;
+ }
+
+ foreach (var img in previewImages) {
+ ((Gtk.Container)img.Parent).Remove (img);
+ img.Destroy ();
+ }
+ previewImages.Clear ();
+
+ if (data.Length == 1) {
+ headerBox.Show ();
+ ShowAddin (data[0]);
+ }
+ else if (data.Length > 1) {
+ headerBox.Hide ();
+ StringBuilder sb = new StringBuilder ();
+ sb.Append (Catalog.GetString ("Multiple selection:\n\n"));
+ bool allowUpdate = AllowInstall;
+ bool allowInstall = true;
+ bool allowUninstall = AllowInstall;
+ bool allowEnable = true;
+ bool allowDisable = true;
+
+ foreach (object o in data) {
+ Addin installed;
+ if (o is Addin) {
+ Addin a = (Addin)o;
+ installed = a;
+ selectedAddin.Add (a);
+ sb.Append (a.Name);
+ }
+ else {
+ AddinRepositoryEntry entry = (AddinRepositoryEntry) o;
+ selectedEntry.Add (entry);
+ sb.Append (entry.Addin.Name);
+ installed = AddinManager.Registry.GetAddin (Addin.GetIdName (entry.Addin.Id));
+ }
+ if (installed != null) {
+ if (GetUpdate (installed) == null)
+ allowUpdate = false;
+ allowInstall = false;
+ if (installed.Enabled)
+ allowEnable = false;
+ else
+ allowDisable = false;
+ } else
+ allowEnable = allowDisable = allowUninstall = allowUpdate = false;
+
+ sb.Append ('\n');
+ labelDesc.Text = sb.ToString ();
+
+ if (allowEnable) {
+ btnDisable.Visible = true;
+ btnDisable.Label = Catalog.GetString ("Enable");
+ } else if (allowDisable) {
+ btnDisable.Visible = true;
+ btnDisable.Label = Catalog.GetString ("Disable");
+ } else
+ btnDisable.Visible = false;
+ btnInstall.Visible = allowInstall;
+ btnUninstall.Visible = allowUninstall;
+ btnUpdate.Visible = allowUpdate;
+ }
+ }
+ else {
+ headerBox.Hide ();
+ btnDisable.Visible = false;
+ btnInstall.Visible = false;
+ btnUninstall.Visible = false;
+ btnUpdate.Visible = false;
+ eboxButs.Visible = false;
+ labelDesc.Text = Catalog.GetString ("No selection");
+ }
+ }
+
+
+ void ShowAddin (object data)
+ {
+ AddinHeader sinfo = null;
+ Addin installed = null;
+ AddinHeader updateInfo = null;
+ string repo = "";
+ string downloadSize = null;
+
+ topHeaderBox.Hide ();
+
+ if (data is Addin) {
+ installed = (Addin) data;
+ sinfo = SetupService.GetAddinHeader (installed);
+ var entry = GetUpdate (installed);
+ if (entry != null) {
+ updateInfo = entry.Addin;
+ selectedEntry.Add (entry);
+ }
+ foreach (var prop in sinfo.Properties) {
+ if (prop.Name.StartsWith ("PreviewImage"))
+ previewImages.Add (new ImageContainer (installed, prop.Value));
+ }
+ string icon32 = sinfo.Properties.GetPropertyValue ("Icon32");
+ if (icon32.Length > 0)
+ titleIcon = new ImageContainer (installed, icon32);
+ }
+ else if (data is AddinRepositoryEntry) {
+ AddinRepositoryEntry entry = (AddinRepositoryEntry) data;
+ sinfo = entry.Addin;
+ installed = AddinManager.Registry.GetAddin (Addin.GetIdName (sinfo.Id));
+ if (installed != null && Addin.CompareVersions (installed.Version, sinfo.Version) > 0)
+ updateInfo = sinfo;
+ selectedEntry.Add (entry);
+ string rname = !string.IsNullOrEmpty (entry.RepositoryName) ? entry.RepositoryName : entry.RepositoryUrl;
+ repo = "<small><b>" + Catalog.GetString ("Available in repository:") + "</b>\n" + GLib.Markup.EscapeText (rname) + "\n\n</small>";
+ foreach (var prop in sinfo.Properties) {
+ if (prop.Name.StartsWith ("PreviewImage"))
+ previewImages.Add (new ImageContainer (entry, prop.Value));
+ }
+ string icon32 = sinfo.Properties.GetPropertyValue ("Icon32");
+ if (icon32.Length > 0)
+ titleIcon = new ImageContainer (entry, icon32);
+ int size;
+ if (int.TryParse (sinfo.Properties.GetPropertyValue ("DownloadSize"), out size)) {
+ float fs = ((float)size) / 1048576f;
+ downloadSize = fs.ToString ("0.00 MB");
+ }
+ } else
+ selectedEntry.Clear ();
+
+ if (installed != null)
+ selectedAddin.Add (installed);
+
+ string missingDepsTxt = null;
+
+ if (sinfo == null) {
+ btnDisable.Visible = false;
+ btnUninstall.Visible = false;
+ btnUpdate.Visible = false;
+ } else {
+ string version;
+ string newVersion = null;
+ if (installed != null) {
+ btnInstall.Visible = false;
+ btnUpdate.Visible = updateInfo != null && AllowInstall;
+ btnDisable.Visible = true;
+ btnDisable.Label = installed.Enabled ? Catalog.GetString ("Disable") : Catalog.GetString ("Enable");
+ btnDisable.Visible = installed.Description.CanDisable;
+ btnUninstall.Visible = installed.Description.CanUninstall;
+ version = installed.Version;
+ var missingDeps = Services.GetMissingDependencies (installed);
+ if (updateInfo != null) {
+ newVersion = updateInfo.Version;
+ labelHeader.Markup = "<b><span color='black'>" + Catalog.GetString ("Update available") + "</span></b>";
+// topHeaderBox.BackgroundColor = new Gdk.Color (0, 132, 208);
+ imageHeader.Pixbuf = Gdk.Pixbuf.LoadFromResource ("software-update-available.png");
+ topHeaderBox.BackgroundColor = new Gdk.Color (255, 176, 0);
+ topHeaderBox.Show ();
+ }
+ else if (missingDeps.Any ()) {
+ labelHeader.Markup = "<b><span color='black'>" + Catalog.GetString ("This add-in can't be loaded due to missing dependencies") + "</span></b>";
+ topHeaderBox.BackgroundColor = new Gdk.Color (255, 176, 0);
+ imageHeader.SetFromStock (Gtk.Stock.DialogWarning, Gtk.IconSize.Menu);
+ topHeaderBox.Show ();
+ missingDepsTxt = "";
+ foreach (var mdep in missingDeps) {
+ if (mdep.Found != null)
+ missingDepsTxt += "\n" + string.Format (Catalog.GetString ("Required: {0} v{1}, found v{2}"), mdep.Addin, mdep.Required, mdep.Found);
+ else
+ missingDepsTxt += "\n" + string.Format (Catalog.GetString ("Missing: {0} v{1}"), mdep.Addin, mdep.Required);
+ }
+ }
+ } else {
+ btnInstall.Visible = AllowInstall;
+ btnUpdate.Visible = false;
+ btnDisable.Visible = false;
+ btnUninstall.Visible = false;
+ version = sinfo.Version;
+ }
+ labelName.Markup = "<b><big>" + GLib.Markup.EscapeText(sinfo.Name) + "</big></b>";
+
+ string ver;
+ if (newVersion != null) {
+ ver = "<small><b>" + Catalog.GetString ("Installed version") + ":</b> " + version + "</small>\n";
+ ver += "<small><b>" + Catalog.GetString ("Repository version") + ":</b> " + newVersion + "</small>";
+ }
+ else
+ ver = "<small><b>" + Catalog.GetString ("Version") + " " + version + "</b></small>";
+
+ if (downloadSize != null)
+ ver += "\n<small><b>" + Catalog.GetString ("Download size") + ":</b> " + downloadSize + "</small>";
+ if (missingDepsTxt != null)
+ ver += "\n\n" + GLib.Markup.EscapeText (Catalog.GetString ("The following depedencies required by this add-in are not available:")) + missingDepsTxt;
+ labelVersion.Markup = ver;
+
+ string desc = GLib.Markup.EscapeText (sinfo.Description);
+ labelDesc.Markup = repo + GLib.Markup.EscapeText (desc);
+
+ foreach (var img in previewImages)
+ vboxDesc.PackStart (img, false, false, 0);
+
+ urlButton.Visible = !string.IsNullOrEmpty (sinfo.Url);
+ infoUrl = sinfo.Url;
+
+ if (titleIcon != null) {
+ boxTitle.PackEnd (titleIcon, false, false, 0);
+ labelName.WidthRequest = titleWidth - 32;
+ labelVersion.WidthRequest = titleWidth - 32;
+ } else {
+ labelName.WidthRequest = titleWidth;
+ labelVersion.WidthRequest = titleWidth;
+ }
+
+ if (IsRealized)
+ SetComponentsBg ();
+ }
+ }
+
+ public AddinRepositoryEntry GetUpdate (Addin a)
+ {
+ AddinRepositoryEntry[] updates = service.Repositories.GetAvailableAddinUpdates (Addin.GetIdName (a.Id));
+ AddinRepositoryEntry best = null;
+ string bestVersion = a.Version;
+ foreach (AddinRepositoryEntry e in updates) {
+ if (Addin.CompareVersions (bestVersion, e.Addin.Version) > 0) {
+ best = e;
+ bestVersion = e.Addin.Version;
+ }
+ }
+ return best;
+ }
+
+ protected virtual void OnBtnInstallClicked (object sender, System.EventArgs e)
+ {
+ if (InstallClicked != null)
+ InstallClicked (this, e);
+ }
+
+ protected virtual void OnBtnDisableClicked (object sender, System.EventArgs e)
+ {
+ if (EnableDisableClicked != null)
+ EnableDisableClicked (this, e);
+ }
+
+ protected virtual void OnBtnUpdateClicked (object sender, System.EventArgs e)
+ {
+ if (UpdateClicked != null)
+ UpdateClicked (this, e);
+ }
+
+ protected virtual void OnBtnUninstallClicked (object sender, System.EventArgs e)
+ {
+ if (UninstallClicked != null)
+ UninstallClicked (this, e);
+ }
+
+ protected override void OnRealized ()
+ {
+ base.OnRealized ();
+ HslColor gcol = ebox.Style.Background (Gtk.StateType.Normal);
+ gcol.L -= 0.03;
+ ebox.ModifyBg (Gtk.StateType.Normal, gcol);
+ ebox2.ModifyBg (Gtk.StateType.Normal, gcol);
+ scrolledwindow.ModifyBg (Gtk.StateType.Normal, gcol);
+ SetComponentsBg ();
+ }
+
+ void SetComponentsBg ()
+ {
+ HslColor gcol = ebox.Style.Background (Gtk.StateType.Normal);
+ //gcol.L -= 0.03;
+ if (titleIcon != null)
+ titleIcon.ModifyBg (Gtk.StateType.Normal, gcol);
+ foreach (var i in previewImages)
+ i.ModifyBg (Gtk.StateType.Normal, gcol);
+ }
+
+ protected virtual void OnUrlButtonClicked (object sender, System.EventArgs e)
+ {
+ System.Diagnostics.Process.Start (infoUrl);
+ }
+ }
+
+ class ImageContainer: Gtk.EventBox
+ {
+ AddinRepositoryEntry aentry;
+ IAsyncResult aresult;
+ Gtk.Image image;
+ bool destroyed;
+
+ ImageContainer ()
+ {
+ image = new Gtk.Image ();
+ Add (image);
+ image.SetAlignment (0.5f, 0f);
+ Show ();
+ }
+
+ public ImageContainer (AddinRepositoryEntry aentry, string fileName): this ()
+ {
+ this.aentry = aentry;
+ aresult = aentry.BeginDownloadSupportFile (fileName, ImageDownloaded, null);
+ }
+
+ public ImageContainer (Addin addin, string fileName): this ()
+ {
+ string path = System.IO.Path.Combine (addin.Description.BasePath, fileName);
+ LoadImage (File.OpenRead (path));
+ }
+
+ void ImageDownloaded (object state)
+ {
+ Gtk.Application.Invoke (delegate {
+ if (destroyed)
+ return;
+ try {
+ LoadImage (aentry.EndDownloadSupportFile (aresult));
+ } catch {
+ // ignore
+ }
+ });
+ }
+
+ void LoadImage (Stream s)
+ {
+ using (s) {
+ Gdk.PixbufLoader loader = new Gdk.PixbufLoader (s);
+ Gdk.Pixbuf pix = image.Pixbuf = loader.Pixbuf;
+ loader.Dispose ();
+ if (pix.Width > 250) {
+ Gdk.Pixbuf spix = pix.ScaleSimple (250, (250 * pix.Height) / pix.Width, Gdk.InterpType.Hyper);
+ pix.Dispose ();
+ pix = spix;
+ }
+ image.Pixbuf = pix;
+ image.Show ();
+ }
+ }
+
+ protected override void OnDestroyed ()
+ {
+ destroyed = true;
+ base.OnDestroyed ();
+ }
+ }
+}
+
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInstaller.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInstaller.cs
new file mode 100644
index 0000000..b2f2f85
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInstaller.cs
@@ -0,0 +1,25 @@
+
+
+using System;
+using Mono.Addins.Setup;
+using Mono.Unix;
+
+namespace Mono.Addins.GuiGtk3
+{
+ public class AddinInstaller: IAddinInstaller
+ {
+ public void InstallAddins (AddinRegistry reg, string message, string[] addinIds)
+ {
+ AddinInstallerDialog dlg = new AddinInstallerDialog (reg, message, addinIds);
+ try {
+ if (dlg.Run () == (int) Gtk.ResponseType.Cancel)
+ throw new InstallException (Catalog.GetString ("Installation cancelled"));
+ else if (dlg.ErrMessage != null)
+ throw new InstallException (dlg.ErrMessage);
+ }
+ finally {
+ dlg.Destroy ();
+ }
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInstallerDialog.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInstallerDialog.cs
new file mode 100644
index 0000000..7bdfc4b
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinInstallerDialog.cs
@@ -0,0 +1,186 @@
+//
+// AddinInstallerDialog.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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.Threading;
+using System.Collections;
+using Mono.Addins.Setup;
+using Mono.Addins.Description;
+using Mono.Unix;
+using Gtk;
+using UI = Gtk.Builder.ObjectAttribute;
+
+namespace Mono.Addins.GuiGtk3
+{
+ internal class AddinInstallerDialog : Gtk.Dialog, IProgressStatus
+ {
+ //From UI File
+ [UI] Label addinList;
+ [UI] ProgressBar progressBar;
+ [UI] Button buttonCancel;
+ [UI] Button buttonOk;
+
+ PackageCollection entries = new PackageCollection ();
+ string[] addinIds;
+ bool addinsNotFound;
+ string errMessage;
+ SetupService setup;
+
+ public AddinInstallerDialog (AddinRegistry reg, string message, string[] addinIds)
+ {
+ this.Build();
+
+ this.addinIds = addinIds;
+ setup = new SetupService (reg);
+
+ if (!CheckAddins (true))
+ UpdateRepos ();
+ }
+
+ bool CheckAddins (bool updating)
+ {
+ string txt = "";
+ entries.Clear ();
+ bool addinsNotFound = false;
+ foreach (string id in addinIds) {
+ string name = Addin.GetIdName (id);
+ string version = Addin.GetIdVersion (id);
+ AddinRepositoryEntry[] ares = setup.Repositories.GetAvailableAddin (name, version);
+ if (ares.Length == 0) {
+ addinsNotFound = true;
+ if (updating)
+ txt += "<span foreground='grey'><b>" + name + " " + version + "</b> (searching add-in)</span>\n";
+ else
+ txt += "<span foreground='red'><b>" + name + " " + version + "</b> (not found)</span>\n";
+ } else {
+ entries.Add (Package.FromRepository (ares[0]));
+ txt += "<b>" + ares[0].Addin.Name + " " + ares[0].Addin.Version + "</b>\n";
+ }
+ }
+ PackageCollection toUninstall;
+ DependencyCollection unresolved;
+ if (!setup.ResolveDependencies (this, entries, out toUninstall, out unresolved)) {
+ foreach (Dependency dep in unresolved) {
+ txt += "<span foreground='red'><b>" + dep.Name + "</b> (not found)</span>\n";
+ }
+ addinsNotFound = true;
+ }
+ addinList.Markup = txt;
+ return !addinsNotFound;
+ }
+
+ void UpdateRepos ()
+ {
+ progressBar.Show ();
+ setup.Repositories.UpdateAllRepositories (this);
+ progressBar.Hide ();
+ addinsNotFound = CheckAddins (false);
+ if (errMessage != null) {
+ Services.ShowError (null, errMessage, this, true);
+ errMessage = null;
+ }
+ }
+
+ public int LogLevel {
+ get {
+ return 1;
+ }
+ }
+
+ public bool IsCanceled {
+ get {
+ return false;
+ }
+ }
+
+ public bool AddinsNotFound {
+ get {
+ return addinsNotFound;
+ }
+ }
+
+ public string ErrMessage {
+ get {
+ return errMessage;
+ }
+ }
+
+ public void SetMessage (string msg)
+ {
+ progressBar.Text = msg;
+ while (Gtk.Application.EventsPending ())
+ Gtk.Application.RunIteration ();
+ }
+
+ public void SetProgress (double progress)
+ {
+ progressBar.Fraction = progress;
+ while (Gtk.Application.EventsPending ())
+ Gtk.Application.RunIteration ();
+ }
+
+ public void Log (string msg)
+ {
+ }
+
+ public void ReportWarning (string message)
+ {
+ }
+
+ public void ReportError (string message, System.Exception exception)
+ {
+ errMessage = message;
+ }
+
+ public void Cancel ()
+ {
+ }
+
+ protected virtual void OnButtonOkClicked (object sender, System.EventArgs e)
+ {
+ if (addinsNotFound) {
+ errMessage = Catalog.GetString ("Some of the required add-ins were not found");
+ Respond (Gtk.ResponseType.Ok);
+ }
+ else {
+ errMessage = null;
+ progressBar.Show ();
+ progressBar.Fraction = 0;
+ progressBar.Text = "";
+ bool res = setup.Install (this, entries);
+ if (!res) {
+ buttonCancel.Sensitive = buttonOk.Sensitive = false;
+ if (errMessage == null)
+ errMessage = Catalog.GetString ("Installation failed");
+ Services.ShowError (null, errMessage, this, true);
+ }
+ }
+ Respond (Gtk.ResponseType.Ok);
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinManagerDialog.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinManagerDialog.cs
new file mode 100644
index 0000000..8cf5c52
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinManagerDialog.cs
@@ -0,0 +1,573 @@
+//
+// AddinManagerDialog.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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;
+using Mono.Addins.Setup;
+using Mono.Addins;
+using Mono.Unix;
+using System.Threading;
+using System.Text;
+using System.Collections.Generic;
+using System.Linq;
+using UI = Gtk.Builder.ObjectAttribute;
+
+namespace Mono.Addins.GuiGtk3
+{
+ class AddinManagerDialog : Dialog, IDisposable
+ {
+ //Connected from the UI file
+ [UI] TreeView addinTree;
+ [UI] TreeView galleryTreeView;
+ [UI] TreeView updatesTreeView;
+ [UI] ComboBox repoCombo;
+ [UI] VBox vboxUpdates;
+ [UI] VBox vboxGallery;
+ [UI] ScrolledWindow scrolledUpdates;
+ [UI] ScrolledWindow scrolledGallery;
+ [UI] EventBox eboxRepoUpdates;
+ [UI] EventBox eboxRepo;
+ [UI] Label labelUpdates;
+ [UI] Button buttonUpdateAll;
+ //Manually fill in from the UI File
+ [UI] AddinInfoView addininfoInstalled; //TODO: Might need to init manually
+ [UI] AddinInfoView addininfoGallery;
+ [UI] AddinInfoView addininfoUpdates;
+ [UI] Notebook notebook;
+
+ AddinTreeWidget tree;
+ AddinTreeWidget galleryTree;
+ AddinTreeWidget updatesTree;
+
+ SetupService service = new SetupService ();
+ ListStore repoStore;
+ int lastRepoActive;
+ SearchEntry filterEntry;
+ Label installedTabLabel;
+ Label updatesTabLabel;
+ Label galleryTabLabel;
+
+ const string AllRepoMarker = "__ALL";
+ const string ManageRepoMarker = "__MANAGE";
+
+ internal bool AllowInstall
+ {
+ set {
+ addininfoInstalled.AllowInstall = value;
+ addininfoGallery.AllowInstall = value;
+ addininfoUpdates.AllowInstall = value;
+ }
+ }
+
+ public AddinManagerDialog (Builder builder, IntPtr handle): base (handle)
+ {
+ builder.Autoconnect (this);
+// TransientFor = parent;
+// HasSeparator = false;
+
+// Services.PlaceDialog (this, parent);
+ Show ();
+
+ addininfoInstalled.Init (service);
+ addininfoGallery.Init (service);
+
+ addinTree.Selection.Mode = SelectionMode.Multiple;
+ tree = new AddinTreeWidget (addinTree);
+ addinTree.Selection.Changed += OnSelectionChanged;
+ tree.VersionVisible = false;
+
+ galleryTreeView.Selection.Mode = SelectionMode.Multiple;
+ galleryTree = new AddinTreeWidget (galleryTreeView);
+ galleryTree.VersionVisible = false;
+ galleryTree.ShowInstalledMarkers = true;
+ galleryTreeView.Selection.Changed += OnGallerySelectionChanged;
+
+ updatesTreeView.Selection.Mode = SelectionMode.Multiple;
+ updatesTree = new AddinTreeWidget (updatesTreeView);
+ updatesTree.VersionVisible = false;
+ updatesTree.ShowCategories = false;
+ updatesTree.ShowInstalledMarkers = true;
+ updatesTreeView.Selection.Changed += OnGallerySelectionChanged;
+
+ repoStore = new ListStore (typeof(string), typeof(string));
+ repoCombo.Model = repoStore;
+ CellRendererText crt = new CellRendererText ();
+ repoCombo.PackStart (crt, true);
+ repoCombo.AddAttribute (crt, "text", 0);
+ repoCombo.RowSeparatorFunc = delegate(ITreeModel model, TreeIter iter) {
+ string val = (string) model.GetValue (iter, 0);
+ return val == "---";
+ };
+
+ // Make sure the tree has the focus when switching tabs
+
+ vboxUpdates.FocusChain = new Widget [] { scrolledUpdates, eboxRepoUpdates };
+ vboxGallery.FocusChain = new Widget [] { scrolledGallery, eboxRepo };
+
+ // Improve the look of the headers
+
+ HBox tab = new HBox (false, 3);
+ tab.PackStart (new Image (Gdk.Pixbuf.LoadFromResource ("plugin-22.png")), false, false, 0);
+ installedTabLabel = new Label (Catalog.GetString ("Installed"));
+ tab.PackStart (installedTabLabel, true, true, 0);
+ tab.BorderWidth = 3;
+ tab.ShowAll ();
+ notebook.SetTabLabel (notebook.GetNthPage (0), tab);
+
+ tab = new HBox (false, 3);
+ tab.PackStart (new Image (Gdk.Pixbuf.LoadFromResource ("plugin-update-22.png")), false, false, 0);
+ updatesTabLabel = new Label (Catalog.GetString ("Updates"));
+ tab.PackStart (updatesTabLabel, true, true, 0);
+ tab.BorderWidth = 3;
+ tab.ShowAll ();
+ notebook.SetTabLabel (notebook.GetNthPage (1), tab);
+
+ tab = new HBox (false, 3);
+ tab.PackStart (new Image (Gdk.Pixbuf.LoadFromResource ("system-software-update_22.png")), false, false, 0);
+ galleryTabLabel = new Label (Catalog.GetString ("Gallery"));
+ tab.PackStart (galleryTabLabel, true, true, 0);
+ tab.BorderWidth = 3;
+ tab.ShowAll ();
+ notebook.SetTabLabel (notebook.GetNthPage (2), tab);
+
+ // Gradient header for the updates and gallery tabs
+
+ HeaderBox hb = new HeaderBox (1, 0, 1, 1);
+ hb.SetPadding (6,6,6,6);
+ hb.GradientBackround = true;
+ hb.Show ();
+ hb.Replace (eboxRepo);
+
+ hb = new HeaderBox (1, 0, 1, 1);
+ hb.SetPadding (6,6,6,6);
+ hb.GradientBackround = true;
+ hb.Show ();
+ hb.Replace (eboxRepoUpdates);
+
+ InsertFilterEntry ();
+
+ FillRepos ();
+ repoCombo.Active = 0;
+
+ LoadAll ();
+ }
+
+ void InsertFilterEntry ()
+ {
+ filterEntry = new SearchEntry ();
+ filterEntry.Entry.SetSizeRequest (200, filterEntry.Entry.SizeRequest ().Height);
+ filterEntry.Parent = notebook;
+ filterEntry.Show ();
+ notebook.SizeAllocated += delegate {
+ RepositionFilter ();
+ };
+ filterEntry.TextChanged += delegate {
+ tree.SetFilter (filterEntry.Text);
+ galleryTree.SetFilter (filterEntry.Text);
+ updatesTree.SetFilter (filterEntry.Text);
+ LoadAll ();
+ addinTree.ExpandAll ();
+ galleryTreeView.ExpandAll ();
+ };
+ RepositionFilter ();
+ }
+
+ void RepositionFilter ()
+ {
+ int w = filterEntry.SizeRequest ().Width;
+ int h = filterEntry.SizeRequest ().Height;
+ var alloc = notebook.Allocation;
+ filterEntry.SetAllocation (new Gdk.Rectangle (alloc.Left + alloc.Width - 1 - w, alloc.Y, w, h));
+ }
+
+// public override void Dispose ()
+// {
+// base.Dispose ();
+// Destroy ();
+// }
+
+ internal void OnSelectionChanged (object sender, EventArgs args)
+ {
+ UpdateAddinInfo ();
+ }
+
+ internal void OnManageRepos (object sender, EventArgs e)
+ {
+ ManageSitesDialog dlg = new ManageSitesDialog (this, service);
+ try {
+ dlg.Run ();
+ } finally {
+ dlg.Destroy ();
+ }
+ }
+
+ void LoadAll ()
+ {
+ LoadInstalled ();
+ LoadGallery ();
+ LoadUpdates ();
+ UpdateAddinInfo ();
+ }
+
+ void UpdateAddinInfo ()
+ {
+ addininfoInstalled.ShowAddins (tree.ActiveAddinsData);
+ addininfoGallery.ShowAddins (galleryTree.ActiveAddinsData);
+ addininfoUpdates.ShowAddins (updatesTree.ActiveAddinsData);
+ }
+
+ void LoadInstalled ()
+ {
+ object s = tree.SaveStatus ();
+
+ int count = 0;
+ tree.Clear ();
+ foreach (Addin ainfo in AddinManager.Registry.GetModules (AddinSearchFlags.IncludeAddins | AddinSearchFlags.LatestVersionsOnly)) {
+ if (Services.InApplicationNamespace (service, ainfo.Id) && !ainfo.Description.IsHidden) {
+ AddinHeader ah = SetupService.GetAddinHeader (ainfo);
+ if (IsFiltered (ah))
+ continue;
+ AddinStatus st = AddinStatus.Installed;
+ if (!ainfo.Enabled || Services.GetMissingDependencies (ainfo).Any())
+ st |= AddinStatus.Disabled;
+ if (addininfoInstalled.GetUpdate (ainfo) != null)
+ st |= AddinStatus.HasUpdate;
+ tree.AddAddin (ah, ainfo, st);
+ count++;
+ }
+ }
+
+ if (count > 0)
+ tree.RestoreStatus (s);
+ else
+ tree.ShowEmptyMessage ();
+
+ UpdateAddinInfo ();
+
+ installedTabLabel.Text = Catalog.GetString ("Installed");
+
+ if (filterEntry.Text.Length != 0 && count > 0)
+ installedTabLabel.Text += " (" + count + ")";
+ }
+
+ void FillRepos ()
+ {
+ int i = repoCombo.Active;
+ repoStore.Clear ();
+
+ repoStore.AppendValues (Catalog.GetString ("All repositories"), AllRepoMarker);
+
+ foreach (AddinRepository rep in service.Repositories.GetRepositories ()) {
+ if (rep.Enabled)
+ repoStore.AppendValues (rep.Title, rep.Url);
+ }
+ repoStore.AppendValues ("---", "");
+ repoStore.AppendValues (Catalog.GetString ("Manage Repositories..."), ManageRepoMarker);
+ repoCombo.Active = i;
+ }
+
+ string GetRepoSelection ()
+ {
+ Gtk.TreeIter iter;
+ if (!repoCombo.GetActiveIter (out iter))
+ return null;
+ return (string) repoStore.GetValue (iter, 1);
+ }
+
+ void LoadGallery ()
+ {
+ object s = galleryTree.SaveStatus ();
+
+ galleryTree.Clear ();
+
+ string rep = GetRepoSelection ();
+
+ AddinRepositoryEntry[] reps;
+ if (rep == AllRepoMarker)
+ reps = service.Repositories.GetAvailableAddins (RepositorySearchFlags.LatestVersionsOnly);
+ else
+ reps = service.Repositories.GetAvailableAddins (rep, RepositorySearchFlags.LatestVersionsOnly);
+
+ int count = 0;
+
+ foreach (AddinRepositoryEntry arep in reps)
+ {
+ if (!Services.InApplicationNamespace (service, arep.Addin.Id))
+ continue;
+
+ if (IsFiltered (arep.Addin))
+ continue;
+
+ AddinStatus status = AddinStatus.NotInstalled;
+
+ // Find whatever version is installed
+ Addin sinfo = AddinManager.Registry.GetAddin (Addin.GetIdName (arep.Addin.Id));
+
+ if (sinfo != null) {
+ status |= AddinStatus.Installed;
+ if (!sinfo.Enabled || Services.GetMissingDependencies (sinfo).Any())
+ status |= AddinStatus.Disabled;
+ if (Addin.CompareVersions (sinfo.Version, arep.Addin.Version) > 0)
+ status |= AddinStatus.HasUpdate;
+ }
+ galleryTree.AddAddin (arep.Addin, arep, status);
+ count++;
+ }
+
+ if (count > 0)
+ galleryTree.RestoreStatus (s);
+ else
+ galleryTree.ShowEmptyMessage ();
+
+ galleryTabLabel.Text = Catalog.GetString ("Gallery");
+
+ if (filterEntry.Text.Length != 0 && count > 0)
+ galleryTabLabel.Text += " (" + count + ")";
+ }
+
+ void LoadUpdates ()
+ {
+ object s = updatesTree.SaveStatus ();
+
+ updatesTree.Clear ();
+
+ AddinRepositoryEntry[] reps;
+ reps = service.Repositories.GetAvailableAddins (RepositorySearchFlags.LatestVersionsOnly);
+
+ int count = 0;
+
+ foreach (AddinRepositoryEntry arep in reps)
+ {
+ if (!Services.InApplicationNamespace (service, arep.Addin.Id))
+ continue;
+
+ // Find whatever version is installed
+ Addin sinfo = AddinManager.Registry.GetAddin (Addin.GetIdName (arep.Addin.Id));
+ if (sinfo == null || !sinfo.Enabled || Addin.CompareVersions (sinfo.Version, arep.Addin.Version) <= 0)
+ continue;
+
+ if (IsFiltered (arep.Addin))
+ continue;
+
+ AddinStatus status = AddinStatus.Installed;
+ if (!sinfo.Enabled || Services.GetMissingDependencies (sinfo).Any())
+ status |= AddinStatus.Disabled;
+
+ updatesTree.AddAddin (arep.Addin, arep, status | AddinStatus.HasUpdate);
+ count++;
+ }
+
+ labelUpdates.Text = string.Format (Catalog.GetPluralString ("{0} update available", "{0} updates available", count), count);
+ updatesTabLabel.Text = Catalog.GetString ("Updates");
+ if (count > 0)
+ updatesTabLabel.Text += " (" + count + ")";
+
+ buttonUpdateAll.Visible = count > 0;
+
+ if (count > 0)
+ updatesTree.RestoreStatus (s);
+ else
+ updatesTree.ShowEmptyMessage ();
+ }
+
+ bool IsFiltered (AddinHeader ah)
+ {
+ if (filterEntry.Text.Length == 0)
+ return false;
+ if (ah.Name.IndexOf (filterEntry.Text, StringComparison.CurrentCultureIgnoreCase) != -1)
+ return false;
+ if (ah.Description.IndexOf (filterEntry.Text, StringComparison.CurrentCultureIgnoreCase) != -1)
+ return false;
+ if (ah.Id.IndexOf (filterEntry.Text, StringComparison.CurrentCultureIgnoreCase) != -1)
+ return false;
+ return true;
+ }
+
+ void ManageSites ()
+ {
+ ManageSitesDialog dlg = new ManageSitesDialog (this, service);
+ try {
+ dlg.Run ();
+ repoCombo.Active = lastRepoActive;
+ FillRepos ();
+ } finally {
+ dlg.Destroy ();
+ }
+ }
+
+ protected virtual void OnRepoComboChanged (object sender, System.EventArgs e)
+ {
+ if (GetRepoSelection () == ManageRepoMarker)
+ ManageSites ();
+ else
+ LoadGallery ();
+ lastRepoActive = repoCombo.Active;
+ }
+
+ protected virtual void OnGallerySelectionChanged (object sender, System.EventArgs e)
+ {
+ UpdateAddinInfo ();
+ }
+
+ protected virtual void OnButtonRefreshClicked (object sender, System.EventArgs e)
+ {
+ ProgressDialog pdlg = new ProgressDialog (this);
+ pdlg.Show ();
+ pdlg.SetMessage (AddinManager.CurrentLocalizer.GetString ("Updating repository"));
+ bool updateDone = false;
+
+ Thread t = new Thread (delegate () {
+ try {
+ service.Repositories.UpdateAllRepositories (pdlg);
+ } finally {
+ updateDone = true;
+ }
+ });
+ t.Start ();
+ while (!updateDone) {
+ while (Gtk.Application.EventsPending ())
+ Gtk.Application.RunIteration ();
+ Thread.Sleep (50);
+ }
+ pdlg.Destroy ();
+ LoadGallery ();
+ LoadUpdates ();
+ }
+
+ protected virtual void OnInstallClicked (object sender, System.EventArgs e)
+ {
+ InstallDialog dlg = new InstallDialog (this, service);
+ try {
+ List<AddinRepositoryEntry> selectedEntry = ((AddinInfoView)sender).SelectedEntries;
+ dlg.InitForInstall (selectedEntry.ToArray ());
+ if (dlg.Run () == (int) Gtk.ResponseType.Ok)
+ LoadAll ();
+ } finally {
+ dlg.Destroy ();
+ }
+ }
+
+ protected virtual void OnUninstallClicked (object sender, System.EventArgs e)
+ {
+ List<Addin> selectedAddin = ((AddinInfoView)sender).SelectedAddins;
+ InstallDialog dlg = new InstallDialog (this, service);
+ try {
+ dlg.InitForUninstall (selectedAddin.ToArray ());
+ if (dlg.Run () == (int) Gtk.ResponseType.Ok) {
+ LoadAll ();
+ }
+ } finally {
+ dlg.Destroy ();
+ }
+ }
+
+ protected virtual void OnUpdateClicked (object sender, System.EventArgs e)
+ {
+ List<AddinRepositoryEntry> selectedEntry = ((AddinInfoView)sender).SelectedEntries;
+ InstallDialog dlg = new InstallDialog (this, service);
+ try {
+ dlg.InitForInstall (selectedEntry.ToArray ());
+ if (dlg.Run () == (int) Gtk.ResponseType.Ok)
+ LoadAll ();
+ } finally {
+ dlg.Destroy ();
+ }
+ }
+
+ protected virtual void OnEnableDisableClicked (object sender, System.EventArgs e)
+ {
+ try {
+ foreach (Addin a in ((AddinInfoView)sender).SelectedAddins) {
+ a.Enabled = !a.Enabled;
+ }
+ LoadAll ();
+ }
+ catch (Exception ex) {
+ Services.ShowError (ex, null, this, true);
+ }
+ }
+
+ protected virtual void OnUpdateAll (object sender, System.EventArgs e)
+ {
+ object[] data = updatesTree.AddinsData;
+ AddinRepositoryEntry[] entries = new AddinRepositoryEntry [data.Length];
+ Array.Copy (data, entries, data.Length);
+ InstallDialog dlg = new InstallDialog (this, service);
+ try {
+ dlg.InitForInstall (entries);
+ if (dlg.Run () == (int) Gtk.ResponseType.Ok)
+ LoadAll ();
+ } finally {
+ dlg.Destroy ();
+ }
+ }
+
+ static string lastFolder;
+
+ protected virtual void OnButtonInstallFromFileClicked (object sender, System.EventArgs e)
+ {
+ string[] files;
+ Gtk.FileChooserDialog dlg = new Gtk.FileChooserDialog (Catalog.GetString ("Install Add-in Package"), this, FileChooserAction.Open);
+ try {
+ if (lastFolder != null)
+ dlg.SetCurrentFolder (lastFolder);
+ else
+ dlg.SetCurrentFolder (Environment.GetFolderPath (Environment.SpecialFolder.Personal));
+ dlg.SelectMultiple = true;
+
+ Gtk.FileFilter f = new Gtk.FileFilter ();
+ f.AddPattern ("*.mpack");
+ f.Name = Catalog.GetString ("Add-in packages");
+ dlg.AddFilter (f);
+
+ f = new Gtk.FileFilter ();
+ f.AddPattern ("*");
+ f.Name = Catalog.GetString ("All files");
+ dlg.AddFilter (f);
+
+ dlg.AddButton (Gtk.Stock.Cancel, ResponseType.Cancel);
+ dlg.AddButton (Gtk.Stock.Open, ResponseType.Ok);
+ if (dlg.Run () != (int) Gtk.ResponseType.Ok)
+ return;
+ files = dlg.Filenames;
+ lastFolder = dlg.CurrentFolder;
+ } finally {
+ dlg.Destroy ();
+ }
+
+ InstallDialog idlg = new InstallDialog (this, service);
+ try {
+ idlg.InitForInstall (files);
+ if (idlg.Run () == (int) Gtk.ResponseType.Ok)
+ LoadAll ();
+ } finally {
+ idlg.Destroy ();
+ }
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinManagerWindow.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinManagerWindow.cs
new file mode 100644
index 0000000..ce98235
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinManagerWindow.cs
@@ -0,0 +1,75 @@
+//
+// AddinManagerWindow.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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 Mono.Addins.GuiGtk3
+{
+ public class AddinManagerWindow
+ {
+ private static bool mAllowInstall = true;
+
+ public static bool AllowInstall
+ {
+ get { return mAllowInstall; }
+ set { mAllowInstall = value; }
+ }
+
+ private AddinManagerWindow()
+ {
+ }
+
+ private static void InitDialog (AddinManagerDialog dlg)
+ {
+ dlg.AllowInstall = AllowInstall;
+ }
+
+ public static Gtk.Window Show (Gtk.Window parent)
+ {
+
+ Gtk.Builder builder = new Gtk.Builder (null, "Mono.Addins.GuiGtk3.interfaces.AddinManagerDialog.ui", null);
+ AddinManagerDialog dlg = new AddinManagerDialog (builder, builder.GetObject ("window1").Handle);
+ InitDialog (dlg);
+ parent.Add (dlg);
+ dlg.Show ();
+ return dlg;
+ }
+
+// public static void Run (Gtk.Window parent)
+// {
+// AddinManagerDialog dlg = new AddinManagerDialog (parent);
+// try {
+// InitDialog (dlg);
+// dlg.Run ();
+// } finally {
+// dlg.Destroy ();
+// }
+// }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinTreeWidget.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinTreeWidget.cs
new file mode 100644
index 0000000..3326f3c
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/AddinTreeWidget.cs
@@ -0,0 +1,572 @@
+//
+// AddinTreeWidget.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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;
+using Gtk;
+using Gdk;
+using Mono.Addins;
+using Mono.Addins.Setup;
+using Mono.Unix;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace Mono.Addins.GuiGtk3
+{
+ public class AddinTreeWidget
+ {
+ protected Gtk.TreeView treeView;
+ protected Gtk.TreeStore treeStore;
+ bool allowSelection;
+ ArrayList selected = new ArrayList ();
+ Hashtable addinData = new Hashtable ();
+ TreeViewColumn versionColumn;
+ string filter;
+ Dictionary<string,Gdk.Pixbuf> cachedIcons = new Dictionary<string, Gdk.Pixbuf> ();
+ bool disposed;
+
+ Gdk.Pixbuf iconInstalled;
+ Gdk.Pixbuf updateOverlay;
+ Gdk.Pixbuf installedOverlay;
+
+ public event EventHandler SelectionChanged;
+
+ const int ColAddin = 0;
+ const int ColData = 1;
+ const int ColName = 2;
+ const int ColVersion = 3;
+ const int ColAllowSelection = 4;
+ const int ColSelected = 5;
+ const int ColImage = 6;
+ const int ColShowImage = 7;
+
+ public AddinTreeWidget (Gtk.TreeView treeView)
+ {
+ iconInstalled = Gdk.Pixbuf.LoadFromResource ("plugin-32.png");
+ updateOverlay = Gdk.Pixbuf.LoadFromResource ("software-update-available-overlay.png");
+ installedOverlay = Gdk.Pixbuf.LoadFromResource ("installed-overlay.png");
+
+ this.treeView = treeView;
+ ArrayList list = new ArrayList ();
+ AddStoreTypes (list);
+ Type[] types = (Type[]) list.ToArray (typeof(Type));
+ treeStore = new Gtk.TreeStore (types);
+ treeView.Model = treeStore;
+ CreateColumns ();
+ ShowCategories = true;
+
+ treeView.Destroyed += HandleTreeViewDestroyed;
+ }
+
+ void HandleTreeViewDestroyed (object sender, EventArgs e)
+ {
+ disposed = true;
+ foreach (var px in cachedIcons.Values)
+ if (px != null) px.Dispose ();
+ }
+
+ internal void SetFilter (string text)
+ {
+ this.filter = text;
+ }
+
+ internal void ShowEmptyMessage ()
+ {
+ treeStore.AppendValues (null, null, Catalog.GetString ("No add-ins found"), "", false, false, null, false);
+ }
+
+ protected virtual void AddStoreTypes (ArrayList list)
+ {
+ list.Add (typeof(object));
+ list.Add (typeof(object));
+ list.Add (typeof(string));
+ list.Add (typeof(string));
+ list.Add (typeof(bool));
+ list.Add (typeof(bool));
+ list.Add (typeof (Pixbuf));
+ list.Add (typeof(bool));
+ }
+
+ protected virtual void CreateColumns ()
+ {
+ TreeViewColumn col = new TreeViewColumn ();
+ col.Title = Catalog.GetString ("Add-in");
+
+ CellRendererToggle crtog = new CellRendererToggle ();
+ crtog.Activatable = true;
+ crtog.Toggled += new ToggledHandler (OnAddinToggled);
+ col.PackStart (crtog, false);
+
+ CellRendererPixbuf pr = new CellRendererPixbuf ();
+ col.PackStart (pr, false);
+ col.AddAttribute (pr, "pixbuf", ColImage);
+ col.AddAttribute (pr, "visible", ColShowImage);
+
+ CellRendererText crt = new CellRendererText ();
+ crt.Ellipsize = Pango.EllipsizeMode.End;
+ col.PackStart (crt, true);
+
+ col.AddAttribute (crt, "markup", ColName);
+ col.AddAttribute (crtog, "visible", ColAllowSelection);
+ col.AddAttribute (crtog, "active", ColSelected);
+ col.Expand = true;
+ treeView.AppendColumn (col);
+
+ col = new TreeViewColumn ();
+ col.Title = Catalog.GetString ("Version");
+ col.PackStart (crt, true);
+ col.AddAttribute (crt, "markup", ColVersion);
+ versionColumn = col;
+ treeView.AppendColumn (col);
+ }
+
+ public bool AllowSelection {
+ get { return allowSelection; }
+ set { allowSelection = value; }
+ }
+
+ public bool VersionVisible {
+ get {
+ return versionColumn.Visible;
+ }
+ set {
+ versionColumn.Visible = value;
+ treeView.HeadersVisible = value;
+ }
+ }
+
+ public bool ShowCategories { get; set; }
+
+ void OnAddinToggled (object o, ToggledArgs args)
+ {
+ TreeIter it;
+ if (treeStore.GetIter (out it, new TreePath (args.Path))) {
+ bool sel = !(bool) treeStore.GetValue (it, 5);
+ treeStore.SetValue (it, 5, sel);
+ AddinHeader info = (AddinHeader) treeStore.GetValue (it, 0);
+ if (sel)
+ selected.Add (info);
+ else
+ selected.Remove (info);
+
+ OnSelectionChanged (EventArgs.Empty);
+ }
+ }
+
+ protected virtual void OnSelectionChanged (EventArgs e)
+ {
+ if (SelectionChanged != null)
+ SelectionChanged (this, e);
+ }
+
+ public void Clear ()
+ {
+ addinData.Clear ();
+ selected.Clear ();
+ treeStore.Clear ();
+ }
+
+ public TreeIter AddAddin (AddinHeader info, object dataItem, bool enabled)
+ {
+ return AddAddin (info, dataItem, enabled, true);
+ }
+
+ public TreeIter AddAddin (AddinHeader info, object dataItem, bool enabled, bool userDir)
+ {
+ return AddAddin (info, dataItem, enabled ? AddinStatus.Installed : AddinStatus.Disabled | AddinStatus.Installed);
+ }
+
+ public TreeIter AddAddin (AddinHeader info, object dataItem, AddinStatus status)
+ {
+ addinData [info] = dataItem;
+ TreeIter iter;
+ if (ShowCategories) {
+ TreeIter piter = TreeIter.Zero;
+ if (info.Category == "") {
+ string otherCat = Catalog.GetString ("Other");
+ piter = FindCategory (otherCat);
+ } else {
+ piter = FindCategory (info.Category);
+ }
+ iter = treeStore.AppendNode (piter);
+ } else {
+ iter = treeStore.AppendNode ();
+ }
+ UpdateRow (iter, info, dataItem, status);
+ return iter;
+ }
+
+ protected virtual void UpdateRow (TreeIter iter, AddinHeader info, object dataItem, AddinStatus status)
+ {
+ bool sel = selected.Contains (info);
+
+ treeStore.SetValue (iter, ColAddin, info);
+ treeStore.SetValue (iter, ColData, dataItem);
+
+ string name = EscapeWithFilterMarker (info.Name);
+ if (!string.IsNullOrEmpty (info.Description)) {
+ string desc = info.Description;
+ int i = desc.IndexOf ('\n');
+ if (i != -1)
+ desc = desc.Substring (0, i);
+ name += "\n<small><span foreground=\"darkgrey\">" + EscapeWithFilterMarker (desc) + "</span></small>";
+ }
+
+ if (status != AddinStatus.Disabled) {
+ treeStore.SetValue (iter, ColName, name);
+ treeStore.SetValue (iter, ColVersion, info.Version);
+ treeStore.SetValue (iter, ColAllowSelection, allowSelection);
+ }
+ else {
+ treeStore.SetValue (iter, ColName, "<span foreground=\"grey\">" + name + "</span>");
+ treeStore.SetValue (iter, ColVersion, "<span foreground=\"grey\">" + info.Version + "</span>");
+ treeStore.SetValue (iter, ColAllowSelection, false);
+ }
+
+ treeStore.SetValue (iter, ColShowImage, true);
+ treeStore.SetValue (iter, ColSelected, sel);
+ SetRowIcon (iter, info, dataItem, status);
+ }
+
+ void SetRowIcon (TreeIter it, AddinHeader info, object dataItem, AddinStatus status)
+ {
+ string customIcom = info.Properties.GetPropertyValue ("Icon32");
+ string iconId = info.Id + " " + info.Version + " " + customIcom;
+ Gdk.Pixbuf customPix;
+
+ if (customIcom.Length == 0) {
+ customPix = null;
+ iconId = "__";
+ }
+ else if (!cachedIcons.TryGetValue (iconId, out customPix)) {
+
+ if (dataItem is Addin) {
+ string file = Path.Combine (((Addin)dataItem).Description.BasePath, customIcom);
+ if (File.Exists (file)) {
+ try {
+ customPix = new Gdk.Pixbuf (file);
+ } catch (Exception ex) {
+ Console.WriteLine (ex);
+ }
+ }
+ cachedIcons [iconId] = customPix;
+ }
+ else if (dataItem is AddinRepositoryEntry) {
+ AddinRepositoryEntry arep = (AddinRepositoryEntry) dataItem;
+ string tmpId = iconId;
+ arep.BeginDownloadSupportFile (customIcom, delegate (IAsyncResult res) {
+ Gtk.Application.Invoke (delegate {
+ LoadRemoteIcon (it, tmpId, arep, res, info, dataItem, status);
+ });
+ }, null);
+ iconId = "__";
+ }
+ }
+
+ StoreIcon (it, iconId, customPix, status);
+ }
+
+ Gdk.Pixbuf GetCachedIcon (string id, string effect, Func<Gdk.Pixbuf> pixbufGenerator)
+ {
+ Gdk.Pixbuf pix;
+ if (!cachedIcons.TryGetValue (id + "_" + effect, out pix))
+ cachedIcons [id + "_" + effect] = pix = pixbufGenerator ();
+ return pix;
+ }
+
+ internal bool ShowInstalledMarkers = false;
+
+ void StoreIcon (TreeIter it, string iconId, Gdk.Pixbuf customPix, AddinStatus status)
+ {
+ if (customPix == null)
+ customPix = iconInstalled;
+
+ if ((status & AddinStatus.Installed) == 0) {
+ treeStore.SetValue (it, ColImage, customPix);
+ return;
+ } else if (ShowInstalledMarkers && (status & AddinStatus.HasUpdate) == 0) {
+ customPix = GetCachedIcon (iconId, "InstalledOverlay", delegate { return Services.AddIconOverlay (customPix, installedOverlay); });
+ iconId = iconId + "_Installed";
+ }
+
+ if ((status & AddinStatus.Disabled) != 0) {
+ customPix = GetCachedIcon (iconId, "Desaturate", delegate { return Services.DesaturateIcon (customPix); });
+ iconId = iconId + "_Desaturate";
+ }
+ if ((status & AddinStatus.HasUpdate) != 0)
+ customPix = GetCachedIcon (iconId, "UpdateOverlay", delegate { return Services.AddIconOverlay (customPix, updateOverlay); });
+
+ treeStore.SetValue (it, ColImage, customPix);
+ }
+
+
+ void LoadRemoteIcon (TreeIter it, string iconId, AddinRepositoryEntry arep, IAsyncResult res, AddinHeader info, object dataItem, AddinStatus status)
+ {
+ if (!disposed && treeStore.IterIsValid (it)) {
+ Gdk.Pixbuf customPix = null;
+ try {
+ Gdk.PixbufLoader loader = new Gdk.PixbufLoader (arep.EndDownloadSupportFile (res));
+ customPix = loader.Pixbuf;
+ } catch (Exception ex) {
+ Console.WriteLine (ex);
+ }
+ cachedIcons [iconId] = customPix;
+ StoreIcon (it, iconId, customPix, status);
+ }
+ }
+
+ string EscapeWithFilterMarker (string txt)
+ {
+ if (string.IsNullOrEmpty (filter))
+ return GLib.Markup.EscapeText (txt);
+
+ StringBuilder sb = new StringBuilder ();
+ int last = 0;
+ int i = txt.IndexOf (filter, StringComparison.CurrentCultureIgnoreCase);
+ while (i != -1) {
+ sb.Append (GLib.Markup.EscapeText (txt.Substring (last, i - last)));
+ sb.Append ("<span color='blue'>").Append (txt.Substring (i, filter.Length)).Append ("</span>");
+ last = i + filter.Length;
+ i = txt.IndexOf (filter, last, StringComparison.CurrentCultureIgnoreCase);
+ }
+ if (last < txt.Length)
+ sb.Append (GLib.Markup.EscapeText (txt.Substring (last, txt.Length - last)));
+ return sb.ToString ();
+ }
+
+ public object GetAddinData (AddinHeader info)
+ {
+ return addinData [info];
+ }
+
+ public AddinHeader[] GetSelectedAddins ()
+ {
+ return (AddinHeader[]) selected.ToArray (typeof(AddinHeader));
+ }
+
+ TreeIter FindCategory (string namePath)
+ {
+ TreeIter iter = TreeIter.Zero;
+ string[] paths = namePath.Split ('/');
+ foreach (string name in paths) {
+ TreeIter child;
+ if (!FindCategory (iter, name, out child)) {
+ if (iter.Equals (TreeIter.Zero))
+ iter = treeStore.AppendValues (null, null, name, "", false, false, null, false);
+ else
+ iter = treeStore.AppendValues (iter, null, null, name, "", false, false, null, false);
+ }
+ else
+ iter = child;
+ }
+ return iter;
+ }
+
+ bool FindCategory (TreeIter piter, string name, out TreeIter child)
+ {
+ if (piter.Equals (TreeIter.Zero)) {
+ if (!treeStore.GetIterFirst (out child))
+ return false;
+ }
+ else if (!treeStore.IterChildren (out child, piter))
+ return false;
+
+ do {
+ if (((string) treeStore.GetValue (child, ColName)) == name) {
+ return true;
+ }
+ } while (treeStore.IterNext (ref child));
+
+ return false;
+ }
+
+ public AddinHeader ActiveAddin {
+ get {
+ AddinHeader[] sel = ActiveAddins;
+ if (sel.Length > 0)
+ return sel[0];
+ else
+ return null;
+ }
+ }
+
+ public AddinHeader[] ActiveAddins {
+ get {
+ List<AddinHeader> list = new List<AddinHeader> ();
+ foreach (TreePath p in treeView.Selection.GetSelectedRows ()) {
+ TreeIter iter;
+ treeStore.GetIter (out iter, p);
+ AddinHeader ah = (AddinHeader) treeStore.GetValue (iter, 0);
+ if (ah != null)
+ list.Add (ah);
+ }
+ return list.ToArray ();
+ }
+ }
+
+ public object ActiveAddinData {
+ get {
+ AddinHeader ai = ActiveAddin;
+ return ai != null ? GetAddinData (ai) : null;
+ }
+ }
+
+ public object[] ActiveAddinsData {
+ get {
+ List<object> res = new List<object> ();
+ foreach (AddinHeader ai in ActiveAddins) {
+ res.Add (GetAddinData (ai));
+ }
+ return res.ToArray ();
+ }
+ }
+
+ public object[] AddinsData {
+ get {
+ object[] data = new object [addinData.Count];
+ addinData.Values.CopyTo (data, 0);
+ return data;
+ }
+ }
+
+ public object SaveStatus ()
+ {
+ TreeIter iter;
+ ArrayList list = new ArrayList ();
+
+ // Save the current selection
+ list.Add (treeView.Selection.GetSelectedRows ());
+
+ if (!treeStore.GetIterFirst (out iter))
+ return null;
+
+ // Save the expand state
+ do {
+ SaveStatus (list, iter);
+ } while (treeStore.IterNext (ref iter));
+
+ return list;
+ }
+
+ void SaveStatus (ArrayList list, TreeIter iter)
+ {
+ Gtk.TreePath path = treeStore.GetPath (iter);
+ if (treeView.GetRowExpanded (path))
+ list.Add (path);
+ if (treeStore.IterChildren (out iter, iter)) {
+ do {
+ SaveStatus (list, iter);
+ } while (treeStore.IterNext (ref iter));
+ }
+ }
+
+ public void RestoreStatus (object ob)
+ {
+ if (ob == null)
+ return;
+
+ // The first element is the selection
+ ArrayList list = (ArrayList) ob;
+ TreePath[] selpaths = (TreePath[]) list [0];
+ list.RemoveAt (0);
+
+ foreach (TreePath path in list)
+ treeView.ExpandRow (path, false);
+
+ foreach (TreePath p in selpaths)
+ treeView.Selection.SelectPath (p);
+ }
+
+ public void SelectAll ()
+ {
+ TreeIter iter;
+
+ if (!treeStore.GetIterFirst (out iter))
+ return;
+ do {
+ SelectAll (iter);
+ } while (treeStore.IterNext (ref iter));
+ OnSelectionChanged (EventArgs.Empty);
+ }
+
+ void SelectAll (TreeIter iter)
+ {
+ AddinHeader info = (AddinHeader) treeStore.GetValue (iter, ColAddin);
+
+ if (info != null) {
+ treeStore.SetValue (iter, ColSelected, true);
+ if (!selected.Contains (info))
+ selected.Add (info);
+ treeView.ExpandToPath (treeStore.GetPath (iter));
+ } else {
+ if (treeStore.IterChildren (out iter, iter)) {
+ do {
+ SelectAll (iter);
+ } while (treeStore.IterNext (ref iter));
+ }
+ }
+ }
+
+ public void UnselectAll ()
+ {
+ TreeIter iter;
+ if (!treeStore.GetIterFirst (out iter))
+ return;
+ do {
+ UnselectAll (iter);
+ } while (treeStore.IterNext (ref iter));
+ OnSelectionChanged (EventArgs.Empty);
+ }
+
+ void UnselectAll (TreeIter iter)
+ {
+ AddinHeader info = (AddinHeader) treeStore.GetValue (iter, ColAddin);
+ if (info != null) {
+ treeStore.SetValue (iter, ColSelected, false);
+ selected.Remove (info);
+ } else {
+ if (treeStore.IterChildren (out iter, iter)) {
+ do {
+ UnselectAll (iter);
+ } while (treeStore.IterNext (ref iter));
+ }
+ }
+ }
+ }
+
+ [Flags]
+ public enum AddinStatus
+ {
+ NotInstalled = 0,
+ Installed = 1,
+ Disabled = 2,
+ HasUpdate = 4
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ErrorDialog.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ErrorDialog.cs
new file mode 100644
index 0000000..2ecdd5b
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ErrorDialog.cs
@@ -0,0 +1,104 @@
+//
+// ErrorDialog.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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;
+using UI = Gtk.Builder.ObjectAttribute;
+
+namespace Mono.Addins.GuiGtk3
+{
+ class ErrorDialog : Dialog
+ {
+ //From UI File
+ [UI] Button okButton;
+ [UI] Expander expander;
+ [UI] Label descriptionLabel;
+ [UI] TextView detailsTextView;
+
+ TextTag tagNoWrap;
+ TextTag tagWrap;
+
+ public ErrorDialog (Window parent)
+ {
+ Build ();
+ TransientFor = parent;
+ okButton.Clicked += new EventHandler (OnClose);
+ expander.Activated += new EventHandler (OnExpanded);
+ descriptionLabel.ModifyBg (StateType.Normal, new Gdk.Color (255,0,0));
+
+ tagNoWrap = new TextTag ("nowrap");
+ tagNoWrap.WrapMode = WrapMode.None;
+ detailsTextView.Buffer.TagTable.Add (tagNoWrap);
+
+ tagWrap = new TextTag ("wrap");
+ tagWrap.WrapMode = WrapMode.Word;
+ detailsTextView.Buffer.TagTable.Add (tagWrap);
+
+ expander.Visible = false;
+ }
+
+ public string Message {
+ get { return descriptionLabel.Text; }
+ set {
+ string message = value;
+ while (message.EndsWith ("\r") || message.EndsWith ("\n"))
+ message = message.Substring (0, message.Length - 1);
+ if (!message.EndsWith (".")) message += ".";
+ descriptionLabel.Text = message;
+ }
+ }
+
+ public void AddDetails (string text, bool wrapped)
+ {
+ TextIter it = detailsTextView.Buffer.EndIter;
+ if (wrapped)
+ detailsTextView.Buffer.InsertWithTags (ref it, text, tagWrap);
+ else
+ detailsTextView.Buffer.InsertWithTags (ref it, text, tagNoWrap);
+ expander.Visible = true;
+ }
+
+ void OnClose (object sender, EventArgs args)
+ {
+ Destroy ();
+ }
+
+ void OnExpanded (object sender, EventArgs args)
+ {
+ GLib.Timeout.Add (100, new GLib.TimeoutHandler (UpdateSize));
+ }
+
+ bool UpdateSize ()
+ {
+ int w, h;
+ GetSize (out w, out h);
+ Resize (w, 1);
+ return false;
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HeaderBox.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HeaderBox.cs
new file mode 100644
index 0000000..ddbd282
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HeaderBox.cs
@@ -0,0 +1,196 @@
+//
+// HeaderBox.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+//
+// 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 Mono.Addins.GuiGtk3
+{
+ class HeaderBox: Bin
+ {
+ Gtk.Widget child;
+ int topMargin;
+ int bottomMargin;
+ int leftMargin;
+ int rightMargin;
+
+ int topPadding;
+ int bottomPadding;
+ int leftPadding;
+ int rightPadding;
+
+ bool useCustomColor;
+ Gdk.Color customColor;
+
+ public HeaderBox ()
+ {
+ }
+
+ public HeaderBox (int topMargin, int bottomMargin, int leftMargin, int rightMargin)
+ {
+ SetMargins (topMargin, bottomMargin, leftMargin, rightMargin);
+ }
+
+ public void Replace (Gtk.Bin parent)
+ {
+ Gtk.Widget c = parent.Child;
+ parent.Remove (c);
+ Add (c);
+ parent.Add (this);
+ }
+
+ public void SetMargins (int topMargin, int bottomMargin, int leftMargin, int rightMargin)
+ {
+ this.topMargin = topMargin;
+ this.bottomMargin = bottomMargin;
+ this.leftMargin = leftMargin;
+ this.rightMargin = rightMargin;
+ }
+
+ public void SetPadding (int topPadding, int bottomPadding, int leftPadding, int rightPadding)
+ {
+ this.topPadding = topPadding;
+ this.bottomPadding = bottomPadding;
+ this.leftPadding = leftPadding;
+ this.rightPadding = rightPadding;
+ }
+
+ public bool GradientBackround { get; set; }
+
+ public Gdk.Color BackgroundColor {
+ get { return customColor; }
+ set { customColor = value; useCustomColor = true; }
+ }
+
+ public void ResetBackgroundColor ()
+ {
+ useCustomColor = false;
+ }
+
+ protected override void OnAdded (Widget widget)
+ {
+ base.OnAdded (widget);
+ child = widget;
+ }
+
+// protected override void OnSizeRequested (ref Requisition requisition)
+// {
+// if (child != null) {
+// requisition = child.SizeRequest ();
+// requisition.Width += leftMargin + rightMargin + leftPadding + rightPadding;
+// requisition.Height += topMargin + bottomMargin + topPadding + bottomPadding;
+// } else {
+// requisition.Width = 0;
+// requisition.Height = 0;
+// }
+// }
+
+ public new void GetPreferredWidth (out int width)
+ {
+ if (child != null) {
+ Requisition req = child.SizeRequest ();
+ req.Width += leftMargin + rightMargin + leftPadding + rightPadding;
+ width = req.Width;
+ } else {
+ width = 0;
+ }
+ }
+
+ public new void GetPreferredHeight (out int height)
+ {
+ if (child != null) {
+ Requisition req = child.SizeRequest ();
+ req.Height += topMargin + bottomMargin + topPadding + bottomPadding;
+ height = req.Height;
+ } else {
+ height = 0;
+ }
+ }
+
+ protected override void OnSizeAllocated (Gdk.Rectangle allocation)
+ {
+ base.OnSizeAllocated (allocation);
+ if (allocation.Width > leftMargin + rightMargin + leftPadding + rightPadding) {
+ allocation.X += leftMargin + leftPadding;
+ allocation.Width -= leftMargin + rightMargin + leftPadding + rightPadding;
+ }
+ if (allocation.Height > topMargin + bottomMargin + topPadding + bottomPadding) {
+ allocation.Y += topMargin + topPadding;
+ allocation.Height -= topMargin + bottomMargin + topPadding + bottomPadding;
+ }
+ if (child != null)
+ child.SizeAllocate (allocation);
+ }
+
+ public new void Draw (Cairo.Context cr)
+ {
+ Gdk.Rectangle rect;
+
+ if (GradientBackround) {
+ rect = new Gdk.Rectangle (Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height);
+ HslColor gcol = useCustomColor ? customColor : Parent.Style.Background (Gtk.StateType.Normal);
+
+ cr.NewPath ();
+ cr.MoveTo (rect.X, rect.Y);
+ cr.RelLineTo (rect.Width, 0);
+ cr.RelLineTo (0, rect.Height);
+ cr.RelLineTo (-rect.Width, 0);
+ cr.RelLineTo (0, -rect.Height);
+ cr.ClosePath ();
+ using (Cairo.Gradient pat = new Cairo.LinearGradient (rect.X, rect.Y, rect.X, rect.Y + rect.Height - 1)) {
+ Cairo.Color color1 = gcol;
+ pat.AddColorStop (0, color1);
+ gcol.L -= 0.1;
+ if (gcol.L < 0)
+ gcol.L = 0;
+ pat.AddColorStop (1, gcol);
+ cr.Pattern = pat;
+ cr.FillPreserve ();
+ }
+
+ }
+
+ bool res = base.OnExposeEvent (evnt);
+
+ Gdk.GC borderColor = Parent.Style.DarkGC (Gtk.StateType.Normal);
+
+ rect = Allocation;
+ for (int n=0; n<topMargin; n++)
+ GdkWindow.DrawLine (borderColor, rect.X, rect.Y + n, rect.Left + rect.Width - 1, rect.Y + n);
+
+ for (int n=0; n<bottomMargin; n++)
+ GdkWindow.DrawLine (borderColor, rect.X, rect.Top + rect.Height - 1 - n, rect.Left + rect.Width - 1, rect.Top + rect.Height - 1 - n);
+
+ for (int n=0; n<leftMargin; n++)
+ GdkWindow.DrawLine (borderColor, rect.X + n, rect.Y, rect.X + n, rect.Top + rect.Height - 1);
+
+ for (int n=0; n<rightMargin; n++)
+ GdkWindow.DrawLine (borderColor, rect.Left + rect.Width - 1 - n, rect.Y, rect.Left + rect.Width - 1 - n, rect.Top + rect.Height - 1);
+
+ return res;
+ }
+ }
+}
+
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HoverImageButton.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HoverImageButton.cs
new file mode 100644
index 0000000..220d4e9
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HoverImageButton.cs
@@ -0,0 +1,265 @@
+/***************************************************************************
+ * HoverImageButton.cs
+ *
+ * Copyright (C) 2007 Novell, Inc.
+ * Written by Aaron Bockover <abockover@novell.com>
+ ****************************************************************************/
+
+/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
+ *
+ * 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 Mono.Addins.GuiGtk3
+{
+ class HoverImageButton : EventBox
+ {
+ private static Gdk.Cursor hand_cursor = new Gdk.Cursor(Gdk.CursorType.Hand1);
+
+ private IconSize icon_size = IconSize.Menu;
+ private string [] icon_names = { "image-missing", Stock.MissingImage };
+ private Gdk.Pixbuf normal_pixbuf;
+ private Gdk.Pixbuf active_pixbuf;
+ private Image image;
+ private bool is_hovering;
+ private bool is_pressed;
+
+ private bool draw_focus = true;
+
+ private event EventHandler clicked;
+
+ public event EventHandler Clicked {
+ add { clicked += value; }
+ remove { clicked -= value; }
+ }
+
+ public HoverImageButton()
+ {
+ CanFocus = true;
+
+ image = new Image();
+ image.Show();
+ Add(image);
+ }
+
+ public HoverImageButton(IconSize size, string icon_name) : this(size, new string [] { icon_name })
+ {
+ }
+
+ public HoverImageButton(IconSize size, string [] icon_names) : this()
+ {
+ this.icon_size = size;
+ this.icon_names = icon_names;
+ }
+
+ public new void Activate()
+ {
+ EventHandler handler = clicked;
+ if(handler != null) {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ private bool changing_style = false;
+ protected override void OnStyleSet(Style previous_style)
+ {
+ if(changing_style) {
+ return;
+ }
+
+ changing_style = true;
+ if (normal_pixbuf == null)
+ LoadPixbufs();
+ changing_style = false;
+ }
+
+ protected override bool OnEnterNotifyEvent(Gdk.EventCrossing evnt)
+ {
+ image.GdkWindow.Cursor = hand_cursor;
+ is_hovering = true;
+ UpdateImage();
+ return base.OnEnterNotifyEvent(evnt);
+ }
+
+ protected override bool OnLeaveNotifyEvent(Gdk.EventCrossing evnt)
+ {
+ is_hovering = false;
+ UpdateImage();
+ return base.OnLeaveNotifyEvent(evnt);
+ }
+
+ protected override bool OnFocusInEvent(Gdk.EventFocus evnt)
+ {
+ bool ret = base.OnFocusInEvent(evnt);
+ UpdateImage();
+ return ret;
+ }
+
+ protected override bool OnFocusOutEvent(Gdk.EventFocus evnt)
+ {
+ bool ret = base.OnFocusOutEvent(evnt);
+ UpdateImage();
+ return ret;
+ }
+
+ protected override bool OnButtonPressEvent(Gdk.EventButton evnt)
+ {
+ if(evnt.Button != 1) {
+ return base.OnButtonPressEvent(evnt);
+ }
+
+ HasFocus = true;
+ is_pressed = true;
+ QueueDraw();
+
+ return base.OnButtonPressEvent(evnt);
+ }
+
+ protected override bool OnButtonReleaseEvent(Gdk.EventButton evnt)
+ {
+ if(evnt.Button != 1) {
+ return base.OnButtonReleaseEvent(evnt);
+ }
+
+ is_pressed = false;
+ QueueDraw();
+ Activate();
+
+ return base.OnButtonReleaseEvent(evnt);
+ }
+
+ public new void Draw (Cairo.Context cr)
+ {
+ base.Draw (cr);
+
+ PropagateDraw (Child, cr);
+
+ if(HasFocus && draw_focus) {
+ Style.PaintFocus(Style, cr, StateType.Normal, this, "button",
+ 0, 0, Allocation.Width, Allocation.Height);
+ }
+ }
+
+ private void UpdateImage()
+ {
+ image.Pixbuf = is_hovering || is_pressed || HasFocus
+ ? active_pixbuf : normal_pixbuf;
+ }
+
+ private void LoadPixbufs()
+ {
+ int width, height;
+ Icon.SizeLookup(icon_size, out width, out height);
+ IconTheme theme = IconTheme.GetForScreen(Screen);
+
+ if(normal_pixbuf != null) {
+ normal_pixbuf.Dispose();
+ normal_pixbuf = null;
+ }
+
+ if(active_pixbuf != null) {
+ active_pixbuf.Dispose();
+ active_pixbuf = null;
+ }
+
+ for(int i = 0; i < icon_names.Length; i++) {
+ try {
+ normal_pixbuf = RenderIcon(icon_names[i], icon_size, null)
+ ?? theme.LoadIcon(icon_names[i], width, 0);
+ active_pixbuf = ColorShiftPixbuf(normal_pixbuf, 30);
+ break;
+ } catch {
+ }
+ }
+
+ UpdateImage();
+ }
+
+ public Gdk.Pixbuf Pixbuf {
+ get { return this.normal_pixbuf; }
+ set {
+ this.normal_pixbuf = value;
+ active_pixbuf = ColorShiftPixbuf(normal_pixbuf, 30);
+ UpdateImage();
+ }
+ }
+
+
+ private static byte PixelClamp(int val)
+ {
+ return (byte)System.Math.Max(0, System.Math.Min(255, val));
+ }
+
+ private unsafe Gdk.Pixbuf ColorShiftPixbuf(Gdk.Pixbuf src, byte shift)
+ {
+ Gdk.Pixbuf dest = new Gdk.Pixbuf(src.Colorspace, src.HasAlpha, src.BitsPerSample, src.Width, src.Height);
+
+ byte *src_pixels_orig = (byte *)src.Pixels;
+ byte *dest_pixels_orig = (byte *)dest.Pixels;
+
+ for(int i = 0; i < src.Height; i++) {
+ byte *src_pixels = src_pixels_orig + i * src.Rowstride;
+ byte *dest_pixels = dest_pixels_orig + i * dest.Rowstride;
+
+ for(int j = 0; j < src.Width; j++) {
+ *(dest_pixels++) = PixelClamp(*(src_pixels++) + shift);
+ *(dest_pixels++) = PixelClamp(*(src_pixels++) + shift);
+ *(dest_pixels++) = PixelClamp(*(src_pixels++) + shift);
+
+ if(src.HasAlpha) {
+ *(dest_pixels++) = *(src_pixels++);
+ }
+ }
+ }
+
+ return dest;
+ }
+
+ public string [] IconNames {
+ get { return icon_names; }
+ set {
+ icon_names = value;
+ LoadPixbufs();
+ }
+ }
+
+ public IconSize IconSize {
+ get { return icon_size; }
+ set {
+ icon_size = value;
+ LoadPixbufs();
+ }
+ }
+
+ public Image Image {
+ get { return image; }
+ }
+
+ public bool DrawFocus {
+ get { return draw_focus; }
+ set {
+ draw_focus = value;
+ QueueDraw();
+ }
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HslColor.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HslColor.cs
new file mode 100644
index 0000000..0012d24
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/HslColor.cs
@@ -0,0 +1,164 @@
+//
+// HslColor.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
+//
+// 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 Gdk;
+
+namespace Mono.Addins.GuiGtk3
+{
+ struct HslColor
+ {
+ public double H {
+ get;
+ set;
+ }
+
+ public double S {
+ get;
+ set;
+ }
+
+ public double L {
+ get;
+ set;
+ }
+
+ static Gdk.Color black = new Gdk.Color (0, 0, 0);
+ public static implicit operator Color (HslColor hsl)
+ {
+ if (hsl.L > 1) hsl.L = 1;
+ if (hsl.L < 0) hsl.L = 0;
+ if (hsl.H > 1) hsl.H = 1;
+ if (hsl.H < 0) hsl.H = 0;
+ if (hsl.S > 1) hsl.S = 1;
+ if (hsl.S < 0) hsl.S = 0;
+
+ double r = 0, g = 0, b = 0;
+
+ if (hsl.L == 0)
+ return black;
+
+ if (hsl.S == 0) {
+ r = g = b = hsl.L;
+ } else {
+ double temp2 = hsl.L <= 0.5 ? hsl.L * (1.0 + hsl.S) : hsl.L + hsl.S -(hsl.L * hsl.S);
+ double temp1 = 2.0 * hsl.L - temp2;
+
+ double[] t3 = new double[] { hsl.H + 1.0 / 3.0, hsl.H, hsl.H - 1.0 / 3.0};
+ double[] clr= new double[] { 0, 0, 0};
+ for (int i = 0; i < 3; i++) {
+ if (t3[i] < 0)
+ t3[i] += 1.0;
+ if (t3[i] > 1)
+ t3[i]-=1.0;
+ if (6.0 * t3[i] < 1.0)
+ clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0;
+ else if (2.0 * t3[i] < 1.0)
+ clr[i] = temp2;
+ else if (3.0 * t3[i] < 2.0)
+ clr[i] = (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - t3[i]) * 6.0);
+ else
+ clr[i] = temp1;
+ }
+
+ r = clr[0];
+ g = clr[1];
+ b = clr[2];
+ }
+ return new Color ((byte)(255 * r),
+ (byte)(255 * g),
+ (byte)(255 * b));
+ }
+
+ public static Cairo.Color ToCairoColor (Gdk.Color color)
+ {
+ return new Cairo.Color ((double)color.Red / ushort.MaxValue,
+ (double)color.Green / ushort.MaxValue,
+ (double)color.Blue / ushort.MaxValue);
+ }
+
+ public static implicit operator Cairo.Color (HslColor hsl)
+ {
+ return ToCairoColor ((Gdk.Color)hsl);
+ }
+
+ public static implicit operator HslColor (Color color)
+ {
+ return new HslColor (color);
+ }
+
+ public HslColor (Color color) : this ()
+ {
+ double r = color.Red / (double)ushort.MaxValue;
+ double g = color.Green / (double)ushort.MaxValue;
+ double b = color.Blue / (double)ushort.MaxValue;
+
+ double v = System.Math.Max (r, g);
+ v = System.Math.Max (v, b);
+
+ double m = System.Math.Min (r, g);
+ m = System.Math.Min (m, b);
+
+ this.L = (m + v) / 2.0;
+ if (this.L <= 0.0)
+ return;
+ double vm = v - m;
+ this.S = vm;
+
+ if (this.S > 0.0) {
+ this.S /= (this.L <= 0.5) ? (v + m) : (2.0 - v - m);
+ } else {
+ return;
+ }
+
+ double r2 = (v - r) / vm;
+ double g2 = (v - g) / vm;
+ double b2 = (v - b) / vm;
+
+ if (r == v) {
+ this.H = (g == m ? 5.0 + b2 : 1.0 - g2);
+ } else if (g == v) {
+ this.H = (b == m ? 1.0 + r2 : 3.0 - b2);
+ } else {
+ this.H = (r == m ? 3.0 + g2 : 5.0 - r2);
+ }
+ this.H /= 6.0;
+ }
+
+ public static double Brightness (Gdk.Color c)
+ {
+ double r = c.Red / (double)ushort.MaxValue;
+ double g = c.Green / (double)ushort.MaxValue;
+ double b = c.Blue / (double)ushort.MaxValue;
+ return System.Math.Sqrt (r * .241 + g * .691 + b * .068);
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("[HslColor: H={0}, S={1}, L={2}]", H, S, L);
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/InstallDialog.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/InstallDialog.cs
new file mode 100644
index 0000000..464fbec
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/InstallDialog.cs
@@ -0,0 +1,288 @@
+//
+// InstallDialog.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+//
+// 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 Mono.Addins.Setup;
+using Mono.Addins.Description;
+using System.Text;
+using Mono.Unix;
+using System.Threading;
+using System.Linq;
+using System.Collections.Generic;
+using UI = Gtk.Builder.ObjectAttribute;
+using Gtk;
+
+namespace Mono.Addins.GuiGtk3
+{
+ internal class InstallDialog : Gtk.Dialog
+ {
+ //From UI File
+ [UI] VBox boxProgress;
+ [UI] Button buttonOk;
+ [UI] Label labelInfo;
+ [UI] ScrolledWindow scrolledwindow1;
+ [UI] HSeparator insSeparator;
+ [UI] Label globalProgressLabel;
+ [UI] ProgressBar mainProgressBar;
+ [UI] Button buttonCancel;
+
+ string[] filesToInstall;
+ AddinRepositoryEntry[] addinsToInstall;
+ PackageCollection packagesToInstall;
+ SetupService service;
+ Gtk.ResponseType response = Gtk.ResponseType.None;
+ IEnumerable<string> uninstallIds;
+ InstallMonitor installMonitor;
+ bool installing;
+ const int MaxHeight = 350;
+
+ public InstallDialog (Gtk.Window parent, SetupService service)
+ {
+ this.Build ();
+ this.service = service;
+ TransientFor = parent;
+ WindowPosition = Gtk.WindowPosition.CenterOnParent;
+// Services.PlaceDialog (this, parent);
+ boxProgress.Visible = false;
+ Resizable = false;
+ }
+
+ public void InitForInstall (AddinRepositoryEntry[] addinsToInstall)
+ {
+ this.addinsToInstall = addinsToInstall;
+ FillSummaryPage ();
+// Services.PlaceDialog (this, TransientFor);
+ }
+
+ public void InitForInstall (string[] filesToInstall)
+ {
+ this.filesToInstall = filesToInstall;
+ FillSummaryPage ();
+// Services.PlaceDialog (this, TransientFor);
+ }
+
+ public void InitForUninstall (Addin[] info)
+ {
+ this.uninstallIds = info.Select (a => a.Id);
+ buttonOk.Label = Catalog.GetString ("Uninstall");
+
+ HashSet<Addin> sinfos = new HashSet<Addin> ();
+
+ StringBuilder sb = new StringBuilder ();
+ sb.Append ("<b>").Append (Catalog.GetString ("The following packages will be uninstalled:")).Append ("</b>\n\n");
+ foreach (var a in info) {
+ sb.Append (a.Name + "\n\n");
+ sinfos.UnionWith (service.GetDependentAddins (a.Id, true));
+ }
+
+ if (sinfos.Count > 0) {
+ sb.Append ("<b>").Append (Catalog.GetString ("There are other add-ins that depend on the previous ones which will also be uninstalled:")).Append ("</b>\n\n");
+ foreach (Addin si in sinfos)
+ sb.Append (si.Description.Name + "\n");
+ }
+
+ ShowMessage (sb.ToString ());
+// Services.PlaceDialog (this, TransientFor);
+ }
+
+ void FillSummaryPage ()
+ {
+ PackageCollection packs = new PackageCollection ();
+
+ if (filesToInstall != null) {
+ foreach (string file in filesToInstall) {
+ packs.Add (Package.FromFile (file));
+ }
+ }
+ else {
+ foreach (AddinRepositoryEntry arep in addinsToInstall) {
+ packs.Add (Package.FromRepository (arep));
+ }
+ }
+
+ packagesToInstall = new PackageCollection (packs);
+
+ PackageCollection toUninstall;
+ DependencyCollection unresolved;
+ bool res;
+
+ InstallMonitor m = new InstallMonitor ();
+ res = service.ResolveDependencies (m, packs, out toUninstall, out unresolved);
+
+ StringBuilder sb = new StringBuilder ();
+ if (!res) {
+ sb.Append ("<b><span foreground=\"red\">").Append (Catalog.GetString ("The selected add-ins can't be installed because there are dependency conflicts.")).Append ("</span></b>\n");
+ foreach (string s in m.Errors) {
+ sb.Append ("<b><span foreground=\"red\">" + s + "</span></b>\n");
+ }
+ sb.Append ("\n");
+ }
+
+ if (m.Warnings.Count != 0) {
+ foreach (string w in m.Warnings) {
+ sb.Append ("<b><span foreground=\"red\">" + w + "</span></b>\n");
+ }
+ sb.Append ("\n");
+ }
+
+ sb.Append ("<b>").Append (Catalog.GetString ("The following packages will be installed:")).Append ("</b>\n\n");
+ foreach (Package p in packs) {
+ sb.Append (p.Name);
+ if (!p.SharedInstall)
+ sb.Append (Catalog.GetString (" (in user directory)"));
+ sb.Append ("\n");
+ }
+ sb.Append ("\n");
+
+ if (toUninstall.Count > 0) {
+ sb.Append ("<b>").Append (Catalog.GetString ("The following packages need to be uninstalled:")).Append ("</b>\n\n");
+ foreach (Package p in toUninstall) {
+ sb.Append (p.Name + "\n");
+ }
+ sb.Append ("\n");
+ }
+
+ if (unresolved.Count > 0) {
+ sb.Append ("<b>").Append (Catalog.GetString ("The following dependencies could not be resolved:")).Append ("</b>\n\n");
+ foreach (Dependency p in unresolved) {
+ sb.Append (p.Name + "\n");
+ }
+ sb.Append ("\n");
+ }
+ buttonOk.Sensitive = res;
+ ShowMessage (sb.ToString ());
+ }
+
+ void ShowMessage (string txt)
+ {
+ labelInfo.Markup = txt.TrimEnd ('\n','\t',' ');
+ if (labelInfo.SizeRequest ().Height > MaxHeight) {
+ scrolledwindow1.VscrollbarPolicy = Gtk.PolicyType.Automatic;
+ scrolledwindow1.HeightRequest = MaxHeight;
+ }
+ else {
+ scrolledwindow1.HeightRequest = labelInfo.SizeRequest ().Height;
+ }
+ }
+
+ protected virtual void OnButtonOkClicked (object sender, System.EventArgs e)
+ {
+ if (response != Gtk.ResponseType.None) {
+ Respond (response);
+ return;
+ }
+ Install ();
+ }
+
+ protected virtual void OnButtonCancelClicked (object sender, System.EventArgs e)
+ {
+ if (installing) {
+ if (Services.AskQuestion (Catalog.GetString ("Are you sure you want to cancel the installation?")))
+ installMonitor.Cancel ();
+ } else
+ Respond (Gtk.ResponseType.Cancel);
+ }
+
+ void Install ()
+ {
+ insSeparator.Visible = true;
+ boxProgress.Visible = true;
+ buttonOk.Sensitive = false;
+
+ string txt;
+ string errmessage;
+ string warnmessage;
+
+ ThreadStart oper;
+
+ if (uninstallIds == null) {
+ installMonitor = new InstallMonitor (globalProgressLabel, mainProgressBar, Catalog.GetString ("Installing Add-ins"));
+ oper = new ThreadStart (RunInstall);
+ errmessage = Catalog.GetString ("The installation failed!");
+ warnmessage = Catalog.GetString ("The installation has completed with warnings.");
+ } else {
+ installMonitor = new InstallMonitor (globalProgressLabel, mainProgressBar, Catalog.GetString ("Uninstalling Add-ins"));
+ oper = new ThreadStart (RunUninstall);
+ errmessage = Catalog.GetString ("The uninstallation failed!");
+ warnmessage = Catalog.GetString ("The uninstallation has completed with warnings.");
+ }
+
+ installing = true;
+ oper ();
+ installing = false;
+
+ buttonCancel.Visible = false;
+ buttonOk.Label = Gtk.Stock.Close;
+ buttonOk.UseStock = true;
+
+ if (installMonitor.Success && installMonitor.Warnings.Count == 0) {
+ Respond (Gtk.ResponseType.Ok);
+ return;
+ } else if (installMonitor.Success) {
+ txt = "<b>" + warnmessage + "</b>\n\n";
+ foreach (string s in installMonitor.Warnings)
+ txt += GLib.Markup.EscapeText (s) + "\n";
+ response = Gtk.ResponseType.Ok;
+ buttonOk.Sensitive = true;
+ } else {
+ buttonCancel.Label = Gtk.Stock.Close;
+ buttonCancel.UseStock = true;
+ txt = "<span foreground=\"red\"><b>" + errmessage + "</b></span>\n\n";
+ foreach (string s in installMonitor.Errors)
+ txt += GLib.Markup.EscapeText (s) + "\n";
+ response = Gtk.ResponseType.Cancel;
+ buttonOk.Sensitive = true;
+ }
+
+ ShowMessage (txt);
+ }
+
+ void RunInstall ()
+ {
+ try {
+ if (filesToInstall != null)
+ service.Install (installMonitor, filesToInstall);
+ else
+ service.Install (installMonitor, packagesToInstall);
+ } catch (Exception ex) {
+ installMonitor.Errors.Add (ex.Message);
+ } finally {
+ installMonitor.Dispose ();
+ }
+ }
+
+ void RunUninstall ()
+ {
+ try {
+ service.Uninstall (installMonitor, uninstallIds);
+ } catch (Exception ex) {
+ installMonitor.Errors.Add (ex.Message);
+ } finally {
+ installMonitor.Dispose ();
+ }
+ }
+ }
+}
+
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/InstallMonitor.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/InstallMonitor.cs
new file mode 100644
index 0000000..e5deaa7
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/InstallMonitor.cs
@@ -0,0 +1,133 @@
+//
+// AddinInstallDialog.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+//
+// 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.Text;
+using System.Threading;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using Mono.Unix;
+using Gtk;
+using Mono.Addins.Setup;
+using Mono.Addins.Description;
+namespace Mono.Addins.GuiGtk3
+{
+ class InstallMonitor: IProgressStatus, IDisposable
+ {
+ Label progressLabel;
+ ProgressBar progressBar;
+ StringCollection errors = new StringCollection ();
+ StringCollection warnings = new StringCollection ();
+ bool canceled;
+ bool done;
+ string mainOperation;
+
+ public InstallMonitor (Label progressLabel, ProgressBar progressBar, string mainOperation)
+ {
+ this.progressLabel = progressLabel;
+ this.progressBar = progressBar;
+ this.mainOperation = mainOperation;
+ }
+
+ public InstallMonitor ()
+ {
+ }
+
+ public void SetMessage (string msg)
+ {
+ if (progressLabel != null)
+ progressLabel.Markup = "<b>" + GLib.Markup.EscapeText (mainOperation) + "</b>\n" + GLib.Markup.EscapeText (msg);
+ RunPendingEvents ();
+ }
+
+ public void SetProgress (double progress)
+ {
+ if (progressBar != null)
+ progressBar.Fraction = progress;
+ RunPendingEvents ();
+ }
+
+ public void Log (string msg)
+ {
+ Console.WriteLine (msg);
+ }
+
+ public void ReportWarning (string message)
+ {
+ warnings.Add (message);
+ }
+
+ public void ReportError (string message, Exception exception)
+ {
+ errors.Add (message);
+ }
+
+ public bool IsCanceled {
+ get { return canceled; }
+ }
+
+ public StringCollection Errors {
+ get { return errors; }
+ }
+
+ public StringCollection Warnings {
+ get { return warnings; }
+ }
+
+ public void Cancel ()
+ {
+ canceled = true;
+ }
+
+ public int LogLevel {
+ get { return 1; }
+ }
+
+ public void Dispose ()
+ {
+ done = true;
+ }
+
+ public void WaitForCompleted ()
+ {
+ while (!done) {
+ RunPendingEvents ();
+ Thread.Sleep (50);
+ }
+ }
+
+ public bool Success {
+ get { return errors.Count == 0; }
+ }
+
+ void RunPendingEvents ()
+ {
+ while (Gtk.Application.EventsPending ())
+ Gtk.Application.RunIteration ();
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ManageSitesDialog.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ManageSitesDialog.cs
new file mode 100644
index 0000000..df35c62
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ManageSitesDialog.cs
@@ -0,0 +1,179 @@
+//
+// ManageSitesDialog.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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;
+using Mono.Unix;
+using System.Threading;
+
+using Mono.Addins.Setup;
+using Gtk;
+using UI = Gtk.Builder.ObjectAttribute;
+
+
+namespace Mono.Addins.GuiGtk3
+{
+ class ManageSitesDialog : Dialog
+ {
+ //From UI File
+ [UI] TreeView repoTree;
+ [UI] Button btnRemove;
+
+ ListStore treeStore;
+ SetupService service;
+
+ public ManageSitesDialog (Gtk.Window parent, SetupService service)
+ {
+ Build ();
+ TransientFor = parent;
+// Services.PlaceDialog (this, parent);
+ this.service = service;
+ treeStore = new Gtk.ListStore (typeof (string), typeof (string), typeof(bool));
+ repoTree.Model = treeStore;
+ repoTree.HeadersVisible = false;
+ var crt = new Gtk.CellRendererToggle ();
+ crt.Toggled += HandleRepoToggled;
+ repoTree.AppendColumn ("", crt, "active", 2);
+ repoTree.AppendColumn ("", new Gtk.CellRendererText (), "markup", 1);
+ repoTree.Selection.Changed += new EventHandler(OnSelect);
+
+ AddinRepository[] reps = service.Repositories.GetRepositories ();
+ foreach (AddinRepository rep in reps)
+ AppendRepository (rep);
+
+ btnRemove.Sensitive = false;
+ }
+
+// public override void Dispose ()
+// {
+// base.Dispose ();
+// Destroy ();
+// }
+
+ void AppendRepository (AddinRepository rep)
+ {
+ string txt = GLib.Markup.EscapeText (rep.Title) + "\n<span color='darkgray'>" + GLib.Markup.EscapeText (rep.Url) + "</span>";
+ treeStore.AppendValues (rep.Url, txt, rep.Enabled);
+ }
+
+ protected void OnAdd (object sender, EventArgs e)
+ {
+ NewSiteDialog dlg = new NewSiteDialog (this);
+ try {
+ if (dlg.Run ()) {
+ string url = dlg.Url;
+ if (!url.StartsWith ("http://") && !url.StartsWith ("https://") && !url.StartsWith ("file://")) {
+ url = "http://" + url;
+ }
+
+ try {
+ new Uri (url);
+ } catch {
+ Services.ShowError (null, "Invalid url: " + url, null, true);
+ }
+
+ if (!service.Repositories.ContainsRepository (url)) {
+ ProgressDialog pdlg = new ProgressDialog (this);
+ pdlg.Show ();
+ pdlg.SetMessage (AddinManager.CurrentLocalizer.GetString ("Registering repository"));
+
+ bool done = false;
+ AddinRepository rr = null;
+ Exception error = null;
+
+ ThreadPool.QueueUserWorkItem (delegate {
+ try {
+ rr = service.Repositories.RegisterRepository (pdlg, url, true);
+ } catch (System.Exception ex) {
+ error = ex;
+ } finally {
+ done = true;
+ }
+ });
+
+ while (!done) {
+ if (Gtk.Application.EventsPending ())
+ Gtk.Application.RunIteration ();
+ else
+ Thread.Sleep (100);
+ }
+
+ pdlg.Destroy ();
+
+ if (pdlg.HadError) {
+ if (rr != null)
+ service.Repositories.RemoveRepository (rr.Url);
+ return;
+ }
+
+ if (error != null) {
+ Services.ShowError (error, "The repository could not be registered", null, true);
+ return;
+ }
+
+ AppendRepository (rr);
+ }
+ }
+ } finally {
+ dlg.Destroy ();
+ }
+ }
+
+ protected void OnRemove (object sender, EventArgs e)
+ {
+ Gtk.ITreeModel foo;
+ Gtk.TreeIter iter;
+ if (!repoTree.Selection.GetSelected (out foo, out iter))
+ return;
+
+ string rep = (string) treeStore.GetValue (iter, 0);
+ service.Repositories.RemoveRepository (rep);
+
+ treeStore.Remove (ref iter);
+ }
+
+ void HandleRepoToggled (object o, ToggledArgs args)
+ {
+ Gtk.TreeIter iter;
+ if (!treeStore.GetIterFromString (out iter, args.Path))
+ return;
+
+ bool newVal = !(bool) treeStore.GetValue (iter, 2);
+ string rep = (string) treeStore.GetValue (iter, 0);
+ service.Repositories.SetRepositoryEnabled (rep, newVal);
+
+ treeStore.SetValue (iter, 2, newVal);
+ }
+
+ protected void OnSelect(object sender, EventArgs e)
+ {
+ btnRemove.Sensitive = repoTree.Selection.CountSelectedRows() > 0;
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/NewSiteDialog.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/NewSiteDialog.cs
new file mode 100644
index 0000000..719b546
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/NewSiteDialog.cs
@@ -0,0 +1,124 @@
+//
+// NewSiteDialog.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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;
+using UI = Gtk.Builder.ObjectAttribute;
+
+namespace Mono.Addins.GuiGtk3
+{
+ class NewSiteDialog : Dialog
+ {
+ //From UI File
+ [UI] Entry pathEntry;
+ [UI] Entry urlText;
+ [UI] RadioButton btnOnlineRep;
+ [UI] Button btnOk;
+
+ public NewSiteDialog (Gtk.Window parent)
+ {
+ Build ();
+ TransientFor = parent;
+// Services.PlaceDialog (this, parent);
+ pathEntry.Sensitive = false;
+ CheckValues ();
+ }
+
+// public override void Dispose ()
+// {
+// base.Dispose ();
+// Destroy ();
+// }
+
+ public string Url {
+ get {
+ if (btnOnlineRep.Active)
+ return urlText.Text;
+ else if (pathEntry.Text.Length > 0)
+ return "file://" + pathEntry.Text;
+ else
+ return string.Empty;
+ }
+ }
+
+ void CheckValues ()
+ {
+ btnOk.Sensitive = (Url != "");
+ }
+
+ public new bool Run ()
+ {
+ ShowAll ();
+ return ((ResponseType) base.Run ()) == ResponseType.Ok;
+ }
+
+ protected void OnClose (object sender, EventArgs args)
+ {
+ Destroy ();
+ }
+
+ protected void OnOptionClicked (object sender, EventArgs e)
+ {
+ if (btnOnlineRep.Active) {
+ urlText.Sensitive = true;
+ pathEntry.Sensitive = false;
+ } else {
+ urlText.Sensitive = false;
+ pathEntry.Sensitive = true;
+ }
+ CheckValues ();
+ }
+
+ protected virtual void OnButtonBrowseClicked(object sender, System.EventArgs e)
+ {
+ FileChooserDialog dlg = new FileChooserDialog ("Select Folder", this, FileChooserAction.SelectFolder);
+ try {
+ dlg.AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel);
+ dlg.AddButton (Gtk.Stock.Open, Gtk.ResponseType.Ok);
+
+ dlg.SetFilename (Environment.GetFolderPath (Environment.SpecialFolder.Personal));
+ if (dlg.Run () == (int) ResponseType.Ok) {
+ pathEntry.Text = dlg.Filename;
+ }
+ } finally {
+ dlg.Destroy ();
+ }
+ }
+
+ protected virtual void OnPathEntryChanged(object sender, System.EventArgs e)
+ {
+ CheckValues ();
+ }
+
+ protected virtual void OnUrlTextChanged (object sender, System.EventArgs e)
+ {
+ CheckValues ();
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ProgressDialog.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ProgressDialog.cs
new file mode 100644
index 0000000..34105e2
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/ProgressDialog.cs
@@ -0,0 +1,120 @@
+// ProgressDialog.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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;
+using UI = Gtk.Builder.ObjectAttribute;
+
+namespace Mono.Addins.GuiGtk3
+{
+ internal class ProgressDialog : Gtk.Dialog, IProgressStatus
+ {
+ //From UI file
+ [UI] Label labelMessage;
+ [UI] ProgressBar progressbar;
+ [UI] TextView textview;
+ [UI] Button buttonCancel;
+
+ bool cancelled;
+ bool hadError;
+
+ public ProgressDialog (Gtk.Window parent)
+ {
+ this.Build();
+// Services.PlaceDialog (this, parent);
+ }
+
+ public bool IsCanceled {
+ get {
+ return cancelled;
+ }
+ }
+
+ public int LogLevel {
+ get {
+ return 1;
+ }
+ }
+
+ public bool HadError {
+ get {
+ return hadError;
+ }
+ }
+
+ public void SetMessage (string msg)
+ {
+ Gtk.Application.Invoke (delegate {
+ labelMessage.Text = msg;
+ });
+ }
+
+ public void SetProgress (double progress)
+ {
+ Gtk.Application.Invoke (delegate {
+ progressbar.Fraction = progress;
+ });
+ }
+
+ public void Log (string msg)
+ {
+ Gtk.Application.Invoke (delegate {
+ Gtk.TextIter it = textview.Buffer.EndIter;
+ textview.Buffer.Insert (ref it, msg + "\n");
+ });
+ }
+
+ public void ReportWarning (string message)
+ {
+ Log ("WARNING: " + message);
+ }
+
+ public void ReportError (string message, Exception exception)
+ {
+ Log ("Error: " + message);
+ if (exception != null)
+ Log (exception.ToString ());
+ Gtk.Application.Invoke (delegate {
+ Services.ShowError (exception, message, null, true);
+ });
+ hadError = true;
+ }
+
+ public void Cancel ()
+ {
+ Gtk.Application.Invoke (delegate {
+ cancelled = true;
+ buttonCancel.Sensitive = false;
+ });
+ }
+
+ protected virtual void OnButtonCancelClicked (object sender, System.EventArgs e)
+ {
+ Cancel ();
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/SearchEntry.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/SearchEntry.cs
new file mode 100644
index 0000000..f3a667d
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/SearchEntry.cs
@@ -0,0 +1,130 @@
+//
+// SearchEntry.cs
+//
+// Author:
+// Aaron Bockover <abockover@novell.com>
+// Gabriel Burt <gburt@novell.com>
+//
+// Copyright 2007-2010 Novell, Inc.
+//
+// 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 Mono.Addins.GuiGtk3
+{
+ [System.ComponentModel.ToolboxItem(true)]
+ class SearchEntry : EventBox
+ {
+ HBox box = new HBox ();
+ Gtk.Entry entry = new Gtk.Entry ();
+ HoverImageButton iconFind;
+ HoverImageButton iconClean;
+ const int notifyDelay = 50;
+ bool notifying;
+
+ public SearchEntry ()
+ {
+ entry.HasFrame = false;
+ box.PackStart (entry, true, true, 0);
+ iconFind = new HoverImageButton (IconSize.Menu, Gtk.Stock.Find);
+ box.PackStart (iconFind, false, false, 0);
+ iconClean = new HoverImageButton (IconSize.Menu, Gtk.Stock.Clear);
+ box.PackStart (iconClean, false, false, 0);
+ box.BorderWidth = 1;
+
+ HeaderBox hbox = new HeaderBox (1,1,1,1);
+ hbox.Show ();
+ hbox.Add (box);
+ Add (hbox);
+
+ ModifyBg (StateType.Normal, entry.Style.Base (StateType.Normal));
+ iconClean.ModifyBg (StateType.Normal, entry.Style.Base (StateType.Normal));
+ iconFind.ModifyBg (StateType.Normal, entry.Style.Base (StateType.Normal));
+
+ iconClean.BorderWidth = 1;
+ iconClean.CanFocus = false;
+ iconFind.BorderWidth = 1;
+ iconFind.CanFocus = false;
+
+ iconClean.Clicked += delegate {
+ entry.Text = string.Empty;
+ };
+
+ iconFind.Clicked += delegate {
+ FireSearch ();
+ };
+
+ entry.Activated += delegate {
+ FireSearch ();
+ };
+
+ ShowAll ();
+ UpdateIcon ();
+
+ entry.Changed += delegate {
+ UpdateIcon ();
+ FireSearch ();
+ };
+ }
+
+ public event EventHandler TextChanged;
+
+ public Gtk.Entry Entry {
+ get {
+ return this.entry;
+ }
+ set {
+ entry = value;
+ }
+ }
+
+ public string Text {
+ get { return entry.Text; }
+ }
+
+ void UpdateIcon ()
+ {
+ if (entry.Text.Length > 0) {
+ iconFind.Hide ();
+ iconClean.Show ();
+ }
+ else {
+ iconFind.Show ();
+ iconClean.Hide ();
+ }
+ }
+
+ void FireSearch ()
+ {
+ if (!notifying) {
+ notifying = true;
+ GLib.Timeout.Add (notifyDelay, delegate {
+ notifying = false;
+ if (TextChanged != null)
+ TextChanged (this, EventArgs.Empty);
+ return false;
+ });
+ }
+ }
+ }
+}
diff --git a/Mono.Addins.GuiGtk3/Mono.Addins.Gui/Services.cs b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/Services.cs
new file mode 100644
index 0000000..24d4d9f
--- /dev/null
+++ b/Mono.Addins.GuiGtk3/Mono.Addins.Gui/Services.cs
@@ -0,0 +1,152 @@
+//
+// Services.cs
+//
+// Author:
+// Lluis Sanchez Gual
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// 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;
+using Mono.Unix;
+using Mono.Addins.Setup;
+using Mono.Addins.Description;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace Mono.Addins.GuiGtk3
+{
+ internal class Services
+ {
+ public static bool InApplicationNamespace (SetupService service, string id)
+ {
+ return service.ApplicationNamespace == null || id.StartsWith (service.ApplicationNamespace + ".");
+ }
+
+ public static bool AskQuestion (string question)
+ {
+ MessageDialog md = new MessageDialog (null, DialogFlags.Modal | DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.YesNo, question);
+ try {
+ int response = md.Run ();
+ return ((ResponseType) response == ResponseType.Yes);
+ } finally {
+ md.Destroy ();
+ }
+ }
+
+ public static void ShowError (Exception ex, string message, Window parent, bool modal)
+ {
+ ErrorDialog dlg = new ErrorDialog (parent);
+
+ if (message == null) {
+ if (ex != null)
+ dlg.Message = string.Format (Catalog.GetString ("Exception occurred: {0}"), ex.Message);
+ else {
+ dlg.Message = "An unknown error occurred";
+ dlg.AddDetails (Environment.StackTrace, false);
+ }
+ } else
+ dlg.Message = message;
+
+ if (ex != null) {
+ dlg.AddDetails (string.Format (Catalog.GetString ("Exception occurred: {0}"), ex.Message) + "\n\n", true);
+ dlg.AddDetails (ex.ToString (), false);
+ }
+
+ if (modal) {
+ dlg.Run ();
+ dlg.Destroy ();
+ } else
+ dlg.Show ();
+ }
+
+ public struct MissingDepInfo
+ {
+ public string Addin;
+ public string Required;
+ public string Found;
+ }
+
+ public static IEnumerable<MissingDepInfo> GetMissingDependencies (Addin addin)
+ {
+ IEnumerable<Addin> allAddins = AddinManager.Registry.GetAddins ().Union (AddinManager.Registry.GetAddinRoots ());
+ foreach (var dep in addin.Description.MainModule.Dependencies) {
+ AddinDependency adep = dep as AddinDependency;
+ if (adep != null) {
+ if (!allAddins.Any (a => Addin.GetIdName (a.Id) == Addin.GetIdName (adep.FullAddinId) && a.SupportsVersion (adep.Version))) {
+ Addin found = allAddins.FirstOrDefault (a => Addin.GetIdName (a.Id) == Addin.GetIdName (adep.FullAddinId));
+ yield return new MissingDepInfo () { Addin = Addin.GetIdName (adep.FullAddinId), Required = adep.Version, Found = found != null ? found.Version : null };
+ }
+ }
+ }
+ }
+
+ public static Gdk.Pixbuf AddIconOverlay (Gdk.Pixbuf target, Gdk.Pixbuf overlay)
+ {
+ Gdk.Pixbuf res = new Gdk.Pixbuf (target.Colorspace, target.HasAlpha, target.BitsPerSample, target.Width, target.Height);
+ res.Fill (0);
+ target.CopyArea (0, 0, target.Width, target.Height, res, 0, 0);
+ overlay.Composite (res, 0, 0, overlay.Width, overlay.Height, 0, 0, 1, 1, Gdk.InterpType.Bilinear, 255);
+ return res;
+ }
+
+ public static Gdk.Pixbuf DesaturateIcon (Gdk.Pixbuf source)
+ {
+ Gdk.Pixbuf dest = new Gdk.Pixbuf (source.Colorspace, source.HasAlpha, source.BitsPerSample, source.Width, source.Height);
+ dest.Fill (0);
+ source.SaturateAndPixelate (dest, 0, false);
+ return dest;
+ }
+
+ public static Gdk.Pixbuf FadeIcon (Gdk.Pixbuf source)
+ {
+ Gdk.Pixbuf result = source.Copy ();
+ result.Fill (0);
+ result = result.AddAlpha (true, 0, 0, 0);
+ source.Composite (result, 0, 0, source.Width, source.Height, 0, 0, 1, 1, Gdk.InterpType.Bilinear, 128);
+ return result;
+ }
+
+// /// <summary>
+// /// Positions a dialog relative to its parent on platforms where default placement is known to be poor.
+// /// </summary>
+// public static void PlaceDialog (Window child, Window parent)
+// {
+// CenterWindow (child, parent);
+// }
+//
+// /// <summary>Centers a window relative to its parent.</summary>
+// static void CenterWindow (Window child, Window parent)
+// {
+// child.Child.Show ();
+// int w, h, winw, winh, x, y, winx, winy;
+// child.GetSize (out w, out h);
+// parent.GetSize (out winw, out winh);
+// parent.GetPosition (out winx, out winy);
+// x = System.Math.Max (0, (winw - w) /2) + winx;
+// y = System.Math.Max (0, (winh - h) /2) + winy;
+// child.Move (x, y);
+// }
+ }
+}