[gnome-builder/wip/gtk4-port] plugins/create-project: stub out new design



commit e64b9e09934ef15c52a642c69f05a520387819a2
Author: Christian Hergert <chergert redhat com>
Date:   Thu May 26 16:22:25 2022 -0700

    plugins/create-project: stub out new design
    
    This doesn't implement everything yet, but it gets some of the machinery
    in place. In particular, we don't yet have capabilities to move the
    buttons up to the header bar for cancel/create and I'm not sure we'll
    take the time to do that given the necessary bits to wire up actions too.
    
    But once we have action redirection in GTK that'd be a lot easier.
    
    The next step is to move the plugins into libide-projects so that the
    template input object is most of the machinery.

 .../create-project/gbp-create-project-widget.c     | 926 ++-------------------
 .../create-project/gbp-create-project-widget.ui    | 382 +++------
 2 files changed, 168 insertions(+), 1140 deletions(-)
---
diff --git a/src/plugins/create-project/gbp-create-project-widget.c 
b/src/plugins/create-project/gbp-create-project-widget.c
index 98abd23d0..1518989aa 100644
--- a/src/plugins/create-project/gbp-create-project-widget.c
+++ b/src/plugins/create-project/gbp-create-project-widget.c
@@ -1,6 +1,6 @@
 /* gbp-create-project-widget.c
  *
- * Copyright 2016-2019 Christian Hergert <christian hergert me>
+ * Copyright 2016-2022 Christian Hergert <christian hergert me>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,38 +22,23 @@
 
 #include "config.h"
 
+#include <adwaita.h>
 #include <glib/gi18n.h>
-#include <libpeas/peas.h>
-#include <stdlib.h>
-#include <string.h>
 
 #include <libide-greeter.h>
-#include <libide-gtk.h>
+#include <libide-plugins.h>
 #include <libide-projects.h>
 #include <libide-vcs.h>
 
-#include "ide-greeter-private.h"
-
-#include "gbp-create-project-template-icon.h"
 #include "gbp-create-project-widget.h"
 
 struct _GbpCreateProjectWidget
 {
-  GtkWidget             parent_instance;
-
-  PeasExtensionSet     *providers;
-
-  GtkEntry             *app_id_entry;
-  GtkEntry             *project_name_entry;
-  IdeFileChooserEntry  *project_location_entry;
-  IdeRadioBox          *project_language_chooser;
-  GtkFlowBox           *project_template_chooser;
-  GtkSwitch            *versioning_switch;
-  IdeRadioBox          *license_chooser;
-  GtkLabel             *destination_label;
-  GtkButton            *create_button;
+  GtkWidget         parent_instance;
 
-  guint                 invalid_directory : 1;
+  GtkWidget        *main;
+  IdeTemplateInput *input;
+  AdwEntryRow      *location;
 };
 
 enum {
@@ -62,456 +47,81 @@ enum {
   N_PROPS
 };
 
-static GParamSpec *properties [N_PROPS];
-
 G_DEFINE_FINAL_TYPE (GbpCreateProjectWidget, gbp_create_project_widget, GTK_TYPE_WIDGET)
 
-static gboolean
-is_preferred (const gchar *name)
-{
-  return 0 == strcasecmp (name, "c") ||
-         0 == strcasecmp (name, "rust") ||
-         0 == strcasecmp (name, "javascript") ||
-         0 == strcasecmp (name, "python");
-}
-
-static int
-sort_by_name (gconstpointer a,
-              gconstpointer b)
-{
-  const gchar * const *astr = a;
-  const gchar * const *bstr = b;
-  gboolean apref = is_preferred (*astr);
-  gboolean bpref = is_preferred (*bstr);
-
-  if (apref && !bpref)
-    return -1;
-  else if (!apref && bpref)
-    return 1;
-
-  return g_utf8_collate (*astr, *bstr);
-}
-
-static void
-gbp_create_project_widget_add_languages (GbpCreateProjectWidget *self,
-                                         const GList            *templates)
-{
-  g_autoptr(GHashTable) languages = NULL;
-  g_autofree const gchar **keys = NULL;
-  const GList *iter;
-  guint len;
-
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  languages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
-  for (iter = templates; iter != NULL; iter = iter->next)
-    {
-      IdeProjectTemplate *template = iter->data;
-      g_auto(GStrv) template_languages = NULL;
-
-      g_assert (IDE_IS_PROJECT_TEMPLATE (template));
-
-      template_languages = ide_project_template_get_languages (template);
-
-      for (guint i = 0; template_languages [i]; i++)
-        g_hash_table_add (languages, g_strdup (template_languages [i]));
-    }
-
-  keys = (const gchar **)g_hash_table_get_keys_as_array (languages, &len);
-  qsort (keys, len, sizeof (gchar *), sort_by_name);
-  for (guint i = 0; keys[i]; i++)
-    ide_radio_box_add_item (self->project_language_chooser, keys[i], keys[i]);
-}
-
-static gboolean
-validate_name (const gchar *name)
-{
-  if (name == NULL)
-    return FALSE;
-
-  if (g_unichar_isdigit (g_utf8_get_char (name)))
-    return FALSE;
-
-  /* Meson reserved this as keyword and therefore it is
-   * not allowed as project name.
-   *
-   * FIXME: We could query the project template for valid naming
-   *        requirements to display error message to the user.
-   */
-  if (ide_str_equal0 (name, "test"))
-    return FALSE;
-
-  for (; *name; name = g_utf8_next_char (name))
-    {
-      gunichar ch = g_utf8_get_char (name);
-
-      if (g_unichar_isspace (ch))
-        return FALSE;
-
-      if (ch == '/')
-        return FALSE;
-    }
-
-  return TRUE;
-}
+static GParamSpec *properties [N_PROPS];
 
 static gboolean
