working throbber

This commit is contained in:
Vincent Sanders 2019-08-20 16:13:00 +01:00 committed by Daniel Silverstone
parent 89fb88f6de
commit 02c75d0790
5 changed files with 161 additions and 76 deletions

View File

@ -70,6 +70,7 @@
#include "gtk/search.h"
#include "gtk/throbber.h"
#include "gtk/toolbar.h"
#include "gtk/toolbar_items.h"
#include "gtk/window.h"
#include "gtk/gdk.h"
#include "gtk/scaffolding.h"
@ -102,6 +103,13 @@ static gboolean nsgtk_on_##q##_activate_menu(GtkMenuItem *widget, gpointer data)
#define BUTTONHANDLER(q)\
static gboolean nsgtk_on_##q##_activate(GtkButton *widget, gpointer data)
struct nsgtk_menu {
GtkWidget *main; /* left click menu entry */
GtkWidget *rclick; /* right click menu */
GtkWidget *popup; /* popup menu entry */
};
/** Core scaffolding structure. */
struct nsgtk_scaffolding {
/** global linked list of scaffolding for gui interface adjustments */
@ -132,6 +140,9 @@ struct nsgtk_scaffolding {
/** link popup menu */
struct nsgtk_link_menu *link_menu;
/** menu entries widgets for sensativity adjustment */
struct nsgtk_menu menus[PLACEHOLDER_BUTTON];
};
/** current scaffold for model dialogue use */
@ -324,34 +335,6 @@ static void scaffolding_update_context(struct nsgtk_scaffolding *g)
}
/**
* Make the throbber run.
*
* scheduled callback to update the throbber
*
* \param p The context passed when scheduled.
*/
static void nsgtk_throb(void *p)
{
#if 0
nserror res;
GdkPixbuf *pixbuf;
struct nsgtk_scaffolding *g = p;
g->throb_frame++; /* advance to next frame */
res = nsgtk_throbber_get_frame(g->throb_frame, &pixbuf);
if (res == NSERROR_BAD_SIZE) {
g->throb_frame = 1;
res = nsgtk_throbber_get_frame(g->throb_frame, &pixbuf);
}
if (res == NSERROR_OK) {
gtk_image_set_from_pixbuf(g->throbber, pixbuf);
}
nsgtk_schedule(100, nsgtk_throb, p);
#endif
}
/**
@ -2115,23 +2098,20 @@ nserror gui_window_set_url(struct gui_window *gw, nsurl *url)
return NSERROR_OK;
}
void gui_window_start_throbber(struct gui_window* _g)
{
#if 0
static nserror gui_window_start_throbber(struct gui_window* gw)
{
struct nsgtk_scaffolding *g = nsgtk_get_scaffold(_g);
g->buttons[STOP_BUTTON]->sensitivity = true;
g->buttons[RELOAD_BUTTON]->sensitivity = false;
nsgtk_scaffolding_set_sensitivity(g);
scaffolding_update_context(g);
nsgtk_schedule(100, nsgtk_throb, g);
#endif
}
void gui_window_stop_throbber(struct gui_window* _g)
static nserror gui_window_stop_throbber(struct gui_window* gw)
{
#if 0
nserror res;
GdkPixbuf *pixbuf;
struct nsgtk_scaffolding *g = nsgtk_get_scaffold(_g);
@ -2140,10 +2120,6 @@ void gui_window_stop_throbber(struct gui_window* _g)
return;
}
scaffolding_update_context(g);
nsgtk_schedule(-1, nsgtk_throb, g);
g->throb_frame = 0;
if (g->buttons[STOP_BUTTON] != NULL)
g->buttons[STOP_BUTTON]->sensitivity = false;
@ -2152,13 +2128,8 @@ void gui_window_stop_throbber(struct gui_window* _g)
nsgtk_scaffolding_set_sensitivity(g);
res = nsgtk_throbber_get_frame(g->throb_frame, &pixbuf);
if ((res == NSERROR_OK) &&
(g->throbber != NULL)) {
gtk_image_set_from_pixbuf(g->throbber, pixbuf);
}
#endif
}
#endif
static void
@ -2347,15 +2318,6 @@ void nsgtk_scaffolding_reset_offset(struct nsgtk_scaffolding *g)
}
/* exported interface documented in gtk/scaffolding.h */
void nsgtk_scaffolding_update_throbber_ref(struct nsgtk_scaffolding *g)
{
#if 0
g->throbber = GTK_IMAGE(gtk_bin_get_child(
GTK_BIN(g->buttons[THROBBER_ITEM]->button)));
#endif
}
/* exported interface documented in gtk/scaffolding.h */
void nsgtk_scaffolding_update_websearch_ref(struct nsgtk_scaffolding *g)
{
@ -2433,11 +2395,6 @@ void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g)
gtk_widget_set_sensitive(GTK_WIDGET(\
g->buttons[i]->rclick),\
g->buttons[i]->sensitivity);\
if ((g->buttons[i]->location != -1) && \
(g->buttons[i]->button != NULL))\
gtk_widget_set_sensitive(GTK_WIDGET(\
g->buttons[i]->button),\
g->buttons[i]->sensitivity);\
if (g->buttons[i]->popup != NULL)\
gtk_widget_set_sensitive(GTK_WIDGET(\
g->buttons[i]->popup),\

View File

@ -112,7 +112,6 @@ void nsgtk_scaffolding_reset_offset(struct nsgtk_scaffolding *g);
*/
struct nsgtk_scaffolding *nsgtk_scaffolding_iterate(struct nsgtk_scaffolding *g);
void nsgtk_scaffolding_update_throbber_ref(struct nsgtk_scaffolding *g);
void nsgtk_scaffolding_update_websearch_ref(struct nsgtk_scaffolding *g);
@ -172,8 +171,6 @@ nserror nsgtk_scaffolding_new_tab(struct gui_window *gw);
void nsgtk_window_set_title(struct gui_window *gw, const char *title);
nserror gui_window_set_url(struct gui_window *g, struct nsurl *url);
void gui_window_start_throbber(struct gui_window *g);
void gui_window_stop_throbber(struct gui_window *g);
/**
* toolbar style changed

View File

@ -44,9 +44,16 @@
#include "gtk/toolbar_items.h"
#include "gtk/toolbar.h"
/** button location indicating button is not to be shown */
/**
* button location indicating button is not to be shown
*/
#define INACTIVE_LOCATION (-1)
/**
* time (in ms) between throbber animation frame updates
*/
#define THROBBER_FRAME_TIME (100)
/**
* toolbar item context
*/
@ -54,9 +61,6 @@ struct nsgtk_toolbar_item {
GtkToolItem *button;
int location; /* in toolbar */
bool sensitivity;
GtkWidget *main; /* left click menu entry */
GtkWidget *rclick; /* right click menu */
GtkWidget *popup; /* popup menu entry */
void *mhandler; /* menu item clicked */
void *bhandler; /* button clicked */
void *dataplus; /* customization -> toolbar */
@ -83,9 +87,6 @@ struct nsgtk_toolbar {
/** Completions for url_bar */
GtkEntryCompletion *url_bar_completion;
/** Activity throbber */
GtkImage *throbber;
/** Current frame of throbber animation */
int throb_frame;
@ -151,7 +152,6 @@ typedef enum search_buttons {
struct nsgtk_theme {
GtkImage *image[PLACEHOLDER_BUTTON];
GtkImage *searchimage[SEARCH_BUTTONS_COUNT];
/* apng throbber element */
};
@ -364,6 +364,7 @@ void nsgtk_theme_implement(struct nsgtk_scaffolding *g)
if (button == NULL)
continue;
#if 0
/* gtk_image_menu_item_set_image accepts NULL image */
if ((button->main != NULL) &&
(theme[IMAGE_SET_MAIN_MENU] != NULL)) {
@ -371,7 +372,7 @@ void nsgtk_theme_implement(struct nsgtk_scaffolding *g)
GTK_WIDGET(button->main),
GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->image[i]));
gtk_widget_show_all(GTK_WIDGET(button->main));
}
}
if ((button->rclick != NULL) &&
(theme[IMAGE_SET_RCLICK_MENU] != NULL)) {
nsgtk_image_menu_item_set_image(GTK_WIDGET(button->rclick),
@ -388,6 +389,7 @@ void nsgtk_theme_implement(struct nsgtk_scaffolding *g)
image[i]));
gtk_widget_show_all(GTK_WIDGET(button->popup));
}
#endif
if ((button->location != -1) && (button->button != NULL) &&
(theme[IMAGE_SET_BUTTONS] != NULL)) {
gtk_tool_button_set_icon_widget(
@ -546,7 +548,7 @@ make_toolbar_item(nsgtk_toolbar_button i, struct nsgtk_theme *theme)
w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( \
theme->image[p##_BUTTON]), q)); \
} \
break; \
break; \
}
MAKE_STOCKBUTTON(HOME, NSGTK_STOCK_HOME)
@ -1409,7 +1411,7 @@ static void nsgtk_scaffolding_update_url_bar_ref(struct nsgtk_scaffolding *g)
static void
nsgtk_toolbar_set_handler(struct nsgtk_scaffolding *g, nsgtk_toolbar_button i)
{
switch(i){
switch(i) {
case URL_BAR_ITEM:
nsgtk_scaffolding_update_url_bar_ref(g);
g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_urlbar(g)),
@ -1421,7 +1423,6 @@ nsgtk_toolbar_set_handler(struct nsgtk_scaffolding *g, nsgtk_toolbar_button i)
break;
case THROBBER_ITEM:
nsgtk_scaffolding_update_throbber_ref(g);
break;
case WEBSEARCH_ITEM:
@ -1556,6 +1557,9 @@ add_item_to_toolbar(struct nsgtk_toolbar *tb,
tb->buttons[bidx]->button = GTK_TOOL_ITEM(
make_toolbar_item(bidx, theme));
gtk_widget_set_sensitive(tb->buttons[bidx]->button,
tb->buttons[bidx]->sensitivity);
gtk_toolbar_insert(tb->widget,
tb->buttons[bidx]->button,
location);
@ -1640,6 +1644,91 @@ toolbar_item_create(nsgtk_toolbar_button id,
return NSERROR_OK;
}
/**
* set a toolbar items sensitivity
*
* note this does not set menu items sensitivity
*/
static nserror
set_item_sensitivity(struct nsgtk_toolbar_item *item, bool sensitivity)
{
if (item->sensitivity == sensitivity) {
/* item does not require sensitivity changing */
return NSERROR_OK;
}
item->sensitivity = sensitivity;
if ((item->location != -1) && (item->button != NULL)) {
gtk_widget_set_sensitive(GTK_WIDGET(item->button),
item->sensitivity);
}
return NSERROR_OK;
}
/**
* set a toolbar item to a throbber frame number
*
* \param toolbar_item The toolbar item to update
* \param frame The animation frame number to update to
* \return NSERROR_OK on success,
* NSERROR_INVALID if the toolbar item does not contain an image,
* NSERROR_BAD_SIZE if the frame is out of range.
*/
static nserror set_throbber_frame(GtkToolItem *toolbar_item, int frame)
{
nserror res;
GdkPixbuf *pixbuf;
GtkImage *throbber;
if (toolbar_item == NULL) {
/* no toolbar item */
return NSERROR_INVALID;
}
res = nsgtk_throbber_get_frame(frame, &pixbuf);
if (res != NSERROR_OK) {
return res;
}
throbber = GTK_IMAGE(gtk_bin_get_child(GTK_BIN(toolbar_item)));
gtk_image_set_from_pixbuf(throbber, pixbuf);
return NSERROR_OK;
}
/**
* Make the throbber run.
*
* scheduled callback to update the throbber
*
* \param p The context passed when scheduled.
*/
static void next_throbber_frame(void *p)
{
struct nsgtk_toolbar *tb = p;
nserror res;
tb->throb_frame++; /* advance to next frame */
res = set_throbber_frame(tb->buttons[THROBBER_ITEM]->button,
tb->throb_frame);
if (res == NSERROR_BAD_SIZE) {
tb->throb_frame = 1;
res = set_throbber_frame(tb->buttons[THROBBER_ITEM]->button,
tb->throb_frame);
}
/* only schedule next frame if there are no errors */
if (res == NSERROR_OK) {
nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, p);
}
}
/* exported interface documented in toolbar.h */
nserror nsgtk_toolbar_create(GtkBuilder *builder, struct nsgtk_toolbar **tb_out)
{
@ -1750,3 +1839,34 @@ nserror nsgtk_toolbar_update(struct nsgtk_toolbar *tb)
return NSERROR_OK;
}
/* exported interface documented in toolbar.h */
nserror nsgtk_toolbar_throbber(struct nsgtk_toolbar *tb, bool active)
{
nserror res;
GdkPixbuf *pixbuf;
/* when activating the throbber simply schedule the next frame update */
if (active) {
nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, tb);
set_item_sensitivity(tb->buttons[STOP_BUTTON], true);
set_item_sensitivity(tb->buttons[RELOAD_BUTTON], false);
return NSERROR_OK;
}
/* stopping the throbber */
nsgtk_schedule(-1, next_throbber_frame, tb);
tb->throb_frame = 0;
res = set_throbber_frame(tb->buttons[THROBBER_ITEM]->button,
tb->throb_frame);
/* adjust sensitivity of other items */
set_item_sensitivity(tb->buttons[STOP_BUTTON], false);
set_item_sensitivity(tb->buttons[RELOAD_BUTTON], true);
return res;
}

View File

@ -52,6 +52,14 @@ nserror nsgtk_toolbar_destroy(struct nsgtk_toolbar *toolbar);
*/
nserror nsgtk_toolbar_update(struct nsgtk_toolbar *tb);
/**
* Start or stop a throbber in a toolbar
*
* \param toolbar A toolbar returned from a creation
* \param active Trie if the throbber animation should play.
* \return NSERROR_OK on success
*/
nserror nsgtk_toolbar_throbber(struct nsgtk_toolbar *tb, bool active);
/**
* sets up the images for scaffolding.

View File

@ -52,6 +52,7 @@
#include "gtk/compat.h"
#include "gtk/gui.h"
#include "gtk/scaffolding.h"
#include "gtk/toolbar.h"
#include "gtk/local_history.h"
#include "gtk/plotters.h"
#include "gtk/schedule.h"
@ -1344,11 +1345,13 @@ gui_window_event(struct gui_window *gw, enum gui_window_event event)
break;
case GW_EVENT_START_THROBBER:
gui_window_start_throbber(gw);
nsgtk_toolbar_throbber(gw->toolbar, true);
/** \todo menu sensitivity for back/reload */
break;
case GW_EVENT_STOP_THROBBER:
gui_window_stop_throbber(gw);
nsgtk_toolbar_throbber(gw->toolbar, false);
/** \todo menu sensitivity for back/reload */
break;
default: