[gnome-control-center/wip/carlosg/wacom-facelift: 1/6] wacom: Refresh UI




commit bacc04e214faa6d5042d57f58c9c9a7f3ca5947b
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sat Jan 29 17:17:40 2022 +0100

    wacom: Refresh UI
    
    Use libadwaita widgets, and follow recent mockups for this panel.

 panels/wacom/cc-wacom-mapping-panel.c  | 338 -------------------
 panels/wacom/cc-wacom-mapping-panel.h  |  36 --
 panels/wacom/cc-wacom-nav-button.c     | 209 ------------
 panels/wacom/cc-wacom-nav-button.h     |  31 --
 panels/wacom/cc-wacom-page.c           | 598 +++++++++++----------------------
 panels/wacom/cc-wacom-page.h           |   4 -
 panels/wacom/cc-wacom-page.ui          | 114 +++++++
 panels/wacom/cc-wacom-panel.c          | 235 +++----------
 panels/wacom/cc-wacom-panel.ui         |  76 +++++
 panels/wacom/cc-wacom-stylus-page.c    | 382 +++++----------------
 panels/wacom/cc-wacom-stylus-page.h    |   3 -
 panels/wacom/cc-wacom-stylus-page.ui   | 170 ++++++++++
 panels/wacom/gnome-wacom-properties.ui | 324 ------------------
 panels/wacom/meson.build               |   2 -
 panels/wacom/test-wacom.c              |   1 -
 panels/wacom/wacom-stylus-page.ui      | 316 -----------------
 panels/wacom/wacom.gresource.xml       |   5 +-
 17 files changed, 693 insertions(+), 2151 deletions(-)
---
diff --git a/panels/wacom/cc-wacom-page.c b/panels/wacom/cc-wacom-page.c
index 86b098f10..1c4676137 100644
--- a/panels/wacom/cc-wacom-page.c
+++ b/panels/wacom/cc-wacom-page.c
@@ -38,8 +38,6 @@
 #include "cc-wacom-device.h"
 #include "cc-wacom-button-row.h"
 #include "cc-wacom-page.h"
-#include "cc-wacom-nav-button.h"
-#include "cc-wacom-mapping-panel.h"
 #include "cc-wacom-stylus-page.h"
 #include "gsd-enums.h"
 #include "calibrator-gui.h"
@@ -47,20 +45,11 @@
 
 #include <string.h>
 
-#define WID(x) (GtkWidget *) gtk_builder_get_object (page->builder, x)
 #define MWID(x) (GtkWidget *) gtk_builder_get_object (page->mapping_builder, x)
 
 #define THRESHOLD_MISCLICK     15
 #define THRESHOLD_DOUBLECLICK  7
 
-enum {
-       MAPPING_DESCRIPTION_COLUMN,
-       MAPPING_TYPE_COLUMN,
-       MAPPING_BUTTON_COLUMN,
-       MAPPING_BUTTON_DIRECTION,
-       MAPPING_N_COLUMNS
-};
-
 struct _CcWacomPage
 {
        GtkBox          parent_instance;
@@ -68,23 +57,30 @@ struct _CcWacomPage
        CcWacomPanel   *panel;
        CcWacomDevice  *stylus;
        GList          *pads;
-       GtkBuilder     *builder;
-       GtkWidget      *nav;
-       GtkWidget      *notebook;
        CalibArea      *area;
        GSettings      *wacom_settings;
 
-       GtkSizeGroup   *header_group;
+       GtkWidget      *tablet_name;
+       GtkWidget      *tablet_subtitle;
+       GtkWidget      *tablet_icon;
+       GtkWidget      *tablet_display;
+       GtkWidget      *tablet_calibrate;
+       GtkWidget      *tablet_map_buttons;
+       GtkWidget      *tablet_mode;
+       GtkWidget      *tablet_mode_switch;
+       GtkWidget      *tablet_left_handed;
+       GtkWidget      *tablet_left_handed_switch;
+       GtkWidget      *tablet_aspect_ratio;
+       GtkWidget      *tablet_aspect_ratio_switch;
+       GtkWidget      *display_section;
+
+       GnomeRRScreen  *rr_screen;
 
        /* Button mapping */
        GtkBuilder     *mapping_builder;
        GtkWindow      *button_map;
        GtkListStore   *action_store;
 
-       /* Display mapping */
-       GtkWidget      *mapping;
-       GtkWindow      *dialog;
-
        GCancellable   *cancellable;
 
        /* To reach other grouped devices */
@@ -93,26 +89,6 @@ struct _CcWacomPage
 
 G_DEFINE_TYPE (CcWacomPage, cc_wacom_page, GTK_TYPE_BOX)
 
-/* Button combo box storage columns */
-enum {
-       BUTTONNUMBER_COLUMN,
-       BUTTONNAME_COLUMN,
-       N_BUTTONCOLUMNS
-};
-
-/* Tablet mode combo box storage columns */
-enum {
-       MODENUMBER_COLUMN,
-       MODELABEL_COLUMN,
-       N_MODECOLUMNS
-};
-
-/* Tablet mode options - keep in sync with .ui */
-enum {
-       MODE_ABSOLUTE, /* stylus + eraser absolute */
-       MODE_RELATIVE, /* stylus + eraser relative */
-};
-
 /* Different types of layout for the tablet config */
 enum {
        LAYOUT_NORMAL,        /* tracking mode, button mapping */
@@ -120,10 +96,6 @@ enum {
        LAYOUT_SCREEN        /* button mapping, calibration, display resolution */
 };
 
-static void
-set_page_layout (CcWacomPage *page,
-                int          layout);
-
 static int
 get_layout_type (CcWacomDevice *device)
 {
@@ -206,7 +178,7 @@ finish_calibration (CalibArea *area,
 
        calib_area_free (area);
        page->area = NULL;
-       gtk_widget_set_sensitive (WID ("button-calibrate"), TRUE);
+       gtk_widget_set_sensitive (page->tablet_calibrate, TRUE);
 }
 
 static GdkDevice *
@@ -354,13 +326,13 @@ calibrate (CcWacomPage *page)
        g_settings_set_value (page->wacom_settings, "area", array);
 
        run_calibration (page, old_calibration, calibration, monitor);
-       gtk_widget_set_sensitive (WID ("button-calibrate"), FALSE);
+       gtk_widget_set_sensitive (page->tablet_calibrate, FALSE);
 }
 
 static void
-calibrate_button_clicked_cb (CcWacomPage *page)
+on_calibrate_activated (CcWacomPage *self)
 {
-       calibrate (page);
+       calibrate (self);
 }
 
 /* This avoids us crashing when a newer version of
@@ -503,186 +475,33 @@ set_osd_visibility (CcWacomPage *page)
 }
 
 static void
-map_buttons_button_clicked_cb (CcWacomPage *page)
-{
-       set_osd_visibility (page);
-}
-
-static void
-display_mapping_dialog_closed (CcWacomPage *page)
-{
-       int layout;
-
-       gtk_window_destroy (page->dialog);
-       page->dialog = NULL;
-       page->mapping = NULL;
-       layout = get_layout_type (page->stylus);
-       set_page_layout (page, layout);
-}
-
-static void
-display_mapping_button_clicked_cb (CcWacomPage *page)
-{
-  GtkWidget *dialog;
-
-       g_assert (page->mapping == NULL);
-
-       dialog = gtk_dialog_new_with_buttons (_("Display Mapping"),
-                                                   GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (page))),
-                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                                   _("_Close"),
-                                                   GTK_RESPONSE_ACCEPT,
-                                                   NULL);
-  page->dialog = GTK_WINDOW (dialog);
-       page->mapping = cc_wacom_mapping_panel_new ();
-       cc_wacom_mapping_panel_set_device (CC_WACOM_MAPPING_PANEL (page->mapping),
-                                          page->stylus);
-  gtk_window_set_child (page->dialog, page->mapping);
-       g_signal_connect_object (page->dialog, "response",
-                                G_CALLBACK (display_mapping_dialog_closed), page, G_CONNECT_SWAPPED);
-       gtk_window_present (page->dialog);
-
-       g_object_add_weak_pointer (G_OBJECT (page->mapping), (gpointer *) &page->dialog);
-}
-
-static void
-tabletmode_changed_cb (CcWacomPage *page)
-{
-       GtkListStore *liststore;
-       GtkTreeIter iter;
-       gint mode;
-
-       if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (WID ("combo-tabletmode")), &iter))
-               return;
-
-       liststore = GTK_LIST_STORE (WID ("liststore-tabletmode"));
-       gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
-                           MODENUMBER_COLUMN, &mode,
-                           -1);
-
-       g_settings_set_enum (page->wacom_settings, "mapping", mode);
-}
-
-static void
-left_handed_toggled_cb (CcWacomPage *page)
-{
-       gboolean left_handed;
-
-       left_handed = gtk_switch_get_active (GTK_SWITCH (WID ("switch-left-handed")));
-       g_settings_set_boolean (page->wacom_settings, "left-handed", left_handed);
-}
-
-static void
-set_left_handed_from_gsettings (CcWacomPage *page)
-{
-       gboolean left_handed;
-
-       left_handed = g_settings_get_boolean (page->wacom_settings, "left-handed");
-       gtk_switch_set_active (GTK_SWITCH (WID ("switch-left-handed")), left_handed);
-}
-
-static void
-set_mode_from_gsettings (GtkComboBox *combo,
-                        CcWacomPage *page)
-{
-       GDesktopTabletMapping mapping;
-
-       mapping = g_settings_get_enum (page->wacom_settings, "mapping");
-
-       /* this must be kept in sync with the .ui file */
-       gtk_combo_box_set_active (combo, mapping);
-}
-
-static void
-update_display_decoupled_sensitivity (CcWacomPage *page,
-                                     gboolean     active)
+on_map_buttons_activated (CcWacomPage *self)
 {
-       if (get_layout_type (page->stylus) != LAYOUT_SCREEN)
-               return;
-
-       gtk_widget_set_sensitive (WID ("label-trackingmode"), active);
-       gtk_widget_set_sensitive (WID ("combo-tabletmode"), active);
-       gtk_widget_set_sensitive (WID ("display-mapping-button-2"), active);
-
-       gtk_widget_set_sensitive (WID ("button-calibrate"), !active);
+       set_osd_visibility (self);
 }
 
 static void
-set_display_decoupled_from_gsettings (GtkSwitch *sw,
-                                     CcWacomPage *page)
+on_display_selected (GtkWidget   *widget,
+                    GParamSpec  *pspec,
+                    CcWacomPage *page)
 {
-       g_auto(GStrv) output = g_settings_get_strv (page->wacom_settings, "output");
-       gboolean active = g_strcmp0 (output[0], "") != 0;
-
-       gtk_switch_set_active (sw, active);
-       update_display_decoupled_sensitivity (page, active);
-}
-
-static void
-combobox_text_cellrenderer (GtkComboBox *combo, int name_column)
-{
-       GtkCellRenderer *renderer;
-
-       renderer = gtk_cell_renderer_text_new ();
-       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
-       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
-                                       "text", BUTTONNAME_COLUMN, NULL);
-}
-
-static gboolean
-display_clicked_cb (CcWacomPage *page)
-{
-       cc_wacom_panel_switch_to_panel (page->panel, "display");
-       return TRUE;
-}
-
-static gboolean
-mouse_clicked_cb (CcWacomPage *page)
-{
-       cc_wacom_panel_switch_to_panel (page->panel, "mouse");
-       return TRUE;
-}
-
-static void
-decouple_display_toggled_cb (CcWacomPage *page)
-{
-       gboolean active = gtk_switch_get_active (GTK_SWITCH (WID ("switch-decouple-display")));
-
-       update_display_decoupled_sensitivity (page, active);
+       GListModel *list;
+       g_autoptr (GObject) obj = NULL;
+       GVariant *variant;
+       gint idx;
 
-       if (!active) {
-               cc_wacom_device_set_output (page->stylus, NULL);
-       } else {
-               GdkDisplay *display;
-               GnomeRRScreen *rr_screen;
-               GnomeRROutput **outputs, *picked = NULL;
-               g_autoptr(GError) error = NULL;
-               int i;
-
-               display = gtk_widget_get_display (GTK_WIDGET (WID ("switch-decouple-display")));
-               rr_screen = gnome_rr_screen_new (display, &error);
-               if (rr_screen == NULL) {
-                       g_warning ("Could not connect to display manager: %s", error->message);
-                       return;
-               }
+       list = adw_combo_row_get_model (ADW_COMBO_ROW (widget));
+       idx = adw_combo_row_get_selected (ADW_COMBO_ROW (widget));
+       obj = g_list_model_get_item (list, idx);
 
-               outputs = gnome_rr_screen_list_outputs (rr_screen);
-
-               /* Pick *some* output here. decoupled mode can only jump across
-                * monitors, not map to the full span of those. We prefer the
-                * builtin display, falling back to the first output found if
-                * there's none.
-                */
-               for (i = 0; outputs[i] != NULL; i++) {
-                       if (gnome_rr_output_is_builtin_display (outputs[i]))
-                               picked = outputs[i];
-               }
+       variant = g_object_get_data (obj, "value-output");
 
-               if (!picked)
-                       picked = outputs[0];
+       if (variant)
+               g_settings_set_value (page->wacom_settings, "output", g_variant_ref (variant));
+       else
+               g_settings_reset (page->wacom_settings, "output");
 
-               cc_wacom_device_set_output (page->stylus, picked);
-       }
+       gtk_widget_set_sensitive (page->tablet_calibrate, variant == NULL);
 }
 
 /* Boilerplate code goes below */