-directory_exists (GbpCreateProjectWidget *self,
-                  const gchar            *name)
-{
-  g_autoptr(GFile) directory = NULL;
-  g_autoptr(GFile) child = NULL;
-
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (name != NULL);
-
-  directory = ide_file_chooser_entry_get_file (self->project_location_entry);
-  child = g_file_get_child (directory, name);
-
-  self->invalid_directory = g_file_query_exists (child, NULL);
-
-  return self->invalid_directory;
-}
-
-static void
-gbp_create_project_widget_create_cb (GObject      *object,
-                                      GAsyncResult *result,
-                                      gpointer      user_data)
-{
-  GbpCreateProjectWidget *self = (GbpCreateProjectWidget *)object;
-  g_autoptr(GError) error = NULL;
-
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (user_data == NULL);
-
-  if (!gbp_create_project_widget_create_finish (self, result, &error))
-    {
-      g_warning ("Failed to create project: %s", error->message);
-    }
-}
-
-static void
-gbp_create_project_widget_create_clicked (GbpCreateProjectWidget *self,
-                                          GtkButton              *button)
-{
-  GCancellable *cancellable;
-  GtkWidget *workspace;
-
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (GTK_IS_BUTTON (button));
-
-  workspace = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_WORKSPACE);
-  cancellable = ide_workspace_get_cancellable (IDE_WORKSPACE (workspace));
-
-  gbp_create_project_widget_create_async (self,
-                                           cancellable,
-                                           gbp_create_project_widget_create_cb,
-                                           NULL);
-}
-
-static void
-gbp_create_project_widget_name_changed (GbpCreateProjectWidget *self,
-                                        GtkEntry               *entry)
+gbp_create_project_widget_check_ready (GbpCreateProjectWidget *self)
 {
-  g_autofree gchar *project_name = NULL;
-  const gchar *text;
-
   g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (GTK_IS_ENTRY (entry));
-
-  text = gtk_editable_get_text (GTK_EDITABLE (entry));
-  project_name = g_strstrip (g_strdup (text));
-
-  if (ide_str_empty0 (project_name) || !validate_name (project_name))
-    {
-      g_object_set (self->project_name_entry,
-                    "secondary-icon-name", "dialog-warning-symbolic",
-                    "tooltip-text", _("Characters were used which might cause technical issues as a project 
name"),
-                    NULL);
-      gtk_label_set_label (self->destination_label,
-                           _("Your project will be created within a new child directory."));
-    }
-  else if (directory_exists (self, project_name))
-    {
-      g_object_set (self->project_name_entry,
-                    "secondary-icon-name", "dialog-warning-symbolic",
-                    "tooltip-text", _("Directory already exists with that name"),
-                    NULL);
-      gtk_label_set_label (self->destination_label, NULL);
-    }
-  else
-    {
-      g_autofree gchar *formatted = NULL;
-      g_autoptr(GFile) file = ide_file_chooser_entry_get_file (self->project_location_entry);
-      g_autoptr(GFile) child = g_file_get_child (file, project_name);
-      g_autofree gchar *path = g_file_get_path (child);
-      g_autofree gchar *collapsed = ide_path_collapse (path);
-
-      g_object_set (self->project_name_entry,
-                    "secondary-icon-name", NULL,
-                    "tooltip-text", NULL,
-                    NULL);
-
-      /* translators: %s is replaced with a short-form file-system path to the project */
-      formatted = g_strdup_printf (_("Your project will be created within %s."), collapsed);
-      gtk_label_set_label (self->destination_label, formatted);
-    }
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_READY]);
-}
-
-static guint
-count_chars (const gchar *str,
-             gunichar     ch)
-{
-  guint count = 0;
-  for (; *str; str = g_utf8_next_char (str))
-    count += *str == ch;
-  return count;
-}
-
-static gboolean
-application_id_is_valid (const char *app_id)
-{
-  /* g_application_id_is_valid() is necessary, but also not restrictive
-   * enough for new application ids that we need to work with flatpak.
-   */
-  if (!g_application_id_is_valid (app_id))
-    return FALSE;
-
-  /* We need at least a.b.c */
-  if (count_chars (app_id, '.') < 2)
-    return FALSE;
-
-  /* - isn't allowed for Flatpak application ids */
-  if (strchr (app_id, '-') != NULL)
-    return FALSE;
 
   return TRUE;
 }
 
 static void
-gbp_create_project_widget_app_id_changed (GbpCreateProjectWidget *self,
-                                          GtkEntry               *entry)
+on_location_changed_cb (GbpCreateProjectWidget *self,
+                        GtkEditable            *editable)
 {
-  const gchar *app_id;
+  g_autofree char *expanded = NULL;
+  g_autoptr(GFile) directory = NULL;
+  const char *text;
 
   g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (GTK_IS_ENTRY (entry));
-
-  app_id = gtk_editable_get_text (GTK_EDITABLE (entry));
-
-  if (app_id[0] && !application_id_is_valid (app_id))
-    g_object_set (self->app_id_entry,
-                  "secondary-icon-name", "dialog-warning-symbolic",
-                  "tooltip-text", _("Application ID is not valid."),
-                  NULL);
-  else
-    g_object_set (self->app_id_entry,
-                  "secondary-icon-name", NULL,
-                  "tooltip-text", NULL,
-                  NULL);
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_READY]);
-}
+  g_assert (GTK_IS_EDITABLE (editable));
 
-static void
-gbp_create_project_widget_location_changed (GbpCreateProjectWidget *self,
-                                            GParamSpec             *pspec,
-                                            IdeFileChooserEntry    *chooser)
-{
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (IDE_IS_FILE_CHOOSER_ENTRY (chooser));
+  text = gtk_editable_get_text (editable);
+  expanded = ide_path_expand (text);
+  directory = g_file_new_for_path (expanded);
 
-  /* Piggyback on the name changed signal to update things */
-  gbp_create_project_widget_name_changed (self, self->project_name_entry);
+  ide_template_input_set_directory (self->input, directory);
 }
 
 static void
-gbp_create_project_widget_refilter (GbpCreateProjectWidget *self)
+select_folder_response_cb (GbpCreateProjectWidget *self,
+                           int                     response_id,
+                           GtkFileChooserNative   *native)
 {
-  const char *language;
-
   g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
+  g_assert (GTK_IS_FILE_CHOOSER_NATIVE (native));
 
-  language = ide_radio_box_get_active_id (self->project_language_chooser);
-
-  for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->project_template_chooser));
-       child != NULL;
-       child = gtk_widget_get_next_sibling (child))
+  if (response_id == GTK_RESPONSE_ACCEPT)
     {
-      g_auto(GStrv) template_languages = NULL;
-      GbpCreateProjectTemplateIcon *template_icon;
-      IdeProjectTemplate *template;
-      gboolean sensitive = FALSE;
-
-      g_assert (GTK_IS_FLOW_BOX_CHILD (child));
-
-      if (ide_str_empty0 (language))
-        goto apply;
+      g_autoptr(GFile) file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (native));
+      g_autofree char *path = ide_path_collapse (g_file_peek_path (file));
 
