static GtkWidget *
input_source_widget_new (GtkWidget   *chooser,
                         const gchar *type,
                         const gchar *id)
{
  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
  GtkWidget *widget = NULL;

  if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
    {
      const gchar *display_name;

      gnome_xkb_info_get_layout_info (priv->xkb_info, id, &display_name, NULL, NULL, NULL);

      widget = padded_label_new (display_name,
                                 ROW_LABEL_POSITION_START,
                                 ROW_TRAVEL_DIRECTION_NONE,
                                 FALSE);
      g_object_set_data (G_OBJECT (widget), "name", (gpointer) display_name);
      g_object_set_data_full (G_OBJECT (widget), "unaccented-name",
                              cc_util_normalize_casefold_and_unaccent (display_name), g_free);
    }
  else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
    {
#ifdef HAVE_IBUS
      gchar *display_name;
      GtkWidget *image;

      display_name = engine_get_display_name (g_hash_table_lookup (priv->ibus_engines, id));

      widget = padded_label_new (display_name,
                                 ROW_LABEL_POSITION_START,
                                 ROW_TRAVEL_DIRECTION_NONE,
                                 FALSE);
      image = gtk_image_new_from_icon_name ("system-run-symbolic", GTK_ICON_SIZE_MENU);
      set_row_widget_margins (image);
      gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label");
      gtk_box_pack_start (GTK_BOX (widget), image, FALSE, TRUE, 0);

      g_object_set_data_full (G_OBJECT (widget), "name", display_name, g_free);
      g_object_set_data_full (G_OBJECT (widget), "unaccented-name",
                              cc_util_normalize_casefold_and_unaccent (display_name), g_free);
#else
      widget = NULL;
#endif  /* HAVE_IBUS */
    }

  if (widget)
    {
      g_object_set_data (G_OBJECT (widget), "type", (gpointer) type);
      g_object_set_data (G_OBJECT (widget), "id", (gpointer) id);
    }

  return widget;
}
static GtkWidget *
more_widget_new (void)
{
  GtkWidget *widget;
  GtkWidget *arrow;

  widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
  gtk_widget_set_tooltip_text (widget, _("More…"));

  arrow = gtk_image_new_from_icon_name ("view-more-symbolic", GTK_ICON_SIZE_MENU);
  gtk_style_context_add_class (gtk_widget_get_style_context (arrow), "dim-label");
  set_row_widget_margins (arrow);
  gtk_misc_set_alignment (GTK_MISC (arrow), 0.5, 0.5);
  gtk_box_pack_start (GTK_BOX (widget), arrow, TRUE, TRUE, 0);

  return widget;
}
static GtkWidget *
padded_label_new (const gchar        *text,
                  RowLabelPosition    position,
                  RowTravelDirection  direction,
                  gboolean            dim_label)
{
  GtkWidget *widget;
  GtkWidget *label;
  GtkWidget *arrow;
  gdouble alignment;
  gboolean rtl;

  rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);

  if (position == ROW_LABEL_POSITION_START)
    alignment = 0.0;
  else if (position == ROW_LABEL_POSITION_CENTER)
    alignment = 0.5;
  else
    alignment = 1.0;

  widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);

  if (direction == ROW_TRAVEL_DIRECTION_BACKWARD)
    {
      arrow = gtk_image_new_from_icon_name (rtl ? ARROW_NEXT : ARROW_PREV,
                                            GTK_ICON_SIZE_MENU);
      gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
    }

  label = gtk_label_new (text);
  gtk_misc_set_alignment (GTK_MISC (label), alignment, 0.5);
  set_row_widget_margins (label);
  gtk_box_pack_start (GTK_BOX (widget), label, TRUE, TRUE, 0);
  if (dim_label)
    gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");

  if (direction == ROW_TRAVEL_DIRECTION_FORWARD)
    {
      arrow = gtk_image_new_from_icon_name (rtl ? ARROW_PREV : ARROW_NEXT,
                                            GTK_ICON_SIZE_MENU);
      gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
    }

  return widget;
}
static GtkListBoxRow *
more_row_new (void)
{
  GtkWidget *row;
  GtkWidget *box;
  GtkWidget *arrow;

  row = gtk_list_box_row_new ();
  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
  gtk_container_add (GTK_CONTAINER (row), box);
  gtk_widget_set_tooltip_text (row, _("More…"));

  arrow = gtk_image_new_from_icon_name ("view-more-symbolic", GTK_ICON_SIZE_MENU);
  gtk_style_context_add_class (gtk_widget_get_style_context (arrow), "dim-label");
  set_row_widget_margins (arrow);
  gtk_box_pack_start (GTK_BOX (box), arrow, TRUE, TRUE, 0);

  return GTK_LIST_BOX_ROW (row);
}
static GtkWidget *
padded_label_new (const gchar        *text,
                  RowLabelPosition    position,
                  RowTravelDirection  direction,
                  gboolean            dim_label)
{
  GtkWidget *widget;
  GtkWidget *label;
  GtkWidget *arrow;
  GtkAlign alignment;

  if (position == ROW_LABEL_POSITION_START)
    alignment = GTK_ALIGN_START;
  else if (position == ROW_LABEL_POSITION_CENTER)
    alignment = GTK_ALIGN_CENTER;
  else
    alignment = GTK_ALIGN_END;

  widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);

  if (direction == ROW_TRAVEL_DIRECTION_BACKWARD)
    {
      arrow = gtk_image_new_from_icon_name ("go-previous-symbolic", GTK_ICON_SIZE_MENU);
      gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
    }

  label = gtk_label_new (text);
  gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
  gtk_widget_set_halign (label, alignment);
  set_row_widget_margins (label);
  gtk_box_pack_start (GTK_BOX (widget), label, TRUE, TRUE, 0);
  if (dim_label)
    gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");

  if (direction == ROW_TRAVEL_DIRECTION_FORWARD)
    {
      arrow = gtk_image_new_from_icon_name ("go-next-symbolic", GTK_ICON_SIZE_MENU);
      gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
    }

  return widget;
}