hack buttons some more

This commit is contained in:
Matthew Allum 2005-04-29 16:44:17 +00:00
parent 64355c0e48
commit 246e6bdd5d
12 changed files with 426 additions and 32 deletions

View File

@ -1,3 +1,27 @@
2005-04-29 mallum,,, <mallum@openedhand.com>
* clutter/cltr-button.c: (cltr_button_new),
(cltr_button_on_activate), (cltr_button_new_with_label),
(cltr_button_show):
* clutter/cltr-button.h:
* clutter/cltr-label.c: (cltr_label_new), (cltr_label_paint):
* clutter/cltr-private.h:
* clutter/cltr-video.c: (cltr_video_play):
* clutter/cltr-widget.c: (cltr_widget_new), (cltr_widget_abs_x),
(cltr_widget_abs_y), (cltr_widget_abs_x2), (cltr_widget_abs_y2),
(cltr_widget_width), (cltr_widget_height), (cltr_widget_show),
(cltr_widget_focus), (cltr_widget_unfocus),
(cltr_widget_set_focus_next), (cltr_widget_get_focus_next),
(cltr_widget_show_all):
* clutter/cltr-widget.h:
* clutter/cltr-window.c: (cltr_window_new),
(cltr_window_focus_widget):
* clutter/cltr.h:
* clutter/fonts.c: (draw_layout_on_pixbuf), (font_get_pixel_size):
* examples/scratch.c: (main):
Hack buttons some more
2005-04-27 mallum,,, <mallum@openedhand.com>
* clutter/Makefile.am:

View File

@ -3,12 +3,18 @@
struct CltrButton
{
CltrWidget widget;
char *label;
Pixbuf *pixb;
CltrWidget widget;
CltrLabel *label;
CltrButtonActivate activate_cb;
void *activate_cb_data;
CltrButtonState state; /* may be better in widget ? */
};
#define BUTTON_BORDER 1
#define BUTTON_PAD 5
static void
cltr_button_show(CltrWidget *widget);
@ -18,6 +24,12 @@ cltr_button_handle_xevent (CltrWidget *widget, XEvent *xev);
static void
cltr_button_paint(CltrWidget *widget);
static void
cltr_button_focus(CltrWidget *widget);
static void
cltr_button_unfocus(CltrWidget *widget);
CltrWidget*
cltr_button_new(int width, int height)
@ -31,25 +43,44 @@ cltr_button_new(int width, int height)
button->widget.show = cltr_button_show;
button->widget.paint = cltr_button_paint;
button->widget.focus_in = cltr_button_focus;
button->widget.focus_out = cltr_button_unfocus;
button->widget.xevent_handler = cltr_button_handle_xevent;
return CLTR_WIDGET(button);
}
void
cltr_button_on_activate(CltrButton *button,
CltrButtonActivate callback,
void *userdata)
{
button->activate_cb = callback;
button->activate_cb_data = userdata;
}
CltrWidget*
cltr_button_new_with_label(const char *label,
CltrFont *font,
PixbufPixel *col)
{
CltrButton *button = NULL;
int label_width, label_height;
if (font == NULL)
{
/* XXXX grab default font */
}
button = CLTR_BUTTON(cltr_button_new(-1, -1));
button->label = CLTR_LABEL(cltr_label_new(label, font, col));
button->widget.width = cltr_widget_width((CltrWidget*)button->label) + (2 * ( BUTTON_BORDER + BUTTON_PAD));
button->widget.height = cltr_widget_height((CltrWidget*)button->label) + ( 2 * ( BUTTON_BORDER + BUTTON_PAD));
CLTR_DBG("width: %i, height %i",
cltr_widget_width((CltrWidget*)button->label),
cltr_widget_height((CltrWidget*)button->label));
cltr_widget_add_child(CLTR_WIDGET(button),
CLTR_WIDGET(button->label),
( BUTTON_BORDER + BUTTON_PAD),
( BUTTON_BORDER + BUTTON_PAD));
return CLTR_WIDGET(button);
}
@ -60,15 +91,160 @@ cltr_button_show(CltrWidget *widget)
}
static void
cltr_button_focus(CltrWidget *widget)
{
CltrButton *button = CLTR_BUTTON(widget);
if (button->state != CltrButtonStateFocused)
{
button->state = CltrButtonStateFocused;
cltr_widget_queue_paint(widget);
}
}
static void
cltr_button_unfocus(CltrWidget *widget)
{
CltrButton *button = CLTR_BUTTON(widget);
if (button->state != CltrButtonStateInactive)
{
button->state = CltrButtonStateInactive;
cltr_widget_queue_paint(CLTR_WIDGET(button));
}
}
static void
cltr_button_handle_xkeyevent(CltrButton *button, XKeyEvent *xkeyev)
{
KeySym kc;
CltrButtonState old_state;
CltrWidget *next_focus = NULL;
old_state = button->state;
kc = XKeycodeToKeysym(xkeyev->display, xkeyev->keycode, 0);
switch (kc)
{
case XK_Left:
case XK_KP_Left:
if (xkeyev->type != KeyPress)
break;
next_focus = cltr_widget_get_focus_next(CLTR_WIDGET(button), CLTR_WEST);
break;
case XK_Up:
case XK_KP_Up:
if (xkeyev->type != KeyPress)
break;
next_focus = cltr_widget_get_focus_next(CLTR_WIDGET(button), CLTR_NORTH);
break;
case XK_Right:
case XK_KP_Right:
if (xkeyev->type != KeyPress)
break;
next_focus = cltr_widget_get_focus_next(CLTR_WIDGET(button), CLTR_EAST);
break;
case XK_Down:
case XK_KP_Down:
if (xkeyev->type != KeyPress)
break;
next_focus = cltr_widget_get_focus_next(CLTR_WIDGET(button), CLTR_SOUTH);
break;
case XK_Return:
if (xkeyev->type == KeyPress)
{
if (button->state != CltrButtonStateActive)
button->state = CltrButtonStateActive;
CLTR_DBG("press");
if (button->activate_cb)
button->activate_cb(CLTR_WIDGET(button), button->activate_cb_data);
}
else /* KeyRelease */
{
CLTR_DBG("release");
if (button->state != CltrButtonStateFocused)
button->state = CltrButtonStateFocused;
/* What to do about key repeats ? */
}
break;
default:
/* ??? */
}
if (button->state != old_state)
{
CLTR_DBG("queueing paint");
cltr_widget_queue_paint(CLTR_WIDGET(button));
}
if (next_focus)
{
/* Evil - need to centralise focus management */
ClutterMainContext *ctx = CLTR_CONTEXT();
cltr_window_focus_widget(ctx->window, next_focus);
}
}
static gboolean
cltr_button_handle_xevent (CltrWidget *widget, XEvent *xev)
{
CltrButton *button = CLTR_BUTTON(widget);
switch (xev->type)
{
case KeyPress:
case KeyRelease:
CLTR_DBG("KeyPress");
cltr_button_handle_xkeyevent(button, &xev->xkey);
break;
}
}
static void
cltr_button_paint(CltrWidget *widget)
{
CltrButton *button = CLTR_BUTTON(widget);
CLTR_MARK();
glPushMatrix();
glEnable(GL_BLEND);
switch (button->state)
{
case CltrButtonStateFocused:
glColor4f(1.0, 1.0, 0.0, 1.0);
break;
case CltrButtonStateActive:
glColor4f(1.0, 0.0, 0.0, 1.0);
break;
default:
glColor4f(1.0, 1.0, 1.0, 1.0);
}
cltr_glu_rounded_rect(widget->x,
widget->y,
widget->x + widget->width,
widget->y + widget->height,
widget->width/30,
NULL);
glDisable(GL_BLEND);
glPopMatrix();
}