-      template_icon = GBP_CREATE_PROJECT_TEMPLATE_ICON (gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD 
(child)));
-      template = gbp_create_project_template_icon_get_template (template_icon);
-      template_languages = ide_project_template_get_languages (template);
-
-      sensitive = g_strv_contains ((const char * const *)template_languages, language);
-
-    apply:
-      gtk_widget_set_sensitive (child, sensitive);
+      gtk_editable_set_text (GTK_EDITABLE (self->location), path);
     }
-}
 
-static void
-gbp_create_project_widget_language_changed (GbpCreateProjectWidget *self,
-                                            IdeRadioBox            *language_chooser)
-{
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (IDE_IS_RADIO_BOX (language_chooser));
-
-  gbp_create_project_widget_refilter (self);
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_READY]);
-}
-
-static void
-gbp_create_project_widget_template_selected (GbpCreateProjectWidget *self,
-                                             GtkFlowBox             *box,
-                                             GtkFlowBoxChild        *child)
-{
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_READY]);
-}
-
-static gint
-project_template_sort_func (GtkFlowBoxChild *child1,
-                            GtkFlowBoxChild *child2,
-                            gpointer         user_data)
-{
-  GbpCreateProjectTemplateIcon *icon1;
-  GbpCreateProjectTemplateIcon *icon2;
-  IdeProjectTemplate *tmpl1;
-  IdeProjectTemplate *tmpl2;
-
-  icon1 = GBP_CREATE_PROJECT_TEMPLATE_ICON (gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD (child1)));
-  icon2 = GBP_CREATE_PROJECT_TEMPLATE_ICON (gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD (child2)));
-
-  tmpl1 = gbp_create_project_template_icon_get_template (icon1);
-  tmpl2 = gbp_create_project_template_icon_get_template (icon2);
-
-  return ide_project_template_compare (tmpl1, tmpl2);
+  gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (native));
 }
 
 static void