@@ -722,10 +541,8 @@ cc_wacom_page_dispose (GObject *object)
        g_clear_object (&self->cancellable);
        g_clear_pointer (&self->area, calib_area_free);
        g_clear_pointer (&self->button_map, gtk_window_destroy);
-       g_clear_pointer (&self->dialog, gtk_window_destroy);
-       g_clear_object (&self->builder);
-       g_clear_object (&self->header_group);
        g_list_free_full (self->pads, g_object_unref);
+       g_clear_object (&self->rr_screen);
        self->pads = NULL;
 
        self->panel = NULL;
@@ -737,128 +554,135 @@ static void
 cc_wacom_page_class_init (CcWacomPageClass *klass)
 {
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
        object_class->get_property = cc_wacom_page_get_property;
        object_class->set_property = cc_wacom_page_set_property;
        object_class->dispose = cc_wacom_page_dispose;
-}
 
-static void
-remove_link_padding (GtkWidget *widget)
-{
-       g_autoptr(GtkCssProvider) provider = NULL;
-
-       provider = gtk_css_provider_new ();
-       gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider),
-                                        ".link { padding: 0px; }", -1);
-       gtk_style_context_add_provider (gtk_widget_get_style_context (widget),
-                                       GTK_STYLE_PROVIDER (provider),
-                                       GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-}
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/control-center/wacom/cc-wacom-page.ui");
+
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_name);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_subtitle);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_icon);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_display);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_calibrate);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_map_buttons);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_mode);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_mode_switch);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_left_handed);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_left_handed_switch);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_aspect_ratio);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, tablet_aspect_ratio_switch);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPage, display_section);
+
+       gtk_widget_class_bind_template_callback (widget_class, on_map_buttons_activated);
+       gtk_widget_class_bind_template_callback (widget_class, on_calibrate_activated);
+       gtk_widget_class_bind_template_callback (widget_class, on_display_selected);
+}
+
+static void
+update_displays_model (CcWacomPage *page)
+{
+       g_autoptr (GtkStringList) list = NULL;
+       GnomeRROutput **outputs, *cur_output;
+       int i, idx = 0, cur = -1, automatic_item = -1;
+       g_autoptr (GObject) obj = NULL;
+       GVariant *variant;
+
+       outputs = gnome_rr_screen_list_outputs (page->rr_screen);
+       list = gtk_string_list_new (NULL);
+       cur_output = cc_wacom_device_get_output (page->stylus,
+                                                page->rr_screen);
+
+       for (i = 0; outputs[i] != NULL; i++) {
+               GnomeRROutput *output = outputs[i];
+               GnomeRRCrtc *crtc = gnome_rr_output_get_crtc (output);
+               g_autofree gchar *text = NULL;
+               g_autofree gchar *vendor = NULL;
+               g_autofree gchar *product = NULL;
+               g_autofree gchar *serial = NULL;
+               const gchar *name, *disp_name;
+
+               /* Output is turned on? */
+               if (!crtc || gnome_rr_crtc_get_current_mode (crtc) == NULL)
+                       continue;
 
-static void
-cc_wacom_page_init (CcWacomPage *page)
-{
-       g_autoptr(GError) error = NULL;
-       GtkComboBox *combo;
-       GtkWidget *box;
-       char *objects[] = {
-               "main-grid",
-               "liststore-tabletmode",
-               "liststore-buttons",
-               "adjustment-tip-feel",
-               "adjustment-eraser-feel",
-               NULL
-       };
-
-       page->builder = gtk_builder_new ();
-
-       gtk_builder_add_objects_from_resource (page->builder,
-                                               "/org/gnome/control-center/wacom/gnome-wacom-properties.ui",
-                                               objects,
-                                               &error);
-       if (error != NULL) {
-               g_warning ("Error loading UI file: %s", error->message);
-               return;
+               if (output == cur_output)
+                       cur = idx;
+
+               name = gnome_rr_output_get_name (output);
+               disp_name = gnome_rr_output_get_display_name (output);
+               text = g_strdup_printf ("%s (%s)", name, disp_name);
+
+               gnome_rr_output_get_ids_from_edid (output,
+                                                  &vendor,
+                                                  &product,
+                                                  &serial);
+               variant = g_variant_new_strv ((const gchar *[]) { vendor, product, serial }, 3);
+
+               gtk_string_list_append (list, text);
+               obj = g_list_model_get_item (G_LIST_MODEL (list), idx);
+               g_object_set_data_full (G_OBJECT (obj), "value-output",
+                                       variant, (GDestroyNotify) g_variant_unref);
+               idx++;
        }
 
-       box = WID ("main-grid");
-       gtk_box_append (GTK_BOX (page), box);
-       gtk_widget_set_vexpand (GTK_WIDGET (box), TRUE);
-
-       g_signal_connect_object (WID ("button-calibrate"), "clicked",
-                                G_CALLBACK (calibrate_button_clicked_cb), page, G_CONNECT_SWAPPED);
-       g_signal_connect_object (WID ("map-buttons-button"), "clicked",
-                                G_CALLBACK (map_buttons_button_clicked_cb), page, G_CONNECT_SWAPPED);
-
-       combo = GTK_COMBO_BOX (WID ("combo-tabletmode"));
-       combobox_text_cellrenderer (combo, MODELABEL_COLUMN);
-       g_signal_connect_object (combo, "changed",
-                                G_CALLBACK (tabletmode_changed_cb), page, G_CONNECT_SWAPPED);
-
-       g_signal_connect_object (WID ("switch-left-handed"), "notify::active",
-                                G_CALLBACK (left_handed_toggled_cb), page, G_CONNECT_SWAPPED);
-
-       g_signal_connect_object (WID ("display-link"), "activate-link",
-                                G_CALLBACK (display_clicked_cb), page, G_CONNECT_SWAPPED);
-       remove_link_padding (WID ("display-link"));
-
-       g_signal_connect_object (WID ("mouse-link"), "activate-link",
-                                G_CALLBACK (mouse_clicked_cb), page, G_CONNECT_SWAPPED);
-       remove_link_padding (WID ("mouse-link"));
-
-       g_signal_connect_object (WID ("display-mapping-button"), "clicked",
-                                G_CALLBACK (display_mapping_button_clicked_cb), page, G_CONNECT_SWAPPED);
-       g_signal_connect_object (WID ("display-mapping-button-2"), "clicked",
-                                G_CALLBACK (display_mapping_button_clicked_cb), page, G_CONNECT_SWAPPED);
-       g_signal_connect_object (WID ("switch-decouple-display"), "notify::active",
-                                G_CALLBACK (decouple_display_toggled_cb), page, G_CONNECT_SWAPPED);
-
-       page->nav = cc_wacom_nav_button_new ();
-        gtk_widget_set_halign (page->nav, GTK_ALIGN_END);
-        gtk_widget_set_margin_start (page->nav, 10);
-       gtk_widget_show (page->nav);
-       gtk_revealer_set_child (GTK_REVEALER (WID ("navigation-placeholder")), page->nav);
-
-       page->cancellable = g_cancellable_new ();
-}
+       /* All displays item */
+       gtk_string_list_append (list, _("All Displays"));
+       variant = g_variant_new_strv ((const gchar *[]) { "", "", "" }, 3);
+       obj = g_list_model_get_item (G_LIST_MODEL (list), idx);
+       g_object_set_data_full (G_OBJECT (obj), "value-output",
+                               variant, (GDestroyNotify) g_variant_unref);
+       if (cur_output == NULL)
+               cur = idx;
+
+       /* "Automatic" item */
+       if (get_layout_type (page->stylus) == LAYOUT_SCREEN) {
+               g_autoptr (GVariant) user_value = NULL;
+
+               idx++;
+               gtk_string_list_append (list, _("Automatic"));
+               automatic_item = idx;
+
+               user_value = g_settings_get_user_value (page->wacom_settings, "output");
+               if (!user_value)
+                       cur = idx;
+       }
 
-static void
-set_icon_name (CcWacomPage *page,
-              const char  *widget_name,
-              const char  *icon_name)
-{
-       g_autofree gchar *resource = NULL;
+       g_signal_handlers_block_by_func (page->tablet_display, on_display_selected, page);
+       adw_combo_row_set_model (ADW_COMBO_ROW (page->tablet_display), G_LIST_MODEL (list));
+       adw_combo_row_set_selected (ADW_COMBO_ROW (page->tablet_display), cur);
+       g_signal_handlers_unblock_by_func (page->tablet_display, on_display_selected, page);
 
-       resource = g_strdup_printf ("/org/gnome/control-center/wacom/%s.svg", icon_name);
-       gtk_picture_set_resource (GTK_PICTURE (WID (widget_name)), resource);
+       gtk_widget_set_sensitive (page->tablet_calibrate, cur == automatic_item);
 }
 
 static void
-remove_left_handed (CcWacomPage *page)
+cc_wacom_page_init (CcWacomPage *page)
 {
-  gtk_grid_remove (GTK_GRID (WID ("main-controls-grid")), WID ("label-left-handed"));
-  gtk_grid_remove (GTK_GRID (WID ("main-controls-grid")), WID ("switch-left-handed"));
-}
+       g_autoptr (GError) error = NULL;
 
-static void
-remove_display_link (CcWacomPage *page)
-{
-  gtk_grid_remove (GTK_GRID (WID ("main-controls-grid")), WID ("display-link"));
-}
+       gtk_widget_init_template (GTK_WIDGET (page));
+       page->rr_screen = gnome_rr_screen_new (gdk_display_get_default (), &error);
 
-static void
-remove_mouse_link (CcWacomPage *page)
-{
-  gtk_grid_remove (GTK_GRID (WID ("main-controls-grid")), WID ("mouse-link"));
+       if (error)
+               g_warning ("Could not get RR screen: %s", error->message);
+
+       g_signal_connect_object (page->rr_screen, "changed",
+                                G_CALLBACK (update_displays_model),
+                                page, G_CONNECT_SWAPPED);
 }
 
 static void
-remove_decouple_options (CcWacomPage *page)
+set_icon_name (CcWacomPage *page,
+              GtkWidget   *widget,
+              const char  *icon_name)
 {
-  gtk_grid_remove (GTK_GRID (WID ("main-controls-grid")), WID ("label-decouple-display"));
-  gtk_grid_remove (GTK_GRID (WID ("main-controls-grid")), WID ("switch-decouple-display"));
-  gtk_grid_remove (GTK_GRID (WID ("main-controls-grid")), WID ("display-mapping-button-2"));
+       g_autofree gchar *resource = NULL;
+
+       resource = g_strdup_printf ("/org/gnome/control-center/wacom/%s.svg", icon_name);
+       gtk_picture_set_resource (GTK_PICTURE (widget), resource);
 }
 
 static gboolean
@@ -872,62 +696,10 @@ has_monitor (CcWacomPage *page)
                 (WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM)) != 0);
 }
 
