[ekiga/ds-gtk-application] Forms: Added allow_empty parameter to Text Form properties.



commit 9d4950bd3322e19c1eb15e2a241c96c01a69f114
Author: Damien Sandras <dsandras seconix com>
Date:   Mon Oct 6 20:21:36 2014 +0200

    Forms: Added allow_empty parameter to Text Form properties.
    
    It allows defining Forms where some Text entries can not be empty. The
    user will be prevented form validating the Form until the corresponding
    Form text entries have been filled with some text.
    
    It becomes unnecessary to do the check in the callback (and to report an
    error in case of problem).
    
    It has been implemented because HIG3 suggests preventing the user to
    validate incorrect data (when possible).

 lib/engine/components/opal/opal-presentity.cpp |   10 ++--
 lib/engine/framework/form-builder.cpp          |   16 ++++--
 lib/engine/framework/form-builder.h            |   17 +++++--
 lib/engine/framework/form-dumper.cpp           |    8 ++-
 lib/engine/framework/form-dumper.h             |    6 ++-
 lib/engine/framework/form-visitor.h            |    6 ++-
 lib/engine/gui/gtk-core/form-dialog-gtk.cpp    |   63 +++++++++++++++++++++---
 lib/engine/gui/gtk-core/form-dialog-gtk.h      |    6 ++-
 8 files changed, 102 insertions(+), 30 deletions(-)
---
diff --git a/lib/engine/components/opal/opal-presentity.cpp b/lib/engine/components/opal/opal-presentity.cpp
index 6bafae2..dfea858 100644
--- a/lib/engine/components/opal/opal-presentity.cpp
+++ b/lib/engine/components/opal/opal-presentity.cpp
@@ -263,10 +263,12 @@ Opal::Presentity::edit_presentity ()
   g_free (title);
 
   request->action (_("Done"));
-  request->text ("name", _("Name"), get_name (),
-                 _("John Doe"));
-  request->text ("uri", _("URI"), get_uri (),
-                 _("sip:username ekiga net"));
+  request->text ("name", _("Name"),
+                 get_name (),
+                 _("John Doe"), false, false);
+  request->text ("uri", _("URI"),
+                 get_uri (),
+                 _("sip:username ekiga net"), false, false);
 
   request->editable_list ("groups", _("Groups"),
                         get_groups (), existing_groups ());
diff --git a/lib/engine/framework/form-builder.cpp b/lib/engine/framework/form-builder.cpp
index 87800db..91d7225 100644
--- a/lib/engine/framework/form-builder.cpp
+++ b/lib/engine/framework/form-builder.cpp
@@ -83,7 +83,8 @@ Ekiga::FormBuilder::visit (Ekiga::FormVisitor &visitor) const
     case TEXT:
 
       visitor.text (iter_text->name, iter_text->description,
-               iter_text->value, iter_text->tooltip, iter_text->advanced);
+                    iter_text->value, iter_text->tooltip,
+                    iter_text->advanced, iter_text->allow_empty);
       iter_text++;
       break;
 
@@ -93,7 +94,8 @@ Ekiga::FormBuilder::visit (Ekiga::FormVisitor &visitor) const
                            iter_private_text->description,
                            iter_private_text->value,
                            iter_private_text->tooltip,
-                           iter_private_text->advanced);
+                           iter_private_text->advanced,
+                           iter_private_text->allow_empty);
       iter_private_text++;
       break;
 
@@ -294,9 +296,10 @@ Ekiga::FormBuilder::text (const std::string name,
                          const std::string description,
                          const std::string value,
                          const std::string tooltip,
-                         bool advanced)
+                         bool advanced,
+                          bool allow_empty)
 {
-  texts.push_back (TextField (name, description, value, tooltip, advanced));
+  texts.push_back (TextField (name, description, value, tooltip, advanced, allow_empty));
   ordering.push_back (TEXT);
 }
 
@@ -305,9 +308,10 @@ Ekiga::FormBuilder::private_text (const std::string name,
                                  const std::string description,
                                  const std::string value,
                                  const std::string tooltip,
-                                 bool advanced)
+                                  bool advanced,
+                                  bool allow_empty)
 {
-  private_texts.push_back (TextField (name, description, value, tooltip, advanced));
+  private_texts.push_back (TextField (name, description, value, tooltip, advanced, allow_empty));
   ordering.push_back (PRIVATE_TEXT);
 }
 
diff --git a/lib/engine/framework/form-builder.h b/lib/engine/framework/form-builder.h
index 322dd48..8c1cb3f 100644
--- a/lib/engine/framework/form-builder.h
+++ b/lib/engine/framework/form-builder.h
@@ -99,13 +99,15 @@ namespace Ekiga
               const std::string description,
               const std::string value,
               const std::string tooltip,