-gbp_create_project_widget_add_template_buttons (GbpCreateProjectWidget *self,
-                                                 GList                   *templates)
+select_folder_action (GtkWidget  *widget,
+                      const char *action_name,
+                      GVariant   *param)
 {
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  for (const GList *iter = templates; iter; iter = iter->next)
-    {
-      IdeProjectTemplate *template = iter->data;
-      GbpCreateProjectTemplateIcon *template_icon;
-      GtkFlowBoxChild *template_container;
-
-      g_assert (IDE_IS_PROJECT_TEMPLATE (template));
-
-      template_icon = g_object_new (GBP_TYPE_CREATE_PROJECT_TEMPLATE_ICON,
-                                    "visible", TRUE,
-                                    "template", template,
-                                    NULL);
-
-      template_container = g_object_new (GTK_TYPE_FLOW_BOX_CHILD,
-                                         "visible", TRUE,
-                                         NULL);
-      gtk_flow_box_child_set_child (template_container, GTK_WIDGET (template_icon));
-      gtk_flow_box_insert (self->project_template_chooser, GTK_WIDGET (template_container), -1);
-    }
-}
-
-static void
-gbp_create_project_widget_provider_added_cb (PeasExtensionSet *set,
-                                             PeasPluginInfo   *plugin_info,
-                                             PeasExtension    *exten,
-                                             gpointer          user_data)
-{
-  GbpCreateProjectWidget *self = user_data;
-  IdeTemplateProvider *provider = (IdeTemplateProvider *)exten;
-  g_autolist(IdeProjectTemplate) templates = NULL;
-  GtkFlowBoxChild *child;
-
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (PEAS_IS_EXTENSION_SET (set));
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (IDE_IS_TEMPLATE_PROVIDER (provider));
-
-  templates = ide_template_provider_get_project_templates (provider);
-
-  gbp_create_project_widget_add_template_buttons (self, templates);
-  gbp_create_project_widget_add_languages (self, templates);
-
-  gtk_flow_box_invalidate_sort (self->project_template_chooser);
-  gbp_create_project_widget_refilter (self);
-
-  /*
-   * We do the following after every add, because we might get some delayed
-   * additions for templates during startup.
-   */
-
-  /* Default to C, always. We might investigate setting this to the
-   * previously selected item in the future.
-   */
-  ide_radio_box_set_active_id (self->project_language_chooser, "C");
-
-  /* Select the first template that is visible so we have a selection
-   * initially without the user having to select. We might also try to
-   * re-select a previous item in the future.
-   */
-  if ((child = gtk_flow_box_get_child_at_index (self->project_template_chooser, 0)))
-    gtk_flow_box_select_child (self->project_template_chooser, child);
-}
-
-static GFile *
-gbp_create_project_widget_get_directory (GbpCreateProjectWidget *self)
-{
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  return ide_file_chooser_entry_get_file (self->project_location_entry);
-}
-
-static void
-gbp_create_project_widget_set_directory (GbpCreateProjectWidget *self,
-                                         GFile                  *directory)
-{
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-  g_assert (G_IS_FILE (directory));
-
-  ide_file_chooser_entry_set_file (self->project_location_entry, directory);
-}
-
-static void
-gbp_create_project_widget_constructed (GObject *object)
-{
-  GbpCreateProjectWidget *self = GBP_CREATE_PROJECT_WIDGET (object);
-
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  G_OBJECT_CLASS (gbp_create_project_widget_parent_class)->constructed (object);
-
-  self->providers = peas_extension_set_new (peas_engine_get_default (),
-                                            IDE_TYPE_TEMPLATE_PROVIDER,
-                                            NULL);
-
-  g_signal_connect (self->providers,
-                    "extension-added",
-                    G_CALLBACK (gbp_create_project_widget_provider_added_cb),
-                    self);
-
-  peas_extension_set_foreach (self->providers,
-                              gbp_create_project_widget_provider_added_cb,
-                              self);
+  GbpCreateProjectWidget *self = (GbpCreateProjectWidget *)widget;
+  GtkFileChooserNative *native;
+  GtkRoot *root;
+
+  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
+
+  root = gtk_widget_get_root (widget);
+  native = gtk_file_chooser_native_new (_("Select Location"),
+                                        GTK_WINDOW (root),
+                                        GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+                                        _("Select"),
+                                        _("Cancel"));
+  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (native),
+                                       ide_template_input_get_directory (self->input),
+                                       NULL);
+  g_signal_connect_object (native,
+                           "response",
+                           G_CALLBACK (select_folder_response_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+  gtk_native_dialog_show (GTK_NATIVE_DIALOG (native));
 }
 
 static void
@@ -519,79 +129,27 @@ gbp_create_project_widget_dispose (GObject *object)
 {
   GbpCreateProjectWidget *self = (GbpCreateProjectWidget *)object;
 
-  g_clear_object (&self->providers);
+  g_clear_pointer (&self->main, gtk_widget_unparent);
 
   G_OBJECT_CLASS (gbp_create_project_widget_parent_class)->dispose (object);
 }
 
-static gboolean
-gbp_create_project_widget_is_ready (GbpCreateProjectWidget *self)
-{
-  const gchar *text;
-  g_autofree gchar *project_name = NULL;
-  const gchar *app_id;
-  const gchar *language = NULL;
-  GList *selected_template = NULL;
-  gboolean ret = FALSE;
-
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  if (self->invalid_directory)
-    return FALSE;
-
-  text = gtk_editable_get_text (GTK_EDITABLE (self->project_name_entry));
-  project_name = g_strstrip (g_strdup (text));
-
-  if (ide_str_empty0 (project_name) || !validate_name (project_name))
-    return FALSE;
-
-  app_id = gtk_editable_get_text (GTK_EDITABLE (self->app_id_entry));
-  if (app_id[0] && !application_id_is_valid (app_id))
-    return FALSE;
-
-  language = ide_radio_box_get_active_id (self->project_language_chooser);
-
-  if (ide_str_empty0 (language))
-    return FALSE;
-
-  selected_template = gtk_flow_box_get_selected_children (self->project_template_chooser);
-
-  if (selected_template == NULL)
-    return FALSE;
-
-  ret = gtk_widget_get_sensitive (selected_template->data);
-
-  g_list_free (selected_template);
-
-  return ret;
-}
-
-static gboolean
-gbp_create_project_widget_grab_focus (GtkWidget *widget)
-{
-  GbpCreateProjectWidget *self = (GbpCreateProjectWidget *)widget;
-
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  return gtk_widget_grab_focus (GTK_WIDGET (self->project_name_entry));
-}
-
 static void
 gbp_create_project_widget_get_property (GObject    *object,
                                         guint       prop_id,
                                         GValue     *value,
                                         GParamSpec *pspec)
 {
-  GbpCreateProjectWidget *self = GBP_CREATE_PROJECT_WIDGET(object);
+  GbpCreateProjectWidget *self = GBP_CREATE_PROJECT_WIDGET (object);
 
   switch (prop_id)
     {
     case PROP_IS_READY:
-      g_value_set_boolean (value, gbp_create_project_widget_is_ready (self));
+      g_value_set_boolean (value, gbp_create_project_widget_check_ready (self));
       break;
 
     default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
 }
 
@@ -601,382 +159,40 @@ gbp_create_project_widget_class_init (GbpCreateProjectWidgetClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
-  object_class->constructed = gbp_create_project_widget_constructed;
   object_class->dispose = gbp_create_project_widget_dispose;
   object_class->get_property = gbp_create_project_widget_get_property;
 
-  widget_class->grab_focus = gbp_create_project_widget_grab_focus;
-
   properties [PROP_IS_READY] =
-    g_param_spec_boolean ("is-ready",
-                          "Is Ready",
-                          "Is Ready",
-                          FALSE,
+    g_param_spec_boolean ("is-ready", NULL, NULL, FALSE,
                           (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
-  gtk_widget_class_set_css_name (widget_class, "createprojectwidget");
-  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
   gtk_widget_class_set_template_from_resource (widget_class, 
"/plugins/create-project/gbp-create-project-widget.ui");
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, app_id_entry);
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, create_button);
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, destination_label);
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, license_chooser);
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, project_language_chooser);
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, project_location_entry);
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, project_name_entry);
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, project_template_chooser);
-  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, versioning_switch);
+
+  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, input);
+  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, location);
+  gtk_widget_class_bind_template_child (widget_class, GbpCreateProjectWidget, main);
+
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+
+  gtk_widget_class_install_action (widget_class, "create-project.select-folder", NULL, select_folder_action);
+
+  g_type_ensure (IDE_TYPE_TEMPLATE_INPUT);
 }
 
 static void
 gbp_create_project_widget_init (GbpCreateProjectWidget *self)
 {
-  g_autoptr(GFile) projects_dir = NULL;
+  g_autofree char *projects_dir = ide_path_collapse (ide_get_projects_dir ());
 
   gtk_widget_init_template (GTK_WIDGET (self));
 
-  ide_radio_box_add_item (self->license_chooser, "gpl_3", _("GPLv3+"));
-  ide_radio_box_add_item (self->license_chooser, "lgpl_3", _("LGPLv3+"));
-  ide_radio_box_add_item (self->license_chooser, "agpl_3", _("AGPLv3+"));
-  ide_radio_box_add_item (self->license_chooser, "mit_x11", _("MIT/X11"));
-  ide_radio_box_add_item (self->license_chooser, "apache_2", _("Apache 2.0"));
-  ide_radio_box_add_item (self->license_chooser, "gpl_2", _("GPLv2+"));
-  ide_radio_box_add_item (self->license_chooser, "lgpl_2_1", _("LGPLv2.1+"));
-  ide_radio_box_add_item (self->license_chooser, "none", _("No license"));
-
-  projects_dir = g_file_new_for_path (ide_get_projects_dir ());
-  gbp_create_project_widget_set_directory (self, projects_dir);
-
-  g_signal_connect_object (self->project_name_entry,
-                           "changed",
-                           G_CALLBACK (gbp_create_project_widget_name_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (self->app_id_entry,
+  g_signal_connect_object (self->location,
                            "changed",
-                           G_CALLBACK (gbp_create_project_widget_app_id_changed),
+                           G_CALLBACK (on_location_changed_cb),
                            self,
                            G_CONNECT_SWAPPED);
 
-  g_signal_connect_object (self->project_location_entry,
-                           "notify::file",
-                           G_CALLBACK (gbp_create_project_widget_location_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (self->project_language_chooser,
-                           "changed",
-                           G_CALLBACK (gbp_create_project_widget_language_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (self->project_template_chooser,
-                           "child-activated",
-                           G_CALLBACK (gbp_create_project_widget_template_selected),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (self->create_button,
-                           "clicked",
-                           G_CALLBACK (gbp_create_project_widget_create_clicked),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  gtk_flow_box_set_sort_func (self->project_template_chooser,
-                              project_template_sort_func,
-                              NULL, NULL);
-
-  g_object_bind_property (self, "is-ready", self->create_button, "sensitive",
-                          G_BINDING_SYNC_CREATE);
-}
-
-static void
-init_vcs_cb (GObject      *object,
-             GAsyncResult *result,
-             gpointer      user_data)
-{
-  IdeVcsInitializer *vcs = (IdeVcsInitializer *)object;
-  g_autoptr(IdeTask) task = user_data;
-  g_autoptr(IdeProjectInfo) project_info = NULL;
-  g_autoptr(GError) error = NULL;
-  GbpCreateProjectWidget *self;
-  GtkWidget *workspace;
-  GFile *project_file;
-
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (IDE_IS_TASK (task));
-
-  if (!ide_vcs_initializer_initialize_finish (vcs, result, &error))
-    {
-      ide_task_return_error (task, g_steal_pointer (&error));
-      goto cleanup;
-    }
-
-  self = ide_task_get_source_object (task);
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  project_file = ide_task_get_task_data (task);
-
-  project_info = ide_project_info_new ();
-  ide_project_info_set_file (project_info, project_file);
-  ide_project_info_set_directory (project_info, project_file);
-
-  workspace = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_GREETER_WORKSPACE);
-  ide_greeter_workspace_open_project (IDE_GREETER_WORKSPACE (workspace), project_info);
-
-  ide_task_return_boolean (task, TRUE);
-
-cleanup:
-  ide_object_destroy (IDE_OBJECT (vcs));
-}
-
-static void
-extract_cb (GObject      *object,
-            GAsyncResult *result,
-            gpointer      user_data)
-{
-  IdeProjectTemplate *template = (IdeProjectTemplate *)object;
-  g_autoptr(IdeTask) task = user_data;
-  g_autoptr(IdeVcsInitializer) vcs = NULL;
-  g_autoptr(GError) error = NULL;
-  GbpCreateProjectWidget *self;
-  PeasPluginInfo *plugin_info;
-  PeasEngine *engine;
-  IdeContext *context;
-  GFile *project_file;
-
-  /* To keep the UI simple, we only support git from
-   * the creation today. However, at the time of writing
-   * that is our only supported VCS anyway. If you'd like to
-   * add support for an additional VCS, we need to redesign
-   * this part of the UI.
-   */
-  const gchar *vcs_id = "git";
-
-  g_assert (IDE_IS_PROJECT_TEMPLATE (template));
-  g_assert (G_IS_ASYNC_RESULT (result));
-  g_assert (IDE_IS_TASK (task));
-
-  if (!ide_project_template_expand_finish (template, result, &error))
-    {
-      ide_task_return_error (task, g_steal_pointer (&error));
-      return;
-    }
-
-  self = ide_task_get_source_object (task);
-  g_assert (GBP_IS_CREATE_PROJECT_WIDGET (self));
-
-  project_file = ide_task_get_task_data (task);
-  g_assert (G_IS_FILE (project_file));
-
-  if (!gtk_switch_get_active (self->versioning_switch))
-    {
-      g_autoptr(IdeProjectInfo) project_info = NULL;
-      GtkWidget *workspace;
-
-      project_info = ide_project_info_new ();
-      ide_project_info_set_file (project_info, project_file);
-      ide_project_info_set_directory (project_info, project_file);
-
-      workspace = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_GREETER_WORKSPACE);
-      ide_greeter_workspace_open_project (IDE_GREETER_WORKSPACE (workspace), project_info);
-
-      ide_task_return_boolean (task, TRUE);
-      return;
-    }
-
-  engine = peas_engine_get_default ();
-  plugin_info = peas_engine_get_plugin_info (engine, vcs_id);
-  if (plugin_info == NULL)
-    IDE_GOTO (failure);
-
-  context = ide_widget_get_context (GTK_WIDGET (self));
-  vcs = (IdeVcsInitializer *)peas_engine_create_extension (engine, plugin_info,
-                                                           IDE_TYPE_VCS_INITIALIZER,
-                                                           "parent", context,
-                                                           NULL);
-  if (vcs == NULL)
-    IDE_GOTO (failure);
-
-  ide_vcs_initializer_initialize_async (vcs,
-                                        project_file,
-                                        ide_task_get_cancellable (task),
-                                        init_vcs_cb,
-                                        g_object_ref (task));
-
-  return;
-
-failure:
-  ide_task_return_new_error (task,
-                             G_IO_ERROR,
-                             G_IO_ERROR_FAILED,
-                             _("A failure occurred while initializing version control"));
-}
-
-void
-gbp_create_project_widget_create_async (GbpCreateProjectWidget *self,
-                                         GCancellable            *cancellable,
-                                         GAsyncReadyCallback      callback,
-                                         gpointer                 user_data)
-{
-  g_autoptr(IdeTask) task = NULL;
-  g_autoptr(GHashTable) params = NULL;
-  g_autoptr(IdeProjectTemplate) template = NULL;
-  g_autoptr(IdeVcsConfig) vcs_conf = NULL;
-  GValue str = G_VALUE_INIT;
-  g_autofree gchar *name = NULL;
-  g_autofree gchar *path = NULL;
-  g_autoptr(GFile) location = NULL;
-  g_autoptr(GFile) child = NULL;
-  const gchar *language = NULL;
-  const gchar *license_id = NULL;
-  GtkFlowBoxChild *template_container;
-  GbpCreateProjectTemplateIcon *template_icon;
-  PeasEngine *engine;
-  PeasPluginInfo *plugin_info;
-  const gchar *text;
-  const gchar *app_id;
-  const gchar *vcs_id = "git";
-  const gchar *author_name;
-  GList *selected_box_child;
-
-  g_return_if_fail (GBP_CREATE_PROJECT_WIDGET (self));
-  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
-
-  gtk_widget_set_sensitive (GTK_WIDGET (self->create_button), FALSE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->license_chooser), FALSE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->project_language_chooser), FALSE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->project_location_entry), FALSE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->project_name_entry), FALSE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->project_template_chooser), FALSE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->versioning_switch), FALSE);
-
-  selected_box_child = gtk_flow_box_get_selected_children (self->project_template_chooser);
-  template_container = selected_box_child->data;
-  template_icon = GBP_CREATE_PROJECT_TEMPLATE_ICON (gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD 
(template_container)));
-  g_object_get (template_icon,
-                "template", &template,
-                NULL);
-  g_list_free (selected_box_child);
-
-  params = g_hash_table_new_full (g_str_hash,
-                                  g_str_equal,
-                                  g_free,
-                                  (GDestroyNotify)g_variant_unref);
-
-  text = gtk_editable_get_text (GTK_EDITABLE (self->project_name_entry));
-  name = g_strstrip (g_strdup (text));
-  g_hash_table_insert (params,
-                       g_strdup ("name"),
-                       g_variant_ref_sink (g_variant_new_string (g_strdelimit (name, " ", '-'))));
-
-  location = gbp_create_project_widget_get_directory (self);
-  child = g_file_get_child (location, name);
-  path = g_file_get_path (child);
-
-  g_hash_table_insert (params,
-                       g_strdup ("path"),
-                       g_variant_ref_sink (g_variant_new_string (path)));
-
-  language = ide_radio_box_get_active_id (self->project_language_chooser);
-  g_hash_table_insert (params,
-                       g_strdup ("language"),
-                       g_variant_ref_sink (g_variant_new_string (language)));
-
-  license_id = ide_radio_box_get_active_id (IDE_RADIO_BOX (self->license_chooser));
-
-  if (!g_str_equal (license_id, "none"))
-    {
-      g_autofree gchar *license_full_path = NULL;
-      g_autofree gchar *license_short_path = NULL;
-
-      license_full_path = g_strjoin (NULL, "resource://", "/plugins/create-project/license/full/", 
license_id, NULL);
-      license_short_path = g_strjoin (NULL, "resource://", "/plugins/create-project/license/short/", 
license_id, NULL);
-
-      g_hash_table_insert (params,
-                           g_strdup ("license_full"),
-                           g_variant_ref_sink (g_variant_new_string (license_full_path)));
-
-      g_hash_table_insert (params,
-                           g_strdup ("license_short"),
-                           g_variant_ref_sink (g_variant_new_string (license_short_path)));
-    }
-
-  if (gtk_switch_get_active (self->versioning_switch))
-    {
-      g_hash_table_insert (params,
-                           g_strdup ("versioning"),
-                           g_variant_ref_sink (g_variant_new_string ("git")));
-
-      engine = peas_engine_get_default ();
-      plugin_info = peas_engine_get_plugin_info (engine, vcs_id);
-
-      if (plugin_info != NULL)
-        {
-          IdeContext *context;
-
-          context = ide_widget_get_context (GTK_WIDGET (self));
-          vcs_conf = (IdeVcsConfig *)peas_engine_create_extension (engine, plugin_info,
-                                                                   IDE_TYPE_VCS_CONFIG,
-                                                                   "parent", context,
-                                                                   NULL);
-
-          if (vcs_conf != NULL)
-            {
-              g_value_init (&str, G_TYPE_STRING);
-              ide_vcs_config_get_config (vcs_conf, IDE_VCS_CONFIG_FULL_NAME, &str);
-            }
-        }
-    }
-
-  if (G_VALUE_HOLDS_STRING (&str) && !ide_str_empty0 (g_value_get_string (&str)))
-    author_name = g_value_get_string (&str);
-  else
-    author_name = g_get_real_name ();
-
-  app_id = gtk_editable_get_text (GTK_EDITABLE (self->app_id_entry));
-
-  if (ide_str_empty0 (app_id))
-    app_id = "org.example.App";
-
-  g_hash_table_insert (params,
-                       g_strdup ("author"),
-                       g_variant_take_ref (g_variant_new_string (author_name)));
-
-  g_hash_table_insert (params,
-                       g_strdup ("app-id"),
-                       g_variant_take_ref (g_variant_new_string (app_id)));
-
-  g_value_unset (&str);
-
-  task = ide_task_new (self, cancellable, callback, user_data);
-  ide_task_set_task_data (task, g_file_new_for_path (path), g_object_unref);
-
-  ide_project_template_expand_async (template,
-                                     params,
-                                     NULL,
-                                     extract_cb,
-                                     g_object_ref (task));
-}
-
-gboolean
-gbp_create_project_widget_create_finish (GbpCreateProjectWidget  *self,
-                                          GAsyncResult             *result,
-                                          GError                  **error)
-{
-  g_return_val_if_fail (GBP_IS_CREATE_PROJECT_WIDGET (self), FALSE);
-  g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
-
-  gtk_widget_set_sensitive (GTK_WIDGET (self->create_button), TRUE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->license_chooser), TRUE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->project_language_chooser), TRUE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->project_location_entry), TRUE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->project_name_entry), TRUE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->project_template_chooser), TRUE);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->versioning_switch), TRUE);
-
-  return ide_task_propagate_boolean (IDE_TASK (result), error);
+  gtk_editable_set_text (GTK_EDITABLE (self->location), projects_dir);
 }
