PNGS:=$(wildcard ${top_srcdir}/images/*.png)
disobedience_SOURCES=disobedience.h disobedience.c client.c queue.c \
- choose.c misc.c style.h control.c properties.c menu.c \
+ choose.c misc.c control.c properties.c menu.c \
log.c progress.c login.c rtp.c help.c \
- ../lib/memgc.c
+ ../lib/memgc.c appearance.c
disobedience_LDADD=../lib/libdisorder.a $(LIBPCRE) $(LIBGC) $(LIBGCRYPT)
disobedience_LDFLAGS=$(GTK_LIBS)
check: check-help
-disobedience.o: style.h
-
-style.h: ${srcdir}/disobedience.rc ${top_srcdir}/scripts/text2c
- ${top_srcdir}/scripts/text2c style ${srcdir}/disobedience.rc > $@.tmp
- mv $@.tmp $@
-
help.o: manual.h
manual.html: ../doc/disobedience.1 $(top_srcdir)/scripts/htmlman
echo "};"
mv @$.new $@
-EXTRA_DIST=disobedience.rc
-
# check everything has working --help
check-help: all
./disobedience --version > /dev/null
--- /dev/null
+/*
+ * This file is part of Disobedience
+ * Copyright (C) 2007 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
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+/** @file disobedience/appearance.c
+ * @brief Visual appearance of Disobedience
+ *
+ * Originally I attempted to use a built-in rc file to configure
+ * Disobedience's colors. This is quite convenient but fails in the
+ * face of themes, as the theme settings override the application
+ * ones.
+ *
+ * This file therefore collects all the colors of the Disobedience UI
+ * and (in time) will have a configuration dialog too.
+ */
+
+#include "disobedience.h"
+#include "inputline.h"
+#include "split.h"!
+#include <sys/stat.h>
+
+/** @brief Background colors for tools - menus, icons, etc. */
+GdkColor tool_bg = { 0, 0xDC00, 0xDA00, 0xD500 };
+
+/** @brief Background color for active tool */
+GdkColor tool_active;
+
+/** @brief Foreground colors for tools */
+GdkColor tool_fg = { 0, 0x0000, 0x0000, 0x0000 };
+
+/** @brief Foreground colors for inactive tools */
+GdkColor inactive_tool_fg = { 0, 0x8000, 0x8000, 0x8000 };
+
+/** @brief Background for inactive tools (e.g. noncurrent tabs) */
+GdkColor offtool_bg = { 0, 0xC400, 0xC200, 0xBD00 };
+
+/** @brief Background color for the various layouts */
+GdkColor layout_bg = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
+
+/** @brief Title-row background color */
+GdkColor title_bg = { 0, 0x0000, 0x0000, 0x0000 };
+
+/** @brief Title-row foreground color */
+GdkColor title_fg = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
+
+/** @brief Even-row background color */
+GdkColor even_bg = { 0, 0xFFFF, 0xEC00, 0xEBFF };
+
+/** @brief Odd-row background color */
+GdkColor odd_bg = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
+
+/** @brief Active-row background color */
+GdkColor active_bg = { 0, 0xE000, 0xFFFF, 0xE000 };
+
+/** @brief Item foreground color */
+GdkColor item_fg = { 0, 0x0000, 0x0000, 0x0000 };
+
+/** @brief Selected background color */
+GdkColor selected_bg = { 0, 0x4B00, 0x6900, 0x8300 };
+
+/** @brief Selected foreground color */
+GdkColor selected_fg = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
+
+/** @brief Search results */
+GdkColor search_bg = { 0, 0xFFFF, 0xFFFF, 0x0000 };
+
+/** @brief Drag target color */
+GdkColor drag_target = { 0, 0x6666, 0x6666, 0x6666 };
+
+struct colordesc {
+ GdkColor *color;
+ const char *name;
+ const char *description;
+};
+
+#define COLOR(name, description) { &name, #name, description }
+
+/** @brief Table of configurable colors
+ *
+ * Some of the descriptions could be improve!
+ */
+static const struct colordesc colors[] = {
+ COLOR(tool_bg, "Tool background color"),
+ COLOR(tool_fg, "Tool foreground color"),
+ COLOR(offtool_bg, "Subsiduary tool color"),
+ COLOR(layout_bg, "Layout background color"),
+ COLOR(title_bg, "Title row background color"),
+ COLOR(title_fg, "Title row foreground color"),
+ COLOR(even_bg, "Even row background color"),
+ COLOR(odd_bg, "Odd row background color"),
+ COLOR(active_bg, "Playing row background color"),
+ COLOR(item_fg, "Track foreground color"),
+ COLOR(selected_bg, "Selected item background color"),
+ COLOR(selected_fg, "Selected item foreground color"),
+ COLOR(search_bg, "Search result background color"),
+ COLOR(drag_target, "Drag target color"),
+};
+
+#define NCOLORS (sizeof colors / sizeof *colors)
+
+void save_appearance(void) {
+ char *dir, *path, *tmp;
+ FILE *fp = 0;
+ size_t n;
+
+ byte_xasprintf(&dir, "%s/.disorder", getenv("HOME"));
+ byte_xasprintf(&path, "%s/disobedience", dir);
+ byte_xasprintf(&tmp, "%s.tmp", path);
+ mkdir(dir, 02700); /* make sure directory exists */
+ if(!(fp = fopen(tmp, "w"))) {
+ fpopup_msg(GTK_MESSAGE_ERROR, "error opening %s: %s",
+ tmp, strerror(errno));
+ goto done;
+ }
+ for(n = 0; n < NCOLORS; ++n)
+ if(fprintf(fp, "color %-20s 0x%04X 0x%04X 0x%04X\n", colors[n].name,
+ colors[n].color->red,
+ colors[n].color->green,
+ colors[n].color->blue) < 0) {
+ fpopup_msg(GTK_MESSAGE_ERROR, "error writing to %s: %s",
+ tmp, strerror(errno));
+ goto done;
+ }
+ if(fclose(fp) < 0) {
+ fpopup_msg(GTK_MESSAGE_ERROR, "error writing to %s: %s",
+ tmp, strerror(errno));
+ fp = 0;
+ goto done;
+ }
+ fp = 0;
+ if(rename(tmp, path) < 0)
+ fpopup_msg(GTK_MESSAGE_ERROR, "error renaming %s to %s: %s",
+ tmp, path, strerror(errno));
+done:
+ if(fp)
+ fclose(fp);
+}
+
+static inline unsigned clamp(unsigned n) {
+ return n > 0xFFFF ? 0xFFFF : n;
+}
+
+void load_appearance(void) {
+ char *path, *line;
+ FILE *fp;
+ size_t n;
+ char **vec;
+ int nvec;
+
+ byte_xasprintf(&path, "%s/.disorder/disobedience", getenv("HOME"));
+ if(!(fp = fopen(path, "r"))) {
+ if(errno != ENOENT)
+ fpopup_msg(GTK_MESSAGE_ERROR, "error opening %s: %s",
+ path, strerror(errno));
+ return;
+ }
+ while(!inputline(path, fp, &line, '\n')) {
+ if(!(vec = split(line, &nvec, SPLIT_COMMENTS|SPLIT_QUOTES, 0, 0))
+ || !nvec)
+ continue;
+ if(!strcmp(vec[0], "color")) {
+ if(nvec != 5) {
+ error(0, "%s: malformed '%s' command", path, vec[0]);
+ continue;
+ }
+ for(n = 0; n < NCOLORS && strcmp(colors[n].name, vec[1]); ++n)
+ ;
+ if(n >= NCOLORS) {
+ error(0, "%s: unknown color '%s'", path, vec[1]);
+ continue;
+ }
+ colors[n].color->red = strtoul(vec[2], 0, 0);
+ colors[n].color->green = strtoul(vec[3], 0, 0);
+ colors[n].color->blue = strtoul(vec[4], 0, 0);
+ } else
+ /* mention errors but otherwise ignore them */
+ error(0, "%s: unknown command '%s'", path, vec[0]);
+ }
+ if(ferror(fp)) {
+ fpopup_msg(GTK_MESSAGE_ERROR, "error reading %s: %s",
+ path, strerror(errno));
+ fclose(fp);
+ }
+ tool_active = tool_bg;
+ tool_active.red = clamp(105 * tool_active.red / 100);
+ tool_active.green = clamp(105 * tool_active.green / 100);
+ tool_active.blue = clamp(105 * tool_active.blue / 100);
+}
+
+/** @brief Callback used by set_tool_colors() */
+static void set_tool_colors_callback(GtkWidget *w,
+ gpointer attribute((unused)) data) {
+ set_tool_colors(w);
+}
+
+/** @brief Recursively set tool widget colors */
+void set_tool_colors(GtkWidget *w) {
+ GtkWidget *child;
+
+ gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &tool_bg);
+ gtk_widget_modify_bg(w, GTK_STATE_SELECTED, &selected_bg);
+ gtk_widget_modify_bg(w, GTK_STATE_PRELIGHT, &selected_bg);
+ gtk_widget_modify_bg(w, GTK_STATE_INSENSITIVE, &tool_bg);
+ gtk_widget_modify_fg(w, GTK_STATE_NORMAL, &tool_fg);
+ gtk_widget_modify_fg(w, GTK_STATE_SELECTED, &selected_fg);
+ gtk_widget_modify_fg(w, GTK_STATE_PRELIGHT, &selected_fg);
+ gtk_widget_modify_fg(w, GTK_STATE_INSENSITIVE, &inactive_tool_fg);
+ if(GTK_IS_CONTAINER(w))
+ gtk_container_foreach(GTK_CONTAINER(w), set_tool_colors_callback, 0);
+ if(GTK_IS_MENU_ITEM(w)
+ && (child = gtk_menu_item_get_submenu(GTK_MENU_ITEM(w))))
+ set_tool_colors(child);
+}
+
+/** @brief Set the colors for a slider */
+void set_slider_colors(GtkWidget *w) {
+ if(!w)
+ return;
+ gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &tool_bg);
+ gtk_widget_modify_bg(w, GTK_STATE_ACTIVE, &tool_bg);
+ gtk_widget_modify_bg(w, GTK_STATE_SELECTED, &tool_active);
+ gtk_widget_modify_bg(w, GTK_STATE_PRELIGHT, &tool_active);
+ gtk_widget_modify_fg(w, GTK_STATE_NORMAL, &tool_fg);
+ gtk_widget_modify_fg(w, GTK_STATE_ACTIVE, &tool_fg);
+ gtk_widget_modify_fg(w, GTK_STATE_SELECTED, &tool_fg);
+ gtk_widget_modify_fg(w, GTK_STATE_PRELIGHT, &tool_fg);
+}
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+fill-column:79
+indent-tabs-mode:nil
+End:
+*/
GtkRequisition req;
struct displaydata d, cd;
GdkPixbuf *pb;
- const char *name;
const int search_result = is_search_result(cn->path);
D(("display_tree %s %d,%d", cn->path, x, y));
MTAG_POP();
}
assert(cn->container);
- /* Make sure the widget name is right */
- name = (cn->flags & CN_EXPANDABLE
- ? "choose-dir"
- : search_result ? "choose-search" : "choose");
- gtk_widget_set_name(cn->label, name);
- gtk_widget_set_name(cn->container, name);
+ /* Set colors */
+ if(search_result)
+ gtk_widget_modify_bg(cn->container, GTK_STATE_NORMAL, &search_bg);
+ else
+ gtk_widget_modify_bg(cn->container, GTK_STATE_NORMAL, &layout_bg);
+ gtk_widget_modify_bg(cn->container, GTK_STATE_SELECTED, &selected_bg);
+ gtk_widget_modify_bg(cn->container, GTK_STATE_PRELIGHT, &selected_bg);
+ gtk_widget_modify_fg(cn->label, GTK_STATE_NORMAL, &item_fg);
+ gtk_widget_modify_fg(cn->label, GTK_STATE_SELECTED, &selected_fg);
+ gtk_widget_modify_fg(cn->label, GTK_STATE_PRELIGHT, &selected_fg);
/* Make sure the icon is right */
if(cn->flags & CN_EXPANDABLE)
gtk_arrow_set(GTK_ARROW(cn->arrow),
menuitems[n].handlerid = g_signal_connect
(menuitems[n].w, "activate", G_CALLBACK(menuitems[n].activate), cn);
}
+ set_tool_colors(menu);
/* Pop up the menu */
gtk_widget_show_all(menu);
gtk_menu_popup(GTK_MENU(menu), 0, 0, 0, 0,
/* Cancel button to clear the search */
NW(button);
clearsearch = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_widget_modify_bg(clearsearch, GTK_STATE_NORMAL, &tool_bg);
+ gtk_widget_modify_bg(clearsearch, GTK_STATE_ACTIVE, &tool_active);
+ gtk_widget_modify_bg(clearsearch, GTK_STATE_PRELIGHT, &tool_active);
+ gtk_widget_modify_bg(clearsearch, GTK_STATE_SELECTED, &tool_active);
g_signal_connect(G_OBJECT(clearsearch), "clicked",
G_CALLBACK(clearsearch_clicked), 0);
gtk_tooltips_set_tip(tips, clearsearch, "Clear search terms", "");
g_signal_connect(G_OBJECT(prevsearch), "clicked",
G_CALLBACK(prev_clicked), 0);
gtk_widget_set_sensitive(prevsearch, 0);
+ gtk_widget_modify_bg(prevsearch, GTK_STATE_NORMAL, &tool_bg);
+ gtk_widget_modify_bg(prevsearch, GTK_STATE_ACTIVE, &tool_active);
+ gtk_widget_modify_bg(prevsearch, GTK_STATE_PRELIGHT, &tool_active);
+ gtk_widget_modify_bg(prevsearch, GTK_STATE_SELECTED, &tool_active);
+ gtk_widget_modify_bg(prevsearch, GTK_STATE_INSENSITIVE, &tool_active);
nextsearch = iconbutton("down.png", "Next search result");
g_signal_connect(G_OBJECT(nextsearch), "clicked",
G_CALLBACK(next_clicked), 0);
gtk_widget_set_sensitive(nextsearch, 0);
+ gtk_widget_modify_bg(nextsearch, GTK_STATE_NORMAL, &tool_bg);
+ gtk_widget_modify_bg(nextsearch, GTK_STATE_ACTIVE, &tool_active);
+ gtk_widget_modify_bg(nextsearch, GTK_STATE_PRELIGHT, &tool_active);
+ gtk_widget_modify_bg(nextsearch, GTK_STATE_SELECTED, &tool_active);
+ gtk_widget_modify_bg(nextsearch, GTK_STATE_INSENSITIVE, &tool_active);
/* hbox packs the search tools button together on a line */
NW(hbox);
* namespace */
NW(layout);
chooselayout = gtk_layout_new(0, 0);
+ gtk_widget_modify_bg(chooselayout, GTK_STATE_NORMAL, &layout_bg);
choose_reset();
register_reset(choose_reset);
/* Create the popup menus */
0, 1, n, n + 1);
}
/* The layout is scrollable */
- scrolled = scroll_widget(chooselayout, "choose");
+ scrolled = scroll_widget(chooselayout);
vadjust = gtk_layout_get_vadjustment(GTK_LAYOUT(chooselayout));
/* The scrollable layout and the search hbox go together in a vbox */
for(n = 0; n < NICONS; ++n) {
NW(button);
icons[n].button = gtk_button_new();
+ gtk_widget_modify_bg(icons[n].button, GTK_STATE_NORMAL, &tool_bg);
+ gtk_widget_modify_bg(icons[n].button, GTK_STATE_ACTIVE, &tool_active);
+ gtk_widget_modify_bg(icons[n].button, GTK_STATE_PRELIGHT, &tool_active);
+ gtk_widget_modify_bg(icons[n].button, GTK_STATE_SELECTED, &tool_active);
if((pb = find_image(icons[n].icon))) {
NW(image);
content = gtk_image_new_from_pixbuf(pb);
v = gtk_hscale_new(volume_adj);
NW(hscale);
b = gtk_hscale_new(balance_adj);
+ set_slider_colors(v);
+ set_slider_colors(b);
gtk_scale_set_digits(GTK_SCALE(v), 10);
gtk_scale_set_digits(GTK_SCALE(b), 10);
gtk_widget_set_size_request(v, 192, -1);
/* Apologies for the numerous de-consting casts, but GLib et al do not seem to
* have heard of const. */
-#include "style.h" /* generated style */
-
/* Variables --------------------------------------------------------------- */
/** @brief Event loop */
/** @brief Create and populate the main tab group */
static GtkWidget *notebook(void) {
tabs = gtk_notebook_new();
+ /* The current tab is _NORMAL, the rest are _ACTIVE, which is bizarre but
+ * produces not too dreadful appearance */
+ gtk_widget_modify_bg(tabs, GTK_STATE_NORMAL, &tool_bg);
+ gtk_widget_modify_bg(tabs, GTK_STATE_ACTIVE, &tool_active);
+ gtk_widget_modify_fg(tabs, GTK_STATE_NORMAL, &tool_fg);
+ gtk_widget_modify_fg(tabs, GTK_STATE_ACTIVE, &tool_fg);
g_signal_connect(tabs, "switch-page", G_CALLBACK(tab_switched), 0);
gtk_notebook_append_page(GTK_NOTEBOOK(tabs), queue_widget(),
gtk_label_new("Queue"));
FALSE, /* expand */
FALSE, /* fill */
0);
- gtk_widget_set_name(toplevel, "disobedience");
+ gtk_widget_modify_bg(toplevel, GTK_STATE_NORMAL, &tool_bg);
}
#if MDEBUG
#endif
if(!setlocale(LC_CTYPE, "")) fatal(errno, "error calling setlocale");
gtk_init(&argc, &argv);
- gtk_rc_parse_string(style);
while((n = getopt_long(argc, argv, "hVc:dtHC", options, 0)) >= 0) {
switch(n) {
case 'h': help();
}
}
signal(SIGPIPE, SIG_IGN);
+ load_appearance();
/* create the event loop */
D(("create main loop"));
mainloop = g_main_loop_new(0, 0);
void properties_reset(void);
-GtkWidget *scroll_widget(GtkWidget *child, const char *name);
+GtkWidget *scroll_widget(GtkWidget *child);
/* Wrap a widget up for scrolling */
GdkPixbuf *find_image(const char *name);
void start_rtp(void);
void stop_rtp(void);
+/* Appearance */
+
+extern GdkColor tool_bg, tool_fg, offtool_bg, layout_bg, even_bg, odd_bg;
+extern GdkColor active_bg, selected_bg, selected_fg, search_bg;
+extern GdkColor title_bg, title_fg, item_fg, drag_target, tool_active;
+
+void save_appearance(void);
+void load_appearance(void);
+void set_tool_colors(GtkWidget *w);
+void set_slider_colors(GtkWidget *w);
+
/* Widget leakage debugging rubbish ---------------------------------------- */
#if MDEBUG
+++ /dev/null
-#
-# This file is part of DisOrder.
-# Copyright (C) 2006, 2007 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
-# 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA
-#
-
-# Default style for Disobedience
-#
-# See e.g. http://developer.gnome.org/doc/API/2.0/gtk/gtk-Resource-Files.html
-# for syntax documentation.
-
-style "disobedience-default"
-{
- bg[NORMAL] = { 1.0, 1.0, 1.0 }
- fg[NORMAL] = { 0.0, 0.0, 0.0 }
- bg[PRELIGHT] = { 1.0, 1.0, 1.0 }
- fg[PRELIGHT] = { 1.0, 1.0, 1.0 }
-}
-
-style "disobedience-playing"
-{
- bg[NORMAL] = { 0.875, 1.0, 0.875 }
- fg[NORMAL] = { 0.0, 0.0, 0.0 }
-}
-
-style "disobedience-even"
-{
- bg[NORMAL] = { 1.0, 0.921875, 0.921875 }
- fg[NORMAL] = { 0.0, 0.0, 0.0 }
-}
-
-style "disobedience-odd"
-{
- bg[NORMAL] = { 1.0, 1.0, 1.0 }
- fg[NORMAL] = { 0.0, 0.0, 0.0 }
-}
-
-style "disobedience-search"
-{
- bg[NORMAL] = { 1.0, 1.0, 0.0 }
- fg[NORMAL] = { 0.0, 0.0, 0.0 }
-}
-
-style "disobedience-title"
-{
- bg[NORMAL] = { 0.0, 0.0, 0.0 }
- fg[NORMAL] = { 1.0, 1.0, 1.0 }
- font_name = "Bold"
-}
-
-style "disobedience-drag"
-{
- bg[NORMAL] = { 0.4, 0.4, 0.4 }
- fg[NORMAL] = { 1.0, 1.0, 1.0 }
-}
-
-# The main tabs
-widget "disobedience.*.choose" style : application "disobedience-default"
-widget "disobedience.*.choose-dir" style : application "disobedience-default"
-widget "disobedience.*.queue" style : application "disobedience-default"
-widget "disobedience.*.recent" style : application "disobedience-default"
-
-# Drag target
-widget "disobedience.*.queue-drag" style : application "disobedience-drag"
-
-# Rows in the queue/recent tabs
-widget "disobedience.*.row-playing" style : application "disobedience-playing"
-widget "disobedience.*.row-even" style : application "disobedience-even"
-widget "disobedience.*.row-odd" style : application "disobedience-odd"
-widget "disobedience.*.row-title" style : application "disobedience-title"
-
-# Search results
-widget "disobedience.*.choose-search" style : application "disobedience-search"
gtk_window_set_title(GTK_WINDOW(help_window), "Disobedience Manual Page");
view = gtk_text_view_new_with_buffer(html_buffer(manual));
gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);
- gtk_container_add(GTK_CONTAINER(help_window),
- scroll_widget(view,
- "help"));
+ gtk_container_add(GTK_CONTAINER(help_window), scroll_widget(view));
gtk_window_set_default_size(GTK_WINDOW(help_window), 512, 512);
gtk_widget_show_all(help_window);
}
/** @brief Create the menu bar widget */
GtkWidget *menubar(GtkWidget *w) {
+ GtkWidget *m;
+
static const GtkItemFactoryEntry entries[] = {
{
(char *)"/File", /* path */
"<GdisorderMain>/Edit/Track properties");
assert(selectall_widget != 0);
assert(properties_widget != 0);
- return gtk_item_factory_get_widget(mainmenufactory,
- "<GdisorderMain>");
- /* menu bar had better not expand vertically if the window is too big */
+ m = gtk_item_factory_get_widget(mainmenufactory,
+ "<GdisorderMain>");
+ set_tool_colors(m);
+ return m;
}
/*
/** @brief Put scrollbars around a widget
* @param child Widget to surround
- * @param widgetname Name for (both) widgets
* @return Scroll widget
*/
-GtkWidget *scroll_widget(GtkWidget *child,
- const char *widgetname) {
+GtkWidget *scroll_widget(GtkWidget *child) {
GtkWidget *scroller = gtk_scrolled_window_new(0, 0);
GtkAdjustment *adj;
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroller),
child);
}
- /* Apply a name to the widget so it can be recolored */
- gtk_widget_set_name(GTK_BIN(scroller)->child, widgetname);
- gtk_widget_set_name(scroller, widgetname);
+ set_slider_colors(GTK_SCROLLED_WINDOW(scroller)->hscrollbar);
+ set_slider_colors(GTK_SCROLLED_WINDOW(scroller)->vscrollbar);
return scroller;
}
/* Put it all together */
vbox = gtk_vbox_new(FALSE, 1);
gtk_box_pack_start(GTK_BOX(vbox),
- scroll_widget(properties_table,
- "properties"),
+ scroll_widget(properties_table),
TRUE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(vbox), buttonbox, FALSE, FALSE, 1);
gtk_container_add(GTK_CONTAINER(properties_window), vbox);
* ql_added.
*/
struct queuelike {
- /** @brief Name of this queue */
- const char *name;
-
/** @brief Called when an update completes */
void (*notify)(void);
selection_cleanup(ql->selection);
}
-/** @brief Wrap up a widget for putting into the queue or title */
+/** @brief Wrap up a widget for putting into the queue or title
+ * @param label Label to contain
+ * @param color Pointer to color
+ * @param wp Updated with maximum width (or NULL)
+ * @return New widget
+ */
static GtkWidget *wrap_queue_cell(GtkWidget *label,
- const char *name,
+ const GdkColor *bgcolor,
+ const GdkColor *fgcolor,
int *wp) {
GtkRequisition req;
GtkWidget *bg;
gtk_widget_size_request(label, &req);
if(req.width > *wp) *wp = req.width;
}
- /* Set widget names */
- gtk_widget_set_name(bg, name);
- gtk_widget_set_name(label, name);
+ /* Set colors */
+ gtk_widget_modify_bg(bg, GTK_STATE_NORMAL, bgcolor);
+ gtk_widget_modify_bg(bg, GTK_STATE_SELECTED, &selected_bg);
+ gtk_widget_modify_bg(bg, GTK_STATE_PRELIGHT, &selected_bg);
+ gtk_widget_modify_fg(label, GTK_STATE_NORMAL, fgcolor);
+ gtk_widget_modify_fg(label, GTK_STATE_SELECTED, &selected_fg);
+ gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &selected_fg);
return bg;
}
const struct queue_entry *q,
int row,
int col,
- const char *name,
+ const GdkColor *bgcolor,
+ const GdkColor *fgcolor,
int *wp) {
GtkWidget *label;
D(("get_queue_cell %d %d", row, col));
label = ql->columns[col].widget(ql, q, ql->columns[col].data);
gtk_misc_set_alignment(GTK_MISC(label), ql->columns[col].xalign, 0);
- return wrap_queue_cell(label, name, wp);
+ return wrap_queue_cell(label, bgcolor, fgcolor, wp);
}
/** @brief Add a padding cell to the end of a row */
-static GtkWidget *get_padding_cell(const char *name) {
+static GtkWidget *get_padding_cell(const GdkColor *bgcolor,
+ const GdkColor *fgcolor) {
D(("get_padding_cell"));
NW(label);
- return wrap_queue_cell(gtk_label_new(""), name, 0);
+ return wrap_queue_cell(gtk_label_new(""), bgcolor, fgcolor, 0);
}
/* User button press and menu ---------------------------------------------- */
g_signal_connect(ql->dragmark, "destroy",
G_CALLBACK(gtk_widget_destroyed), &ql->dragmark);
gtk_widget_set_size_request(ql->dragmark, 10240, row ? 4 : 2);
- gtk_widget_set_name(ql->dragmark, "queue-drag");
+ gtk_widget_modify_bg(ql->dragmark, GTK_STATE_NORMAL, &drag_target);
gtk_layout_put(GTK_LAYOUT(ql->mainlayout), ql->dragmark, 0,
(row + 1) * ql->mainrowheight - !!row);
} else
struct queue_entry *q;
int row, col;
GList *c, *children;
- const char *name;
+ const GdkColor *bgcolor;
GtkRequisition req;
GtkWidget *w;
int maxwidths[MAXCOLUMNS], x, y, titlerowheight;
/* Construct the widgets */
for(q = ql->q, row = 0; q; q = q->next, ++row) {
/* Figure out the widget name for this row */
- if(q == playing_track) name = "row-playing";
- else name = row % 2 ? "row-even" : "row-odd";
+ if(q == playing_track) bgcolor = &active_bg;
+ else bgcolor = row % 2 ? &even_bg : &odd_bg;
/* Make the widget for each column */
for(col = 0; col <= ql->ncolumns; ++col) {
/* Create and store the widget */
if(col < ql->ncolumns)
- w = get_queue_cell(ql, q, row, col, name, &maxwidths[col]);
+ w = get_queue_cell(ql, q, row, col, bgcolor, &item_fg,
+ &maxwidths[col]);
else
- w = get_padding_cell(name);
+ w = get_padding_cell(bgcolor, &item_fg);
ql->cells[row * (ql->ncolumns + 1) + col] = w;
/* Maybe mark it draggable */
if(draggable_row(q)) {
struct queue_entry *(*fixup)(struct queue_entry *),
void (*notify)(void),
struct queue_menuitem *menuitems,
- const char *name,
const struct column *columns,
int ncolumns) {
GtkWidget *vbox, *mainscroll, *titlescroll, *label;
ql->fixup = fixup;
ql->notify = notify;
ql->menuitems = menuitems;
- ql->name = name;
ql->mainrowheight = !0; /* else division by 0 */
ql->selection = selection_new();
ql->columns = columns;
/* Create the layouts */
NW(layout);
ql->mainlayout = gtk_layout_new(0, 0);
+ gtk_widget_modify_bg(ql->mainlayout, GTK_STATE_NORMAL, &layout_bg);
NW(layout);
ql->titlelayout = gtk_layout_new(0, 0);
/* Scroll the layouts */
- ql->mainscroll = mainscroll = scroll_widget(ql->mainlayout, name);
- titlescroll = scroll_widget(ql->titlelayout, name);
+ ql->mainscroll = mainscroll = scroll_widget(ql->mainlayout);
+ titlescroll = scroll_widget(ql->titlelayout);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(titlescroll),
GTK_POLICY_NEVER, GTK_POLICY_NEVER);
mainadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(mainscroll));
NW(label);
label = gtk_label_new(ql->columns[col].name);
gtk_misc_set_alignment(GTK_MISC(label), ql->columns[col].xalign, 0);
- ql->titlecells[col] = wrap_queue_cell(label, "row-title", 0);
+ ql->titlecells[col] = wrap_queue_cell(label, &title_bg, &title_fg, 0);
gtk_layout_put(GTK_LAYOUT(ql->titlelayout), ql->titlecells[col], 0, 0);
}
- ql->titlecells[col] = get_padding_cell("row-title");
+ ql->titlecells[col] = get_padding_cell(&title_bg, &title_fg);
gtk_layout_put(GTK_LAYOUT(ql->titlelayout), ql->titlecells[col], 0, 0);
/* Pack the lot together in a vbox */
NW(vbox);
g_signal_connect(ql->mainlayout, "button-press-event",
G_CALLBACK(mainlayout_button), ql);
#endif
+ set_tool_colors(ql->menu);
return vbox;
}
/* We pass choose_update() as our notify function since the choose screen
* marks tracks that are playing/in the queue. */
return queuelike(&ql_queue, fixup_queue, choose_update, queue_menu,
- "queue", maincolumns, NMAINCOLUMNS);
+ maincolumns, NMAINCOLUMNS);
}
/** @brief Arrange an update of the queue widget
GtkWidget *recent_widget(void) {
D(("recent_widget"));
register_reset(recent_update);
- return queuelike(&ql_recent, fixup_recent, 0, recent_menu, "recent",
+ return queuelike(&ql_recent, fixup_recent, 0, recent_menu,
maincolumns, NMAINCOLUMNS);
}
GtkWidget *added_widget(void) {
D(("added_widget"));
register_reset(added_update);
- return queuelike(&ql_added, 0/*fixup*/, 0/*notify*/, added_menu, "added",
+ return queuelike(&ql_added, 0/*fixup*/, 0/*notify*/, added_menu,
addedcolumns, NADDEDCOLUMNS);
}