View File

@ -5,10 +5,26 @@
typedef struct CltrButton CltrButton;
typedef enum CltrButtonState
{
CltrButtonStateDisabled,
CltrButtonStateInactive,
CltrButtonStateFocused,
CltrButtonStateActive,
}
CltrButtonState;
typedef void (*CltrButtonActivate) (CltrWidget *widget, void *userdata) ;
#define CLTR_BUTTON(w) ((CltrButton*)(w))
CltrWidget*
cltr_button_new(int width, int height);
void
cltr_button_on_activate(CltrButton *button,
CltrButtonActivate callback,
void* userdata);
#endif

View File

@ -36,21 +36,20 @@ cltr_label_new(const char *text,
if (width && height)
{
PixbufPixel bg = { 0xff, 0x0, 0x0, 0xff };
PixbufPixel bg = { 0xff, 0xff, 0xff, 0x00 };
label->text = strdup(text);
label->pixb = pixbuf_new(width, height);
pixbuf_fill_rect(label->pixb, 0, 0, -1, -1, &bg);
/*
font_draw(font,
label->pixb,
label->text,
0,
0,
col);
*/
label->texture = cltr_texture_new(label->pixb);
}
@ -106,6 +105,8 @@ cltr_label_paint(CltrWidget *widget)
{
CltrLabel *label = CLTR_LABEL(widget);
CLTR_MARK();
if (label->text)
{
glPushMatrix();
@ -115,15 +116,13 @@ cltr_label_paint(CltrWidget *widget)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
/* glColor4ub(100, 200, 50, 100); */
/* glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); */
cltr_texture_render_to_gl_quad(label->texture,
widget->x,
widget->y,
widget->x + widget->width ,
widget->y + widget->height);
cltr_widget_abs_x(widget),
cltr_widget_abs_y(widget),
cltr_widget_abs_x2(widget),
cltr_widget_abs_y2(widget));
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);

View File

@ -32,11 +32,13 @@
typedef void (*WidgetPaintMethod) (CltrWidget *widget ) ;
typedef void (*WidgetShowMethod) (CltrWidget *widget ) ;
typedef void (*WidgetDestroyMethod) (CltrWidget *widget) ;
typedef void (*WidgetFocusMethod) (CltrWidget *widget) ;
typedef void (*WidgetUnfocusMethod) (CltrWidget *widget) ;
typedef gboolean (*WidgetXEventHandler) (CltrWidget *widget, XEvent *xev) ;
struct CltrWidget
{
int type;
int x,y,width,height;
CltrWidget *parent;
@ -44,11 +46,18 @@ struct CltrWidget
GList *children;
/* focus */
CltrWidget *focus_next_north, *focus_next_south,
*focus_next_west, *focus_next_east;
/* methods */
WidgetPaintMethod paint;
WidgetShowMethod show;
WidgetDestroyMethod destroy;
WidgetFocusMethod focus_in;
WidgetUnfocusMethod focus_out;
WidgetXEventHandler xevent_handler;
};

View File

@ -442,7 +442,7 @@ cltr_video_play(CltrVideo *video)
GST_STATE_PLAYING) == GST_STATE_FAILURE)
g_error ("Could not set state to PLAYING");
g_timeout_add(FPS_TO_TIMEOUT(20), (GSourceFunc) cltr_video_idler, video);
g_timeout_add(FPS_TO_TIMEOUT(30), (GSourceFunc) cltr_video_idler, video);
}
void