diff --git a/src/plugins/create-project/gbp-create-project-widget.ui 
b/src/plugins/create-project/gbp-create-project-widget.ui
index a2a925794..c1140ffd7 100644
--- a/src/plugins/create-project/gbp-create-project-widget.ui
+++ b/src/plugins/create-project/gbp-create-project-widget.ui
@@ -2,336 +2,157 @@
 <interface>
   <template class="GbpCreateProjectWidget" parent="GtkWidget">
     <child>
-      <object class="GtkScrolledWindow" id="scroller">
-        <property name="propagate-natural-height">true</property>
-        <property name="propagate-natural-width">true</property>
-        <property name="hscrollbar-policy">never</property>
+      <object class="AdwClamp" id="main">
+        <property name="orientation">horizontal</property>
+        <property name="maximum-size">550</property>
         <child>
           <object class="GtkBox">
-            <property name="orientation">vertical</property>
-            <property name="hexpand">true</property>
-            <property name="vexpand">true</property>
-            <property name="margin-top">72</property>
-            <property name="margin-start">64</property>
-            <property name="margin-end">64</property>
+            <property name="margin-top">64</property>
             <property name="margin-bottom">64</property>
-            <property name="valign">start</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">24</property>
             <child>
-              <object class="IdeThreeGrid" id="three_grid">
-                <property name="column-spacing">12</property>
-                <property name="row-spacing">24</property>
+              <object class="AdwPreferencesGroup">
                 <child>
