[gtk/wip/baedert/transforms6: 58/70] Add form entry test



commit 4d19fba78ce1b0f5df2875be5cdb3e3f16560981
Author: Timm Bäder <mail baedert org>
Date:   Thu Aug 16 11:51:41 2018 +0200

    Add form entry test

 tests/meson.build     |   1 +
 tests/testformentry.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 230 insertions(+)
---
diff --git a/tests/meson.build b/tests/meson.build
index eb739680a5..c6b6d2e559 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -43,6 +43,7 @@ gtk_tests = [
   ['testflowbox'],
   ['testfontchooser'],
   ['testfontoptions'],
+  ['testformentry'],
   ['testframe'],
   ['testfullscreen'],
   ['testgiconpixbuf'],
diff --git a/tests/testformentry.c b/tests/testformentry.c
new file mode 100644
index 0000000000..0105fd4030
--- /dev/null
+++ b/tests/testformentry.c
@@ -0,0 +1,229 @@
+#include <gtk/gtk.h>
+
+
+#define GTK_TYPE_FORM_ENTRY (gtk_form_entry_get_type ())
+G_DECLARE_FINAL_TYPE (GtkFormEntry, gtk_form_entry, GTK, FORM_ENTRY, GtkWidget)
+
+#define FINAL_SCALE 0.7
+#define TRANSITION_DURATION (200 * 1000)
+
+struct _GtkFormEntry
+{
+  GtkWidget parent_instance;
+
+  GtkWidget *entry;
+  GtkWidget *placeholder;
+
+  double placeholder_scale;
+};
+
+G_DEFINE_TYPE (GtkFormEntry, gtk_form_entry, GTK_TYPE_WIDGET)
+
+
+static void
+gtk_form_entry_size_allocate (GtkWidget *widget,
+                              int        width,
+                              int        height,
+                              int        baseline)
+{
+  GtkFormEntry *self = (GtkFormEntry *)widget;
+  int placeholder_height;
+  int top;
+
+  gtk_widget_measure (self->placeholder, GTK_ORIENTATION_VERTICAL, -1,
+                      &placeholder_height, NULL, NULL, NULL);
+  top = placeholder_height * FINAL_SCALE;
+
+  gtk_widget_size_allocate (self->entry,
+                            &(GtkAllocation) {
+                              0, top,
+                              width, height - top
+                            }, -1);
+
+  /* Placeholder allocation depends on self->placeholder_scale.
+   * If that's 1.0, we don't scale it and center it on the
+   * GtkEntry. Otherwise, we move it up until y = 0. */
+  {
+    const int max_y = top + ((height - top) / 2) - (placeholder_height / 2);
+    const double t = self->placeholder_scale; /* TODO: Interpolate */
+    const int y = 0 + (t * max_y);
+    int x;
+    graphene_matrix_t m;
+
+    /* Get 0 in entry coords so we can position the placeholder there. */
+    gtk_widget_translate_coordinates (self->entry, widget, 0, 0, &x, NULL);
+
+    x *= t;
+
+    gtk_widget_size_allocate (self->placeholder,
+                              &(GtkAllocation) {
+                                x, y,
+                                width,
+                                placeholder_height
+                              }, -1);
+
+    graphene_matrix_init_scale (&m,
+                                CLAMP (t, FINAL_SCALE, 1.0),
+                                CLAMP (t, FINAL_SCALE, 1.0),
+                                1);
+    gtk_widget_set_transform (self->placeholder, &m);
+  }
+}
+
+static void
+gtk_form_entry_measure (GtkWidget      *widget,
+                        GtkOrientation  orientation,
+                        int             for_size,
+                        int            *minimum,
+                        int            *natural,
+                        int            *minimum_baseline,
+                        int            *natural_baseline)
+{
+  GtkFormEntry *self = (GtkFormEntry *)widget;
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      int min1, nat1;
+      int min2, nat2;
+
+      gtk_widget_measure (self->entry, orientation, for_size,
+                          &min1, &nat1, NULL, NULL);
+
+      gtk_widget_measure (self->entry, orientation, for_size,
+                          &min2, &nat2, NULL, NULL);
+
+      *minimum = MAX (min1, min2);
+      *natural = MAX (nat1, nat2);
+    }
+  else /* VERTICAL */
+    {
+      int min, nat;
+      int pmin, pnat;
+
+      gtk_widget_measure (self->entry, orientation, -1,
+                          &min, &nat, NULL, NULL);
+
+      gtk_widget_measure (self->entry, orientation, -1,
+                          &pmin, &pnat, NULL, NULL);
+
+      *minimum = min + (pmin * FINAL_SCALE);
+      *natural = nat + (pnat * FINAL_SCALE);
+    }
+}
+
+static gboolean
+tick_cb (GtkWidget     *widget,
+         GdkFrameClock *frame_clock,
+         gpointer       user_data)
+{
+  GtkFormEntry *self = user_data;
+
+  self->placeholder_scale -= 0.02;
+
+  gtk_widget_queue_allocate (GTK_WIDGET (self));
+  gtk_widget_queue_draw (self->placeholder);
+
+  if (self->placeholder_scale <= 0)
+    {
+      self->placeholder_scale = 0;
+      return G_SOURCE_REMOVE;
+    }
+
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+gtk_form_entry_focused (GtkEventControllerKey *controller,
+                        gpointer               user_data)
+{
+  GtkFormEntry *self = user_data;
+
+  gtk_widget_add_tick_callback (GTK_WIDGET (self), tick_cb, self, NULL);
+}
+
+static void
+gtk_form_entry_unfocused (GtkEventControllerKey *controller,
+                          gpointer               user_data)
+{
+  GtkFormEntry *self = user_data;
+
+  self->placeholder_scale = 1.0;
+  gtk_widget_queue_allocate (GTK_WIDGET (self));
+  gtk_widget_queue_draw (self->placeholder);
+}
+
+
+static void
+gtk_form_entry_class_init (GtkFormEntryClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  widget_class->measure = gtk_form_entry_measure;
+  widget_class->size_allocate = gtk_form_entry_size_allocate;
+}
+
+static void
+gtk_form_entry_init (GtkFormEntry *self)
+{
+  GtkEventController *key_controller;
+  gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
+
+  self->entry = gtk_entry_new ();
+  self->placeholder = gtk_label_new ("");
+  gtk_label_set_xalign (GTK_LABEL (self->placeholder), 0);
+  self->placeholder_scale = 1.0;
+
+  gtk_widget_set_parent (self->entry, GTK_WIDGET (self));
+  gtk_widget_set_parent (self->placeholder, GTK_WIDGET (self));
+
+  key_controller = gtk_event_controller_key_new ();
+  g_signal_connect (key_controller, "focus-in", G_CALLBACK (gtk_form_entry_focused), self);
+  g_signal_connect (key_controller, "focus-out", G_CALLBACK (gtk_form_entry_unfocused), self);
+  gtk_widget_add_controller (self->entry, key_controller);
+}
+
+GtkWidget *
+gtk_form_entry_new (const char *text)
+{
+   GtkWidget *w = g_object_new (GTK_TYPE_FORM_ENTRY, NULL);
+
+   gtk_label_set_text (GTK_LABEL (((GtkFormEntry*)w)->placeholder), text);
+
+   return w;
+}
+
+int
+main (int argc, char **argv)
+{
+  GtkWidget *window;
+  GtkWidget *box;
+  GtkWidget *form_entry1;
+  GtkWidget *form_entry2;
+
+  gtk_init ();
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  form_entry1 = gtk_form_entry_new ("First Name");
+  form_entry2 = gtk_form_entry_new ("Last Name");
+
+  gtk_container_add (GTK_CONTAINER (box), form_entry1);
+  gtk_container_add (GTK_CONTAINER (box), form_entry2);
+
+
+  gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
+  gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
+  gtk_container_add (GTK_CONTAINER (window), box);
+
+
+
+  gtk_window_set_default_size ((GtkWindow *)window, 200, 200);
+  g_signal_connect (window, "close-request", G_CALLBACK (gtk_main_quit), NULL);
+  gtk_widget_show (window);
+
+
+  gtk_main ();
+
+  return 0;
+}


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