diff --git a/Greenshot/Destinations/PickerDestination.cs b/Greenshot/Destinations/PickerDestination.cs index bda6cb7df..9ccf8477b 100644 --- a/Greenshot/Destinations/PickerDestination.cs +++ b/Greenshot/Destinations/PickerDestination.cs @@ -34,7 +34,7 @@ using GreenshotPlugin.UnmanagedHelpers; namespace Greenshot.Destinations { /// - /// Description of PickerDestination. + /// The PickerDestination shows a context menu with all possible destinations, so the user can "pick" one /// public class PickerDestination : AbstractDestination { private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(PickerDestination)); @@ -59,6 +59,14 @@ namespace Greenshot.Destinations { } } + /// + /// This method will create the destination picker menu + /// + /// Boolean if the dynamic values also need to be added + /// The surface which can be exported + /// Details for the surface + /// The list of destinations to show + /// public static ContextMenuStrip CreatePickerMenu(bool addDynamics, ISurface surface, ICaptureDetails captureDetails, IEnumerable destinations) { ContextMenuStrip menu = new ContextMenuStrip(); menu.Closing += delegate(object source, ToolStripDropDownClosingEventArgs eventArgs) { @@ -106,7 +114,8 @@ namespace Greenshot.Destinations { } } else { LOG.Info("Export failed, showing menu again"); - menu.Show(); + // This prevents the problem that the context menu shows in the task-bar + ShowMenuAtCursor(menu); } } ); @@ -129,6 +138,10 @@ namespace Greenshot.Destinations { return menu; } + /// + /// This method will show the supplied context menu at the mouse cursor, also makes sure it has focus and it's not visible in the taskbar. + /// + /// public static void ShowMenuAtCursor(ContextMenuStrip menu) { // find a suitable location Point location = Cursor.Position; @@ -146,6 +159,13 @@ namespace Greenshot.Destinations { menu.Focus(); } + /// + /// Export the capture with the destination picker + /// + /// Did the user select this destination? + /// Surface to export + /// Details of the capture + /// true if export was made public override bool ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { List destinations = new List(); foreach(IDestination destination in DestinationHelper.GetAllDestinations()) { diff --git a/Greenshot/Forms/MainForm.Designer.cs b/Greenshot/Forms/MainForm.Designer.cs index 87944b7cf..f74247495 100644 --- a/Greenshot/Forms/MainForm.Designer.cs +++ b/Greenshot/Forms/MainForm.Designer.cs @@ -52,7 +52,7 @@ namespace Greenshot { this.contextmenu_capturewindow = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); this.contextmenu_capturefullscreen = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); this.contextmenu_captureie = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); - this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripPluginSeparator = new System.Windows.Forms.ToolStripSeparator(); this.contextmenu_captureclipboard = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); this.contextmenu_openfile = new GreenshotPlugin.Controls.GreenshotToolStripMenuItem(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); @@ -79,7 +79,7 @@ namespace Greenshot { this.contextmenu_capturewindow, this.contextmenu_capturefullscreen, this.contextmenu_captureie, - this.toolStripSeparator4, + this.toolStripPluginSeparator, this.contextmenu_captureclipboard, this.contextmenu_openfile, this.toolStripSeparator2, @@ -134,10 +134,11 @@ namespace Greenshot { this.contextmenu_captureie.Size = new System.Drawing.Size(308, 22); this.contextmenu_captureie.DropDownOpening += new System.EventHandler(this.CaptureIEMenuDropDownOpening); // - // toolStripSeparator4 + // toolStripPluginSeparator // - this.toolStripSeparator4.Name = "toolStripSeparator4"; - this.toolStripSeparator4.Size = new System.Drawing.Size(305, 6); + this.toolStripPluginSeparator.Name = "toolStripSeparator4"; + this.toolStripPluginSeparator.Size = new System.Drawing.Size(305, 6); + this.toolStripPluginSeparator.Tag = "PluginsAreAddedBefore"; // // contextmenu_captureclipboard // @@ -251,7 +252,7 @@ namespace Greenshot { private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_captureie; private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_donate; private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_openfile; - private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripSeparator toolStripPluginSeparator; private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_captureclipboard; private GreenshotPlugin.Controls.GreenshotToolStripMenuItem contextmenu_quicksettings; private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; diff --git a/GreenshotImgurPlugin/Forms/ImgurHistory.cs b/GreenshotImgurPlugin/Forms/ImgurHistory.cs index 9ca25f91d..b795b6adc 100644 --- a/GreenshotImgurPlugin/Forms/ImgurHistory.cs +++ b/GreenshotImgurPlugin/Forms/ImgurHistory.cs @@ -121,7 +121,7 @@ namespace GreenshotImgurPlugin { // Should fix Bug #3378699 pictureBox1.Image = pictureBox1.ErrorImage; try { - new PleaseWaitForm().ShowAndWait(ImgurPlugin.Attributes.Name, Language.GetString("imgur", LangKey.communication_wait), Language.GetString("CANCEL"), + new PleaseWaitForm().ShowAndWait(ImgurPlugin.Attributes.Name, Language.GetString("imgur", LangKey.communication_wait), delegate() { ImgurUtils.DeleteImgurImage(imgurInfo); } diff --git a/GreenshotImgurPlugin/ImgurConfiguration.cs b/GreenshotImgurPlugin/ImgurConfiguration.cs index 4873f18f3..23e140e07 100644 --- a/GreenshotImgurPlugin/ImgurConfiguration.cs +++ b/GreenshotImgurPlugin/ImgurConfiguration.cs @@ -69,7 +69,7 @@ namespace GreenshotImgurPlugin { public bool ShowConfigDialog() { SettingsForm settingsForm = null; - new PleaseWaitForm().ShowAndWait(ImgurPlugin.Attributes.Name, Language.GetString("imgur", LangKey.communication_wait), Language.GetString("CANCEL"), + new PleaseWaitForm().ShowAndWait(ImgurPlugin.Attributes.Name, Language.GetString("imgur", LangKey.communication_wait), delegate() { settingsForm = new SettingsForm(this); } diff --git a/GreenshotImgurPlugin/ImgurPlugin.cs b/GreenshotImgurPlugin/ImgurPlugin.cs index a541936dc..f76efe454 100644 --- a/GreenshotImgurPlugin/ImgurPlugin.cs +++ b/GreenshotImgurPlugin/ImgurPlugin.cs @@ -145,7 +145,7 @@ namespace GreenshotImgurPlugin { ImgurInfo imgurInfo = null; // Run upload in the background - new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("imgur", LangKey.communication_wait), Language.GetString("CANCEL"), + new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("imgur", LangKey.communication_wait), delegate() { imgurInfo = ImgurUtils.UploadToImgur(stream.GetBuffer(), (int)stream.Length, captureDetails.Title, filename); LOG.InfoFormat("Storing imgur upload for hash {0} and delete hash {1}", imgurInfo.Hash, imgurInfo.DeleteHash); diff --git a/GreenshotJiraPlugin/Forms/JiraForm.cs b/GreenshotJiraPlugin/Forms/JiraForm.cs index 6abca8b91..17404e7da 100644 --- a/GreenshotJiraPlugin/Forms/JiraForm.cs +++ b/GreenshotJiraPlugin/Forms/JiraForm.cs @@ -128,40 +128,41 @@ namespace GreenshotJiraPlugin { private void jiraFilterBox_SelectedIndexChanged(object sender, EventArgs e) { if (jiraConnector.isLoggedIn) { - BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait)); - try { - uploadButton.Enabled = false; - JiraFilter filter = (JiraFilter)jiraFilterBox.SelectedItem; - if (filter == null) { - return; - } - JiraIssue[] issues = jiraConnector.getIssuesForFilter(filter.Id); - jiraListView.BeginUpdate(); - jiraListView.Items.Clear(); - if (issues.Length > 0) { - jiraListView.Columns.Clear(); - LangKey[] columns = { LangKey.column_id, LangKey.column_created, LangKey.column_assignee, LangKey.column_reporter, LangKey.column_summary }; - foreach (LangKey column in columns) { - jiraListView.Columns.Add(Language.GetString("jira", column)); - } - foreach (JiraIssue issue in issues) { - ListViewItem item = new ListViewItem(issue.Key); - item.Tag = issue; - item.SubItems.Add(issue.Created.Value.ToString("d", DateTimeFormatInfo.InvariantInfo)); - item.SubItems.Add(issue.Assignee); - item.SubItems.Add(issue.Reporter); - item.SubItems.Add(issue.Summary); - jiraListView.Items.Add(item); - } - for (int i = 0; i < columns.Length; i++) { - jiraListView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent); - } - } - jiraListView.EndUpdate(); - jiraListView.Refresh(); - } finally { - backgroundForm.CloseDialog(); + JiraIssue[] issues = null; + uploadButton.Enabled = false; + JiraFilter filter = (JiraFilter)jiraFilterBox.SelectedItem; + if (filter == null) { + return; } + // Run upload in the background + new PleaseWaitForm().ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait), + delegate() { + issues = jiraConnector.getIssuesForFilter(filter.Id); + } + ); + jiraListView.BeginUpdate(); + jiraListView.Items.Clear(); + if (issues.Length > 0) { + jiraListView.Columns.Clear(); + LangKey[] columns = { LangKey.column_id, LangKey.column_created, LangKey.column_assignee, LangKey.column_reporter, LangKey.column_summary }; + foreach (LangKey column in columns) { + jiraListView.Columns.Add(Language.GetString("jira", column)); + } + foreach (JiraIssue issue in issues) { + ListViewItem item = new ListViewItem(issue.Key); + item.Tag = issue; + item.SubItems.Add(issue.Created.Value.ToString("d", DateTimeFormatInfo.InvariantInfo)); + item.SubItems.Add(issue.Assignee); + item.SubItems.Add(issue.Reporter); + item.SubItems.Add(issue.Summary); + jiraListView.Items.Add(item); + } + for (int i = 0; i < columns.Length; i++) { + jiraListView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent); + } + } + jiraListView.EndUpdate(); + jiraListView.Refresh(); } } diff --git a/GreenshotJiraPlugin/Jira.cs b/GreenshotJiraPlugin/Jira.cs index 100a79e22..94e0e805a 100644 --- a/GreenshotJiraPlugin/Jira.cs +++ b/GreenshotJiraPlugin/Jira.cs @@ -28,6 +28,7 @@ using GreenshotJiraPlugin; using GreenshotPlugin.Controls; using GreenshotPlugin.Core; using Greenshot.IniFile; +using System.Threading; namespace Jira { #region transport classes @@ -118,17 +119,16 @@ namespace Jira { this.url = config.Url; this.timeout = config.Timeout; if (!suppressBackgroundForm) { - BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait)); - try { - jira = new JiraSoapServiceService(); - } finally { - backgroundForm.CloseDialog(); - } + new PleaseWaitForm().ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait), + delegate() { + jira = new JiraSoapServiceService(); + } + ); } else { jira = new JiraSoapServiceService(); } jira.Url = url; - jira.Proxy = NetworkHelper.CreateProxy(new Uri(url)); + jira.Proxy = NetworkHelper.CreateProxy(new Uri(url)); } ~JiraConnector() { @@ -140,16 +140,23 @@ namespace Jira { /// /// true if login was done sucessfully private bool doLogin(string user, string password, bool suppressBackgroundForm) { - BackgroundForm backgroundForm = null; - if (!suppressBackgroundForm) { - backgroundForm = BackgroundForm.ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait)); - } - try { + + // This is what needs to be done + ThreadStart jiraLogin = delegate { LOG.DebugFormat("Loggin in"); this.credentials = jira.login(user, password); LOG.DebugFormat("Logged in"); this.loggedInTime = DateTime.Now; this.loggedIn = true; + + }; + // Here we do it + try { + if (!suppressBackgroundForm) { + new PleaseWaitForm().ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait), jiraLogin); + } else { + jiraLogin.Invoke(); + } } catch (Exception e) { // check if auth failed if (e.Message.Contains(AUTH_FAILED_EXCEPTION_NAME)) { @@ -161,10 +168,6 @@ namespace Jira { e.Data.Add("user", user); e.Data.Add("url", url); throw; - } finally { - if (backgroundForm != null) { - backgroundForm.CloseDialog(); - } } return true; } @@ -177,7 +180,7 @@ namespace Jira { try { // Get the system name, so the user knows where to login to string systemName = url.Replace(DEFAULT_POSTFIX,""); - CredentialsDialog dialog = new CredentialsDialog(systemName); + CredentialsDialog dialog = new CredentialsDialog(systemName); dialog.Name = null; while (dialog.Show(dialog.Name) == DialogResult.OK) { if (doLogin(dialog.Name, dialog.Password, suppressBackgroundForm)) { @@ -301,7 +304,7 @@ namespace Jira { jira.addAttachmentsToIssue(credentials, issueKey, new string[] { filename }, (sbyte[]) (Array)buffer); } catch (Exception ex2) { LOG.WarnFormat("Failed to use alternative method, error was: {0}", ex2.Message); - throw ex2; + throw ex2; } } } diff --git a/GreenshotJiraPlugin/JiraDestination.cs b/GreenshotJiraPlugin/JiraDestination.cs index c6f429177..2dbfdc8a8 100644 --- a/GreenshotJiraPlugin/JiraDestination.cs +++ b/GreenshotJiraPlugin/JiraDestination.cs @@ -113,17 +113,19 @@ namespace GreenshotJiraPlugin { // COPY stream to buffer buffer = stream.ToArray(); } - BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait)); try { - jiraPlugin.JiraConnector.addAttachment(jira.Key, filename, buffer); + // Run upload in the background + new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait), + delegate() { + jiraPlugin.JiraConnector.addAttachment(jira.Key, filename, buffer); + } + ); LOG.Debug("Uploaded to Jira."); - backgroundForm.CloseDialog(); surface.UploadURL = jiraPlugin.JiraConnector.getURL(jira.Key); surface.SendMessageEvent(this, SurfaceMessageTyp.UploadedUrl, Language.GetFormattedString("exported_to", FormatUpload(jira))); surface.Modified = false; return true; } catch (Exception e) { - backgroundForm.CloseDialog(); MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message); } } else { @@ -140,17 +142,19 @@ namespace GreenshotJiraPlugin { // COPY stream to buffer buffer = stream.ToArray(); } - BackgroundForm backgroundForm = BackgroundForm.ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait)); try { - jiraForm.upload(buffer); + // Run upload in the background + new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait), + delegate() { + jiraForm.upload(buffer); + } + ); LOG.Debug("Uploaded to Jira."); - backgroundForm.CloseDialog(); surface.UploadURL = jiraPlugin.JiraConnector.getURL(jiraForm.getJiraIssue().Key); surface.SendMessageEvent(this, SurfaceMessageTyp.UploadedUrl, Language.GetFormattedString("exported_to", FormatUpload(jiraForm.getJiraIssue()))); surface.Modified = false; return true; } catch(Exception e) { - backgroundForm.CloseDialog(); MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message); } } diff --git a/GreenshotPlugin/Controls/PleaseWaitForm.cs b/GreenshotPlugin/Controls/PleaseWaitForm.cs index 049b52238..e962c7e0f 100644 --- a/GreenshotPlugin/Controls/PleaseWaitForm.cs +++ b/GreenshotPlugin/Controls/PleaseWaitForm.cs @@ -22,6 +22,7 @@ using System; using System.Drawing; using System.Windows.Forms; using System.Threading; +using GreenshotPlugin.Core; namespace GreenshotPlugin.Controls { /// @@ -40,7 +41,7 @@ namespace GreenshotPlugin.Controls { } /// - /// Prevent the close button showing + /// Prevent the close-window button showing /// private const int CP_NOCLOSE_BUTTON = 0x200; protected override CreateParams CreateParams { @@ -51,17 +52,26 @@ namespace GreenshotPlugin.Controls { } } - public void ShowAndWait(string title, string text, string cancelText, ThreadStart waitDelegate) { + /// + /// Show the "please wait" form, execute the code from the delegate and wait until execution finishes. + /// The supplied delegate will be wrapped with a try/catch so this method can return any exception that was thrown. + /// + /// The title of the form (and Thread) + /// The text in the form + /// delegate { with your code } + public void ShowAndWait(string title, string text, ThreadStart waitDelegate) { this.title = title; this.Text = title; this.label_pleasewait.Text = text; - this.cancelButton.Text = cancelText; + this.cancelButton.Text = Language.GetString("CANCEL"); + // Make sure the form is shown. Show(); + // Variable to store the exception, if one is generated, from inside the thread. Exception threadException = null; try { - // Wrap the passed delegate in a try/catch which saves the exception + // Wrap the passed delegate in a try/catch which makes it possible to save the exception waitFor = new Thread(new ThreadStart( delegate { try { @@ -93,6 +103,11 @@ namespace GreenshotPlugin.Controls { } } + /// + /// Called if the cancel button is clicked, will use Thread.Abort() + /// + /// + /// void CancelButtonClick(object sender, EventArgs e) { LOG.DebugFormat("Cancel clicked on {0}", title); cancelButton.Enabled = false; diff --git a/GreenshotPlugin/Core/PluginUtils.cs b/GreenshotPlugin/Core/PluginUtils.cs index 39bcc1a60..ff9f93db4 100644 --- a/GreenshotPlugin/Core/PluginUtils.cs +++ b/GreenshotPlugin/Core/PluginUtils.cs @@ -90,7 +90,7 @@ namespace GreenshotPlugin.Core { } } /// - /// Helper method to add a MenuItem to the Greenshot context menu + /// Helper method to add a plugin MenuItem to the Greenshot context menu /// /// /// @@ -102,8 +102,17 @@ namespace GreenshotPlugin.Core { // Try to find a separator, so we insert ourselves after it for(int i=0; i < contextMenu.Items.Count; i++) { if (contextMenu.Items[i].GetType() == typeof(ToolStripSeparator)) { - contextMenu.Items.Insert(i+1, item); - addedItem = true; + // Check if we need to add a new separator, which is done if the first found has a Tag with the value "PluginsAreAddedBefore" + if ("PluginsAreAddedBefore".Equals(contextMenu.Items[i].Tag)) { + ToolStripSeparator separator = new ToolStripSeparator(); + separator.Size = new Size(305, 6); + contextMenu.Items.Insert(i, separator); + contextMenu.Items.Insert(i+1, item); + addedItem = true; + } else { + contextMenu.Items.Insert(i+1, item); + addedItem = true; + } break; } }