-                  <object class="GtkLabel" id="project_name_label">
-                    <property name="halign">end</property>
-                    <property name="label" translatable="yes">Project Name</property>
-                    <property name="valign">start</property>
-                    <layout>
-                      <property name="column">left</property>
-                      <property name="row">0</property>
-                    </layout>
+                  <object class="AdwEntryRow" id="project_name">
+                    <property name="title" translatable="yes">Project Name</property>
+                    <property name="text" bind-source="input" bind-property="name" 
bind-flags="sync-create|bidirectional"/>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkBox">
-                    <property name="spacing">6</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="GtkEntry" id="project_name_entry">
-                        <property name="width-chars">50</property>
-                        <property name="hexpand">true</property>
-                        <property name="vexpand">true</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkLabel">
-                        <property name="xalign">0.0</property>
-                        <property name="wrap">true</property>
-                        <property name="max-width-chars">60</property>
-                        <property name="label" translatable="yes">Unique name that is used for your 
project’s folder and other technical resources. Should be in lower case without spaces and may not start with 
a number.</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                        <attributes>
-                          <attribute name="scale" value="0.833333"/>
-                        </attributes>
-                      </object>
-                    </child>
-                    <layout>
-                      <property name="column">center</property>
-                      <property name="row">0</property>
-                    </layout>
-                  </object>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="app_id_label">
-                    <property name="halign">end</property>
-                    <property name="label" translatable="yes">Application ID</property>
-                    <property name="valign">start</property>
-                    <layout>
-                      <property name="column">left</property>
-                      <property name="row">1</property>
-                    </layout>
+                  <object class="GtkLabel">
+                    <property name="label" translatable="yes">A unique name that is used for the project 
folder and other resources. The name should be in lower case without spaces and should not start with a 
number.</property>
+                    <property name="margin-top">12</property>
+                    <property name="wrap">true</property>
+                    <property name="xalign">0</property>
+                    <style>
+                      <class name="caption"/>
+                      <class name="dim-label"/>
+                    </style>
                   </object>
                 </child>