-              bool advanced = false);
+              bool advanced = false,
+               bool allow_empty = true);
 
     void private_text (const std::string text,
                       const std::string description,
                       const std::string value,
                       const std::string tooltip,
-                      bool advanced = false);
+                       bool advanced = false,
+                       bool allow_empty = true);
 
     void multi_text (const std::string text,
                     const std::string description,
@@ -165,9 +167,13 @@ namespace Ekiga
                 const std::string _description,
                 const std::string _value,
                 const std::string _tooltip,
-                bool _advanced): name(_name),
-                                 description(_description),
-                  value(_value), tooltip (_tooltip), advanced(_advanced)
+                bool _advanced,
+                 bool _allow_empty): name(_name),
+                                     description(_description),
+                                     value(_value),
+                                     tooltip (_tooltip),
+                                     advanced(_advanced),
+                                     allow_empty(_allow_empty)
       {}
 
       const std::string name;
@@ -175,6 +181,7 @@ namespace Ekiga
       const std::string value;
       const std::string tooltip;
       bool advanced;
+      bool allow_empty;
     };
 
     struct MultiTextField
diff --git a/lib/engine/framework/form-dumper.cpp b/lib/engine/framework/form-dumper.cpp
index eab4937..db86d3c 100644
--- a/lib/engine/framework/form-dumper.cpp
+++ b/lib/engine/framework/form-dumper.cpp
@@ -104,12 +104,14 @@ void
 Ekiga::FormDumper::text (const std::string name,
                         const std::string description,
                         const std::string value,
-                        bool advanced)
+                        bool advanced,
+                         bool allow_empty)
 {
   out << "Text field " << name
       << " (default value: " << value << "): " << std::endl
       << description
       << (advanced?"[advanced]":"")
+      << (allow_empty?"[allow_empty]":"")
       << std::endl;
 }
 
@@ -117,12 +119,14 @@ void
 Ekiga::FormDumper::private_text (const std::string name,
                                 const std::string description,
                                 const std::string value,
-                                bool advanced)
+                                bool advanced,
+                                 bool allow_empty)
 {
   out << "Private text field " << name
       << " (default value: " << value << "): " << std::endl
       << description
       << (advanced?"[advanced]":"")
+      << (allow_empty?"[allow_empty]":"")
       << std::endl;
 }
 