-static void
-set_grid_row (CcWacomPage *page,
-              const gchar *grid_name,
-              const gchar *widget_name,
-              gint         row)
-{
-  GtkLayoutManager *layout_manager = gtk_widget_get_layout_manager (WID (grid_name));
-  GtkLayoutChild *layout_child = gtk_layout_manager_get_layout_child (layout_manager, WID (widget_name));
-  gtk_grid_layout_child_set_row (GTK_GRID_LAYOUT_CHILD (layout_child), row);
-}
-
-static void
-set_page_layout (CcWacomPage *page,
-                int          layout)
-{
-       WacomIntegrationFlags integration_flags;
-
-       integration_flags = cc_wacom_device_get_integration_flags (page->stylus);
-
-       if ((integration_flags &
-            (WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM)) != 0) {
-               /* FIXME: Check we've got a puck, or a corresponding touchpad device */
-               remove_mouse_link (page);
-       }
-
-       switch (layout) {
-       case LAYOUT_NORMAL:
-               remove_left_handed (page);
-               remove_display_link (page);
-               remove_decouple_options (page);
-               break;
-       case LAYOUT_REVERSIBLE:
-               remove_display_link (page);
-               remove_decouple_options (page);
-               break;
-       case LAYOUT_SCREEN:
-               remove_left_handed (page);
-
-    gtk_box_remove (GTK_BOX (WID ("tablet-buttons-box")), WID ("display-mapping-button"));
-
-               gtk_widget_show (WID ("button-calibrate"));
-               gtk_widget_set_sensitive (WID ("button-calibrate"),
-                                         has_monitor (page));
-
-               set_grid_row (page, "main-controls-grid", "label-trackingmode", 5);
-    set_grid_row (page, "main-controls-grid", "combo-tabletmode", 5);
-               break;
-       default:
-               g_assert_not_reached ();
-       }
-}
-
 static void
 update_pad_availability (CcWacomPage *page)
 {
-       gtk_widget_set_visible (WID ("map-buttons-button"), page->pads != NULL);
+       gtk_widget_set_visible (page->tablet_map_buttons, page->pads != NULL);
 }
 
 static void
@@ -971,6 +743,29 @@ check_remove_pad (CcWacomPage *page,
        update_pad_availability (page);
 }
 
+static GVariant *
+tablet_mode_bind_set (const GValue       *value,
+                     const GVariantType *expected_type,
+                     gpointer            user_data)
+{
+       gboolean setting;
+
+       setting = g_value_get_boolean (value);
+
+       return g_variant_new_string (setting ? "absolute" : "relative");
+}
+
+static gboolean
+tablet_mode_bind_get (GValue   *value,
+                     GVariant *variant,
+                     gpointer  user_data)
+{
+       g_value_set_boolean (value,
+                            g_strcmp0 (g_variant_get_string (variant, NULL),
+                                       "absolute") == 0);
+       return TRUE;
+}
+
 GtkWidget *
 cc_wacom_page_new (CcWacomPanel  *panel,
                   CcWacomDevice *stylus)
