diff options
-rw-r--r-- | slashapp/ChangeLog | 6 | ||||
-rw-r--r-- | slashapp/display.c | 738 | ||||
-rw-r--r-- | slashapp/properties.c | 11 | ||||
-rw-r--r-- | slashapp/slashapp.c | 78 | ||||
-rw-r--r-- | slashapp/slashapp.h | 91 |
5 files changed, 660 insertions, 264 deletions
diff --git a/slashapp/ChangeLog b/slashapp/ChangeLog index 0886689bd..1b7096035 100644 --- a/slashapp/ChangeLog +++ b/slashapp/ChangeLog @@ -1,3 +1,9 @@ +2000-09-29 Justin Maurer <justin@helixcode.com> + + * Large changes to several files in order to support varying + panel sizes. display.c was stolen from tick-a-stat. Proxy + support is coming! + 2000-05-14 Andreas Hyden <a.hyden@cyberpoint.se> * slashapp_applet.desktop: Added Swedish translation. diff --git a/slashapp/display.c b/slashapp/display.c index f74bf626b..d5cf66208 100644 --- a/slashapp/display.c +++ b/slashapp/display.c @@ -1,28 +1,71 @@ -/*###################################################################*/ -/*## ##*/ -/*###################################################################*/ +/* tick-a-stat, a GNOME panel applet + * (C) 1999 John Ellis + * + * Author: John Ellis + * + */ -#include "slashapp.h" -#include "back.xpm" #include "noimage.xpm" +#include "slashapp.h" -static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *icon, - gint offset, gint center, gint show_count, gint delay); -static void free_info_line(AppData *ad, InfoData *id); -static gint check_info_for_removal(AppData *ad, InfoData *id); -static GList *next_info_line(AppData *ad); static void redraw_display(AppData *ad); -static void draw_pixmap(AppData *ad, GdkPixmap *smap, GdkPixmap *tmap, gint x, gint y, gint w, gint h, gint xo, gint yo); +static void draw_pixmap(AppData *ad, GdkPixmap *smap, GdkBitmap *mask, GdkPixmap *tmap, gint x, gint y, gint w, gint h, gint xo, gint yo); + +static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *icon, + gint offset, gint center, gint show_count, gint delay, gint priority); +static void free_info_line(AppData *ad, InfoData *id); + + +static InfoData *next_info_line(AppData *ad); + static void scroll_display_up(AppData *ad, gint m); -static void draw_display_line(AppData *ad); +static gint draw_display_line(AppData *ad); static gint update_display_cb(gpointer data); + + +static gint line_is_in_click_list(AppData *ad, InfoData *id); +static void free_click_list(AppData *ad); static void register_click_func(AppData *ad, InfoData *id); static void scroll_click_func(AppData *ad, gint m); static int display_click(GtkWidget *w, GdkEventButton *event, gpointer data); static void display_motion(GtkWidget *w, GdkEventMotion *event, gpointer data); +static void calc_display_sizes(AppData *ad); +static void create_display_pixmaps(AppData *ad); + +/* + *---------------------------------------------------------------------------- + * display generic drawing + *---------------------------------------------------------------------------- + */ + +static void redraw_display(AppData *ad) +{ + gdk_window_set_back_pixmap(ad->draw_area->window,ad->display,FALSE); + gdk_window_clear(ad->draw_area->window); +} + +static void draw_pixmap(AppData *ad, GdkPixmap *smap, GdkBitmap *mask, GdkPixmap *tmap, gint x, gint y, gint w, gint h, gint xo, gint yo) +{ + gdk_gc_set_clip_mask(ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], mask); + gdk_gc_set_clip_origin(ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], x - xo, y - yo); + + gdk_draw_pixmap(tmap, + ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], + smap, xo, yo, x, y, w, h); + + gdk_gc_set_clip_mask(ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], NULL); + gdk_gc_set_clip_origin(ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], 0, 0); +} + +/* + *---------------------------------------------------------------------------- + * display line addition/removal (private) + *---------------------------------------------------------------------------- + */ + static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *icon, - gint offset, gint center, gint show_count, gint delay) + gint offset, gint center, gint show_count, gint delay, gint priority) { InfoData *id; if (!text) return NULL; @@ -31,6 +74,8 @@ static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *ico id->click_func = NULL; id->data = NULL; id->free_func = NULL; + id->pre_func = NULL; + id->end_func = NULL; id->text = g_strdup(text); @@ -72,29 +117,15 @@ static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *ico id->show_count = show_count; id->end_delay = delay; + id->priority = priority; return id; } static void free_info_line(AppData *ad, InfoData *id) { - GList *list = ad->click_list; - if (!id) return; - while(list) - { - GList *w = list; - ClickData *cd = w->data; - list = list->next; - - if (cd->line_id == id) - { - ad->click_list = g_list_remove(ad->click_list, cd); - g_free(cd); - } - } - g_free(id->text); g_free(id->icon_path); @@ -103,25 +134,33 @@ static void free_info_line(AppData *ad, InfoData *id) if (id->data && id->free_func) id->free_func(id->data); g_free(id); + return; + ad = NULL; } void free_all_info_lines(AppData *ad) { - GList *list = ad->text; + GList *work = ad->info_list; - if (!list) return; - while(list) + while(work) { - InfoData *id = list->data; - free_info_line(ad, id); - list = list->next; + InfoData *id = work->data; + work = work->next; + ad->info_list = g_list_remove(ad->info_list, id); + if (!line_is_in_click_list(ad, id)) free_info_line(ad, id); } - g_list_free(ad->text); - ad->text = NULL; + + free_click_list(ad); } +/* + *---------------------------------------------------------------------------- + * display line addition/removal (public) + *---------------------------------------------------------------------------- + */ + InfoData *add_info_line(AppData *ad, gchar *text, gchar *icon_path, gint offset, gint center, - gint show_count, gint delay) + gint show_count, gint delay, gint priority) { InfoData *id; GtkWidget *icon = NULL; @@ -134,201 +173,273 @@ InfoData *add_info_line(AppData *ad, gchar *text, gchar *icon_path, gint offset, icon = gnome_pixmap_new_from_xpm_d(noimage_xpm); } - id = create_info_line(text, icon_path, icon, offset, center, show_count, delay); + id = create_info_line(text, icon_path, icon, offset, center, show_count, delay, priority); if (id) { - ad->text = g_list_append(ad->text, id); - ad->text_lines++; + ad->info_list = g_list_append(ad->info_list, id); } return id; } InfoData *add_info_line_with_pixmap(AppData *ad, gchar *text, GtkWidget *icon, gint offset, gint center, - gint show_count, gint delay) + gint show_count, gint delay, gint priority) { InfoData *id; - id = create_info_line(text, NULL, icon, offset, center, show_count, delay); + id = create_info_line(text, NULL, icon, offset, center, show_count, delay, priority); if (id) { - ad->text = g_list_append(ad->text, id); - ad->text_lines++; + ad->info_list = g_list_append(ad->info_list, id); } return id; } +void set_info_click_signal(InfoData *id, void (*click_func)(gpointer data, InfoData *id, AppData *ad), + gpointer data, void (*free_func)(gpointer data)) +{ + if (!id) return; + id->click_func = click_func; + id->data = data; + id->free_func = free_func; +} + +void set_info_signals(InfoData *id, + void (*click_func)(gpointer data, InfoData *id, AppData *ad), + void (*free_func)(gpointer data), + void (*pre_func)(gpointer data, InfoData *id, AppData *ad), + void (*end_func)(gpointer data, InfoData *id, AppData *ad), + gpointer data) +{ + if (!id) return; + id->click_func = click_func; + id->free_func = free_func; + id->pre_func = pre_func; + id->end_func = end_func; + id->data = data; +} + void remove_info_line(AppData *ad, InfoData *id) { + GList *work; if (!id) return; - if (ad->current_text && ad->current_text->data == id) - { - /* if current line is being displayed, schedule to remove */ - id->show_count = 1; - } - else + + work = g_list_find(ad->info_list, id); + + if (work) { - ad->text = g_list_remove(ad->text, id); - free_info_line(ad, id); - ad->text_lines--; + ad->info_list = g_list_remove(ad->info_list, id); + if (!line_is_in_click_list(ad, id)) + { + if (ad->info_current == id) + ad->free_current = TRUE; + else + free_info_line(ad, id); + } } } void remove_all_lines(AppData *ad) { - GList *list; - - list = ad->text; - while (list) + GList *work = ad->info_list; + while (work) { - InfoData *id = list->data; - list = list->next; - remove_info_line(ad, id); + InfoData *id = work->data; + work = work->next; + ad->info_list = g_list_remove(ad->info_list, id); + if (!line_is_in_click_list(ad, id)) free_info_line(ad, id); } } -void set_info_click_signal(InfoData *id, void (*click_func)(AppData *ad, gpointer data), - gpointer data, void (*free_func)(gpointer data)) +/* + *---------------------------------------------------------------------------- + * display internal management + *---------------------------------------------------------------------------- + */ + +static gint line_is_in_line_list(AppData *ad, InfoData *id) { - if (!id) return; - id->click_func = click_func; - id->data = data; - id->free_func = free_func; + GList *work = NULL; + work = g_list_find(ad->info_list, id); + + if (work) return TRUE; + return FALSE; } -static gint check_info_for_removal(AppData *ad, InfoData *id) +static gint info_line_unref(AppData *ad, InfoData *id) { if (id->show_count > 0) { id->show_count--; - if (id->show_count == 0) + if (id->show_count < 1) { remove_info_line(ad, id); - if (!ad->text) - { - ad->current_text = NULL; - return TRUE; - } + return TRUE; } } return FALSE; } -static GList *next_info_line(AppData *ad) +static InfoData *first_unshown_info_line(GList *list) { - GList *list = ad->text; - - /* check for the first unshown info item, they have priority*/ - while(list) + GList *work = list; + InfoData *ret_id = NULL; + while(work) { InfoData *id = list->data; - if (!id->shown) return list; - list = list->next; + if (!id->shown) + { + if (!ret_id || (ret_id && id->priority > ret_id->priority)) + { + ret_id = id; + } + } + work = work->next; } - /* all have been shown, just return the next line */ - list = ad->current_text->next; - if (!list) list = ad->text; - return list; + return ret_id; } -static void redraw_display(AppData *ad) +static InfoData *first_info_line(GList *list) { - gdk_window_set_back_pixmap(ad->draw_area->window,ad->display,FALSE); - gdk_window_clear(ad->draw_area->window); + InfoData *id = first_unshown_info_line(list); + if (id) return id; + + if (list) return list->data; + + return NULL; } -static void draw_pixmap(AppData *ad, GdkPixmap *smap, GdkPixmap *tmap, gint x, gint y, gint w, gint h, gint xo, gint yo) + +static InfoData *next_info_line_from_line(AppData *ad, InfoData *id) { - gdk_draw_pixmap(tmap, - ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], - smap, xo, yo, x, y, w, h); + GList *work; + InfoData *wid; + + work = g_list_find(ad->info_list, id); + if (!work) + { + return first_info_line(ad->info_list); + } + + wid = first_unshown_info_line(ad->info_list); + if (wid) return wid; + + if (work->next) + { + work = work->next; + return work->data; + } + + if (ad->info_list->data == id && id->show_count != 1) return NULL; + + return ad->info_list->data; +} + +static InfoData *next_info_line(AppData *ad) +{ + InfoData *id; + + if (!ad->info_list) return NULL; + + if (ad->info_next && line_is_in_line_list(ad, ad->info_next)) + { + id = ad->info_next; + ad->info_next = NULL; + return id; + } + + id = first_unshown_info_line(ad->info_list); + if (id) return id; + + return ad->info_list->data; } -static void scroll_display_up(AppData *ad, gint m) +static void display_info_finished(AppData *ad, InfoData *id) { - draw_pixmap (ad, ad->display, ad->disp_buf, 0, 0, ad->width, ad->height - m, 0, m); - draw_pixmap (ad, ad->disp_buf, ad->display, 0, 0, ad->width, ad->height - m, 0, 0); - draw_pixmap (ad, ad->background, ad->display, 0, ad->height - m, ad->width, m, 0, ad->height - m); - if (ad->current_text) + if (id->end_func) id->end_func(id->data, id, ad); + if (id == ad->info_current) { - InfoData *id = ad->current_text->data; - if (id->icon && id->icon_h > ad->current_line_pos * ad->scroll_height) + ad->info_next = next_info_line_from_line(ad, id); + if (ad->free_current) { - gint x,y; - gint xo, yo; - gint w, h; - - x = 2; - y = ad->height - m; - xo = 0; - if (m == ad->scroll_height) - yo = ad->current_line_pos * ad->scroll_height; - else - yo = (ad->current_line_pos * ad->scroll_height) + ad->scroll_height - ad->scroll_pos; - w = id->icon_w; - h = m; - if (h + yo > id->icon_h) h = id->icon_h - yo; - if (yo < id->icon_h && h > 0) - draw_pixmap (ad, GNOME_PIXMAP(id->icon)->pixmap, ad->display, - x, y, w, h, xo, yo); + free_info_line(ad, ad->info_current); + ad->free_current = FALSE; } + ad->info_current = NULL; } - redraw_display(ad); - scroll_click_func(ad, m); + info_line_unref(ad, id); +} + +/* + *---------------------------------------------------------------------------- + * display icon drawing + *---------------------------------------------------------------------------- + */ + +/* returns the number of lines drawn, 0 means end of icon */ +static gint display_draw_icon(AppData *ad, InfoData *id, gint n) +{ + if (id->icon && id->icon_h >= ad->y_pos - n) + { + gint x,y; + gint xo, yo; + gint w, h; + + x = 2; + y = ad->height - n; + xo = 0; + yo = ad->y_pos - n; + w = id->icon_w; + h = n; + if (h > id->icon_h - yo) h = id->icon_h - yo; + draw_pixmap (ad, GNOME_PIXMAP(id->icon)->pixmap, GNOME_PIXMAP(id->icon)->mask, + ad->display, x, y, w, h, xo, yo); + return h; + } + + return 0; } -static void draw_display_line(AppData *ad) +/* + *---------------------------------------------------------------------------- + * display line drawing + *---------------------------------------------------------------------------- + */ + +static gint draw_display_line(AppData *ad) { InfoData *id; - gint new_x_pos; gchar c; GdkFont *font; + gint new_line = FALSE; + int len; /* byte length of a character */ - if (!ad->text) return; - if (!ad->current_text) ad->current_text = ad->text; - id = ad->current_text->data; - if (!id) return; + if (!ad->info_current && !ad->info_list) return TRUE; + + if (!ad->info_current) + { + ad->info_current = next_info_line(ad); + if (!ad->info_current) return TRUE; + + ad->text_pos = 0; + ad->x_pos = 0; + ad->y_pos = 0; + } + + id = ad->info_current; + id->shown = TRUE; font = ad->draw_area->style->font; - if (ad->new_line) + if (ad->x_pos == 0) { - if (ad->text_pos > id->length) - { - GList *temp; - if (id->icon && id->icon_h > ad->current_line_pos * ad->text_height) - { - ad->scroll_pos = ad->scroll_height; - ad->current_line_pos ++; - if (id->icon_h <= ad->current_line_pos * ad->text_height) - ad->scroll_count = id->end_delay / 10 * (1000 / UPDATE_DELAY); - return; - } - id->shown = TRUE; - ad->text_pos = 0; - temp = next_info_line(ad); - ad->current_text = NULL; - ad->current_line_pos = 0; - check_info_for_removal(ad, id); - if (!ad->text || !temp) return; - ad->current_text = temp; - id = ad->current_text->data; - } - ad->new_line = FALSE; - ad->x_pos = 0; - if (id->icon && id->icon_h > ad->current_line_pos * ad->text_height) + /* add or do any callbacks if new info */ + if (ad->y_pos == 0) { - gint x,y; - gint xo, yo; - gint w, h; - x = 2; - y = ad->height - ad->text_height; - xo = 0; - yo = ad->current_line_pos * ad->text_height; - w = id->icon_w; - h = id->icon_h - (ad->current_line_pos * ad->text_height); - draw_pixmap (ad, GNOME_PIXMAP(id->icon)->pixmap, ad->display, x, y, w, h, xo, yo); + if (id->pre_func) id->pre_func(id->data, id, ad); + if (id->click_func) register_click_func(ad, id); + ad->y_pos = ad->scroll_height; } if (id->center && !id->icon) { @@ -343,76 +454,119 @@ static void draw_display_line(AppData *ad) } } else - ad->x_pos = id->offset; - - /* add the click check */ - if (id->click_func && ad->current_line_pos == 0) { - register_click_func(ad, id); + display_draw_icon(ad, id, ad->scroll_height); + ad->x_pos += id->offset; } } + /* skip leading space on new line */ c = id->text[ad->text_pos]; + len = mblen(&id->text[ad->text_pos], id->length); if (ad->x_pos == id->offset && c == ' ' && - ad->text_pos < id->length - 1 && id->text[ad->text_pos +1] != ' ') + ad->text_pos < id->length - 1 && id->text[ad->text_pos + len] != ' ') { - ad->text_pos++; + ad->text_pos += len; c = id->text[ad->text_pos]; + len = mblen(&id->text[ad->text_pos], id->length); } - new_x_pos = ad->x_pos + gdk_char_width (font, c); gdk_draw_text(ad->display, font, - ad->draw_area->style->black_gc, - ad->x_pos, ad->height - ad->text_y_line, id->text + ad->text_pos, 1); + ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], + ad->x_pos, ad->height - ad->text_y_line, id->text + ad->text_pos, len); + ad->x_pos += gdk_text_width(font, &id->text[ad->text_pos], len); + ad->text_pos += len; - ad->text_pos ++; - if (ad->text_pos > id->length) + if (ad->text_pos >= id->length) { - ad->new_line = TRUE; + new_line = TRUE; } else { - ad->x_pos = new_x_pos; c = id->text[ad->text_pos]; - if (ad->x_pos + gdk_char_width (font, c) > ad->width) + len = mblen(&id->text[ad->text_pos], id->length); + if (ad->x_pos + gdk_text_width(font, &id->text[ad->text_pos], len) > ad->width) { - ad->new_line = TRUE; + new_line = TRUE; } else if (c == '\n') { ad->text_pos++; - ad->new_line = TRUE; + new_line = TRUE; } else if (c == ' ' && ad->text_pos < id->length) { gint word_length; - gint l = strlen(id->text); gint p; p = ad->text_pos + 1; - while (p < l && id->text[p] != ' ' && id->text[p] != '\n') p++; - word_length = gdk_text_width(font, id->text + ad->text_pos, - p - ad->text_pos); + while (p < id->length && id->text[p] != ' ' && id->text[p] != '\n') p++; + word_length = gdk_text_width(font, id->text + ad->text_pos, p - ad->text_pos); if (ad->x_pos + word_length > ad->width) { ad->text_pos++; - ad->new_line = TRUE; + new_line = TRUE; } } } - if (ad->new_line) + if (new_line) { - ad->current_line_pos ++; + ad->x_pos = 0; ad->scroll_pos = ad->scroll_height; - - if (ad->text_pos > id->length) + if (ad->text_pos >= id->length) + { ad->scroll_count = id->end_delay / 10 * (1000 / UPDATE_DELAY); - else + if (!id->icon || id->icon_h <= ad->y_pos) + { + display_info_finished(ad, ad->info_current); + } + } + else + { ad->scroll_count = ad->scroll_delay / 10 * (1000 / UPDATE_DELAY); + } + } + + return new_line; +} +/* + *---------------------------------------------------------------------------- + * display scrolling + *---------------------------------------------------------------------------- + */ + +static void scroll_display_up(AppData *ad, gint n) +{ + draw_pixmap (ad, ad->display, NULL, ad->disp_buf, 0, 0, ad->width, ad->height - n, 0, n); + draw_pixmap (ad, ad->disp_buf, NULL, ad->display, 0, 0, ad->width, ad->height - n, 0, 0); + draw_pixmap (ad, ad->background, NULL, ad->display, 0, ad->height - n, ad->width, n, 0, ad->height - n); + ad->y_pos += n; + if (ad->info_current) + { + gint drawn = display_draw_icon(ad, ad->info_current, n); + if (ad->text_pos >= ad->info_current->length) + { + if (drawn > 0) + { + ad->scroll_pos += drawn; + } + else + { + display_info_finished(ad, ad->info_current); + } + } } + redraw_display(ad); + scroll_click_func(ad, n); } +/* + *---------------------------------------------------------------------------- + * main display loop + *---------------------------------------------------------------------------- + */ + static gint update_display_cb(gpointer data) { AppData *ad = data; @@ -424,21 +578,23 @@ static gint update_display_cb(gpointer data) return TRUE; } - if (ad->new_line && ad->scroll_pos > 0) + if (!ad->info_list && !ad->info_current) return TRUE; + + /* draw the scrolling */ + if (ad->scroll_pos > 0) { - /* draw the scrolling */ + gint n; if (ad->smooth_scroll) { - gint s = ad->scroll_speed; - if (ad->scroll_pos - s < 1) s = ad->scroll_pos - 1; - scroll_display_up(ad, s); + n = ad->scroll_speed; + if (ad->scroll_pos - n < 0) n = ad->scroll_pos; } else { - if (ad->scroll_pos - ad->scroll_speed < 1) - scroll_display_up(ad, ad->scroll_height); + n = ad->scroll_pos; } - ad->scroll_pos -= ad->scroll_speed; + scroll_display_up(ad, n); + ad->scroll_pos -= n; return TRUE; } @@ -449,13 +605,18 @@ static gint update_display_cb(gpointer data) } else { - draw_display_line(ad); - while(!ad->new_line) draw_display_line(ad); + while(!draw_display_line(ad)); redraw_display(ad); } return TRUE; } +/* + *---------------------------------------------------------------------------- + * display mouse and pointer functions + *---------------------------------------------------------------------------- + */ + void set_mouse_cursor (AppData *ad, gint icon) { GdkCursor *cursor = gdk_cursor_new (icon); @@ -463,6 +624,33 @@ void set_mouse_cursor (AppData *ad, gint icon) gdk_cursor_destroy (cursor); } +static gint line_is_in_click_list(AppData *ad, InfoData *id) +{ + GList *work = ad->click_list; + + while(work) + { + ClickData *cd = work->data; + if (id == cd->line_id) return TRUE; + work = work->next; + } + + return FALSE; +} + +static void free_click_list(AppData *ad) +{ + GList * work = ad->click_list; + while (work) + { + ClickData *cd = work->data; + work = work->next; + ad->click_list = g_list_remove(ad->click_list, cd); + if (!line_is_in_click_list(ad, cd->line_id)) free_info_line(ad, cd->line_id); + g_free(cd); + } +} + static void register_click_func(AppData *ad, InfoData *id) { ClickData *cd; @@ -473,19 +661,20 @@ static void register_click_func(AppData *ad, InfoData *id) cd->line_id = id; cd->click_func = id->click_func; - cd->data = id->data; cd->x = 0; cd->y = ad->height - ad->scroll_height; cd->w = ad->width; cd->h = ad->scroll_height; + cd->free_id = FALSE; + ad->click_list = g_list_append(ad->click_list, cd); scroll_click_func(ad, 0); } -static void scroll_click_func(AppData *ad, gint m) +static void scroll_click_func(AppData *ad, gint n) { GList *list = ad->click_list; gint proximity = FALSE; @@ -496,17 +685,20 @@ static void scroll_click_func(AppData *ad, gint m) ClickData *cd = w->data; list = list->next; - cd->y -= m; + cd->y -= n; - if (ad->current_text) + if (ad->info_current) { - InfoData *id = ad->current_text->data; - if (id == cd->line_id && ad->text_pos <= id->length) cd->h += m; + InfoData *id = ad->info_current; + if (id == cd->line_id) cd->h += n; } if (cd->y + cd->h < 1) { ad->click_list = g_list_remove(ad->click_list, cd); + if (!line_is_in_line_list(ad, cd->line_id) && + !line_is_in_click_list(ad, cd->line_id)) + free_info_line(ad, cd->line_id); g_free(cd); } else @@ -546,7 +738,9 @@ static int display_click(GtkWidget *w, GdkEventButton *event, gpointer data) if (x >= cd->x && x < cd->x + cd->w && y >= cd->y && y < cd->y + cd->h) { - if (cd->click_func) cd->click_func(ad, cd->data); + if (cd->click_func) + cd->click_func(cd->line_id->data, + cd->line_id, ad); } list = list->next; @@ -585,40 +779,141 @@ static void display_motion(GtkWidget *w, GdkEventMotion *event, gpointer data) w = NULL; } -void init_app_display(AppData *ad) +/* + *---------------------------------------------------------------------------- + * display initialization and resizing + *---------------------------------------------------------------------------- + */ + +static void calc_display_sizes(AppData *ad) +{ + if (ad->follow_hint_width) + { +#ifdef HAVE_PANEL_PIXEL_SIZE + ad->width_hint = applet_widget_get_free_space(APPLET_WIDGET(ad->applet)); + if (ad->width_hint < 8) ad->width_hint = 200; /* no space or corner panel */ +#endif + ad->win_width = ad->width_hint; + } + else + { + ad->win_width = ad->user_width; + } + ad->width = ad->win_width - 4; /* hard coded, this is bound to break */ + + if (ad->follow_hint_height) + { + ad->win_height = ad->sizehint; + } + else + { + ad->win_height = ad->user_height; + } + ad->height = ad->win_height - 4; /* hard coded, this is bound to break */ +} + +static void create_display_pixmaps(AppData *ad) { - gint w, h; +/* the old way ? + ad->display_w = gnome_pixmap_new_from_xpm_d_at_size(back_xpm, ad->width, ad->height); + ad->display = GNOME_PIXMAP(ad->display_w)->pixmap; + ad->disp_buf_w = gnome_pixmap_new_from_xpm_d_at_size(back_xpm, ad->width, ad->height); + ad->disp_buf = GNOME_PIXMAP(ad->disp_buf_w)->pixmap; + ad->background_w = gnome_pixmap_new_from_xpm_d_at_size(back_xpm, ad->width, ad->height); + ad->background = GNOME_PIXMAP(ad->background_w)->pixmap; +*/ + + /* clear any current pixmaps */ + if (ad->display) gdk_pixmap_unref(ad->display); + if (ad->disp_buf) gdk_pixmap_unref(ad->disp_buf); + if (ad->background) gdk_pixmap_unref(ad->background); + ad->display = NULL; + ad->disp_buf = NULL; + ad->background = NULL; + + ad->display = gdk_pixmap_new (ad->applet->window, ad->width, ad->height, -1); + ad->disp_buf = gdk_pixmap_new (ad->applet->window, ad->width, ad->height, -1); + ad->background = gdk_pixmap_new (ad->applet->window, ad->width, ad->height, -1); + + gdk_draw_rectangle (ad->display, + ad->applet->style->base_gc[GTK_STATE_NORMAL], + TRUE, 0, 0, ad->width, ad->height); + gdk_draw_rectangle (ad->disp_buf, + ad->applet->style->base_gc[GTK_STATE_NORMAL], + TRUE, 0, 0, ad->width, ad->height); + gdk_draw_rectangle (ad->background, + ad->applet->style->base_gc[GTK_STATE_NORMAL], + TRUE, 0, 0, ad->width, ad->height); +} +void resized_app_display(AppData *ad, gint force) +{ + gint old_w = ad->width; + gint old_h = ad->height; + + calc_display_sizes(ad); + + if (old_w == ad->width && old_h == ad->height && !force) return; + +/* old way? + gtk_widget_destroy(ad->display_w); + gtk_widget_destroy(ad->disp_buf_w); + gtk_widget_destroy(ad->background_w); +*/ + + create_display_pixmaps(ad); + gtk_widget_set_usize(ad->applet, ad->win_width, ad->win_height); + gtk_drawing_area_size(GTK_DRAWING_AREA(ad->draw_area), ad->width, ad->height); + + ad->text_height = ad->draw_area->style->font->ascent + + ad->draw_area->style->font->descent; + ad->text_y_line = ad->draw_area->style->font->descent; + + ad->scroll_height = ad->text_height; + + redraw_display(ad); +} + +/* this is called when themes and fonts change */ +static void app_display_style_change_cb(GtkWidget *widget, GtkStyle *previous_style, gpointer data) +{ + AppData *ad = data; + + /* the size does not change, but this causes a redraw + in the case that the background color changed */ + resized_app_display(ad, TRUE); + return; + widget = NULL; + previous_style = NULL; +} + +void init_app_display(AppData *ad) +{ ad->scroll_delay = 20; - ad->current_line = 0; - ad->current_line_pos = 0; ad->scroll_count = 0; ad->scroll_pos = 0; - ad->new_line = TRUE; - ad->text_pos = 0; - ad->text = NULL; - ad->current_text = NULL; + ad->info_list = NULL; + ad->free_current = FALSE; + ad->info_current = NULL; + ad->info_next = NULL; ad->click_list = NULL; - ad->display_w = gnome_pixmap_new_from_xpm_d(back_xpm); - ad->display = GNOME_PIXMAP(ad->display_w)->pixmap; - ad->disp_buf_w = gnome_pixmap_new_from_xpm_d(back_xpm); - ad->disp_buf = GNOME_PIXMAP(ad->disp_buf_w)->pixmap; - ad->background_w = gnome_pixmap_new_from_xpm_d(back_xpm); - ad->background = GNOME_PIXMAP(ad->background_w)->pixmap; + ad->display = NULL; + ad->disp_buf = NULL; + ad->background = NULL; - gdk_window_get_size(ad->display, &w, &h); + calc_display_sizes(ad); + create_display_pixmaps(ad); - ad->width = w; - ad->height = h; + gtk_widget_set_usize(ad->applet, ad->win_width, ad->win_height); ad->frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(ad->frame), GTK_SHADOW_IN); gtk_widget_show(ad->frame); ad->draw_area = gtk_drawing_area_new(); - gtk_drawing_area_size(GTK_DRAWING_AREA(ad->draw_area), w, h); + gtk_drawing_area_size(GTK_DRAWING_AREA(ad->draw_area), ad->width, ad->height); gtk_widget_set_events (ad->draw_area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK); gtk_signal_connect(GTK_OBJECT(ad->draw_area),"motion_notify_event", (GtkSignalFunc) display_motion, ad); @@ -639,6 +934,9 @@ void init_app_display(AppData *ad) redraw_display(ad); + gtk_signal_connect(GTK_OBJECT(ad->draw_area),"style_set", + (GtkSignalFunc) app_display_style_change_cb, ad); + ad->display_timeout_id = gtk_timeout_add(UPDATE_DELAY, (GtkFunction)update_display_cb, ad); } diff --git a/slashapp/properties.c b/slashapp/properties.c index d8c15c660..8ffc745e1 100644 --- a/slashapp/properties.c +++ b/slashapp/properties.c @@ -49,8 +49,9 @@ void property_save(gchar *path, AppData *ad) gnome_config_set_int("slashapp/new_browser_window", ad->new_browser_window); + gnome_config_pop_prefix(); gnome_config_sync(); - gnome_config_pop_prefix(); + gnome_config_drop_all(); } static void article_delay_cb(GtkObject *adj, gpointer data) @@ -171,7 +172,7 @@ void property_show(AppletWidget *applet, gpointer data) GtkWidget *button; GtkObject *adj; GtkWidget *spin; - /* GtkWidget *entry; */ + GtkWidget *text; if(ad->propwindow) { @@ -209,12 +210,12 @@ void property_show(AppletWidget *applet, gpointer data) gtk_container_add(GTK_CONTAINER(frame), vbox1); gtk_widget_show(vbox1); - button = gtk_check_button_new_with_label (_("Show topic images")); +/* button = gtk_check_button_new_with_label (_("Show topic images")); gtk_box_pack_start(GTK_BOX(vbox1), button, FALSE, FALSE, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), ad->p_show_images); gtk_signal_connect (GTK_OBJECT(button),"clicked",(GtkSignalFunc) show_images_cb, ad); gtk_widget_show(button); - + button = gtk_check_button_new_with_label (_("Show department")); gtk_box_pack_start(GTK_BOX(vbox1), button, FALSE, FALSE, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), ad->p_show_department); @@ -226,7 +227,7 @@ void property_show(AppletWidget *applet, gpointer data) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), ad->p_show_info); gtk_signal_connect (GTK_OBJECT(button),"clicked",(GtkSignalFunc) show_info_cb, ad); gtk_widget_show(button); - +*/ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); diff --git a/slashapp/slashapp.c b/slashapp/slashapp.c index c1a27d072..38ab06148 100644 --- a/slashapp/slashapp.c +++ b/slashapp/slashapp.c @@ -43,8 +43,30 @@ AppData *create_new_app(GtkWidget *applet) if(!ad->slashapp_dir) g_error("Can't create slashapp dir in .gnome/\n"); + ad->orient = ORIENT_UP; + ad->sizehint = 48; + ad->width_hint = 200; + + ad->win_width = 200; + ad->win_height = 48; + ad->follow_hint_width = FALSE; + ad->follow_hint_height = TRUE; + ad->user_width = 200; + ad->user_height = 48; + ad->draw_area = NULL; + init_app_display(ad); + /* from tick-a-stat */ + gtk_signal_connect(GTK_OBJECT(ad->applet),"change_orient", + GTK_SIGNAL_FUNC(applet_change_orient), ad); +#ifdef HAVE_PANEL_PIXEL_SIZE + gtk_signal_connect(GTK_OBJECT(ad->applet),"change_pixel_size", + GTK_SIGNAL_FUNC(applet_change_pixel_size), ad); +#endif + + gtk_widget_set_usize(ad->applet, 10, 10); + /* connect all the signals to handlers */ gtk_signal_connect(GTK_OBJECT(ad->applet), "destroy", GTK_SIGNAL_FUNC(destroy_applet), ad); @@ -67,9 +89,9 @@ AppData *create_new_app(GtkWidget *applet) gtk_timeout_add(refresh_time, get_current_headlines, ad); icon = gnome_pixmap_new_from_xpm_d(slashsplash_xpm); - add_info_line_with_pixmap(ad, "", icon, 0, FALSE, 1, 0); - add_info_line(ad, "SlashApp\n", NULL, 0, TRUE, 1, 0); - add_info_line(ad, _("Loading headlines..."), NULL, 0, FALSE, 1, 20); + add_info_line_with_pixmap(ad, "", icon, 0, FALSE, 1, 0, 10); + add_info_line(ad, "SlashApp\n", NULL, 0, TRUE, 1, 0, 10); + add_info_line(ad, _("Loading headlines..."), NULL, 0, FALSE, 1, 20, 10); gtk_widget_show(ad->applet); ad->startup_timeout_id = gtk_timeout_add(5000, startup_delay_cb, ad); @@ -77,6 +99,33 @@ AppData *create_new_app(GtkWidget *applet) return ad; } +static void applet_change_orient(GtkWidget *w, PanelOrientType o, gpointer data){ + AppData *ad = data; + ad->orient = o; + + if (!ad->draw_area) return; /* we are done if in startup */ + + resized_app_display(ad, FALSE); + return; + w = NULL; +} + +#ifdef HAVE_PANEL_PIXEL_SIZE +static void applet_change_pixel_size(GtkWidget *w, int size, gpointer data) +{ + AppData *ad = data; + + ad->sizehint = size; + + if (!ad->draw_area) return; /* we are done if in startup */ + + resized_app_display(ad, FALSE); + return; + w = NULL; +} +#endif + + gchar *check_for_dir(char *d) { if(!g_file_exists(d)) { @@ -133,14 +182,14 @@ void about_cb(AppletWidget *widget, gpointer data) sprintf(version, _("%d.%d.%d"), APPLET_VERSION_MAJ, APPLET_VERSION_MIN, APPLET_VERSION_REV); - authors[0] = _("Justin Maurer <justin@slashdot.org>"); + authors[0] = _("Justin Maurer <justin@helixcode.com>"); authors[1] = _("John Ellis <johne@bellatlantic.net>"); authors[2] = _("Craig Small <csmall@eye-net.com.au>"); authors[3] = _("Frederic Devernay <devernay@istar.fr>"); authors[4] = NULL; about = gnome_about_new(_("SlashApp"), version, - _("(C) 1998-1999"), + _("(C) 1998-2000"), authors, _("A stock ticker-like applet\n"), NULL); @@ -264,7 +313,7 @@ void refresh_cb(AppletWidget *widget, gpointer data) remove_all_lines(ad); icon = gnome_pixmap_new_from_xpm_d(slashsplash_xpm); - add_info_line_with_pixmap(ad, "", icon, 0, FALSE, 1, 0); + add_info_line_with_pixmap(ad, "", icon, 0, FALSE, 1, 0, 5); if(ad->startup_timeout_id > 0) return; @@ -290,7 +339,7 @@ int get_current_headlines(gpointer data) filename = g_strconcat(ad->slashapp_dir, "/", "headlines", NULL); file = fopen(filename, "w"); if(file) { - http_get_to_file(ad->host, ad->port, ad->proxy, ad->resource, + http_get_to_file(ad->host, ad->port, ad->proxy_url, ad->resource, file, data); fclose(file); parse_headlines(data); @@ -309,7 +358,7 @@ void parse_headlines(gpointer data) if (s.st_size == 0) { g_warning(_("Unable to parse document\n")); add_info_line(ad, "Can't parse XML. Net connection down?", - NULL, 0, FALSE, FALSE, delay); + NULL, 0, FALSE, FALSE, delay, 5); return; } @@ -318,7 +367,7 @@ void parse_headlines(gpointer data) if (doc==NULL) { g_warning(_("Unable to parse document\n")); add_info_line(ad, "Can't parse XML. Net connection down?", - NULL, 0, FALSE, FALSE, delay); + NULL, 0, FALSE, FALSE, delay, 5); return; } @@ -412,10 +461,14 @@ void tree_walk(xmlNodePtr root, gpointer data) char *image = layer_find(item[i]->childs, "iamge", "No image"); */ char *temp = g_strconcat(title, NULL); - id = add_info_line(ad, temp, NULL, 0, FALSE, FALSE, delay); + id = add_info_line(ad, temp, NULL, 0, FALSE, FALSE, delay, 10); +/* set_info_signals(id, click_headline_cb, g_free, NULL, NULL, url); + */ + set_info_click_signal(id, click_headline_cb, g_strdup(url), g_free); - add_info_line(ad, "", NULL, 0, FALSE, FALSE, delay); + + add_info_line(ad, "", NULL, 0, FALSE, FALSE, delay, 10); } } @@ -453,7 +506,8 @@ char *layer_find(xmlNodePtr node, char *match, char *fail) void click_headline_cb(AppData *ad, gpointer data) { - gchar *url = data; + InfoData *id = data; + gchar *url = id->data; if(url) gnome_url_show(url); return; diff --git a/slashapp/slashapp.h b/slashapp/slashapp.h index 3cfaf8f4e..ed8a4059c 100644 --- a/slashapp/slashapp.h +++ b/slashapp/slashapp.h @@ -16,6 +16,36 @@ #define UPDATE_DELAY 70 typedef struct _AppData AppData; +typedef struct _InfoData InfoData; + +struct _InfoData +{ + gchar *text; /* any length, but be reasonable */ + gint length; + gchar *icon_path; /* location of icon */ + GtkWidget *icon; /* maximum 24 x 24 please (or be reasonable)*/ + gint icon_w; + gint icon_h; + gint offset; /* offset of text from left, set to line text up even with no icon */ + gint center; /* Center text, only has effect if text fits on one line */ + gint shown; + gint show_count; /* when 0 show forever, other wise times to show (1 or +) */ + gint end_delay; /* time to delay after displaying last character of text + this number is calculated from tenths of a second */ + + /* click callback stuff */ + + void (*click_func)(gpointer data, InfoData *id, AppData *ad); + gpointer data; + void (*free_func)(gpointer data); + + /* from tick-a-stat */ + gint priority; + void(*pre_func)(gpointer data, InfoData *id, AppData *ad); + void(*end_func)(gpointer data, InfoData *id, AppData *ad); +}; + + struct _AppData { GtkWidget *applet; @@ -92,32 +122,34 @@ struct _AppData GtkWidget *article_list; gchar *host; - gchar *proxy; + gchar *proxy_url; + gchar *proxy_user; + gchar *proxy_passwd; + gboolean use_proxy; gchar *resource; gint port; -}; -typedef struct _InfoData InfoData; -struct _InfoData -{ - gchar *text; /* any length, but be reasonable */ - gint length; - gchar *icon_path; /* location of icon */ - GtkWidget *icon; /* maximum 24 x 24 please (or be reasonable)*/ - gint icon_w; - gint icon_h; - gint offset; /* offset of text from left, set to line text up even with no icon */ - gint center; /* Center text, only has effect if text fits on one line */ - gint shown; - gint show_count; /* when 0 show forever, other wise times to show (1 or +) */ - gint end_delay; /* time to delay after displaying last character of text - this number is calculated from tenths of a second */ - - /* click callback stuff */ - - void (*click_func)(AppData *ad, gpointer data); - gpointer data; - void (*free_func)(gpointer data); + /* from tick-a-stat */ + + PanelOrientType orient; + gint sizehint; + gint width_hint; + + gint win_height; + gint win_width; + gint follow_hint_height; + gint follow_hint_width; + gint user_width; + + gint user_height; + + InfoData *info_next; + InfoData *info_current; + + gint free_current; + + GList *info_list; + gint y_pos; }; typedef struct _ClickData ClickData; @@ -128,20 +160,23 @@ struct _ClickData gint y; gint w; gint h; - void (*click_func)(AppData *ad, gpointer data); gpointer data; + + /* from tick-a-stat */ + gint free_id; + void (*click_func)(gpointer data, InfoData *id, AppData *ad); }; /* display.c */ void free_all_info_lines(AppData *ad); InfoData *add_info_line(AppData *ad, gchar *text, gchar *icon_path, gint offset, gint center, - gint show_count, gint delay); + gint show_count, gint delay, gint priority); InfoData *add_info_line_with_pixmap(AppData *ad, gchar *text, GtkWidget *icon, gint offset, gint center, - gint show_count, gint delay); + gint show_count, gint delay, gint priority); void remove_info_line(AppData *ad, InfoData *id); void remove_all_lines(AppData *ad); -void set_info_click_signal(InfoData *id, void (*click_func)(AppData *ad, gpointer data), +void set_info_click_signal(InfoData *id, void (*click_func)(gpointer data, InfoData *id, AppData *ad), gpointer data, void (*free_func)(gpointer data)); void set_mouse_cursor (AppData *ad, gint icon); void init_app_display(AppData *ad); @@ -152,6 +187,8 @@ void property_save(gchar *path, AppData *ad); void property_show(AppletWidget *applet, gpointer data); /* slashapp.c */ +static void applet_change_orient(GtkWidget *w, PanelOrientType o, gpointer data); +static void applet_change_pixel_size(GtkWidget *w, int size, gpointer data); AppData *create_new_app(GtkWidget *applet); gchar *check_for_dir(char *d); void destroy_applet(GtkWidget *widget, gpointer data); |