[geary/wip/713739-inline: 4/37] Allow only a single inline composition at a time



commit 7b86131da2264c6212910b7914fa9e003a2c6b96
Author: Robert Schroll <rschroll gmail com>
Date:   Sat May 25 01:56:35 2013 -0400

    Allow only a single inline composition at a time
    
    With this, we introduce a dialog when you would try to add another.  We
    also use this when changing the selected conversation with a composer
    open.

 src/client/components/main-window.vala             |    2 +
 src/client/composer/composer-embed.vala            |  119 +++++++++++++-------
 src/client/composer/composer-widget.vala           |    4 +-
 .../conversation-list/conversation-list-view.vala  |    4 +
 src/client/dialogs/alert-dialog.vala               |    4 +-
 5 files changed, 86 insertions(+), 47 deletions(-)
---
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index b42162b..2433895 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -18,6 +18,7 @@ public class MainWindow : Gtk.ApplicationWindow {
     public ConversationListView conversation_list_view  { get; private set; }
     public ConversationViewer conversation_viewer { get; private set; default = new ConversationViewer(); }
     public StatusBar status_bar { get; private set; default = new StatusBar(); }
+    public ComposerEmbed composer_embed { get; private set; }
     
     public int window_width { get; set; }
     public int window_height { get; set; }
@@ -38,6 +39,7 @@ public class MainWindow : Gtk.ApplicationWindow {
         title = GearyApplication.NAME;
         
         conversation_list_view = new ConversationListView(conversation_list_store);
+        composer_embed = new ComposerEmbed(conversation_viewer);
         
         add_events(Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.KEY_RELEASE_MASK
             | Gdk.EventMask.FOCUS_CHANGE_MASK);
diff --git a/src/client/composer/composer-embed.vala b/src/client/composer/composer-embed.vala
index 3d78e6d..ee3377c 100644
--- a/src/client/composer/composer-embed.vala
+++ b/src/client/composer/composer-embed.vala
@@ -6,51 +6,18 @@
 
 public class ComposerEmbed : Gtk.Box, ComposerContainer {
     
-    public ulong signal_id;
-    private string embed_id;
-    private ComposerWidget composer;
+    private static string embed_id = "composer_embed";
+    
+    private ComposerWidget? composer = null;
+    private ConversationViewer conversation_viewer;
     
     public Gtk.Window top_window {
         get { return (Gtk.Window) get_toplevel(); }
     }
     
-    private static ConversationViewer conversation_viewer {
-        get { return GearyApplication.instance.controller.main_window.conversation_viewer; }
-    }
-    
-    public static bool create_embed(ComposerWidget composer, Geary.Email? referred) {
-        if (referred == null)
-            return false;
-        
-        WebKit.DOM.HTMLElement? email_element = conversation_viewer.web_view.get_dom_document()
-            .get_element_by_id(conversation_viewer.get_div_id(referred.id)) as WebKit.DOM.HTMLElement;
-        if (email_element == null)
-            return false;
-        
-        string id = "%x".printf(Random.next_int());
-        ComposerEmbed plugin = new ComposerEmbed(id);
-        plugin.signal_id = conversation_viewer.web_view.create_plugin_widget.connect(() => {
-            conversation_viewer.web_view.disconnect(plugin.signal_id);
-            return plugin;
-        });
-        
-        try {
-            conversation_viewer.web_view.settings.enable_plugins = true;
-            email_element.insert_adjacent_html("afterend",
-                @"<embed width='100%' height='600' type='composer' id='$id' />");
-        } catch (Error error) {
-            debug("Error creating embed element: %s", error.message);
-            return false;
-        } finally {
-            conversation_viewer.web_view.settings.enable_plugins = false;
-        }
-        plugin.insert_composer(composer);
-        return true;
-    }
-    
-    public ComposerEmbed(string embed_id) {
+    public ComposerEmbed(ConversationViewer conversation_viewer) {
         Object(orientation: Gtk.Orientation.VERTICAL);
-        this.embed_id = embed_id;
+        this.conversation_viewer = conversation_viewer;
         
         Gtk.Toolbar toolbar = new Gtk.Toolbar();
         toolbar.set_icon_size(Gtk.IconSize.MENU);
@@ -66,12 +33,68 @@ public class ComposerEmbed : Gtk.Box, ComposerContainer {
         
         close.clicked.connect(on_close);
         detach.clicked.connect(on_detach);
+        conversation_viewer.web_view.create_plugin_widget.connect(on_plugin_requested);
     }
     
-    private void insert_composer(ComposerWidget composer) {
-        pack_start(composer, true, true);
+    public void new_composer(ComposerWidget new_composer, Geary.Email? referred) {
+        if (!abandon_existing_composition(new_composer))
+            return;
+        
+        WebKit.DOM.HTMLElement? email_element = null;
+        if (referred != null)
+            email_element = conversation_viewer.web_view.get_dom_document().get_element_by_id(
+                conversation_viewer.get_div_id(referred.id)) as WebKit.DOM.HTMLElement;
+        if (email_element == null) {
+            // TODO: clear conversation list selection and put in alone
+            new ComposerWindow(new_composer);
+            return;
+        }
+        
+        try {
+            conversation_viewer.web_view.settings.enable_plugins = true;
+            email_element.insert_adjacent_html("afterend",
+                @"<embed width='100%' height='600' type='composer' id='$embed_id' />");
+        } catch (Error error) {
+            debug("Error creating embed element: %s", error.message);
+            return;
+        } finally {
+            conversation_viewer.web_view.settings.enable_plugins = false;
+        }
+        pack_start(new_composer, true, true);
         show_all();
-        this.composer = composer;
+        present();
+        this.composer = new_composer;
+    }
+    
+    public bool abandon_existing_composition(ComposerWidget? new_composer = null) {
+        if (composer == null)
+            return true;
+        
+        present();
+        AlertDialog dialog;
+        if (new_composer != null)
+            dialog = new AlertDialog(top_window, Gtk.MessageType.QUESTION,
+                _("Do you want to discard the existing composition?"), null, Gtk.Stock.DISCARD,
+                Gtk.Stock.CANCEL, _("Open New Composition Window"), Gtk.ResponseType.YES);
+        else
+            dialog = new AlertDialog(top_window, Gtk.MessageType.QUESTION,
+                _("Do you want to discard the existing composition?"), null, Gtk.Stock.DISCARD,
+                Gtk.Stock.CANCEL, _("Move Composition to New Window"), Gtk.ResponseType.YES);
+        Gtk.ResponseType response = dialog.run();
+        if (response == Gtk.ResponseType.OK) {
+            close();
+            return true;
+        }
+        if (new_composer != null) {
+            if (response == Gtk.ResponseType.YES)
+                new ComposerWindow(new_composer);
+            else
+                new_composer.destroy();
+        } else if (response == Gtk.ResponseType.YES) {
+            on_detach();
+            return true;
+        }
+        return false;
     }
     
     private void on_close() {
@@ -82,9 +105,14 @@ public class ComposerEmbed : Gtk.Box, ComposerContainer {
     private void on_detach() {
         remove(composer);
         new ComposerWindow(composer);
+        composer = null;
         close();
     }
     
+    private Gtk.Widget on_plugin_requested() {
+        return this;
+    }
+    
     public void present() {
         conversation_viewer.web_view.get_dom_document().get_element_by_id(embed_id).scroll_into_view(true);
     }
@@ -94,13 +122,18 @@ public class ComposerEmbed : Gtk.Box, ComposerContainer {
     }
     
     private void close() {
+        if (composer != null) {
+            remove(composer);
+            composer.destroy();
+            composer = null;
+        }
+        
         WebKit.DOM.Element embed = 
conversation_viewer.web_view.get_dom_document().get_element_by_id(embed_id);
         try{
             embed.parent_element.remove_child(embed);
         } catch (Error error) {
             warning("Could not remove embed from WebView: %s", error.message);
         }
-        destroy();  // We seem to need this to ensure the ComposerWidget is destroyed.
     }
 }
 
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index 5fabb71..d493956 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -461,8 +461,8 @@ public class ComposerWidget : Gtk.EventBox {
         if (!from_multiple.visible)
             open_drafts_folder_async.begin(cancellable_drafts);
         
-        if (!ComposerEmbed.create_embed(this, referred))
-            new ComposerWindow(this);
+        ((MainWindow) GearyApplication.instance.controller.main_window).composer_embed.
+            new_composer(this, referred);
     }
     
     public ComposerWidget.from_mailto(Geary.Account account, string mailto) {
diff --git a/src/client/conversation-list/conversation-list-view.vala 
b/src/client/conversation-list/conversation-list-view.vala
index 1d5c0de..138762f 100644
--- a/src/client/conversation-list/conversation-list-view.vala
+++ b/src/client/conversation-list/conversation-list-view.vala
@@ -203,6 +203,10 @@ public class ConversationListView : Gtk.TreeView {
             }
         }
         
+        if (!get_selection().path_is_selected(path) && !((MainWindow) GearyApplication.
+            instance.controller.main_window).composer_embed.abandon_existing_composition())
+            return true;
+        
         if (event.button == 3 && event.type == Gdk.EventType.BUTTON_PRESS) {
             Geary.App.Conversation conversation = conversation_list_store.get_conversation_at_path(path);
             
diff --git a/src/client/dialogs/alert-dialog.vala b/src/client/dialogs/alert-dialog.vala
index a9b88b5..1675d38 100644
--- a/src/client/dialogs/alert-dialog.vala
+++ b/src/client/dialogs/alert-dialog.vala
@@ -4,10 +4,10 @@
  * (version 2.1 or later).  See the COPYING file in this distribution.
  */
 
-abstract class AlertDialog : Object {
+class AlertDialog : Object {
     private Gtk.MessageDialog dialog;
     
-    protected AlertDialog(Gtk.Window? parent, Gtk.MessageType message_type, string primary, string? 
secondary,
+    public AlertDialog(Gtk.Window? parent, Gtk.MessageType message_type, string primary, string? secondary,
         string? ok_button, string? cancel_button, string? tertiary_button,
         Gtk.ResponseType tertiary_response_type) {
         dialog = new Gtk.MessageDialog(parent, Gtk.DialogFlags.DESTROY_WITH_PARENT, message_type,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]