@@ -986,23 +781,38 @@ cc_wacom_page_new (CcWacomPanel  *panel,
        page->panel = panel;
        page->stylus = stylus;
 
-       set_page_layout (page, get_layout_type (stylus));
+       gtk_widget_set_visible (page->tablet_left_handed,
+                               get_layout_type (stylus) == LAYOUT_REVERSIBLE);
+       gtk_widget_set_visible (page->tablet_calibrate,
+                               get_layout_type (stylus) == LAYOUT_SCREEN);
 
        /* FIXME move this to construct */
        page->wacom_settings  = cc_wacom_device_get_settings (stylus);
-       set_mode_from_gsettings (GTK_COMBO_BOX (WID ("combo-tabletmode")), page);
-       if (get_layout_type (page->stylus) == LAYOUT_SCREEN)
-               set_display_decoupled_from_gsettings (GTK_SWITCH (WID ("switch-decouple-display")), page);
 
        /* Tablet name */
-       gtk_label_set_text (GTK_LABEL (WID ("label-tabletmodel")), cc_wacom_device_get_name (stylus));
-
-       /* Left-handedness */
-       if (cc_wacom_device_is_reversible (stylus))
-               set_left_handed_from_gsettings (page);
+       gtk_label_set_text (GTK_LABEL (page->tablet_name), cc_wacom_device_get_name (stylus));
+
+       g_settings_bind_with_mapping (page->wacom_settings, "mapping",
+                                     page->tablet_mode_switch, "active",
+                                     G_SETTINGS_BIND_DEFAULT,
+                                     tablet_mode_bind_get,
+                                     tablet_mode_bind_set,
+                                     NULL, NULL);
+       g_settings_bind_with_mapping (page->wacom_settings, "mapping",
+                                     page->display_section, "sensitive",
+                                     G_SETTINGS_BIND_DEFAULT,
+                                     tablet_mode_bind_get,
+                                     tablet_mode_bind_set,
+                                     NULL, NULL);
+       g_settings_bind (page->wacom_settings, "left-handed",
+                        page->tablet_left_handed_switch, "active",
+                        G_SETTINGS_BIND_DEFAULT);
+       g_settings_bind (page->wacom_settings, "keep-aspect",
+                        page->tablet_aspect_ratio_switch, "active",
+                        G_SETTINGS_BIND_DEFAULT);
 
        /* Tablet icon */
-       set_icon_name (page, "image-tablet", cc_wacom_device_get_icon_name (stylus));
+       set_icon_name (page, page->tablet_icon, cc_wacom_device_get_icon_name (stylus));
 
        /* Listen to changes in related/paired pads */
        page->manager = gsd_device_manager_get ();
@@ -1017,20 +827,10 @@ cc_wacom_page_new (CcWacomPanel  *panel,
        for (l = pads; l ; l = l->next)
                check_add_pad (page, l->data);
 
-       return GTK_WIDGET (page);
-}
-
-void
-cc_wacom_page_set_navigation (CcWacomPage *page,
-                             GtkNotebook *notebook,
-                             gboolean     ignore_first_page)
-{
-       g_return_if_fail (CC_IS_WACOM_PAGE (page));
+       update_pad_availability (page);
+       update_displays_model (page);
 
-       g_object_set (G_OBJECT (page->nav),
-                     "notebook", notebook,
-                     "ignore-first", ignore_first_page,
-                     NULL);
+       return GTK_WIDGET (page);
 }
 
 void
diff --git a/panels/wacom/cc-wacom-page.h b/panels/wacom/cc-wacom-page.h
index 56b32ac87..76a16ecc1 100644
--- a/panels/wacom/cc-wacom-page.h
+++ b/panels/wacom/cc-wacom-page.h
@@ -32,10 +32,6 @@ G_DECLARE_FINAL_TYPE (CcWacomPage, cc_wacom_page, CC, WACOM_PAGE, GtkBox)
 GtkWidget * cc_wacom_page_new (CcWacomPanel  *panel,
                               CcWacomDevice *stylus);
 
-void cc_wacom_page_set_navigation (CcWacomPage *page,
-                                  GtkNotebook *notebook,
-                                  gboolean     ignore_first_page);
-
 void        cc_wacom_page_calibrate        (CcWacomPage *page);
 
 gboolean    cc_wacom_page_can_calibrate    (CcWacomPage *page);
diff --git a/panels/wacom/cc-wacom-page.ui b/panels/wacom/cc-wacom-page.ui
new file mode 100644
index 000000000..654b2a1f7
--- /dev/null
+++ b/panels/wacom/cc-wacom-page.ui
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="CcWacomPage" parent="GtkBox">
+    <property name="orientation">vertical</property>
+    <property name="spacing">24</property>
+    <child>
+      <object class="GtkBox">
+        <child>
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
+            <property name="hexpand">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="tablet_name">
+                <property name="halign">start</property>
+                <style>
+                  <class name="heading"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="tablet_subtitle">
+                <property name="halign">start</property>
+                <property name="wrap">True</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkPicture" id="tablet_icon">
+            <property name="halign">end</property>
+            <property name="valign">start</property>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="AdwPreferencesGroup">
+        <child>
+          <object class="AdwActionRow" id="tablet_mode">
+            <property name="title" translatable="yes">Tablet Mode</property>
+            <property name="subtitle" translatable="yes">Use absolute positioning for the pen</property>
+            <child>
+              <object class="GtkSwitch" id="tablet_mode_switch">
+                <property name="valign">center</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwActionRow" id="tablet_left_handed">
+            <property name="title" translatable="yes">Left Hand Orientation</property>
+            <property name="subtitle" translatable="yes">Tablet and Express Keys™ are rotated for left hand 
use</property>
+            <child>
+              <object class="GtkSwitch" id="tablet_left_handed_switch">
+                <property name="valign">center</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwActionRow" id="tablet_map_buttons">
+            <property name="title" translatable="yes">Map Buttons</property>
+            <property name="activatable">True</property>
+            <signal name="activated" handler="on_map_buttons_activated" object="CcWacomPage" swapped="yes" />
+            <child type="suffix">
+              <object class="GtkImage">
+                <property name="icon-name">go-next-symbolic</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+
+    <child>
+      <object class="AdwPreferencesGroup" id="display_section">
+        <child>
+          <object class="AdwComboRow" id="tablet_display">
+            <property name="width_request">100</property>
+            <property name="title" translatable="yes" context="display setting">Map to Monitor</property>
+            <signal name="notify::selected-item" handler="on_display_selected" swapped="no"/>
+          </object>
+        </child>
+        <child>
+          <object class="AdwActionRow" id="tablet_aspect_ratio">
+            <property name="title" translatable="yes">Keep Aspect Ratio</property>
+            <property name="subtitle" translatable="yes">Only use a portion of the tablet surface to keep 
monitor aspect ratio</property>
+            <child>
+              <object class="GtkSwitch" id="tablet_aspect_ratio_switch">
+                <property name="valign">center</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwActionRow" id="tablet_calibrate">
+            <property name="title" translatable="yes">Calibrate</property>
+            <property name="activatable">True</property>
+            <signal name="activated" handler="on_calibrate_activated" object="CcWacomPage" swapped="yes" />
+            <child type="suffix">
+              <object class="GtkImage">
+                <property name="icon-name">go-next-symbolic</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/panels/wacom/cc-wacom-panel.c b/panels/wacom/cc-wacom-panel.c
index f75e4baf8..0c808c24b 100644
--- a/panels/wacom/cc-wacom-panel.c
+++ b/panels/wacom/cc-wacom-panel.c
@@ -39,20 +39,16 @@
 #include <gdk/wayland/gdkwayland.h>
 #endif
 
-#define WID(x) (GtkWidget *) gtk_builder_get_object (self->builder, x)
-
 struct _CcWacomPanel
 {
        CcPanel           parent_instance;
 
-       GtkBuilder       *builder;
-       GtkWidget        *stack;
-       GtkWidget        *switcher;
-       GtkWidget        *tablet_notebook;
-       GtkWidget        *stylus_notebook;
        GtkWidget        *test_popover;
        GtkWidget        *test_draw_area;
        GtkWidget        *test_button;
+       GtkWidget        *scrollable;
+       GtkWidget        *tablets;
+       GtkWidget        *styli;
        GHashTable       *devices; /* key=GsdDevice, value=CcWacomDevice */
        GHashTable       *pages; /* key=CcWacomDevice, value=GtkWidget */
        GHashTable       *stylus_pages; /* key=CcWacomTool, value=GtkWidget */
@@ -60,8 +56,11 @@ struct _CcWacomPanel
 
        CcTabletToolMap  *tablet_tool_map;
 
+       GtkAdjustment    *vadjustment;
        GtkGesture       *stylus_gesture;
 
+       GtkWidget        *highlighted_widget;
+
        /* DBus */
        GDBusProxy    *proxy;
 };
@@ -135,12 +134,27 @@ lookup_wacom_device (CcWacomPanel *self,
        return NULL;
 }
 
+static void
+highlight_widget (CcWacomPanel *self, GtkWidget *widget)
+{
+       double y;
+
+       if (self->highlighted_widget == widget)
+               return;
+
+       gtk_widget_translate_coordinates (widget,
+                                         self->scrollable,
+                                         0, 0,
+                                         NULL, &y);
+       gtk_adjustment_set_value (self->vadjustment, y);
+       self->highlighted_widget = widget;
+}
+
 static CcWacomPage *
-set_device_page (CcWacomPanel *self, const gchar *device_name)
+update_highlighted_device (CcWacomPanel *self, const gchar *device_name)
 {
        CcWacomPage *page;
        CcWacomDevice *wacom_device;
-       gint current;
 
        if (device_name == NULL)
                return NULL;
@@ -152,8 +166,7 @@ set_device_page (CcWacomPanel *self, const gchar *device_name)
        }
 
        page = g_hash_table_lookup (self->pages, wacom_device);
-       current = gtk_notebook_page_num (GTK_NOTEBOOK (self->tablet_notebook), GTK_WIDGET (page));
-       gtk_notebook_set_current_page (GTK_NOTEBOOK (self->tablet_notebook), current);
+       highlight_widget (self, GTK_WIDGET (page));
 
        return page;
 }
@@ -181,7 +194,7 @@ run_operation_from_params (CcWacomPanel *self, GVariant *parameters)
 
        switch (n_params) {
                case 3:
-                       page = set_device_page (self, device_name);
+                       page = update_highlighted_device (self, device_name);
                        if (page == NULL)
                                return;
 
@@ -202,7 +215,7 @@ run_operation_from_params (CcWacomPanel *self, GVariant *parameters)
                                g_warning ("Ignoring unrecognized operation '%s'", operation);
                        }
                case 2:
-                       set_device_page (self, device_name);
+                       update_highlighted_device (self, device_name);
                        break;
                case 1:
                        g_assert_not_reached ();
@@ -266,8 +279,6 @@ cc_wacom_panel_dispose (GObject *object)
        }
 
 
-       g_clear_object (&self->builder);
-
        g_clear_pointer (&self->devices, g_hash_table_unref);
        g_clear_object (&self->proxy);
        g_clear_pointer (&self->pages, g_hash_table_unref);
@@ -299,13 +310,10 @@ check_remove_stylus_pages (CcWacomPanel *self)
         */
        g_hash_table_iter_init (&iter, self->stylus_pages);
        while (g_hash_table_iter_next (&iter, (gpointer*) &tool, (gpointer*) &page)) {
-               gint page_num;
-
                if (g_list_find (total, tool))
                        continue;
 
-               page_num = gtk_notebook_page_num (GTK_NOTEBOOK (self->stylus_notebook), page);
-               gtk_notebook_remove_page (GTK_NOTEBOOK (self->stylus_notebook), page_num);
+               gtk_box_remove (GTK_BOX (self->styli), page);
                g_hash_table_iter_remove (&iter);
        }
 }
@@ -320,14 +328,9 @@ add_stylus (CcWacomPanel *self,
                return FALSE;
 
        page = cc_wacom_stylus_page_new (tool);
-       cc_wacom_stylus_page_set_navigation (CC_WACOM_STYLUS_PAGE (page),
-                                            GTK_NOTEBOOK (self->stylus_notebook));
-       gtk_notebook_append_page (GTK_NOTEBOOK (self->stylus_notebook), page, NULL);
+       gtk_box_append (GTK_BOX (self->styli), page);
        g_hash_table_insert (self->stylus_pages, tool, page);
 
-       if (gtk_notebook_get_current_page (GTK_NOTEBOOK (self->stylus_notebook)) == 0)
-               gtk_notebook_set_current_page (GTK_NOTEBOOK (self->stylus_notebook), 1);
-
        return TRUE;
 }
 
@@ -346,21 +349,13 @@ update_test_button (CcWacomPanel *self)
 }
 
 static void
