chiark / gitweb /
Merge toolbar redesign.
authorRichard Kettlewell <rjk@greenend.org.uk>
Sun, 13 Dec 2009 16:42:59 +0000 (16:42 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sun, 13 Dec 2009 16:42:59 +0000 (16:42 +0000)
24 files changed:
disobedience/added.c
disobedience/choose-menu.c
disobedience/control.c
disobedience/disobedience.c
disobedience/manual/button-pause.png
disobedience/manual/button-playing.png
disobedience/manual/button-random.png
disobedience/manual/button-rtp.png
disobedience/manual/button-scratch.png
disobedience/manual/disobedience.css
disobedience/manual/queue.png
disobedience/manual/queue2.png
disobedience/manual/window.html
disobedience/menu.c
disobedience/playlists.c
disobedience/popup.c
disobedience/popup.h
disobedience/queue.c
disobedience/recent.c
images/Makefile.am
images/cards-simple-fanned.svg [new file with mode: 0644]
images/cards-thin.svg [new file with mode: 0644]
images/cards24.png [new file with mode: 0644]
images/cards48.png [new file with mode: 0644]

index aa15f48902d83079396d6ec566e1b44f253c286c..04e1d77e13e233d0d569efcd86b20e12df46fa21 100644 (file)
@@ -80,10 +80,10 @@ static const struct queue_column added_columns[] = {
 
 /** @brief Pop-up menu for new tracks list */
 static struct menuitem added_menuitems[] = {
-  { "Track properties", ql_properties_activate, ql_properties_sensitive, 0, 0 },
-  { "Play track", ql_play_activate, ql_play_sensitive, 0, 0 },
-  { "Select all tracks", ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
-  { "Deselect all tracks", ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
+  { "Track properties", GTK_STOCK_PROPERTIES, ql_properties_activate, ql_properties_sensitive, 0, 0 },
+  { "Play track", GTK_STOCK_MEDIA_PLAY, ql_play_activate, ql_play_sensitive, 0, 0 },
+  { "Select all tracks", GTK_STOCK_SELECT_ALL, ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
+  { "Deselect all tracks", NULL, ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
 };
 
 struct queuelike ql_added = {
index 61943d251fcb81544bb9a88250e22fb15dd7fd6d..b0f59b5dad7deb3b6b23f104c6ca8061362f1243 100644 (file)
@@ -265,6 +265,7 @@ static void choose_playchildren_played(void attribute((unused)) *v,
 static struct menuitem choose_menuitems[] = {
   {
     "Play track",
+    GTK_STOCK_MEDIA_PLAY,
     choose_play_activate,
     choose_play_sensitive,
     0,
@@ -272,6 +273,7 @@ static struct menuitem choose_menuitems[] = {
   },
   {
     "Track properties",
+    GTK_STOCK_PROPERTIES,
     choose_properties_activate,
     choose_properties_sensitive,
     0,
@@ -279,6 +281,7 @@ static struct menuitem choose_menuitems[] = {
   },
   {
     "Select children",
+    NULL,
     choose_selectchildren_activate,
     choose_selectchildren_sensitive,
     0,
@@ -286,6 +289,7 @@ static struct menuitem choose_menuitems[] = {
   },
   {
     "Play children",
+    NULL,
     choose_playchildren_activate,
     choose_selectchildren_sensitive,    /* re-use */
     0,
@@ -293,6 +297,7 @@ static struct menuitem choose_menuitems[] = {
   },
   {
     "Deselect all tracks",
+    NULL,
     choose_selectnone_activate,
     choose_selectnone_sensitive,
     0,
index bc3c2c5cac696f799a801da35e90e1c643e471dc..b2dfce0da5f883e22ac57327efc350a380469771 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2006-2008 Richard Kettlewell
+ * Copyright (C) 2006-2009 Richard Kettlewell
  *
  * 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
@@ -25,7 +25,9 @@
 
 struct icon;
 
-static void clicked_icon(GtkButton *, gpointer);
+static void clicked_icon(GtkToolButton *, gpointer);
+static void toggled_icon(GtkToggleToolButton *button,
+                         gpointer user_data);
 static void clicked_menu(GtkMenuItem *, gpointer userdata);
 static void toggled_menu(GtkCheckMenuItem *, gpointer userdata);
 
@@ -60,6 +62,9 @@ static void control_minimode(const char *event,
 /** @brief Guard against feedback */
 int suppress_actions = 1;
 
+/** @brief Toolbar widget */
+static GtkWidget *toolbar;
+
 /** @brief Definition of an icon
  *
  * We have two kinds of icon:
@@ -72,21 +77,27 @@ int suppress_actions = 1;
  * (All icons can be sensitive or insensitive, separately to the above.)
  */
 struct icon {
-  /** @brief Filename for 'on' image */
-  const char *icon_on;
+  /** @brief TRUE to use GTK+ stock icons instead of filenames */
+  gboolean stock;
+
+  /** @brief TRUE for toggle buttons, FALSE for action buttons */
+  gboolean toggle;
+  
+  /** @brief Filename for image or stock string */
+  const char *icon;
 
   /** @brief Text for 'on' tooltip */
   const char *tip_on;
 
-  /** @brief Filename for 'off' image or NULL for an action icon */
-  const char *icon_off;
-
-  /** @brief Text for 'off tooltip */
+  /** @brief Text for 'off' tooltip */
   const char *tip_off;
 
   /** @brief Associated menu item or NULL */
   const char *menuitem;
 
+  /** @brief Label text */
+  const char *label;
+
   /** @brief Events that change this icon, separated by spaces */
   const char *events;
 
@@ -124,16 +135,16 @@ struct icon {
   /** @brief Pointer to menu item */
   GtkWidget *item;
 
-  GtkWidget *image_on;
-  GtkWidget *image_off;
+  GtkWidget *image;
 };
 
 static int pause_resume_on(void) {
-  return !(last_state & DISORDER_TRACK_PAUSED);
+  return !!(last_state & DISORDER_TRACK_PAUSED);
 }
 
 static int pause_resume_sensitive(void) {
-  return !!(last_state & DISORDER_PLAYING)
+  return playing_track
+    && !!(last_state & DISORDER_PLAYING)
     && (last_rights & RIGHT_PAUSE);
 }
 
@@ -169,19 +180,23 @@ static int rtp_sensitive(void) {
 /** @brief Table of all icons */
 static struct icon icons[] = {
   {
-    icon_on: "pause32.png",
-    tip_on: "Pause playing track",
-    icon_off: "play32.png",
-    tip_off: "Resume playing track",
+    toggle: TRUE,
+    stock: TRUE,
+    icon: GTK_STOCK_MEDIA_PAUSE,
+    label: "Pause",
+    tip_on: "Resume playing track",
+    tip_off: "Pause playing track",
     menuitem: "<GdisorderMain>/Control/Playing",
     on: pause_resume_on,
     sensitive: pause_resume_sensitive,
-    action_go_on: disorder_eclient_resume,
-    action_go_off: disorder_eclient_pause,
-    events: "pause-changed playing-changed rights-changed",
+    action_go_on: disorder_eclient_pause,
+    action_go_off: disorder_eclient_resume,
+    events: "pause-changed playing-changed rights-changed playing-track-changed",
   },
   {
-    icon_on: "cross32.png",
+    stock: TRUE,
+    icon: GTK_STOCK_STOP,
+    label: "Scratch",
     tip_on: "Cancel playing track",
     menuitem: "<GdisorderMain>/Control/Scratch",
     sensitive: scratch_sensitive,
@@ -189,9 +204,11 @@ static struct icon icons[] = {
     events: "playing-track-changed rights-changed",
   },
   {
-    icon_on: "randomenabled32.png",
+    toggle: TRUE,
+    stock: FALSE,
+    icon: "cards24.png",
+    label: "Random",
     tip_on: "Disable random play",
-    icon_off: "randomdisabled32.png",
     tip_off: "Enable random play",
     menuitem: "<GdisorderMain>/Control/Random play",
     on: random_enabled,
@@ -201,9 +218,11 @@ static struct icon icons[] = {
     events: "random-changed rights-changed",
   },
   {
-    icon_on: "playenabled32.png",
+    toggle: TRUE,
+    stock: TRUE,
+    icon: GTK_STOCK_MEDIA_PLAY,
+    label: "Play",
     tip_on: "Disable play",
-    icon_off: "playdisabled32.png",
     tip_off: "Enable play",
     on: playing_enabled,
     sensitive: playing_sensitive,
@@ -212,9 +231,11 @@ static struct icon icons[] = {
     events: "enabled-changed rights-changed",
   },
   {
-    icon_on: "rtpenabled32.png",
+    toggle: TRUE,
+    stock: TRUE,
+    icon: GTK_STOCK_CONNECT,
+    label: "RTP",
     tip_on: "Stop playing network stream",
-    icon_off: "rtpdisabled32.png",
     tip_off: "Play network stream",
     menuitem: "<GdisorderMain>/Control/Network player",
     on: rtp_enabled,
@@ -235,36 +256,52 @@ static GtkWidget *balance_widget;
 
 /** @brief Create the control bar */
 GtkWidget *control_widget(void) {
-  GtkWidget *hbox = gtk_hbox_new(FALSE, 1), *vbox;
+  GtkWidget *hbox = gtk_hbox_new(FALSE, 1);
   int n;
 
   D(("control_widget"));
   assert(mainmenufactory);              /* ordering must be right */
+  toolbar = gtk_toolbar_new();
+  /* Don't permit overflow arrow as otherwise the toolbar isn't greedy enough
+   * in asking for space.  The ideal is probably to make the volume and balance
+   * sliders hang down from the toolbar so it unavoidably gets the whole width
+   * of the window to play with. */
+  gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolbar), FALSE);
+  gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), 
+                        full_mode ? GTK_TOOLBAR_BOTH : GTK_TOOLBAR_ICONS);
   for(n = 0; n < NICONS; ++n) {
-    /* Create the button */
-    icons[n].button = gtk_button_new();
+    struct icon *const icon = &icons[n];
+    icon->button = (icon->toggle
+                    ? GTK_WIDGET(gtk_toggle_tool_button_new())
+                    : GTK_WIDGET(gtk_tool_button_new(NULL, NULL)));
     gtk_widget_set_style(icons[n].button, tool_style);
-    icons[n].image_on = gtk_image_new_from_pixbuf(find_image(icons[n].icon_on));
-    gtk_widget_set_style(icons[n].image_on, tool_style);
-    g_object_ref(icons[n].image_on);
-    /* If it's a toggle icon, create the 'off' half too */
-    if(icons[n].icon_off) {
-      icons[n].image_off = gtk_image_new_from_pixbuf(find_image(icons[n].icon_off));
-      gtk_widget_set_style(icons[n].image_off, tool_style);
-      g_object_ref(icons[n].image_off);
+    if(icons[n].stock) {
+      /* We'll use the stock icons for this one */
+      icon->image = gtk_image_new_from_stock(icons[n].icon,
+                                             GTK_ICON_SIZE_LARGE_TOOLBAR);
+    } else {
+      /* Create the 'on' image */
+      icon->image = gtk_image_new_from_pixbuf(find_image(icons[n].icon));
     }
-    g_signal_connect(G_OBJECT(icons[n].button), "clicked",
-                     G_CALLBACK(clicked_icon), &icons[n]);
-    /* pop the icon in a vbox so it doesn't get vertically stretch if there are
-     * taller things in the control bar */
-    vbox = gtk_vbox_new(FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(vbox), icons[n].button, TRUE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
+    assert(icon->image);
+    gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(icon->button),
+                                    icon->image);
+    gtk_tool_button_set_label(GTK_TOOL_BUTTON(icon->button),
+                                    icon->label);
+    if(icon->toggle)
+      g_signal_connect(G_OBJECT(icon->button), "toggled",
+                       G_CALLBACK(toggled_icon), icon);
+    else
+      g_signal_connect(G_OBJECT(icon->button), "clicked",
+                       G_CALLBACK(clicked_icon), icon);
+    gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+                       GTK_TOOL_ITEM(icon->button),
+                       -1);
     if(icons[n].menuitem) {
       /* Find the menu item */
       icons[n].item = gtk_item_factory_get_widget(mainmenufactory,
                                                   icons[n].menuitem);
-      if(icons[n].icon_off)
+      if(icon->toggle)
         g_signal_connect(G_OBJECT(icons[n].item), "toggled",
                          G_CALLBACK(toggled_menu), &icons[n]);
       else
@@ -290,12 +327,16 @@ GtkWidget *control_widget(void) {
   gtk_widget_set_style(balance_widget, tool_style);
   gtk_scale_set_digits(GTK_SCALE(volume_widget), 10);
   gtk_scale_set_digits(GTK_SCALE(balance_widget), 10);
-  gtk_widget_set_size_request(volume_widget, 192, -1);
-  gtk_widget_set_size_request(balance_widget, 192, -1);
+  gtk_widget_set_size_request(volume_widget, 128, -1);
+  gtk_widget_set_size_request(balance_widget, 128, -1);
   gtk_widget_set_tooltip_text(volume_widget, "Volume");
   gtk_widget_set_tooltip_text(balance_widget, "Balance");
-  gtk_box_pack_start(GTK_BOX(hbox), volume_widget, FALSE, TRUE, 0);
-  gtk_box_pack_start(GTK_BOX(hbox), balance_widget, FALSE, TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), toolbar,
+                     FALSE/*expand*/, TRUE/*fill*/, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), volume_widget,
+                     FALSE/*expand*/, TRUE/*fill*/, 0);
+  gtk_box_pack_start(GTK_BOX(hbox), balance_widget,
+                     FALSE/*expand*/, TRUE/*fill*/, 0);
   /* space updates rather than hammering the server */
   gtk_range_set_update_policy(GTK_RANGE(volume_widget), GTK_UPDATE_DELAYED);
   gtk_range_set_update_policy(GTK_RANGE(balance_widget), GTK_UPDATE_DELAYED);
@@ -357,22 +398,14 @@ static void icon_changed(const char attribute((unused)) *event,
   int on = icon->on ? icon->on() : 1;
   int sensitive = icon->sensitive ? icon->sensitive() : 1;
   //fprintf(stderr, "sensitive->%d\n", sensitive);
-  GtkWidget *child, *newchild;
 
   ++suppress_actions;
   /* If the connection is down nothing is ever usable */
   if(!(last_state & DISORDER_CONNECTED))
     sensitive = 0;
-  //fprintf(stderr, "(checked connected) sensitive->%d\n", sensitive);
-  /* Replace the child */
-  newchild = on ? icon->image_on : icon->image_off;
-  child = gtk_bin_get_child(GTK_BIN(icon->button));
-  if(child != newchild) {
-    if(child)
-      gtk_container_remove(GTK_CONTAINER(icon->button), child);
-    gtk_container_add(GTK_CONTAINER(icon->button), newchild);
-    gtk_widget_show(newchild);
-  }
+  if(icon->toggle)
+    gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(icon->button),
+                                      on);
   /* If you disable play or random play NOT via the icon (for instance, via the
    * edit menu or via a completely separate command line invocation) then the
    * icon shows up as insensitive.  Hover the mouse over it and the correct
@@ -384,7 +417,7 @@ static void icon_changed(const char attribute((unused)) *event,
   gtk_widget_set_sensitive(icon->button, sensitive);
   /* Icons with an associated menu item */
   if(icon->item) {
-    if(icon->icon_off)
+    if(icon->toggle)
       gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(icon->item), on);
     gtk_widget_set_sensitive(icon->item, sensitive);
   }
@@ -397,13 +430,22 @@ static void icon_action_completed(void attribute((unused)) *v,
     popup_protocol_error(0, err);
 }
 
-static void clicked_icon(GtkButton attribute((unused)) *button,
+static void clicked_icon(GtkToolButton attribute((unused)) *button,
                          gpointer userdata) {
   const struct icon *icon = userdata;
 
   if(suppress_actions)
     return;
-  if(!icon->on || icon->on())
+  icon->action_go_off(client, icon_action_completed, 0);
+}
+
+static void toggled_icon(GtkToggleToolButton attribute((unused)) *button,
+                         gpointer user_data) {
+  const struct icon *icon = user_data;
+
+  if(suppress_actions)
+    return;
+  if(icon->on())
     icon->action_go_off(client, icon_action_completed, 0);
   else
     icon->action_go_on(client, icon_action_completed, 0);
@@ -416,7 +458,7 @@ static void clicked_menu(GtkMenuItem attribute((unused)) *menuitem,
 
 static void toggled_menu(GtkCheckMenuItem attribute((unused)) *menuitem,
                          gpointer userdata) {
-  clicked_icon(NULL, userdata);
+  toggled_icon(NULL, userdata);
 }
 
 /** @brief Called when a volume command completes */
@@ -574,6 +616,8 @@ static void control_minimode(const char attribute((unused)) *event,
     gtk_widget_hide(balance_widget);
     gtk_scale_set_value_pos(GTK_SCALE(volume_widget), GTK_POS_RIGHT);
   }
+  gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), 
+                        full_mode ? GTK_TOOLBAR_BOTH : GTK_TOOLBAR_ICONS);
 }
 
 /*
index 6511b13555a15337df5cafb12ea912e10feb77d6..639eb73c2e74efba3e67a618177ba8740cb2ef52 100644 (file)
@@ -230,7 +230,7 @@ static void check_toplevel_size(const char attribute((unused)) *event,
 
 /** @brief Create and populate the main window */
 static void make_toplevel_window(void) {
-  GtkWidget *const vbox = gtk_vbox_new(FALSE, 1);
+  GtkWidget *const vbox = gtk_vbox_new(FALSE/*homogeneous*/, 1/*spacing*/);
   GtkWidget *const rb = report_box();
 
   D(("top_window"));
index 0aa2f578e2e23c2651dc2b1a3225719398e7f738..565f2271447ad30e2028051897f7c5461b1a8b10 100644 (file)
Binary files a/disobedience/manual/button-pause.png and b/disobedience/manual/button-pause.png differ
index dd64963e06ed13307c0ebdb203b98d6550db3a41..7b6fb2a8651db20438d9ce1dcbca52258fb3c284 100644 (file)
Binary files a/disobedience/manual/button-playing.png and b/disobedience/manual/button-playing.png differ
index 38f978353fff501abd036d5f461a44dc359d7aca..9791c2c51b6e8144eb4cf1938f98209070e32e08 100644 (file)
Binary files a/disobedience/manual/button-random.png and b/disobedience/manual/button-random.png differ
index 00fde8e3b6b5e4aa1650ca33dc1c41e0bb61abf2..ad0d7498be6d021b5df0d84f5f4efbff0456c6c5 100644 (file)
Binary files a/disobedience/manual/button-rtp.png and b/disobedience/manual/button-rtp.png differ
index e8a74f7b2bc8aa8cdb6393606f7166bfad5eddda..c90bfc5067589418ef4d61f7a1a89a2e9005e92f 100644 (file)
Binary files a/disobedience/manual/button-scratch.png and b/disobedience/manual/button-scratch.png differ
index 4c3392c065e737d46cb7d47306460b54a4355dc3..04b6f800bf32b38c7a3e30d10771bc97643156d3 100644 (file)
@@ -78,6 +78,10 @@ td {
   padding: 8px
 }
 
+td:first-child {
+  text-align: right
+}
+
 table {
   margin-left: 2em
 }
index bced68fba3f07a14b21c9aa0c31f2ed10b9424ef..224fc71c6a9fd97a79de5303ab87953dab7e571d 100644 (file)
Binary files a/disobedience/manual/queue.png and b/disobedience/manual/queue.png differ
index 8f8b4c3764038f7824655ce0adabe1cda988ab83..ff5cbedf30feb658b4352e122582da8d0acdc8c5 100644 (file)
Binary files a/disobedience/manual/queue2.png and b/disobedience/manual/queue2.png differ
index 9e983f23608e280be644e698cdbc5f26197e55f0..72fe5f77ffb2ef3669aefcba061807a511f527a3 100644 (file)
@@ -68,8 +68,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
      <tr>
        <td><img src="button-pause.png"></td>
        <td>The pause button.  This only effective when a track is
-       playing.  When it is pressed the playing track is paused and
-       the button turns into a &ldquo;play&rdquo; icon instead.</td>
+       playing.  When it is pressed the playing track is paused.</td>
      </tr>
 
      <tr>
@@ -81,19 +80,20 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
      <tr>
         <td><img src="button-random.png"></td>
-        <td>The random play button.  Random play means that if
+
+        <td>The random play button.  Random play, which is enabled
+        when the button is depressed, means that if
         nothing is playing the server will automatically pick a track
         at random and play that.  Furthermore it will ensure that the
         queue always has a minimum number of tracks, so you can see
-        ahead of time what will play next.<br>
-        As shown, random play is disabled.  The button goes green
-        when it is enabled.</td>
+        ahead of time what will play next.</td>
      </tr>
 
      <tr>
         <td><img src="button-playing.png"></td>
         <td>The playing button.  Normally this would always be left
-        enabled (green).  If it is disabled then nothing will be
+        enabled, i.e. with the button depressed.
+         If it is disabled then nothing will be
         played at all, regardless of whether it was randomly chosen
         or picked by a human.</td>
      </tr>
@@ -104,9 +104,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
         server is playing over the network (as opposed to using a
         local sound card).  When network play is enabled,
         Disobedience runs a client program on your computer to play
-        sound received over the network using your sound card.<br>
-        As shown, network play is disabled.  The button goes green
-        when it is enabled.</td>
+        sound received over the network using your sound card.</td>
      </tr>
    </table>
 
index 8947426241b3832bf90713f2d2914a18e01b49dc..bae0f00d7f0471c018efd2816afbef91af59f79b 100644 (file)
@@ -283,8 +283,8 @@ GtkWidget *menubar(GtkWidget *w) {
       (char *)"<CTRL>A",                /* accelerator */
       menu_tab_action,                  /* callback */
       offsetof(struct tabtype, selectall_activate), /* callback_action */
-      0,                                /* item_type */
-      0                                 /* extra_data */
+      (char *)"<StockItem>",           /* item_type */
+      GTK_STOCK_SELECT_ALL,            /* extra_data */
     },
     {
       (char *)"/Edit/Deselect all tracks", /* path */
@@ -299,8 +299,8 @@ GtkWidget *menubar(GtkWidget *w) {
       0,                                /* accelerator */
       menu_tab_action,                  /* callback */
       offsetof(struct tabtype, properties_activate), /* callback_action */
-      0,                                /* item_type */
-      0                                 /* extra_data */
+      (char *)"<StockItem>",            /* item_type */
+      GTK_STOCK_PROPERTIES,             /* extra_data */
     },
     {
       (char *)"/Edit/Edit playlists",   /* path */
@@ -325,8 +325,8 @@ GtkWidget *menubar(GtkWidget *w) {
       (char *)"<CTRL>S",                /* accelerator */
       0,                                /* callback */
       0,                                /* callback_action */
-      0,                                /* item_type */
-      0                                 /* extra_data */
+      (char *)"<StockItem>",            /* item_type */
+      GTK_STOCK_STOP,                   /* extra_data */
     },
     {
       (char *)"/Control/Playing",       /* path */
@@ -382,8 +382,8 @@ GtkWidget *menubar(GtkWidget *w) {
       0,                                /* accelerator */
       manual_popup,                     /* callback */
       0,                                /* callback_action */
-      0,                                /* item_type */
-      0                                 /* extra_data */
+      (char *)"<StockItem>",            /* item_type */
+      GTK_STOCK_HELP,                   /* extra_data */
     },
     {
       (char *)"/Help/About DisOrder",   /* path */
index 1f836ad89c0f8b5e9206c4a463bb8198757ce03f..4d4194ea76a0e3c5361ed03f2d794ac52920d384 100644 (file)
@@ -151,12 +151,12 @@ static const struct queue_column playlist_columns[] = {
  * - select/deselect all work
  */
 static struct menuitem playlist_menuitems[] = {
-  { "Track properties", ql_properties_activate, ql_properties_sensitive, 0, 0 },
-  { "Play track", ql_play_activate, ql_play_sensitive, 0, 0 },
-  { "Play playlist", playlist_playall_activate, playlist_playall_sensitive, 0, 0 },
-  { "Remove track from playlist", playlist_remove_activate, playlist_remove_sensitive, 0, 0 },
-  { "Select all tracks", ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
-  { "Deselect all tracks", ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
+  { "Track properties", GTK_STOCK_PROPERTIES, ql_properties_activate, ql_properties_sensitive, 0, 0 },
+  { "Play track", GTK_STOCK_MEDIA_PLAY, ql_play_activate, ql_play_sensitive, 0, 0 },
+  { "Play playlist", NULL, playlist_playall_activate, playlist_playall_sensitive, 0, 0 },
+  { "Remove track from playlist", GTK_STOCK_DELETE, playlist_remove_activate, playlist_remove_sensitive, 0, 0 },
+  { "Select all tracks", GTK_STOCK_SELECT_ALL, ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
+  { "Deselect all tracks", NULL, ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
 };
 
 static const GtkTargetEntry playlist_targets[] = {
@@ -995,6 +995,7 @@ static int playlist_picker_remove_sensitive(void *extra) {
 static struct menuitem playlist_picker_menuitems[] = {
   {
     "Select playlist",
+    NULL,
     playlist_picker_select_activate,
     playlist_picker_select_sensitive,
     0,
@@ -1002,6 +1003,7 @@ static struct menuitem playlist_picker_menuitems[] = {
   },
   {
     "Play playlist",
+    GTK_STOCK_MEDIA_PLAY, 
     playlist_picker_play_activate,
     playlist_picker_play_sensitive,
     0,
@@ -1009,6 +1011,7 @@ static struct menuitem playlist_picker_menuitems[] = {
   },
   {
     "Remove playlist",
+    GTK_STOCK_DELETE,
     playlist_picker_remove_activate,
     playlist_picker_remove_sensitive,
     0,
index 1a7c2e5224de2fd8a89b6e682b9c8f0d1b2998fc..d7e91f34117a6c9a8007867ac0725e308d6c18ea 100644 (file)
@@ -34,7 +34,14 @@ void popup(GtkWidget **menup,
     g_signal_connect(menu, "destroy",
                      G_CALLBACK(gtk_widget_destroyed), menup);
     for(int n = 0; n < nitems; ++n) {
-      items[n].w = gtk_menu_item_new_with_label(items[n].name);
+      if(items[n].stock) {
+        GtkWidget *image = gtk_image_new_from_stock(items[n].stock,
+                                                    GTK_ICON_SIZE_MENU);
+        items[n].w = gtk_image_menu_item_new_with_label(items[n].name);
+        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(items[n].w),
+                                      image);
+      } else
+        items[n].w = gtk_menu_item_new_with_label(items[n].name);
       /* TODO accelerators would be useful here.  There might be some
        * interaction with the main menu accelerators, _except_ for playlist
        * case!  */
index 9706e0398b2de45bbe2db7b5dabf1fa0298ed148..25726b2fa451e96ee86bba14626a9c3f4acb8afa 100644 (file)
@@ -26,6 +26,9 @@ struct menuitem {
   /** @brief Menu item name */
   const char *name;
 
+  /** @brief Stock icon name */
+  const char *stock;
+
   /** @brief Called to activate the menu item */
   void (*activate)(GtkMenuItem *menuitem,
                    gpointer user_data);
index 6c0e1362c4aa7231d20214bfd17ac5ce06f56b19..c495bd85cc6471fb47ee58f0f8cbf6c3363d36a7 100644 (file)
@@ -233,12 +233,12 @@ static const struct queue_column queue_columns[] = {
 
 /** @brief Pop-up menu for queue */
 static struct menuitem queue_menuitems[] = {
-  { "Track properties", ql_properties_activate, ql_properties_sensitive, 0, 0 },
-  { "Select all tracks", ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
-  { "Deselect all tracks", ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
-  { "Scratch playing track", ql_scratch_activate, ql_scratch_sensitive, 0, 0 },
-  { "Remove track from queue", ql_remove_activate, ql_remove_sensitive, 0, 0 },
-  { "Adopt track", ql_adopt_activate, ql_adopt_sensitive, 0, 0 },
+  { "Track properties", GTK_STOCK_PROPERTIES, ql_properties_activate, ql_properties_sensitive, 0, 0 },
+  { "Select all tracks", GTK_STOCK_SELECT_ALL, ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
+  { "Deselect all tracks", NULL, ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
+  { "Scratch playing track", GTK_STOCK_STOP, ql_scratch_activate, ql_scratch_sensitive, 0, 0 },
+  { "Remove track from queue", GTK_STOCK_DELETE, ql_remove_activate, ql_remove_sensitive, 0, 0 },
+  { "Adopt track", NULL, ql_adopt_activate, ql_adopt_sensitive, 0, 0 },
 };
 
 static const GtkTargetEntry queue_targets[] = {
index 0e74feb07e7adc8b671057f49ef3c282561b856c..510aac901c964519133f966816db8b80ed304843 100644 (file)
@@ -78,10 +78,10 @@ static const struct queue_column recent_columns[] = {
 
 /** @brief Pop-up menu for recently played list */
 static struct menuitem recent_menuitems[] = {
-  { "Track properties", ql_properties_activate, ql_properties_sensitive,0, 0 },
-  { "Play track", ql_play_activate, ql_play_sensitive, 0, 0 },
-  { "Select all tracks", ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
-  { "Deselect all tracks", ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
+  { "Track properties", GTK_STOCK_PROPERTIES, ql_properties_activate, ql_properties_sensitive,0, 0 },
+  { "Play track", GTK_STOCK_MEDIA_PLAY, ql_play_activate, ql_play_sensitive, 0, 0 },
+  { "Select all tracks", GTK_STOCK_SELECT_ALL, ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
+  { "Deselect all tracks", NULL, ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
 };
 
 struct queuelike ql_recent = {
index ffe393c3f80b388d48f2d6a57828b779f749c6bb..22322edcabc2bfa38cbd4f91c82d65ccf48f277e 100644 (file)
@@ -1,6 +1,6 @@
 #
 # This file is part of DisOrder.
-# Copyright (C) 2005-2008 Richard Kettlewell
+# Copyright (C) 2005-2009 Richard Kettlewell
 #
 # 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
@@ -27,6 +27,7 @@ disobedience32x32.xpm cross.svg go.svg notes.svg noteson.svg pause.svg        \
 query.svg queryon.svg speaker.svg speakeron.svg cross32.png            \
 pause32.png play32.png playdisabled32.png playenabled32.png            \
 randomdisabled32.png randomenabled32.png rtpdisabled32.png             \
-rtpenabled32.png duck55.png
+rtpenabled32.png duck55.png cards24.png cards48.png                    \
+cards-simple-fanned.svg cards-thin.svg
 
 CLEANFILES=$(SEDFILES)
diff --git a/images/cards-simple-fanned.svg b/images/cards-simple-fanned.svg
new file mode 100644 (file)
index 0000000..9ae9730
--- /dev/null
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48"
+   height="48"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   version="1.0"
+   sodipodi:docname="cards-simple-fanned.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/richard/cards/cards-simple-fanned-24.png"
+   inkscape:export-xdpi="45"
+   inkscape:export-ydpi="45">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="17.25"
+     inkscape:cx="24"
+     inkscape:cy="24"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:snap-intersection-line-segments="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-nodes="false"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:window-width="1301"
+     inkscape:window-height="1034"
+     inkscape:window-x="122"
+     inkscape:window-y="20">
+    <inkscape:grid
+       type="xygrid"
+       id="grid2383"
+       visible="true"
+       enabled="true"
+       empspacing="8" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <g
+       id="g3227">
+      <rect
+         transform="matrix(0.9659258,-0.2588191,0.2588191,0.9659258,0,0)"
+         y="8.3028555"
+         x="1.4500779"
+         height="34.000004"
+         width="24.000002"
+         id="rect3292"
+         style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2.00000024;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         transform="matrix(0.9659258,-0.2588191,0.2588191,0.9659258,0,0)"
+         y="9.3028555"
+         x="2.450078"
+         height="32.000004"
+         width="22.000002"
+         id="rect3294"
+         style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.00000023999999987;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         transform="matrix(0.9659258,-0.2588191,0.2588191,0.9659258,0,0)"
+         y="13.302856"
+         x="6.4500785"
+         height="24.000002"
+         width="14.000001"
+         id="rect3296"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:2.00000023999999987;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+    <g
+       id="g3222">
+      <rect
+         y="6.5112176"
+         x="12.457951"
+         height="34"
+         width="24"
+         id="rect3267"
+         style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         y="7.5112176"
+         x="13.457951"
+         height="32"
+         width="22"
+         id="rect2387"
+         style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         y="11.511218"
+         x="17.457951"
+         height="24"
+         width="14"
+         id="rect3159"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+    <g
+       id="g3217">
+      <rect
+         transform="matrix(0.9659258,0.2588191,-0.2588191,0.9659258,0,0)"
+         y="1.7532461"
+         x="22.488214"
+         height="34.000004"
+         width="24.000002"
+         id="rect3276"
+         style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2.00000024;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         transform="matrix(0.9659258,0.2588191,-0.2588191,0.9659258,0,0)"
+         y="2.7532461"
+         x="23.488214"
+         height="32.000004"
+         width="22.000002"
+         id="rect3278"
+         style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.00000023999999987;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         transform="matrix(0.9659258,0.2588191,-0.2588191,0.9659258,0,0)"
+         y="6.7532463"
+         x="27.488214"
+         height="24.000002"
+         width="14.000001"
+         id="rect3280"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:2.00000023999999987;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/images/cards-thin.svg b/images/cards-thin.svg
new file mode 100644 (file)
index 0000000..94e1255
--- /dev/null
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48"
+   height="48"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   version="1.0"
+   sodipodi:docname="cards-thin.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/richard/cards48.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="17.1875"
+     inkscape:cx="24"
+     inkscape:cy="24"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:snap-intersection-line-segments="true"
+     inkscape:snap-bbox="true"
+     inkscape:snap-nodes="false"
+     inkscape:bbox-paths="true"
+     inkscape:bbox-nodes="true"
+     inkscape:window-width="1639"
+     inkscape:window-height="1031"
+     inkscape:window-x="122"
+     inkscape:window-y="20">
+    <inkscape:grid
+       type="xygrid"
+       id="grid2383"
+       visible="true"
+       enabled="true"
+       empspacing="8" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <g
+       id="g3290"
+       transform="matrix(0.9848078,-0.1736482,0.1736482,0.9848078,3.6830881,3.8942155)">
+      <rect
+         y="2"
+         x="2"
+         height="34"
+         width="24"
+         id="rect3292"
+         style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         y="3"
+         x="3"
+         height="32"
+         width="22"
+         id="rect3294"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         y="7"
+         x="7"
+         height="24"
+         width="14"
+         id="rect3296"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+    <g
+       id="g3269"
+       transform="translate(10,3)">
+      <rect
+         y="2"
+         x="2"
+         height="34"
+         width="24"
+         id="rect3267"
+         style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         y="3"
+         x="3"
+         height="32"
+         width="22"
+         id="rect2387"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         y="7"
+         x="7"
+         height="24"
+         width="14"
+         id="rect3159"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+    <g
+       id="g3274"
+       transform="matrix(0.9848078,0.1736482,-0.1736482,0.9848078,16.28172,3.0320659)">
+      <rect
+         y="2"
+         x="2"
+         height="34"
+         width="24"
+         id="rect3276"
+         style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         y="3"
+         x="3"
+         height="32"
+         width="22"
+         id="rect3278"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <rect
+         y="7"
+         x="7"
+         height="24"
+         width="14"
+         id="rect3280"
+         style="fill:#ff0000;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/images/cards24.png b/images/cards24.png
new file mode 100644 (file)
index 0000000..24e90fb
Binary files /dev/null and b/images/cards24.png differ
diff --git a/images/cards48.png b/images/cards48.png
new file mode 100644 (file)
index 0000000..e929b75
Binary files /dev/null and b/images/cards48.png differ