diff --git a/lib/engine/framework/form-dumper.h b/lib/engine/framework/form-dumper.h
index e971987..8279aee 100644
--- a/lib/engine/framework/form-dumper.h
+++ b/lib/engine/framework/form-dumper.h
@@ -79,12 +79,14 @@ namespace Ekiga
     void text (const std::string name,
               const std::string description,
               const std::string value,
-              bool advanced);
+              bool advanced,
+               bool allow_empty);
 
     void private_text (const std::string name,
                       const std::string description,
                       const std::string value,
-                      bool advanced);
+                      bool advanced,
+                       bool allow_empty);
 
     void multi_text (const std::string name,
                     const std::string description,
diff --git a/lib/engine/framework/form-visitor.h b/lib/engine/framework/form-visitor.h
index 65549d5..0af4f83 100644
--- a/lib/engine/framework/form-visitor.h
+++ b/lib/engine/framework/form-visitor.h
@@ -78,13 +78,15 @@ namespace Ekiga
                       const std::string description,
                       const std::string value,
                       const std::string tooltip,
-                      bool advanced) = 0;
+                      bool advanced,
+                       bool allow_empty) = 0;
 
     virtual void private_text (const std::string name,
                               const std::string description,
                               const std::string tooltip,
                               const std::string value,
-                              bool advanced) = 0;
+                               bool advanced,
+                               bool allow_empty) = 0;
 
     virtual void multi_text (const std::string name,
                             const std::string description,
diff --git a/lib/engine/gui/gtk-core/form-dialog-gtk.cpp b/lib/engine/gui/gtk-core/form-dialog-gtk.cpp
index f8edd32..63a84ab 100644
--- a/lib/engine/gui/gtk-core/form-dialog-gtk.cpp
+++ b/lib/engine/gui/gtk-core/form-dialog-gtk.cpp
@@ -44,6 +44,20 @@
  * Declarations : GTK+ Callbacks
  */
 
+
+/** Called when a GtkEntry has new content.
+ *
+ * If the Form text entry does not allow empty values,
+ * the "OK" button will stay unsensitive as long as
+ * the entry does not contain non-empty text.
+ *
+ * @param: data is a pointer to the Form GtkDialog.
+ */
+static void
+text_entry_changed_cb (GtkEntry *entry,
+                       gpointer data);
+
+
 /** Called when a choice has been toggled in the
  * GtkListStore.
  *
@@ -258,10 +272,12 @@ public:
                 const std::string _description,
                 const std::string _placeholder_text,
                 bool _advanced,
+                bool _allow_empty,
                 GtkWidget *_widget): name(_name),
                                      description(_description),
                                      placeholder_text(_placeholder_text),
                                      advanced(_advanced),
+                                     allow_empty(_allow_empty),
                                      widget(_widget)
   { }
 
@@ -270,9 +286,11 @@ public:
 
   void submit (Ekiga::FormBuilder &builder)
   {
-    builder.text (name, description,
+    builder.text (name,
+                  description,
                   gtk_entry_get_text (GTK_ENTRY (widget)), placeholder_text,
-                  advanced);
+                  advanced,
+                  allow_empty);
   }
 
 private:
@@ -281,6 +299,7 @@ private:
   const std::string description;
   const std::string placeholder_text;
   bool advanced;
+  bool allow_empty;
   GtkWidget *widget;
 };
 
@@ -292,9 +311,11 @@ public:
   PrivateTextSubmitter (const std::string _name,
                        const std::string _description,
                        bool _advanced,
+                       bool _allow_empty,
                        GtkWidget *_widget): name(_name),
                                             description(_description),
                                             advanced(_advanced),
+                                            allow_empty(_allow_empty),
                                             widget(_widget)
   { }
 
@@ -305,7 +326,9 @@ public:
   {
     builder.private_text (name, description,
                          gtk_entry_get_text (GTK_ENTRY (widget)),
-                         placeholder_text, advanced);
+                         placeholder_text,
+                          advanced,
+                          allow_empty);
   }
 
 private:
@@ -314,6 +337,7 @@ private:
   const std::string description;
   const std::string placeholder_text;
   bool advanced;
+  bool allow_empty;
   GtkWidget *widget;
 };
 
@@ -666,6 +690,19 @@ editable_list_choice_toggled_cb (G_GNUC_UNUSED GtkCellRendererToggle *cell,
 
 
 static void
+text_entry_changed_cb (GtkEntry *entry,
+                       gpointer data)
+{
+  g_return_if_fail (data);
+  std::string value = gtk_entry_get_text (entry);
+  bool sensitive = (!value.empty () && value.find_first_not_of (' ') != std::string::npos);
+
+  gtk_widget_set_sensitive (gtk_dialog_get_widget_for_response (GTK_DIALOG (data), GTK_RESPONSE_ACCEPT),
+                            sensitive);
+}
+
+
+static void
 multiple_choice_choice_toggled_cb (G_GNUC_UNUSED GtkCellRendererToggle *cell,
                                   gchar *path_str,
                                   gpointer data)
@@ -950,10 +987,13 @@ FormDialog::text (const std::string name,
                  const std::string description,
                  const std::string value,
                  const std::string placeholder_text,
-                 bool advanced)
+                 bool advanced,
+                  bool allow_empty)
 {
   GtkWidget *label = NULL;
   GtkWidget *entry = NULL;
+  bool sensitive = false;
+
   TextSubmitter *submitter = NULL;
 
   grow_fields (advanced);
@@ -968,6 +1008,14 @@ FormDialog::text (const std::string name,
   gtk_entry_set_text (GTK_ENTRY (entry), value.c_str ());
   g_object_set (G_OBJECT (entry), "expand", TRUE, NULL);
 
+  if (!allow_empty) {
+    sensitive = (!value.empty () && value.find_first_not_of (' ') != std::string::npos);
+    gtk_widget_set_sensitive (gtk_dialog_get_widget_for_response (GTK_DIALOG (window), GTK_RESPONSE_ACCEPT),
+                              sensitive);
+    g_signal_connect (entry, "changed",
+                      G_CALLBACK (text_entry_changed_cb), window);
+  }
+
   if (advanced) {
 
     gtk_grid_attach (GTK_GRID (advanced_fields), label,
@@ -986,7 +1034,7 @@ FormDialog::text (const std::string name,
                     1, 1);
   }
 
-  submitter = new TextSubmitter (name, description, placeholder_text, advanced, entry);
+  submitter = new TextSubmitter (name, description, placeholder_text, advanced, allow_empty, entry);
   submitters.push_back (submitter);
 }
 
@@ -996,7 +1044,8 @@ FormDialog::private_text (const std::string name,
                          const std::string description,
                          const std::string value,
                          const std::string placeholder_text,
-                         bool advanced)
+                         bool advanced,
+                          bool allow_empty)
 {
   GtkWidget *label = NULL;
   GtkWidget *widget = NULL;
@@ -1033,7 +1082,7 @@ FormDialog::private_text (const std::string name,
                     1, 1);
   }
 
-  submitter = new PrivateTextSubmitter (name, description, advanced, widget);
+  submitter = new PrivateTextSubmitter (name, description, advanced, allow_empty, widget);
   submitters.push_back (submitter);
 }
 
diff --git a/lib/engine/gui/gtk-core/form-dialog-gtk.h b/lib/engine/gui/gtk-core/form-dialog-gtk.h
index 483547d..90898d5 100644
--- a/lib/engine/gui/gtk-core/form-dialog-gtk.h
+++ b/lib/engine/gui/gtk-core/form-dialog-gtk.h
@@ -87,13 +87,15 @@ public:
             const std::string description,
             const std::string value,
             const std::string placeholder_text,
-            bool advanced);
+            bool advanced,
+             bool allow_empty);
 
   void private_text (const std::string name,
                     const std::string description,
                     const std::string value,
                      const std::string placeholder_text,
-                    bool advanced);
+                     bool advanced,
+                     bool allow_empty);
 
   void multi_text (const std::string name,
                   const std::string description,


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