View File

@ -11,6 +11,46 @@ cltr_widget_new(void)
return w;
}
int
cltr_widget_abs_x(CltrWidget *widget)
{
int x = widget->x;
/* XXX we really need to identify top level window
* this assummes its positioned at 0,0 - but really
* it could be anywhere and need to account for this.
*/
while ((widget = widget->parent) != NULL)
x += widget->x;
return x;
}
int
cltr_widget_abs_y(CltrWidget *widget)
{
int y = widget->y;
while ((widget = widget->parent) != NULL)
y += widget->y;
return y;
}
int
cltr_widget_abs_x2(CltrWidget *widget)
{
return cltr_widget_abs_x(widget) + cltr_widget_width(widget);
}
int
cltr_widget_abs_y2(CltrWidget *widget)
{
return cltr_widget_abs_y(widget) + cltr_widget_height(widget);
}
int
cltr_widget_width(CltrWidget *widget)
{
@ -20,9 +60,10 @@ cltr_widget_width(CltrWidget *widget)
int
cltr_widget_height(CltrWidget *widget)
{
return widget->width;
return widget->height;
}
void
cltr_widget_show(CltrWidget *widget)
{
@ -34,6 +75,73 @@ cltr_widget_show(CltrWidget *widget)
}
}
/* XXX Focus hacks;
*
* Should not call directly but via cltr_window_focus_widget()
*
* need to sort this out.
*/
void
cltr_widget_focus(CltrWidget *widget)
{
if (widget->focus_in)
{
widget->focus_in(widget);
}
}
void
cltr_widget_unfocus(CltrWidget *widget)
{
if (widget->focus_out)
{
widget->focus_out(widget);
}
}
void
cltr_widget_set_focus_next(CltrWidget *widget,
CltrWidget *widget_to_focus,
CltrDirection direction)
{
switch (direction)
{
case CLTR_NORTH:
widget->focus_next_north = widget_to_focus;
break;
case CLTR_SOUTH:
widget->focus_next_south = widget_to_focus;
break;
case CLTR_EAST:
widget->focus_next_east = widget_to_focus;
break;
case CLTR_WEST:
widget->focus_next_west = widget_to_focus;
break;
}
}
CltrWidget*
cltr_widget_get_focus_next(CltrWidget *widget,
CltrDirection direction)
{
switch (direction)
{
case CLTR_NORTH:
return widget->focus_next_north;
case CLTR_SOUTH:
return widget->focus_next_south;
case CLTR_EAST:
return widget->focus_next_east;
case CLTR_WEST:
return widget->focus_next_west;
}
return NULL;
}
void
cltr_widget_show_all(CltrWidget *widget)
{
@ -46,6 +154,8 @@ cltr_widget_show_all(CltrWidget *widget)
CltrWidget *child = CLTR_WIDGET(widget_item->data);
cltr_widget_show(child);
cltr_widget_show_all(child);
}
while ((widget_item = g_list_next(widget_item)) != NULL);
}
@ -56,11 +166,13 @@ cltr_widget_show_all(CltrWidget *widget)
void
cltr_widget_add_child(CltrWidget *widget, CltrWidget *child, int x, int y)
{
widget->children = g_list_append(widget->children, child);
child->parent = widget;
child->x = x;
child->y = y;
}