+              </object>
+            </child>
+            <child>
+              <object class="AdwPreferencesGroup">
                 <child>
-                  <object class="GtkBox">
-                    <property name="spacing">6</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="GtkEntry" id="app_id_entry">
-                        <property name="width-chars">50</property>
-                        <property name="hexpand">true</property>
-                        <property name="vexpand">true</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkLabel">
-                        <property name="xalign">0.0</property>
-                        <property name="wrap">true</property>
-                        <property name="max-width-chars">60</property>
-                        <property name="label" translatable="yes">The Application ID is a reverse 
domain-name identifier used to uniquely identify your application such as “org.gnome.Builder” and may not 
contain dashes.</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                        <attributes>
-                          <attribute name="scale" value="0.833333"/>
-                        </attributes>
-                      </object>
-                    </child>
-                    <layout>
-                      <property name="column">center</property>
-                      <property name="row">1</property>
-                    </layout>
+                  <object class="AdwEntryRow" id="application_id">
+                    <property name="title" translatable="yes">Application ID…</property>
+                    <property name="text" bind-source="input" bind-property="app-id" 
bind-flags="sync-create|bidirectional"/>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel" id="project_location_label">
-                    <property name="halign">end</property>
-                    <property name="label" translatable="yes">Project Location</property>
-                    <property name="valign">start</property>
-                    <layout>
-                      <property name="column">left</property>
-                      <property name="row">2</property>
-                    </layout>
+                  <object class="GtkLabel">
+                    <property name="label" translatable="yes">A reverse domain-name identifier used to 
identify the application, such as "org.gnome.Builder".</property>
+                    <property name="margin-top">12</property>
+                    <property name="wrap">true</property>
+                    <property name="xalign">0</property>
+                    <style>
+                      <class name="caption"/>
+                      <class name="dim-label"/>
+                    </style>
                   </object>
                 </child>
-                <child>
-                  <object class="GtkBox">
-                    <property name="spacing">6</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="IdeFileChooserEntry" id="project_location_entry">
-                        <property name="action">select-folder</property>
-                        <property name="title" translatable="yes">Select Project Directory</property>
-                        <property name="hexpand">true</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="destination_label">
-                        <property name="xalign">0.0</property>
-                        <property name="wrap">true</property>
-                        <property name="max-width-chars">60</property>
-                        <property name="label" translatable="yes">Your project will be created within a new 
child directory.</property>
+              </object>
+            </child>
+            <child>
+              <object class="AdwPreferencesGroup">
+                <child>
+                  <object class="AdwEntryRow" id="location">
+                    <property name="title" translatable="yes">Location</property>
+                    <property name="text">~/Projects</property>
+                    <child type="suffix">
+                      <object class="GtkButton">
+                        <property name="action-name">create-project.select-folder</property>
+                        <property name="valign">center</property>
+                        <property name="icon-name">folder-symbolic</property>
                         <style>
-                          <class name="dim-label"/>
+                          <class name="flat"/>
                         </style>
-                        <attributes>
-                          <attribute name="scale" value="0.833333"/>
-                        </attributes>
                       </object>
                     </child>
-                    <layout>
-                      <property name="column">center</property>
-                      <property name="row">2</property>
-                    </layout>
                   </object>
                 </child>
-
-                <child>
-                  <object class="GtkLabel" id="language_label">
-                    <property name="halign">end</property>
-                    <property name="label" translatable="yes">Language</property>
-                    <property name="valign">start</property>
-                    <layout>
-                      <property name="column">left</property>
-                      <property name="row">3</property>
-                    </layout>
-                  </object>
-                </child>
-                <child>
-                  <object class="IdeRadioBox" id="project_language_chooser">
-                    <property name="hexpand">true</property>
-                    <layout>
-                      <property name="column">center</property>
-                      <property name="row">3</property>
-                    </layout>
-                  </object>
-                </child>
-
-                <child>
-                  <object class="GtkLabel" id="license_label">
-                    <property name="halign">end</property>
-                    <property name="label" translatable="yes">License</property>
-                    <property name="valign">start</property>
-                    <layout>
-                      <property name="column">left</property>
-                      <property name="row">4</property>
-                    </layout>
-                  </object>
-                </child>
-                <child>
-                  <object class="IdeRadioBox" id="license_chooser">
-                    <property name="active-id">gpl_3</property>
-                    <property name="hexpand">true</property>
-                    <layout>
-                      <property name="column">center</property>
-                      <property name="row">4</property>
-                    </layout>
-                  </object>
-                </child>
-
                 <child>
                   <object class="GtkLabel">