-update_stylus_notebook (CcWacomPanel *panel,
-                       CcWacomTool  *stylus)
+update_highlighted_stylus (CcWacomPanel *panel,
+                          CcWacomTool  *stylus)
 {
-       if (panel->stylus_notebook ==
-           gtk_stack_get_visible_child (GTK_STACK (panel->stack))) {
-               GtkWidget *widget;
-               gint page;
-
-               widget = g_hash_table_lookup (panel->stylus_pages, stylus);
-               page = gtk_notebook_page_num (GTK_NOTEBOOK (panel->stylus_notebook), widget);
-               gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->stylus_notebook), page);
-       } else {
-               GtkStackPage *page = gtk_stack_get_page (GTK_STACK (panel->stack), panel->stylus_notebook);
-               gtk_stack_page_set_needs_attention (page, TRUE);
-       }
+       GtkWidget *widget;
+
+       widget = g_hash_table_lookup (panel->stylus_pages, stylus);
+       highlight_widget (panel, widget);
 }
 
 static void
@@ -373,7 +368,6 @@ update_current_tool (CcWacomPanel  *panel,
        CcWacomTool *stylus;
        GsdDevice *gsd_device;
        guint64 serial, id;
-       gboolean added;
 
        if (!tool)
                return;
@@ -423,10 +417,9 @@ update_current_tool (CcWacomPanel  *panel,
                        return;
         }
 
-       added = add_stylus (panel, stylus);
+       add_stylus (panel, stylus);
 
-       if (added)
-               update_stylus_notebook (panel, stylus);
+       update_highlighted_stylus (panel, stylus);
 
        cc_tablet_tool_map_add_relation (panel->tablet_tool_map,
                                         wacom_device, stylus);
@@ -467,7 +460,7 @@ show_mock_stylus_cb (gpointer user_data)
 
        stylus = cc_wacom_tool_new (0, 0, wacom_device);
        add_stylus (panel, stylus);
-       update_stylus_notebook (panel, stylus);
+       update_highlighted_stylus (panel, stylus);
        cc_tablet_tool_map_add_relation (panel->tablet_tool_map,
                                         wacom_device, stylus);
 
@@ -506,6 +499,7 @@ cc_wacom_panel_class_init (CcWacomPanelClass *klass)
 {
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
        CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
        object_class->get_property = cc_wacom_panel_get_property;
        object_class->set_property = cc_wacom_panel_set_property;
@@ -515,18 +509,18 @@ cc_wacom_panel_class_init (CcWacomPanelClass *klass)
        panel_class->get_help_uri = cc_wacom_panel_get_help_uri;
 
        g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
-}
 
-static void
-update_current_page (CcWacomPanel  *self)
-{
-       int num_pages;
+       g_type_ensure (CC_TYPE_DRAWING_AREA);
 
-       num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (self->tablet_notebook));
-       if (num_pages > 1)
-               gtk_notebook_set_current_page (GTK_NOTEBOOK (self->tablet_notebook), 1);
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/control-center/wacom/cc-wacom-panel.ui");
 
-       update_test_button (self);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, scrollable);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_button);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_popover);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_draw_area);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, tablets);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, styli);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, vadjustment);
 }
 
 static void
@@ -564,9 +558,7 @@ add_known_device (CcWacomPanel *self,
        }
 
        page = cc_wacom_page_new (self, device);
-       cc_wacom_page_set_navigation (CC_WACOM_PAGE (page), GTK_NOTEBOOK (self->tablet_notebook), TRUE);
-       gtk_widget_show (page);
-       gtk_notebook_append_page (GTK_NOTEBOOK (self->tablet_notebook), page, NULL);
+       gtk_box_append (GTK_BOX (self->tablets), page);
        g_hash_table_insert (self->pages, device, page);
 }
 
@@ -583,14 +575,13 @@ device_removed_cb (CcWacomPanel     *self,
 
        page = g_hash_table_lookup (self->pages, device);
        if (page) {
-    gint page_num = gtk_notebook_page_num (GTK_NOTEBOOK (self->tablet_notebook), page);
-    gtk_notebook_remove_page (GTK_NOTEBOOK (self->tablet_notebook), page_num);
                g_hash_table_remove (self->pages, device);
+               gtk_box_remove (GTK_BOX (self->tablets), page);
        }
 
        g_hash_table_remove (self->devices, gsd_device);
        check_remove_stylus_pages (self);
-       update_current_page (self);
+       update_test_button (self);
 }
 
 static void
@@ -598,14 +589,7 @@ device_added_cb (CcWacomPanel *self,
                 GsdDevice    *device)
 {
        add_known_device (self, device);
-       update_current_page (self);
-}
-
-static gboolean
-link_activated (CcWacomPanel  *self)
-{
-       cc_wacom_panel_switch_to_panel (self, "bluetooth");
-       return TRUE;
+       update_test_button (self);
 }
 
 void
@@ -639,62 +623,17 @@ got_osd_proxy_cb (GObject      *source_object,
        }
 }
 
-static void
-enbiggen_label (GtkLabel *label)
-{
-       const char *str;
-       g_autofree char *new_str = NULL;
-
-       str = gtk_label_get_text (label);
-       new_str = g_strdup_printf ("<big>%s</big>", str);
-       gtk_label_set_markup (label, new_str);
-}
-
-static void
-on_stack_visible_child_notify_cb (CcWacomPanel *panel)
-{
-       GtkWidget *child;
-
-       child = gtk_stack_get_visible_child (GTK_STACK (panel->stack));
-
-       if (child == panel->stylus_notebook) {
-               GtkStackPage *page = gtk_stack_get_page (GTK_STACK (panel->stack), panel->stylus_notebook);
-               gtk_stack_page_set_needs_attention (page, FALSE);
-       }
-}
-
 static void
 cc_wacom_panel_init (CcWacomPanel *self)
 {
-  GtkWidget *titlebar;
-  GtkWidget *button;
-       GtkWidget *widget;
        GsdDeviceManager *device_manager;
        g_autoptr(GList) devices = NULL;
        GList *l;
        g_autoptr(GError) error = NULL;
-       char *objects[] = {
-               "main-box",
-               "no-stylus-page",
-               NULL
-       };
 
         g_resources_register (cc_wacom_get_resource ());
 
-       self->builder = gtk_builder_new ();
-
-       gtk_builder_add_objects_from_resource (self->builder,
-                                               "/org/gnome/control-center/wacom/gnome-wacom-properties.ui",
-                                               objects,
-                                               &error);
-       gtk_builder_add_objects_from_resource (self->builder,
-                                               "/org/gnome/control-center/wacom/wacom-stylus-page.ui",
-                                               objects,
-                                               &error);
-       if (error != NULL) {
-               g_warning ("Error loading UI file: %s", error->message);
-               return;
-       }
+       gtk_widget_init_template (GTK_WIDGET (self));
 
        self->tablet_tool_map = cc_tablet_tool_map_new ();
 
@@ -708,55 +647,6 @@ cc_wacom_panel_init (CcWacomPanel *self)
                                  got_osd_proxy_cb,
                                  self);
 
-       /* Stack + Switcher */
-       self->stack = gtk_stack_new ();
-       g_object_set (G_OBJECT (self->stack),
-                     "margin-top", 30,
-                     "margin-end", 30,
-                     "margin-start", 30,
-                     "margin-bottom", 30,
-                     NULL);
-
-       g_signal_connect_object (self->stack, "notify::visible-child",
-                                G_CALLBACK (on_stack_visible_child_notify_cb), self, G_CONNECT_SWAPPED);
-
-       self->switcher = gtk_stack_switcher_new ();
-       gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER (self->switcher),
-                                     GTK_STACK (self->stack));
-
-       cc_panel_set_content (CC_PANEL (self), GTK_WIDGET (self->stack));
-       gtk_widget_show (self->stack);
-
-       self->tablet_notebook = gtk_notebook_new ();
-       gtk_notebook_set_show_tabs (GTK_NOTEBOOK (self->tablet_notebook), FALSE);
-       gtk_notebook_set_show_border (GTK_NOTEBOOK (self->tablet_notebook), FALSE);
-       gtk_widget_set_vexpand (self->tablet_notebook, TRUE);
-
-       self->stylus_notebook = gtk_notebook_new ();
-       gtk_notebook_set_show_tabs (GTK_NOTEBOOK (self->stylus_notebook), FALSE);
-       gtk_notebook_set_show_border (GTK_NOTEBOOK (self->stylus_notebook), FALSE);
-       gtk_widget_set_vexpand (self->stylus_notebook, TRUE);
-
-       gtk_stack_add_titled (GTK_STACK (self->stack),
-                             self->stylus_notebook, "stylus",
-                             _("Stylus"));
-       gtk_stack_add_titled (GTK_STACK (self->stack),
-                             self->tablet_notebook, "tablet",
-                             _("Tablet"));
-
-       /* No styli page */
-       widget = WID ("no-stylus-page");
-       enbiggen_label (GTK_LABEL (WID ("no-stylus-label1")));
-       gtk_notebook_append_page (GTK_NOTEBOOK (self->stylus_notebook), widget, NULL);
-
-       /* No tablets page */
-       widget = WID ("main-box");
-       enbiggen_label (GTK_LABEL (WID ("advice-label1")));
-       gtk_notebook_append_page (GTK_NOTEBOOK (self->tablet_notebook), widget, NULL);
-
-       g_signal_connect_object (WID ("linkbutton"), "activate-link",
-                                G_CALLBACK (link_activated), self, G_CONNECT_SWAPPED);
-
        self->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
        self->pages = g_hash_table_new (NULL, NULL);
        self->stylus_pages = g_hash_table_new (NULL, NULL);
@@ -772,28 +662,7 @@ cc_wacom_panel_init (CcWacomPanel *self)
        for (l = devices; l ; l = l->next)
                add_known_device (self, l->data);
 
-       update_current_page (self);
-
-  /* Titlebar widgets */
-       button = gtk_menu_button_new ();
-       gtk_menu_button_set_use_underline (GTK_MENU_BUTTON (button), TRUE);
-       gtk_menu_button_set_label (GTK_MENU_BUTTON (button), _("Test Your _Settings"));
-       gtk_widget_add_css_class (button, "text-button");
-       gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
-
-       self->test_popover = gtk_popover_new ();
-       gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), self->test_popover);
-
-       self->test_draw_area = cc_drawing_area_new ();
-       gtk_widget_set_size_request (self->test_draw_area, 400, 300);
-       gtk_popover_set_child (GTK_POPOVER (self->test_popover), self->test_draw_area);
-
-       self->test_button = button;
        update_test_button (self);