View File

@ -16,6 +16,37 @@ cltr_widget_width(CltrWidget *widget);
int
cltr_widget_height(CltrWidget *widget);
int
cltr_widget_abs_x(CltrWidget *widget);
int
cltr_widget_abs_y(CltrWidget *widget);
int
cltr_widget_abs_x2(CltrWidget *widget);
int
cltr_widget_abs_y2(CltrWidget *widget);
/* These are hacky see notes in .c */
void
cltr_widget_focus(CltrWidget *widget);
void
cltr_widget_unfocus(CltrWidget *widget);
/* ******************************* */
void
cltr_widget_set_focus_next(CltrWidget *widget,
CltrWidget *widget_to_focus,
CltrDirection direction);
CltrWidget*
cltr_widget_get_focus_next(CltrWidget *widget,
CltrDirection direction);
void
cltr_widget_show(CltrWidget *widget);

View File

@ -53,7 +53,7 @@ cltr_window_new(int width, int height)
XSelectInput(CltrCntx.xdpy, win->xwin,
StructureNotifyMask|ExposureMask|
KeyPressMask|PropertyChangeMask);
KeyPressMask|KeyReleaseMask|PropertyChangeMask);
glXMakeCurrent(CltrCntx.xdpy, win->xwin, CltrCntx.gl_context);
@ -164,8 +164,12 @@ cltr_window_focus_widget(CltrWindow *win, CltrWidget *widget)
ClutterMainContext *ctx = CLTR_CONTEXT();
win->focused_child = widget;
if (win->focused_child)
cltr_widget_unfocus(win->focused_child);
cltr_widget_focus(widget);
win->focused_child = widget;
}

View File

@ -21,6 +21,7 @@
#include "pixbuf.h"
#include "fonts.h"
typedef enum CltrDirection
{
CLTR_NORTH,

View File

@ -118,10 +118,16 @@ draw_layout_on_pixbuf (PangoLayout *layout,
int tr1, tg1, tb1, tr2, tg2, tb2;
int a = (*b * color->a + 0x80) >> 8;
/*
/*
this is wrong for when the backing has an
alpha of zero. we need a different algorythm
to handle that - so we can overlay just a font
text texture with no bg
*/
if (!a)
{ b++; continue; }
*/
pixbuf_get_pixel (pixb, i, j, &pixel);
@ -134,8 +140,10 @@ draw_layout_on_pixbuf (PangoLayout *layout,
tb1 = (255 - a) * pixel.b + 0x80;
tb2 = a * color->b + 0x80;
pixel.b = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
tb1 = (255 - a) * pixel.a + 0x80;
tb2 = a * color->a + 0x80;
pixel.a = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
pixbuf_set_pixel (pixb, i, j, &pixel);
b++;
}
@ -194,6 +202,8 @@ font_get_pixel_size (ClutterFont *font,
pango_layout_get_pixel_size (layout, width, height);
printf("gave width:%i, height %i\n", *width, *height);
g_object_unref(G_OBJECT(layout));
}

View File

@ -12,6 +12,8 @@ main(int argc, char **argv)
{
int i;
CltrWidget *win = NULL, *grid = NULL, *test = NULL, *test2 = NULL;
CltrFont *font = NULL;
PixbufPixel col = { 0xff, 0, 0, 0xff };
gchar *img_path = NULL;
gboolean want_fullscreen = FALSE;
@ -51,12 +53,22 @@ main(int argc, char **argv)
if (want_fullscreen)
cltr_window_set_fullscreen(CLTR_WINDOW(win));
font = font_new("Sans 20");
grid = cltr_photo_grid_new(800, 600, cols, cols, img_path);
test = cltr_button_new_with_label("ButtonBoooo\ndsfdsfdsf sss\nsjhsjhsjhs", font, &col);
cltr_window_focus_widget(CLTR_WINDOW(win), grid);
test2 = cltr_button_new_with_label("Button", font, &col);
cltr_widget_add_child(win, grid, 0, 0);
cltr_widget_add_child(win, test, 300, 100);
cltr_widget_add_child(win, test2, 100, 100);
cltr_window_focus_widget(CLTR_WINDOW(win), test);
cltr_widget_set_focus_next(test, test2, CLTR_EAST);
cltr_widget_set_focus_next(test, test2, CLTR_WEST);
cltr_widget_set_focus_next(test2, test, CLTR_EAST);
cltr_widget_set_focus_next(test2, test, CLTR_WEST);
/*