-                    <property name="halign">end</property>
-                    <property name="label" translatable="yes">Version Control</property>
-                    <layout>
-                      <property name="column">left</property>
-                      <property name="row">5</property>
-                    </layout>
+                    <property name="label" translatable="yes">The project will be created in a new 
subdirectory.</property>
+                    <property name="margin-top">12</property>
+                    <property name="wrap">true</property>
+                    <property name="xalign">0</property>
+                    <style>
+                      <class name="caption"/>
+                      <class name="dim-label"/>
+                    </style>
                   </object>
                 </child>
-                <child>
-                  <object class="GtkBox" id="versioning_box">
-                    <property name="orientation">horizontal</property>
-                    <child>
-                      <object class="GtkSwitch" id="versioning_switch">
-                        <property name="active">true</property>
-                        <property name="halign">start</property>
-                      </object>
-                    </child>
-                    <child type="end">
-                      <object class="GtkLabel">
-                        <property name="label" translatable="yes">Uses the Git version control 
system</property>
-                        <property name="margin-start">12</property>
-                        <property name="halign">center</property>
+              </object>
+            </child>
+            <child>
+              <object class="AdwPreferencesGroup">
+                <child>
+                  <object class="AdwActionRow">
+                    <property name="title" translatable="yes">Language</property>
+                    <child type="suffix">
+                      <object class="GtkMenuButton">
+                        <property name="valign">center</property>
+                        <property name="label">C</property>
                         <style>
-                          <class name="dim-label"/>
+                          <class name="flat"/>
                         </style>
-                        <attributes>
-                          <attribute name="scale" value="0.833333"/>
-                        </attributes>
                       </object>
                     </child>
-                    <layout>
-                      <property name="column">center</property>
-                      <property name="row">5</property>
-                    </layout>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkBox">
-                    <child>
-                      <object class="GtkToggleButton" id="license_more">
-                        <property name="active" bind-source="license_chooser" bind-property="show-more" 
bind-flags="bidirectional"/>
-                        <property name="sensitive" bind-source="license_chooser" bind-property="has-more"/>
-                        <property name="valign">start</property>
-                        <property name="vexpand">false</property>
-                        <property name="focus-on-click">false</property>
+                  <object class="AdwActionRow">
+                    <property name="title" translatable="yes">License</property>
+                    <child type="suffix">
+                      <object class="GtkMenuButton">
+                        <property name="valign">center</property>
+                        <property name="label">GPLv3+</property>
                         <style>
                           <class name="flat"/>
-                          <class name="image-button"/>
                         </style>
-                        <child>
-                          <object class="GtkImage">
-                            <property name="icon-name">view-more-symbolic</property>
-                          </object>
-                        </child>
                       </object>
                     </child>
-                    <layout>
-                      <property name="column">right</property>
-                      <property name="row">4</property>
-                    </layout>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkBox">
-                    <child>
-                      <object class="GtkToggleButton" id="language_more">
-                        <property name="active" bind-source="project_language_chooser" 
bind-property="show-more" bind-flags="bidirectional"/>
-                        <property name="sensitive" bind-source="project_language_chooser" 
bind-property="has-more"/>
-                        <property name="valign">start</property>
-                        <property name="vexpand">false</property>
-                        <property name="focus-on-click">false</property>
-                        <style>
-                          <class name="flat"/>
-                          <class name="image-button"/>
-                        </style>
-                        <child>
-                          <object class="GtkImage">
-                            <property name="icon-name">view-more-symbolic</property>
-                          </object>
-                        </child>
+                  <object class="AdwActionRow">
+                    <property name="title" translatable="yes">Version Control</property>
+                    <child type="suffix">
+                      <object class="GtkSwitch">
+                        <property name="valign">center</property>
+                        <property name="active" bind-source="input" bind-property="use-version-control" 
bind-flags="sync-create"/>
                       </object>
                     </child>
-                    <layout>
-                      <property name="column">right</property>
-                      <property name="row">3</property>
-                    </layout>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkBox">
-                    <property name="orientation">horizontal</property>
-                    <property name="margin-top">12</property>
-                    <property name="hexpand">true</property>
-                    <child type="end">
-                      <object class="GtkButton" id="create_button">
-                        <property name="label" translatable="yes">_Create Project</property>
-                        <property name="use-underline">True</property>
-                        <property name="halign">end</property>
+                  <object class="AdwActionRow">
+                    <property name="title" translatable="yes">Template</property>
+                    <child type="suffix">
+                      <object class="GtkMenuButton">
+                        <property name="valign">center</property>
+                        <property name="label">GNOME Application</property>
                         <style>
-                          <class name="suggested-action"/>
+                          <class name="flat"/>
                         </style>
                       </object>
                     </child>
-                    <layout>
-                      <property name="column">1</property>
-                      <property name="row">6</property>
-                    </layout>
                   </object>
                 </child>
               </object>
             </child>
             <child>
-              <object class="GtkBox">
-                <property name="orientation">vertical</property>
-                <property name="hexpand">true</property>
-                <property name="vexpand">true</property>
-                <property name="valign">start</property>
-                <property name="spacing">12</property>
-                <property name="margin-top">24</property>
-                <child>
-                  <object class="GtkLabel">
-                    <property name="label" translatable="yes">Select a Template</property>
-                    <attributes>
-                      <attribute name="weight" value="bold"/>
-                    </attributes>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                </child>
-                <child>
-                  <object class="GtkFlowBox" id="project_template_chooser">
-                    <property name="column-spacing">12</property>
-                    <property name="row-spacing">12</property>
-                    <property name="max-children-per-line">4</property>
-                    <property name="min-children-per-line">4</property>
-                    <property name="halign">center</property>
-                    <property name="valign">start</property>
-                  </object>
-                </child>
+              <object class="GtkButton">
+                <property name="action-name">create-project.expand</property>
+                <property name="label" translatable="yes">Create Project</property>
+                <property name="margin-top">12</property>
+                <property name="halign">end</property>
+                <style>
+                  <class name="suggested-action"/>
+                </style>
               </object>
             </child>
           </object>
@@ -339,15 +160,6 @@
       </object>
     </child>
   </template>
-  <object class="GtkSizeGroup">
-    <property name="mode">vertical</property>
-    <widgets>
-      <widget name="project_name_label"/>
-      <widget name="app_id_label"/>
-      <widget name="project_name_entry"/>
-      <widget name="project_location_label"/>
-      <widget name="license_label"/>
-      <widget name="language_label"/>
-    </widgets>
+  <object class="IdeTemplateInput" id="input">
   </object>
 </interface>


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