-
-  titlebar = cc_panel_get_titlebar (CC_PANEL (self));
-  adw_header_bar_set_title_widget (ADW_HEADER_BAR (titlebar), self->switcher);
-  adw_header_bar_pack_end (ADW_HEADER_BAR (titlebar), button);
 }
 
 GDBusProxy *
diff --git a/panels/wacom/cc-wacom-panel.ui b/panels/wacom/cc-wacom-panel.ui
new file mode 100644
index 000000000..28a9d79b6
--- /dev/null
+++ b/panels/wacom/cc-wacom-panel.ui
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="CcWacomPanel" parent="CcPanel">
+
+    <child type="titlebar-end">
+      <object class="GtkMenuButton" id="test_button">
+        <property name="use_underline">True</property>
+        <property name="valign">center</property>
+        <property name="label" translatable="yes">Test Your _Settings</property>
+        <property name="popover">test_popover</property>
+        <style>
+          <class name="text-button"/>
+        </style>
+      </object>
+    </child>
+
+    <child type="content">
+      <object class="GtkScrolledWindow">
+        <property name="hscrollbar-policy">never</property>
+        <property name="vadjustment">vadjustment</property>
+        <child>
+          <object class="AdwClamp" id="scrollable">
+            <property name="margin_top">32</property>
+            <property name="margin_bottom">32</property>
+            <property name="margin_start">12</property>
+            <property name="margin_end">12</property>
+
+            <child>
+              <object class="GtkBox">
+                <property name="spacing">48</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkBox" id="tablets">
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">48</property>
+                 </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="styli">
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">48</property>
+                 </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+
+  <object class="GtkAdjustment" id="vadjustment" />
+
+  <!-- Test Popover -->
+  <object class="GtkPopover" id="test_popover">
+    <style>
+      <class name="menu" />
+    </style>
+    <child>
+      <object class="GtkBox">
+        <property name="margin-top">12</property>
+        <property name="margin-bottom">12</property>
+        <property name="margin-start">12</property>
+        <property name="margin-end">12</property>
+        <property name="spacing">6</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="CcDrawingArea" id="test_draw_area">
+            <property name="width-request">400</property>
+            <property name="height-request">300</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/panels/wacom/cc-wacom-stylus-page.c b/panels/wacom/cc-wacom-stylus-page.c
index 5d60357a8..d84594a93 100644
--- a/panels/wacom/cc-wacom-stylus-page.c
+++ b/panels/wacom/cc-wacom-stylus-page.c
@@ -21,35 +21,35 @@
 
 #include <config.h>
 
+#include <adwaita.h>
 #include <glib/gi18n.h>
 #include "cc-wacom-stylus-page.h"
-#include "cc-wacom-nav-button.h"
 #include <gtk/gtk.h>
 #include <gdesktop-enums.h>
 
 #include <string.h>
 
-#define WID(x) (GtkWidget *) gtk_builder_get_object (page->builder, x)
-
 struct _CcWacomStylusPage
 {
        GtkBox          parent_instance;
 
+       GtkWidget      *stylus_name;
+       GtkWidget      *stylus_subtitle;
+       GtkWidget      *stylus_icon;
+       GtkWidget      *stylus_button1_action;
+       GtkWidget      *stylus_button2_action;
+       GtkWidget      *stylus_button3_action;
+       GtkWidget      *stylus_eraser_pressure;
+       GtkWidget      *stylus_tip_pressure_scale;
+       GtkWidget      *stylus_eraser_pressure_scale;
+       GtkAdjustment  *stylus_tip_pressure_adjustment;
+       GtkAdjustment  *stylus_eraser_pressure_adjustment;
        CcWacomTool    *stylus;
-       GtkBuilder     *builder;
-       GtkWidget      *nav;
        GSettings      *stylus_settings;
 };
 
 G_DEFINE_TYPE (CcWacomStylusPage, cc_wacom_stylus_page, GTK_TYPE_BOX)
 
