# HG changeset patch
# Node ID d8160062c142
# Parent  f3bece910126
diff --git a/pidgin/meson.build b/pidgin/meson.build
--- a/pidgin/meson.build
+++ b/pidgin/meson.build
@@ -55,6 +55,7 @@ libpidgin_SOURCES = [
 	'pidginpresenceicon.c',
 	'pidginprotocolchooser.c',
 	'pidginstatusbox.c',
+	'pidginstatusdisplay.c',
 	'pidginstatuseditor.c',
 	'pidginstatusmanager.c',
 	'pidginstatusprimitivechooser.c',
@@ -122,6 +123,7 @@ libpidgin_headers = [
 	'pidginpresenceicon.h',
 	'pidginprotocolchooser.h',
 	'pidginstatusbox.h',
+	'pidginstatusdisplay.h',
 	'pidginstatuseditor.h',
 	'pidginstatusmanager.h',
 	'pidginstatusprimitivechooser.h',
diff --git a/pidgin/pidginstatusdisplay.h b/pidgin/pidginstatusdisplay.h
new file mode 100644
--- /dev/null
+++ b/pidgin/pidginstatusdisplay.h
@@ -0,0 +1,129 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined(PIDGIN_GLOBAL_HEADER_INSIDE) && !defined(PIDGIN_COMPILATION)
+# error "only <pidgin.h> may be included directly"
+#endif
+
+#ifndef PIDGIN_STATUS_DISPLAY_H
+#define PIDGIN_STATUS_DISPLAY_H
+
+#include <gtk/gtk.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+#define PIDGIN_TYPE_STATUS_DISPLAY (pidgin_status_display_get_type())
+G_DECLARE_FINAL_TYPE(PidginStatusDisplay, pidgin_status_display,
+                     PIDGIN, STATUS_DISPLAY, GtkBox)
+
+/**
+ * pidgin_status_display_new:
+ *
+ * Creates a display for a status.
+ *
+ * Returns: (transfer full): The status display.
+ *
+ * Since: 3.0.0
+ */
+GtkWidget *pidgin_status_display_new(void);
+
+/**
+ * pidgin_status_display_new_for_primitive:
+ * @primitive: The status primitive to display.
+ *
+ * Creates a display for a status primitive.
+ *
+ * Returns: (transfer full): The status display.
+ *
+ * Since: 3.0.0
+ */
+GtkWidget *pidgin_status_display_new_for_primitive(PurpleStatusPrimitive primitive);
+
+/**
+ * pidgin_status_display_new_for_saved_status:
+ * @status: The status to display.
+ *
+ * Creates a display for a saved status.
+ *
+ * Returns: (transfer full): The status display.
+ *
+ * Since: 3.0.0
+ */
+GtkWidget *pidgin_status_display_new_for_saved_status(PurpleSavedStatus *status);
+
+/**
+ * pidgin_status_display_get_primitive:
+ * @display: The display.
+ *
+ * Gets the currently displayed status primitive.
+ *
+ * Returns: (transfer none): Returns the [type@Purple.StatusPrimitive] that is
+ *          currently displayed.
+ *
+ * Since: 3.0.0
+ */
+PurpleStatusPrimitive pidgin_status_display_get_primitive(PidginStatusDisplay *display);
+
+/**
+ * pidgin_status_display_set_primitive:
+ * @display: The display.
+ * @primitive: The status primitive to display.
+ *
+ * Sets the currently displayed status primitive.
+ *
+ * If a saved status was previously set, it will be unset.
+ *
+ * Since: 3.0.0
+ */
+void pidgin_status_display_set_primitive(PidginStatusDisplay *display, PurpleStatusPrimitive primitive);
+
+/**
+ * pidgin_status_display_get_saved_status:
+ * @display: The display.
+ *
+ * Gets the currently displayed saved status.
+ *
+ * Returns: (transfer none): Returns the [type@Purple.SavedStatus] that is
+ *          currently displayed.
+ *
+ * Since: 3.0.0
+ */
+PurpleSavedStatus *pidgin_status_display_get_saved_status(PidginStatusDisplay *display);
+
+/**
+ * pidgin_status_display_set_saved_status:
+ * @display: The display.
+ * @status: The saved status to display.
+ *
+ * Sets the currently displayed saved status.
+ *
+ * If a status primitive was previously set, it will be unset.
+ *
+ * Since: 3.0.0
+ */
+void pidgin_status_display_set_saved_status(PidginStatusDisplay *display, PurpleSavedStatus *status);
+
+G_END_DECLS
+
+#endif /* PIDGIN_STATUS_DISPLAY_H */
diff --git a/pidgin/pidginstatusdisplay.c b/pidgin/pidginstatusdisplay.c
new file mode 100644
--- /dev/null
+++ b/pidgin/pidginstatusdisplay.c
@@ -0,0 +1,274 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+#include <glib/gi18n-lib.h>
+
+#include <gtk/gtk.h>
+
+#include "pidginstatusdisplay.h"
+#include "pidginiconname.h"
+
+struct _PidginStatusDisplay {
+	GtkBox parent;
+
+	GtkImage *image;
+	GtkLabel *label;
+
+	PurpleStatusPrimitive primitive;
+	PurpleSavedStatus *status;
+};
+
+enum {
+	PROP_0,
+	PROP_PRIMITIVE,
+	PROP_SAVED_STATUS,
+	PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST] = {NULL};
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static void
+pidgin_status_display_refresh(PidginStatusDisplay *display) {
+	const char *icon_name = NULL;
+	char *label = NULL;
+
+	if(display->status != NULL) {
+		PurpleSavedStatus *status = display->status;
+		PurpleStatusPrimitive primitive;
+		GString *text = NULL;
+
+		primitive = purple_savedstatus_get_primitive_type(status);
+		icon_name = pidgin_icon_name_from_status_primitive(primitive, NULL);
+
+		text = g_string_new(purple_savedstatus_get_title(status));
+
+		/* Transient statuses do not have a title, so the savedstatus API
+		 * returns the message when purple_savedstatus_get_title() is called,
+		 * so we don't need to get the message a second time.
+		 */
+		if(!purple_savedstatus_is_transient(status)) {
+			const char *message = NULL;
+
+			message = purple_savedstatus_get_message(status);
+			if(message != NULL) {
+				char *stripped = purple_markup_strip_html(message);
+
+				purple_util_chrreplace(stripped, '\n', ' ');
+				g_string_append_printf(text, " - %s", stripped);
+				g_free(stripped);
+			}
+		}
+
+		label = g_string_free(text, FALSE);
+
+	} else if(display->primitive != PURPLE_STATUS_UNSET) {
+		icon_name = pidgin_icon_name_from_status_primitive(display->primitive,
+		                                                   NULL);
+		label = g_strdup(purple_primitive_get_name_from_type(display->primitive));
+	}
+
+	gtk_image_set_from_icon_name(display->image, icon_name);
+	gtk_label_set_text(display->label, label);
+
+	g_free(label);
+}
+
+/******************************************************************************
+ * GObject implementation
+ *****************************************************************************/
+G_DEFINE_TYPE(PidginStatusDisplay, pidgin_status_display, GTK_TYPE_BOX)
+
+static void
+pidgin_status_display_get_property(GObject *object, guint prop_id,
+                                   GValue *value, GParamSpec *pspec)
+{
+	PidginStatusDisplay *display = PIDGIN_STATUS_DISPLAY(object);
+
+	switch (prop_id) {
+		case PROP_PRIMITIVE:
+			g_value_set_enum(value,
+			                 pidgin_status_display_get_primitive(display));
+			break;
+		case PROP_SAVED_STATUS:
+			g_value_set_pointer(value,
+			                    pidgin_status_display_get_saved_status(display));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+pidgin_status_display_set_property(GObject *object, guint prop_id,
+                                   const GValue *value, GParamSpec *pspec)
+{
+	PidginStatusDisplay *display = PIDGIN_STATUS_DISPLAY(object);
+
+	switch (prop_id) {
+		case PROP_PRIMITIVE:
+			pidgin_status_display_set_primitive(display,
+			                                    g_value_get_enum(value));
+			break;
+		case PROP_SAVED_STATUS:
+			pidgin_status_display_set_saved_status(display,
+			                                       g_value_get_pointer(value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+pidgin_status_display_class_init(PidginStatusDisplayClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+	/* Properties */
+	obj_class->get_property = pidgin_status_display_get_property;
+	obj_class->set_property = pidgin_status_display_set_property;
+
+	/**
+	 * PidginStatusDisplay:primitive:
+	 *
+	 * The status primitive that is currently displayed.
+	 *
+	 * Since: 3.0.0
+	 */
+	properties[PROP_PRIMITIVE] = g_param_spec_enum(
+	        "primitive", "primitive",
+	        "The status primitive that is currently displayed.",
+	        PURPLE_TYPE_STATUS_PRIMITIVE, PURPLE_STATUS_UNSET,
+	        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * PidginStatusDisplay:saved-status:
+	 *
+	 * The saved status that is currently displayed.
+	 *
+	 * Since: 3.0.0
+	 */
+	properties[PROP_SAVED_STATUS] = g_param_spec_pointer(
+	        "saved-status", "saved-status",
+	        "The saved status that is currently displayed.",
+	        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(obj_class, PROP_LAST, properties);
+
+	/* Widget template */
+	gtk_widget_class_set_template_from_resource(
+	        widget_class, "/im/pidgin/Pidgin3/Status/display.ui");
+
+	gtk_widget_class_bind_template_child(widget_class, PidginStatusDisplay,
+	                                     image);
+	gtk_widget_class_bind_template_child(widget_class, PidginStatusDisplay,
+	                                     label);
+}
+
+static void
+pidgin_status_display_init(PidginStatusDisplay *display) {
+	gtk_widget_init_template(GTK_WIDGET(display));
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+GtkWidget *
+pidgin_status_display_new(void) {
+	return g_object_new(PIDGIN_TYPE_STATUS_DISPLAY, NULL);
+}
+
+GtkWidget *
+pidgin_status_display_new_for_primitive(PurpleStatusPrimitive primitive) {
+	return g_object_new(PIDGIN_TYPE_STATUS_DISPLAY,
+	                    "primitive", primitive,
+	                    NULL);
+}
+
+GtkWidget *
+pidgin_status_display_new_for_saved_status(PurpleSavedStatus *status) {
+	return g_object_new(PIDGIN_TYPE_STATUS_DISPLAY,
+	                    "saved-status", status,
+	                    NULL);
+}
+
+PurpleStatusPrimitive
+pidgin_status_display_get_primitive(PidginStatusDisplay *display) {
+	g_return_val_if_fail(PIDGIN_IS_STATUS_DISPLAY(display),
+	                     PURPLE_STATUS_UNSET);
+
+	return display->primitive;
+}
+
+void
+pidgin_status_display_set_primitive(PidginStatusDisplay *display,
+                                    PurpleStatusPrimitive primitive)
+{
+	g_return_if_fail(PIDGIN_IS_STATUS_DISPLAY(display));
+
+	g_object_freeze_notify(G_OBJECT(display));
+
+	display->status = NULL;
+	g_object_notify_by_pspec(G_OBJECT(display), properties[PROP_SAVED_STATUS]);
+
+	if(display->primitive != primitive) {
+		display->primitive = primitive;
+		g_object_notify_by_pspec(G_OBJECT(display),
+		                         properties[PROP_PRIMITIVE]);
+	}
+
+	pidgin_status_display_refresh(display);
+
+	g_object_thaw_notify(G_OBJECT(display));
+}
+
+PurpleSavedStatus *
+pidgin_status_display_get_saved_status(PidginStatusDisplay *display) {
+	g_return_val_if_fail(PIDGIN_IS_STATUS_DISPLAY(display), NULL);
+
+	return display->status;
+}
+
+void
+pidgin_status_display_set_saved_status(PidginStatusDisplay *display,
+                                       PurpleSavedStatus *status)
+{
+	g_return_if_fail(PIDGIN_IS_STATUS_DISPLAY(display));
+
+	g_object_freeze_notify(G_OBJECT(display));
+
+	display->primitive = PURPLE_STATUS_UNSET;
+	g_object_notify_by_pspec(G_OBJECT(display), properties[PROP_PRIMITIVE]);
+
+	if(display->status != status) {
+		display->status = status;
+		g_object_notify_by_pspec(G_OBJECT(display),
+		                         properties[PROP_SAVED_STATUS]);
+	}
+
+	pidgin_status_display_refresh(display);
+
+	g_object_thaw_notify(G_OBJECT(display));
+}
diff --git a/pidgin/pidginstatusmanager.c b/pidgin/pidginstatusmanager.c
--- a/pidgin/pidginstatusmanager.c
+++ b/pidgin/pidginstatusmanager.c
@@ -125,12 +125,11 @@ pidgin_status_manager_add(PidginStatusMa
 	GObject *wrapper = NULL;
 	PurpleStatusPrimitive primitive;
 	gchar *message = NULL;
-	const gchar *icon_name = NULL, *type = NULL;
+	const char *type = NULL;
 
 	message = purple_markup_strip_html(purple_savedstatus_get_message(status));
 
 	primitive = purple_savedstatus_get_primitive_type(status);
-	icon_name = pidgin_icon_name_from_status_primitive(primitive, NULL);
 	type = purple_primitive_get_name_from_type(primitive);
 
 	/* PurpleSavedStatus is a boxed type, so it can't be put in a GListModel;
@@ -140,7 +139,6 @@ pidgin_status_manager_add(PidginStatusMa
 	g_object_set_data_full(wrapper, "title",
 	                       g_strdup(purple_savedstatus_get_title(status)),
 	                       g_free);
-	g_object_set_data_full(wrapper, "icon-name", g_strdup(icon_name), g_free);
 	g_object_set_data_full(wrapper, "type", g_strdup(type), g_free);
 	g_object_set_data_full(wrapper, "message", g_strdup(message), g_free);
 
@@ -208,6 +206,21 @@ pidgin_status_manager_response_cb(GtkDia
 	}
 }
 
+static PurpleStatusPrimitive
+pidgin_status_manager_lookup_primitive_cb(G_GNUC_UNUSED GObject *self,
+                                          GObject *wrapper,
+                                          G_GNUC_UNUSED gpointer data)
+{
+	PurpleStatusPrimitive primitive = PURPLE_STATUS_UNSET;
+
+	if(G_IS_OBJECT(wrapper)) {
+		PurpleSavedStatus *status = g_object_get_data(wrapper, "savedstatus");
+		primitive = purple_savedstatus_get_primitive_type(status);
+	}
+
+	return primitive;
+}
+
 static char *
 pidgin_status_manager_sort_data_cb(GObject *wrapper, const char *name,
                                    G_GNUC_UNUSED gpointer data)
@@ -388,6 +401,8 @@ pidgin_status_manager_class_init(PidginS
 	gtk_widget_class_bind_template_callback(widget_class,
 	                                        pidgin_status_manager_response_cb);
 	gtk_widget_class_bind_template_callback(widget_class,
+	                                        pidgin_status_manager_lookup_primitive_cb);
+	gtk_widget_class_bind_template_callback(widget_class,
 	                                        pidgin_status_manager_lookup_text_data_cb);
 	gtk_widget_class_bind_template_callback(widget_class,
 	                                        pidgin_status_manager_sort_data_cb);
diff --git a/pidgin/pidginstatusprimitivechooser.c b/pidgin/pidginstatusprimitivechooser.c
--- a/pidgin/pidginstatusprimitivechooser.c
+++ b/pidgin/pidginstatusprimitivechooser.c
@@ -32,64 +32,21 @@ G_DEFINE_TYPE(PidginStatusPrimitiveChoos
               ADW_TYPE_COMBO_ROW)
 
 /******************************************************************************
- * Helpers
+ * Callbacks
  *****************************************************************************/
 static PurpleStatusPrimitive
-pidgin_status_primitive_chooser_primitive_from_string(const char *str) {
-	if(purple_strequal(str, "offline")) {
-		return PURPLE_STATUS_OFFLINE;
-	} else if(purple_strequal(str, "available")) {
-		return PURPLE_STATUS_AVAILABLE;
-	} else if(purple_strequal(str, "unavailable")) {
-		return PURPLE_STATUS_UNAVAILABLE;
-	} else if(purple_strequal(str, "invisible")) {
-		return PURPLE_STATUS_INVISIBLE;
-	} else if(purple_strequal(str, "away")) {
-		return PURPLE_STATUS_AWAY;
-	} else if(purple_strequal(str, "extended-away")) {
-		return PURPLE_STATUS_EXTENDED_AWAY;
-	}
-
-	return PURPLE_STATUS_UNSET;
-}
-
-/******************************************************************************
- * Callbacks
- *****************************************************************************/
-static char *
-pidgin_status_primitive_chooser_icon_name_cb(G_GNUC_UNUSED GObject *self,
+pidgin_status_primitive_chooser_primitive_cb(G_GNUC_UNUSED GObject *self,
                                              GtkStringObject *object,
                                              G_GNUC_UNUSED gpointer data)
 {
 	PurpleStatusPrimitive primitive = PURPLE_STATUS_UNSET;
-	const char *value = NULL;
 
-	if(!GTK_IS_STRING_OBJECT(object)) {
-		return NULL;
+	if(GTK_IS_STRING_OBJECT(object)) {
+		const char *value = gtk_string_object_get_string(object);
+		primitive = purple_primitive_get_type_from_id(value);
 	}
 
-	value = gtk_string_object_get_string(object);
-	primitive = pidgin_status_primitive_chooser_primitive_from_string(value);
-
-	return g_strdup(pidgin_icon_name_from_status_primitive(primitive, NULL));
-}
-
-static char *
-pidgin_status_primitive_chooser_label_cb(G_GNUC_UNUSED GObject *self,
-                                         GtkStringObject *object,
-                                         G_GNUC_UNUSED gpointer data)
-{
-	PurpleStatusPrimitive primitive = PURPLE_STATUS_UNSET;
-	const char *value = NULL;
-
-	if(!GTK_IS_STRING_OBJECT(object)) {
-		return NULL;
-	}
-
-	value = gtk_string_object_get_string(object);
-	primitive = pidgin_status_primitive_chooser_primitive_from_string(value);
-
-	return g_strdup(purple_primitive_get_name_from_type(primitive));
+	return primitive;
 }
 
 /******************************************************************************
@@ -109,9 +66,7 @@ pidgin_status_primitive_chooser_class_in
 	        widget_class, "/im/pidgin/Pidgin3/statusprimitivechooser.ui");
 
 	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_status_primitive_chooser_icon_name_cb);
-	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_status_primitive_chooser_label_cb);
+	                                        pidgin_status_primitive_chooser_primitive_cb);
 }
 
 /******************************************************************************
@@ -133,7 +88,7 @@ pidgin_status_primitive_chooser_get_sele
 	selected = adw_combo_row_get_selected_item(ADW_COMBO_ROW(chooser));
 	value = gtk_string_object_get_string(selected);
 
-	return pidgin_status_primitive_chooser_primitive_from_string(value);
+	return purple_primitive_get_type_from_id(value);
 }
 
 void
@@ -152,7 +107,7 @@ pidgin_status_primitive_chooser_set_sele
 		const char *value = NULL;
 
 		value = gtk_string_list_get_string(list, i);
-		candidate = pidgin_status_primitive_chooser_primitive_from_string(value);
+		candidate = purple_primitive_get_type_from_id(value);
 
 		if(primitive == candidate) {
 			adw_combo_row_set_selected(ADW_COMBO_ROW(chooser), i);
diff --git a/pidgin/resources/Status/display.ui b/pidgin/resources/Status/display.ui
new file mode 100644
--- /dev/null
+++ b/pidgin/resources/Status/display.ui
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Pidgin - Internet Messenger
+Copyright (C) Pidgin Developers <devel@pidgin.im>
+
+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 the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see <https://www.gnu.org/licenses/>.
+
+-->
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <!-- interface-license-type gplv2 -->
+  <!-- interface-name Pidgin -->
+  <!-- interface-description Internet Messenger -->
+  <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+  <template class="PidginStatusDisplay" parent="GtkBox">
+    <property name="css-classes">body</property>
+    <property name="orientation">horizontal</property>
+    <property name="spacing">6</property>
+    <child>
+      <object class="GtkImage" id="image"/>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label"/>
+    </child>
+  </template>
+</interface>
diff --git a/pidgin/resources/Status/manager.ui b/pidgin/resources/Status/manager.ui
--- a/pidgin/resources/Status/manager.ui
+++ b/pidgin/resources/Status/manager.ui
@@ -107,28 +107,12 @@ License along with this library; if not,
 <interface>
   <template class="GtkListItem">
     <property name="child">
-      <object class="GtkBox">
-        <property name="orientation">horizontal</property>
-        <child>
-          <object class="GtkImage">
-            <binding name="icon-name">
-              <closure type="gchararray" function="pidgin_status_manager_lookup_text_data_cb">
-                <lookup name="item">GtkListItem</lookup>
-                <constant type="gchararray">icon-name</constant>
-              </closure>
-            </binding>
-          </object>
-        </child>
-        <child>
-          <object class="GtkLabel">
-            <binding name="label">
-              <closure type="gchararray" function="pidgin_status_manager_lookup_text_data_cb">
-                <lookup name="item">GtkListItem</lookup>
-                <constant type="gchararray">type</constant>
-              </closure>
-            </binding>
-          </object>
-        </child>
+      <object class="PidginStatusDisplay">
+        <binding name="primitive">
+          <closure type="PurpleStatusPrimitive" function="pidgin_status_manager_lookup_primitive_cb">
+            <lookup name="item">GtkListItem</lookup>
+          </closure>
+        </binding>
       </object>
     </property>
   </template>
diff --git a/pidgin/resources/pidgin.gresource.xml b/pidgin/resources/pidgin.gresource.xml
--- a/pidgin/resources/pidgin.gresource.xml
+++ b/pidgin/resources/pidgin.gresource.xml
@@ -39,6 +39,7 @@
     <file compressed="true" preprocess="xml-stripblanks">Protocols/detailed-view.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Roomlist/roomlist.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Status/box.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">Status/display.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Status/editor.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Status/manager.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">Whiteboard/whiteboard.ui</file>
diff --git a/pidgin/resources/statusprimitivechooser.ui b/pidgin/resources/statusprimitivechooser.ui
--- a/pidgin/resources/statusprimitivechooser.ui
+++ b/pidgin/resources/statusprimitivechooser.ui
@@ -33,28 +33,12 @@ along with this program; if not, see <ht
 <interface>
   <template class="GtkListItem">
     <property name="child">
-      <object class="GtkBox">
-        <property name="orientation">horizontal</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkImage">
-            <binding name="icon-name">
-              <closure type="gchararray" function="pidgin_status_primitive_chooser_icon_name_cb">
-                <lookup name="item">GtkListItem</lookup>
-              </closure>
-            </binding>
-          </object>
-        </child>
-        <child>
-          <object class="GtkLabel">
-            <property name="xalign">0</property>
-            <binding name="label">
-              <closure type="gchararray" function="pidgin_status_primitive_chooser_label_cb">
-                <lookup name="item">GtkListItem</lookup>
-              </closure>
-            </binding>
-          </object>
-        </child>
+      <object class="PidginStatusDisplay">
+        <binding name="primitive">
+          <closure type="PurpleStatusPrimitive" function="pidgin_status_primitive_chooser_primitive_cb">
+            <lookup name="item">GtkListItem</lookup>
+          </closure>
+        </binding>
       </object>
     </property>
   </template>
@@ -71,7 +55,7 @@ along with this program; if not, see <ht
           <item>unavailable</item>
           <item>invisible</item>
           <item>away</item>
-          <item>extended-away</item>
+          <item>extended_away</item>
         </items>
       </object>
     </property>
