/* Copyright (c) 2008 Christian Dywan <christian@imendio.com>
   This code is licensed under the terms of the expat license */

/* gcc -o button2 button2.c $(pkg-config --cflags --libs gtk+-2.0) -Wall -O1 -g */

#include <gtk/gtk.h>

/* Note that the class implementation used here is not representative
   for common code and merely compressed to keep the example small. */

typedef struct
{
    GtkButton parent_instance;

    GtkWidget* box;
    GtkWidget* label;
    GtkWidget* label2;
    GtkWidget* image;
} WurstButton;

typedef struct
{
    GtkButtonClass parent_class;
}  WurstButtonClass;

#define WURST_TYPE_BUTTON (wurst_button_get_type ())
#define WURST_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
    WURST_TYPE_BUTTON, WurstButton))
#define WURST_IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WURST_TYPE_BUTTON))

G_DEFINE_TYPE (WurstButton, wurst_button, GTK_TYPE_BUTTON);

static GtkWidget*
wurst_button_real_get_label (GtkButton* button)
{
    return WURST_BUTTON (button)->label;
}

static void
wurst_button_real_set_image (GtkButton* button,
                             GtkWidget* image)
{
    GtkWidget* box = WURST_BUTTON (button)->box;

    if (WURST_BUTTON (button)->image == image)
        return;

    if (WURST_BUTTON (button)->image)
        gtk_container_remove (GTK_CONTAINER (box), WURST_BUTTON (button)->image);
    if (image)
        gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 2);
    WURST_BUTTON (button)->image = image;
    g_object_notify (G_OBJECT (button), "image");
}

static GtkWidget*
wurst_button_real_get_image (GtkButton*   button)
{
    return WURST_BUTTON (button)->image;
}

static void
wurst_button_class_init (WurstButtonClass* class)
{
    GtkButtonClass* bclass = GTK_BUTTON_CLASS (class);
    bclass->get_label = wurst_button_real_get_label;
    bclass->set_image = wurst_button_real_set_image;
    bclass->get_image = wurst_button_real_get_image;
}

static void
wurst_button_init (WurstButton* button)
{
    button->box = gtk_hbox_new (FALSE, 2);
    button->label = gtk_label_new ("Weapon");
    button->label2 = gtk_label_new ("<b>Laser beam</b>");
    gtk_label_set_use_markup (GTK_LABEL (button->label2), TRUE);
    button->image = NULL;

    gtk_box_pack_start (GTK_BOX (button->box), button->label, FALSE, FALSE, 2);
    gtk_box_pack_start (GTK_BOX (button->box), button->label2, FALSE, FALSE, 2);
    gtk_container_add (GTK_CONTAINER (button), button->box);
    gtk_widget_show_all (button->box);
}

GtkWidget*
wurst_button_new (void)
{
    GtkWidget* button = g_object_new (WURST_TYPE_BUTTON, NULL);

    return button;
}

void
wurst_button_set_secondary_label (WurstButton* button,
                                  const gchar* label)
{
    gchar* bold;

    g_return_if_fail (WURST_IS_BUTTON (button));

    if (!label) label = "";

    bold = g_strdup_printf ("<b>%s</b>", label);
    gtk_label_set_label (GTK_LABEL (WURST_BUTTON (button)->label2), bold);
    g_free (bold);
}

int
main (int    argc,
      gchar* argv[])
{
  GtkWidget* dialog;
  GtkWidget* label;
  GtkWidget* hbox;
  GtkWidget* button;
  GtkWidget* subbox;
  GtkWidget* image;

  gtk_init (&argc, &argv);
  g_set_application_name ("Schaltflächenzentrale");

  dialog = g_object_new (GTK_TYPE_DIALOG,
                         "icon-name", GTK_STOCK_ABOUT,
                         "title", "Schafläzen",
                         "default-width", 400,
                         "default-height", 200,
                         NULL);
  g_signal_connect (dialog, "response",
                    G_CALLBACK (gtk_main_quit), dialog);

  label = gtk_label_new (
      "Es kommt ein Wandersmann daher, mit einer Wasserflasche und\n"
      "einem Wurstbrot. Sein Gewand ist reich an Knöpfen.");
  gtk_widget_show (label);
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label,
                      FALSE, FALSE, 2);

  hbox = gtk_hbox_new (FALSE, 2);

  button = gtk_button_new_from_stock (GTK_STOCK_INFO);
  gtk_button_set_label (GTK_BUTTON (button), "Ordinary button with icon");
  gtk_widget_show (button);
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);

  button = gtk_button_new_with_label ("I can has image");
  image = gtk_image_new_from_stock (GTK_STOCK_SELECT_COLOR, GTK_ICON_SIZE_BUTTON);
  gtk_button_set_image (GTK_BUTTON (button), image);
  gtk_button_set_image_position (GTK_BUTTON (button), GTK_POS_RIGHT);
  gtk_widget_show (button);
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);

  /* Bad example: this kind of code will break easily,
     for example when disabling button images */
  button = gtk_button_new ();
  subbox = gtk_vbox_new (FALSE, 2);
  image = gtk_image_new_from_stock (GTK_STOCK_SPELL_CHECK, GTK_ICON_SIZE_BUTTON);
  gtk_box_pack_start (GTK_BOX (subbox), image, FALSE, FALSE, 2);
  label = gtk_label_new ("You shall not use bad grammar");
  gtk_box_pack_start (GTK_BOX (subbox), label, FALSE, FALSE, 2);
  gtk_container_add (GTK_CONTAINER (button), subbox);
  gtk_widget_show_all (button);
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);

  /* Good example: our custom button is compatible because
     it overrides the virtual label and image accessors. */
  button = wurst_button_new ();
  image = gtk_image_new_from_stock (GTK_STOCK_SELECT_FONT, GTK_ICON_SIZE_BUTTON);
  gtk_button_set_image (GTK_BUTTON (button), image);
  gtk_button_set_label (GTK_BUTTON (button), GTK_STOCK_HELP);
  wurst_button_set_secondary_label (WURST_BUTTON (button), "Monster");
  gtk_widget_show (button);
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);

  /* This one requires the subclass to use an alignment or misc.
     It's unrelated to the feature, so we don't bother. */
  gtk_button_set_alignment (GTK_BUTTON (button), 0.5, 0.5);

  /* Those work only out of the box with version 2 of the patch */
  gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
  gtk_button_set_use_underline (GTK_BUTTON (button), TRUE);

  /* This one... isn't easy because it depends on the widget hierarchy,
  even more so than the alignment. We don't touch that for now. */
  gtk_button_set_image_position (GTK_BUTTON (button), GTK_POS_TOP);

  gtk_widget_show (hbox);
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
                      TRUE, TRUE, 2);

  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
                          "S.O.S.", GTK_RESPONSE_HELP,
                          "I'm fed up", GTK_RESPONSE_OK,
                          NULL);

  gtk_widget_show (dialog);

  gtk_main ();

  return 0;
}