-/* Button combo box storage columns */
-enum {
-       BUTTONNUMBER_COLUMN,
-       BUTTONNAME_COLUMN,
-       N_BUTTONCOLUMNS
-};
-
 /* GSettings stores pressurecurve as 4 values like the driver. We map slider
  * scale to these values given the array below. These settings were taken from
  * wacomcpl, where they've been around for years.
@@ -82,15 +82,15 @@ set_pressurecurve (GtkRange *range, GSettings *settings, const gchar *key)
 }
 
 static void
-tip_feel_value_changed_cb (CcWacomStylusPage *page)
+on_tip_pressure_value_changed (CcWacomStylusPage *page)
 {
-       set_pressurecurve (GTK_RANGE (WID ("scale-tip-feel")), page->stylus_settings, "pressure-curve");
+       set_pressurecurve (GTK_RANGE (page->stylus_tip_pressure_scale), page->stylus_settings, 
"pressure-curve");
 }
 
 static void
-eraser_feel_value_changed_cb (CcWacomStylusPage *page)
+on_eraser_pressure_value_changed (CcWacomStylusPage *page)
 {
-       set_pressurecurve (GTK_RANGE (WID ("scale-eraser-feel")), page->stylus_settings, 
"eraser-pressure-curve");
+       set_pressurecurve (GTK_RANGE (page->stylus_eraser_pressure_scale), page->stylus_settings, 
"eraser-pressure-curve");
 }
 
 static void
@@ -117,97 +117,6 @@ set_feel_from_gsettings (GtkAdjustment *adjustment, GSettings *settings, const g
        }
 }
 
-static void
-set_button_mapping_from_gsettings (GtkComboBox *combo, GSettings* settings, const gchar *key)
-{
-       GDesktopStylusButtonAction action;
-       GtkTreeModel    *model;
-       GtkTreeIter      iter;
-       gboolean         valid;
-
-       action = g_settings_get_enum (settings, key);
-       model = gtk_combo_box_get_model (combo);
-       valid = gtk_tree_model_get_iter_first (model, &iter);
-
-       while (valid) {
-               gint button;
-
-               gtk_tree_model_get (model, &iter,
-                                   BUTTONNUMBER_COLUMN, &button,
-                                   -1);
-
-               /* Currently button values match logical X buttons. If we
-                * introduce things like double-click, this code must
-                * change. Recommendation: use negative buttons numbers for
-                * special ones.
-                */
-
-               if (button == action) {
-                       gtk_combo_box_set_active_iter (combo, &iter);
-                       break;
-               }
-
-               valid = gtk_tree_model_iter_next (model, &iter);
-       }
-}
-
-static void
-button_changed_cb (CcWacomStylusPage *page)
-{
-       GtkTreeIter             iter;
-       GtkListStore            *liststore;
-       gint                    mapping_b2,
-                               mapping_b3,
-                               mapping_b4;
-
-       if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (WID ("combo-bottombutton")), &iter))
-               return;
-
-       liststore = GTK_LIST_STORE (WID ("liststore-buttons"));
-       gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
-                           BUTTONNUMBER_COLUMN, &mapping_b2,
-                           -1);
-
-       if (cc_wacom_tool_get_num_buttons (page->stylus) > 1) {
-               if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (WID ("combo-topbutton")), &iter))
-                       return;
-
-               gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
-                                   BUTTONNUMBER_COLUMN, &mapping_b3,
-                                   -1);
-       } else {
-               mapping_b3 = 0;
-       }
-
-       if (cc_wacom_tool_get_num_buttons (page->stylus) > 2) {
-               if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (WID ("combo-thirdbutton")), &iter))
-                       return;
-
-               gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
-                                   BUTTONNUMBER_COLUMN, &mapping_b4,
-                                   -1);
-       } else {
-               mapping_b4 = 0;
-       }
-
-       g_settings_set_enum (page->stylus_settings, "button-action", mapping_b2);
-       g_settings_set_enum (page->stylus_settings, "secondary-button-action", mapping_b3);
-       g_settings_set_enum (page->stylus_settings, "tertiary-button-action", mapping_b4);
-}
-
-static void
-combobox_text_cellrenderer (GtkComboBox *combo, int name_column)
-{
-       GtkCellRenderer *renderer;
-
-       renderer = gtk_cell_renderer_text_new ();
-       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
-       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
-                                       "text", BUTTONNAME_COLUMN, NULL);
-}
-
-/* Boilerplate code goes below */
-
 static void
 cc_wacom_stylus_page_get_property (GObject    *object,
                              guint       property_id,
@@ -235,182 +144,80 @@ cc_wacom_stylus_page_set_property (GObject      *object,
 }
 
 static void
-cc_wacom_stylus_page_dispose (GObject *object)
+on_stylus_action_selected (GtkWidget         *widget,
+                          GParamSpec        *pspec,
+                          CcWacomStylusPage *page)
 {
-       CcWacomStylusPage *page = CC_WACOM_STYLUS_PAGE (object);
+       gint idx;
 
-       g_clear_object (&page->builder);
+       idx = adw_combo_row_get_selected (ADW_COMBO_ROW (widget));
 
-       G_OBJECT_CLASS (cc_wacom_stylus_page_parent_class)->dispose (object);
+       if (widget == page->stylus_button1_action)
+               g_settings_set_enum (page->stylus_settings, "button-action", idx);
+       else if (widget == page->stylus_button2_action)
+               g_settings_set_enum (page->stylus_settings, "secondary-button-action", idx);
+       else if (widget == page->stylus_button3_action)
+               g_settings_set_enum (page->stylus_settings, "tertiary-button-action", idx);
 }
 
 static void
 cc_wacom_stylus_page_class_init (CcWacomStylusPageClass *klass)
 {
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
        object_class->get_property = cc_wacom_stylus_page_get_property;
        object_class->set_property = cc_wacom_stylus_page_set_property;
-       object_class->dispose = cc_wacom_stylus_page_dispose;
+
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/control-center/wacom/cc-wacom-stylus-page.ui");
+
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_name);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_subtitle);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_icon);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_button1_action);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_button2_action);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_button3_action);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_eraser_pressure);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_tip_pressure_scale);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, stylus_eraser_pressure_scale);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, 
stylus_tip_pressure_adjustment);
+       gtk_widget_class_bind_template_child (widget_class, CcWacomStylusPage, 
stylus_eraser_pressure_adjustment);
+
+       gtk_widget_class_bind_template_callback (widget_class, on_stylus_action_selected);
+       gtk_widget_class_bind_template_callback (widget_class, on_tip_pressure_value_changed);
+       gtk_widget_class_bind_template_callback (widget_class, on_eraser_pressure_value_changed);
 }
 
 static void
 add_marks (GtkScale *scale)
 {
+#if 0
        gint i;
 
        for (i = 0; i < N_PRESSURE_CURVES; i++)
                gtk_scale_add_mark (scale, i, GTK_POS_BOTTOM, NULL);
+#endif
 }
 
 static void
 cc_wacom_stylus_page_init (CcWacomStylusPage *page)
 {
-       g_autoptr(GError) error = NULL;
-       GtkComboBox *combo;
-       GtkWidget *box;
-       char *objects[] = {
-               "stylus-grid",
-               "liststore-buttons",
-               "adjustment-tip-feel",
-               "adjustment-eraser-feel",
-               NULL
-       };
-
-       page->builder = gtk_builder_new ();
-
-       gtk_builder_add_objects_from_resource (page->builder,
-                                               "/org/gnome/control-center/wacom/wacom-stylus-page.ui",
-                                               objects,
-                                               &error);
-       if (error != NULL) {
-               g_warning ("Error loading UI file: %s", error->message);
-               return;
-       }
+       gtk_widget_init_template (GTK_WIDGET (page));
 
-       box = WID ("stylus-grid");
-       gtk_box_append (GTK_BOX (page), box);
-       gtk_widget_set_vexpand (GTK_WIDGET (box), TRUE);
-
-       add_marks (GTK_SCALE (WID ("scale-tip-feel")));
-       add_marks (GTK_SCALE (WID ("scale-eraser-feel")));
-
-       g_signal_connect_object (WID ("scale-tip-feel"), "value-changed",
-                                 G_CALLBACK (tip_feel_value_changed_cb), page, G_CONNECT_SWAPPED);
-       g_signal_connect_object (WID ("scale-eraser-feel"), "value-changed",
-                                 G_CALLBACK (eraser_feel_value_changed_cb), page, G_CONNECT_SWAPPED);
-
-       combo = GTK_COMBO_BOX (WID ("combo-topbutton"));
-       combobox_text_cellrenderer (combo, BUTTONNAME_COLUMN);
-       g_signal_connect_object (combo, "changed",
-                                 G_CALLBACK (button_changed_cb), page, G_CONNECT_SWAPPED);
-
-       combo = GTK_COMBO_BOX (WID ("combo-bottombutton"));
-       combobox_text_cellrenderer (combo, BUTTONNAME_COLUMN);
-       g_signal_connect_object (combo, "changed",
-                                 G_CALLBACK (button_changed_cb), page, G_CONNECT_SWAPPED);
-
-       combo = GTK_COMBO_BOX (WID ("combo-thirdbutton"));
-       combobox_text_cellrenderer (combo, BUTTONNAME_COLUMN);
-       g_signal_connect_object (G_OBJECT (combo), "changed",
-                                 G_CALLBACK (button_changed_cb), page, G_CONNECT_SWAPPED);
-
-       page->nav = cc_wacom_nav_button_new ();
-        gtk_widget_set_halign (page->nav, GTK_ALIGN_END);
-        gtk_widget_set_margin_start (page->nav, 10);
-       gtk_revealer_set_child (GTK_REVEALER (WID ("navigation-placeholder")), page->nav);
+       add_marks (GTK_SCALE (page->stylus_tip_pressure_scale));
+       add_marks (GTK_SCALE (page->stylus_eraser_pressure_scale));
 }
 
 static void
 set_icon_name (CcWacomStylusPage *page,
-              const char  *widget_name,
-              const char  *icon_name)
+              const char        *icon_name)
 {
+#if 0
        g_autofree gchar *resource = NULL;
 
        resource = g_strdup_printf ("/org/gnome/control-center/wacom/%s.svg", icon_name);
-       gtk_picture_set_resource (GTK_PICTURE (WID (widget_name)), resource);
-}
-
-/* Different types of layout for the stylus config */
-enum {
-       LAYOUT_NORMAL,                      /* eraser, 2 buttons, tip */
-       LAYOUT_INKING,                      /* tip */
-       LAYOUT_AIRBRUSH,                    /* eraser, 1 button, tip */
-       LAYOUT_GENERIC_2_BUTTONS_NO_ERASER, /* 2 buttons, tip, no eraser */
-       LAYOUT_3DPEN,                       /* 3 buttons, tip, no eraser */
-       LAYOUT_OTHER
-};
-
-static void
-remove_buttons (CcWacomStylusPage *page, int n)
-{
-       if (n < 3) {
-               gtk_grid_remove (GTK_GRID (WID ("stylus-controls-grid")), WID ("combo-thirdbutton"));
-               gtk_grid_remove (GTK_GRID (WID ("stylus-controls-grid")), WID ("label-third-button"));
-       }
-       if (n < 2) {
-               gtk_grid_remove (GTK_GRID (WID ("stylus-controls-grid")), WID ("combo-topbutton"));
-               gtk_grid_remove (GTK_GRID (WID ("stylus-controls-grid")), WID ("label-top-button"));
-               gtk_label_set_text (GTK_LABEL (WID ("label-lower-button")), _("Button"));
-       }
-       if (n < 1) {
-               gtk_grid_remove (GTK_GRID (WID ("stylus-controls-grid")), WID ("combo-bottombutton"));
-               gtk_grid_remove (GTK_GRID (WID ("stylus-controls-grid")), WID ("label-lower-button"));
-       }
-}
-
-static void
-remove_eraser (CcWacomStylusPage *page)
-{
-       gtk_grid_remove (GTK_GRID (WID ("stylus-controls-grid")), WID ("eraser-box"));
-       gtk_grid_remove (GTK_GRID (WID ("stylus-controls-grid")), WID ("label-eraser-feel"));
-}
-
-static void
-set_grid_row (CcWacomStylusPage *page,
-             const gchar       *grid_name,
-             const gchar       *widget_name,
-             gint               row)
-{
-  GtkLayoutManager *layout_manager = gtk_widget_get_layout_manager (WID (grid_name));
-  GtkLayoutChild *layout_child = gtk_layout_manager_get_layout_child (layout_manager, WID (widget_name));
-  gtk_grid_layout_child_set_row (GTK_GRID_LAYOUT_CHILD (layout_child), row);
-}
-
-static void
-update_stylus_ui (CcWacomStylusPage *page,
-                 int                layout)
-{
-       switch (layout) {
-       case LAYOUT_NORMAL:
-               remove_buttons (page, 2);
-               break;
-       case LAYOUT_INKING:
-               remove_buttons (page, 0);
-               remove_eraser (page);
-               set_grid_row (page, "stylus-controls-grid", "label-tip-feel", 0);
-               set_grid_row (page, "stylus-controls-grid", "box-tip-feel", 0);
-               break;
-       case LAYOUT_AIRBRUSH:
-               remove_buttons (page, 1);
-               set_grid_row (page, "stylus-controls-grid", "label-lower-button", 1);
-               set_grid_row (page, "stylus-controls-grid", "combo-bottombutton", 1);
-               set_grid_row (page, "stylus-controls-grid", "label-tip-feel", 2);
-               set_grid_row (page, "stylus-controls-grid", "box-tip-feel", 2);
-               break;
-       case LAYOUT_GENERIC_2_BUTTONS_NO_ERASER:
-               remove_buttons (page, 2);
-               remove_eraser (page);
-               break;
-       case LAYOUT_3DPEN:
-               remove_buttons (page, 3);
-               remove_eraser (page);
-               break;
-       case LAYOUT_OTHER:
-               /* We already warn about it in cc_wacom_stylus_page_new () */
-               break;
-       }
+       gtk_picture_set_resource (GTK_PICTURE (page->stylus_icon), resource);
+#endif
 }
 
 GtkWidget *
@@ -418,7 +225,6 @@ cc_wacom_stylus_page_new (CcWacomTool *stylus)
 {
        CcWacomStylusPage *page;
        guint num_buttons;
-       int layout;
        gboolean has_eraser;
 
        g_return_val_if_fail (CC_IS_WACOM_TOOL (stylus), NULL);
@@ -427,56 +233,38 @@ cc_wacom_stylus_page_new (CcWacomTool *stylus)
 
        page->stylus = stylus;
 
+       /* Stylus name */
+       gtk_label_set_text (GTK_LABEL (page->stylus_name),
+                           cc_wacom_tool_get_name (stylus));
+
        /* Icon */
-       set_icon_name (page, "image-stylus", cc_wacom_tool_get_icon_name (stylus));
+       set_icon_name (page, cc_wacom_tool_get_icon_name (stylus));
 
        /* Settings */
        page->stylus_settings = cc_wacom_tool_get_settings (stylus);
        has_eraser = cc_wacom_tool_get_has_eraser (stylus);
 
-       /* Stylus name */
-       gtk_label_set_text (GTK_LABEL (WID ("label-stylus")), cc_wacom_tool_get_name (stylus));
-
        num_buttons = cc_wacom_tool_get_num_buttons (stylus);
-       if (num_buttons == 0 && !has_eraser)
-               layout = LAYOUT_INKING;
-       else if (num_buttons == 2 && has_eraser)
-               layout = LAYOUT_NORMAL;
-       else if (num_buttons == 1 && has_eraser)
-               layout = LAYOUT_AIRBRUSH;
-       else if (num_buttons == 2 && !has_eraser)
-               layout = LAYOUT_GENERIC_2_BUTTONS_NO_ERASER;
-       else if (num_buttons == 3 && !has_eraser)
-               layout = LAYOUT_3DPEN;
-       else {
-               layout = LAYOUT_OTHER;
-               remove_buttons (page, num_buttons);
-
-               /* Gray out eraser if not available */
-               gtk_widget_set_sensitive (WID ("eraser-box"), has_eraser);
-               gtk_widget_set_sensitive (WID ("label-eraser-feel"), has_eraser);
-
-               g_warning ("The layout of this page is not known, %d buttons, %s eraser",
-                          num_buttons, has_eraser ? "with" : "without");
-       }
-
-       update_stylus_ui (page, layout);
-
-       if (num_buttons >= 3)
-               set_button_mapping_from_gsettings (GTK_COMBO_BOX (WID ("combo-thirdbutton")),
-                                                  page->stylus_settings, "tertiary-button-action");
-       if (num_buttons >= 2)
-               set_button_mapping_from_gsettings (GTK_COMBO_BOX (WID ("combo-topbutton")),
-                                                  page->stylus_settings, "secondary-button-action");
-       if (num_buttons >= 1)
-               set_button_mapping_from_gsettings (GTK_COMBO_BOX (WID ("combo-bottombutton")),
-                                                  page->stylus_settings, "button-action");
-       set_feel_from_gsettings (GTK_ADJUSTMENT (WID ("adjustment-tip-feel")),
+       gtk_widget_set_visible (page->stylus_button3_action,
+                               num_buttons >= 3);
+       gtk_widget_set_visible (page->stylus_button2_action,
+                               num_buttons >= 2);
+       gtk_widget_set_visible (page->stylus_button1_action,
+                               num_buttons >= 1);
+       gtk_widget_set_visible (page->stylus_eraser_pressure,
+                               has_eraser);
+
+        adw_combo_row_set_selected (ADW_COMBO_ROW (page->stylus_button1_action),
+                                   g_settings_get_enum (page->stylus_settings, "button-action"));
+        adw_combo_row_set_selected (ADW_COMBO_ROW (page->stylus_button2_action),
+                                   g_settings_get_enum (page->stylus_settings, "secondary-button-action"));
+        adw_combo_row_set_selected (ADW_COMBO_ROW (page->stylus_button3_action),
+                                   g_settings_get_enum (page->stylus_settings, "tertiary-button-action"));
+
+       set_feel_from_gsettings (page->stylus_tip_pressure_adjustment,
                                 page->stylus_settings, "pressure-curve");
-
-       if (has_eraser)
-               set_feel_from_gsettings (GTK_ADJUSTMENT (WID ("adjustment-eraser-feel")),
-                                        page->stylus_settings, "eraser-pressure-curve");
+       set_feel_from_gsettings (page->stylus_eraser_pressure_adjustment,
+                                page->stylus_settings, "eraser-pressure-curve");
 
        return GTK_WIDGET (page);
 }
@@ -486,15 +274,3 @@ cc_wacom_stylus_page_get_tool (CcWacomStylusPage *page)
 {
        return page->stylus;
 }
-
-void
-cc_wacom_stylus_page_set_navigation (CcWacomStylusPage *page,
-                                    GtkNotebook *notebook)
-{
-       g_return_if_fail (CC_IS_WACOM_STYLUS_PAGE (page));
-
-       g_object_set (G_OBJECT (page->nav),
-                     "notebook", notebook,
-                     "ignore-first", TRUE,
-                     NULL);
-}
diff --git a/panels/wacom/cc-wacom-stylus-page.h b/panels/wacom/cc-wacom-stylus-page.h
index 23810d9b0..51ad7d38a 100644
--- a/panels/wacom/cc-wacom-stylus-page.h
+++ b/panels/wacom/cc-wacom-stylus-page.h
@@ -32,7 +32,4 @@ GtkWidget * cc_wacom_stylus_page_new (CcWacomTool *stylus);
 
 CcWacomTool * cc_wacom_stylus_page_get_tool (CcWacomStylusPage *page);
 
-void cc_wacom_stylus_page_set_navigation (CcWacomStylusPage *page,
-                                         GtkNotebook *notebook);
-
 G_END_DECLS
diff --git a/panels/wacom/cc-wacom-stylus-page.ui b/panels/wacom/cc-wacom-stylus-page.ui
new file mode 100644
index 000000000..bb923c304
--- /dev/null
+++ b/panels/wacom/cc-wacom-stylus-page.ui
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="CcWacomStylusPage" parent="GtkBox">
+    <property name="orientation">vertical</property>
+    <property name="spacing">24</property>
+    <child>
+      <object class="GtkBox">
+        <property name="homogeneous">True</property>
+        <child>
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
+            <property name="hexpand">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="stylus_name">
+                <property name="halign">start</property>
+                <style>
+                  <class name="heading"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="stylus_subtitle">
+                <property name="halign">start</property>
+                <property name="wrap">True</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkPicture" id="stylus_icon">
+            <property name="hexpand">True</property>
+            <property name="halign">end</property>
+            <property name="valign">start</property>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="AdwPreferencesGroup">
+        <child>
+          <object class="AdwActionRow" id="stylus_tip_pressure">
+            <property name="title" translatable="yes">Tip Pressure Feel</property>
+            <child>
+              <object class="GtkBox" id="stylus_tip_pressure_box">
+                <child>
+                  <object class="GtkLabel">
+                    <property name="label">Soft</property>
+                    <attributes>
+                      <attribute name="scale" value="0.82999999999999996"/>
+                    </attributes>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkScale" id="stylus_tip_pressure_scale">
+                    <property name="adjustment">stylus_tip_pressure_adjustment</property>
+                    <property name="draw_value">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <signal name="value-changed" handler="on_tip_pressure_value_changed" swapped="yes"/>
+                    <accessibility>
+                      <property name="label">Stylus tip pressure</property>
+                    </accessibility>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="label">Firm</property>
+                    <attributes>
+                      <attribute name="scale" value="0.82999999999999996"/>
+                    </attributes>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="AdwComboRow" id="stylus_button1_action">
+            <property name="width_request">100</property>
+            <property name="title" translatable="yes" context="display setting">Button 1</property>
+            <property name="model">button_model</property>
+            <signal name="notify::selected-item" handler="on_stylus_action_selected" swapped="no"/>
+          </object>
+        </child>
+        <child>
+          <object class="AdwComboRow" id="stylus_button2_action">
+            <property name="width_request">100</property>
+            <property name="title" translatable="yes" context="display setting">Button 2</property>
+            <property name="model">button_model</property>
+            <signal name="notify::selected-item" handler="on_stylus_action_selected" swapped="no"/>
+          </object>
+        </child>
+        <child>
+          <object class="AdwComboRow" id="stylus_button3_action">
+            <property name="width_request">100</property>
+            <property name="title" translatable="yes" context="display setting">Button 3</property>
+            <property name="model">button_model</property>
+            <signal name="notify::selected-item" handler="on_stylus_action_selected" swapped="no"/>
+          </object>
+        </child>
+        <child>
+          <object class="AdwActionRow" id="stylus_eraser_pressure">
+            <property name="title" translatable="yes">Eraser Pressure Feel</property>
+            <child>
+              <object class="GtkBox" id="stylus_eraser_pressure_box">
+                <child>
+                  <object class="GtkLabel">
+                    <property name="label">Soft</property>
+                    <attributes>
+                      <attribute name="scale" value="0.82999999999999996"/>
+                    </attributes>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkScale" id="stylus_eraser_pressure_scale">
+                    <property name="adjustment">stylus_eraser_pressure_adjustment</property>
+                    <property name="draw_value">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <signal name="value-changed" handler="on_eraser_pressure_value_changed" swapped="yes"/>
+                    <accessibility>
+                      <property name="label">Eraser pressure</property>
+                    </accessibility>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="label">Firm</property>
+                    <attributes>
+                      <attribute name="scale" value="0.82999999999999996"/>
+                    </attributes>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+  <object class="GtkAdjustment" id="stylus_tip_pressure_adjustment">
+    <property name="upper">6</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">3</property>
+  </object>
+  <object class="GtkAdjustment" id="stylus_eraser_pressure_adjustment">
+    <property name="upper">6</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">3</property>
+  </object>
+  <object class="GtkSizeGroup" id="sizegroup_pressure">
+    <widgets>
+      <widget name="stylus_tip_pressure_box" />
+      <widget name="stylus_eraser_pressure_box" />
+    </widgets>
+  </object>
+  <object class="GtkStringList" id="button_model">
+    <items>
+      <item>Default</item>
+      <item>Middle Mouse Button Click</item>
+      <item>Right Mouse Button Click</item>
+      <item>Back</item>
+      <item>Forward</item>
+    </items>
+  </object>
+</interface>
diff --git a/panels/wacom/meson.build b/panels/wacom/meson.build
index 7b03ce9e8..2a6969085 100644
--- a/panels/wacom/meson.build
+++ b/panels/wacom/meson.build
@@ -42,8 +42,6 @@ common_sources = files(
   'cc-tablet-tool-map.c',
   'cc-wacom-button-row.c',
   'cc-wacom-device.c',
-  'cc-wacom-mapping-panel.c',
-  'cc-wacom-nav-button.c',
   'cc-wacom-page.c',
   'cc-wacom-stylus-page.c',
   'cc-wacom-tool.c',
diff --git a/panels/wacom/test-wacom.c b/panels/wacom/test-wacom.c
index 97803a12f..ef95aeb57 100644
--- a/panels/wacom/test-wacom.c
+++ b/panels/wacom/test-wacom.c
@@ -38,7 +38,6 @@ add_page (GList *devices,
        g_list_free (devices);
 
        widget = cc_wacom_page_new (NULL, stylus);
-       cc_wacom_page_set_navigation (CC_WACOM_PAGE (widget), GTK_NOTEBOOK (notebook), FALSE);
        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, NULL);
        gtk_widget_show (widget);
 }
diff --git a/panels/wacom/wacom.gresource.xml b/panels/wacom/wacom.gresource.xml
index 846835fad..ce133b751 100644
--- a/panels/wacom/wacom.gresource.xml
+++ b/panels/wacom/wacom.gresource.xml
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/control-center/wacom">
-    <file preprocess="xml-stripblanks">gnome-wacom-properties.ui</file>
-    <file preprocess="xml-stripblanks">wacom-stylus-page.ui</file>
+    <file preprocess="xml-stripblanks">cc-wacom-panel.ui</file>
+    <file preprocess="xml-stripblanks">cc-wacom-page.ui</file>
+    <file preprocess="xml-stripblanks">cc-wacom-stylus-page.ui</file>
     <file preprocess="xml-stripblanks">button-mapping.ui</file>
     <file preprocess="xml-stripblanks">calibrator/calibrator.ui</file>
     <file>calibrator/calibrator.css</file>


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