mutter/clutter/cltr-button.c
2005-05-23 21:21:50 +00:00

295 lines
6.3 KiB
C

#include "cltr-button.h"
#include "cltr-private.h"
struct CltrButton
{
CltrWidget widget;
CltrLabel *label;
Pixmap *pixb;
CltrTexture *texture;
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);
static gboolean
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)
{
CltrButton *button;
button = g_malloc0(sizeof(CltrButton));
button->widget.width = width;
button->widget.height = 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;
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);
}
void
cltr_button_set_label(CltrButton *button,
const char *text,
CltrFont *font,
PixbufPixel *col)
{
int x, y;
if (button->label)
{
cltr_widget_remove_child(CLTR_WIDGET(button),
CLTR_WIDGET(button->label));
cltr_widget_unref(CLTR_WIDGET(button));
/* XXX free up pre-existing label */
}
button->label = CLTR_LABEL(cltr_label_new(text, font, col));
x = (cltr_widget_width(CLTR_WIDGET(button)) - cltr_widget_width(CLTR_WIDGET(button->label)))/2;
y = (cltr_widget_height(CLTR_WIDGET(button)) - cltr_widget_height(CLTR_WIDGET(button->label)))/2;
cltr_widget_add_child(CLTR_WIDGET(button),
CLTR_WIDGET(button->label),
x, y);
}
CltrWidget*
cltr_button_new_with_pixbuf(Pixbuf *pixb)
{
CltrButton *button = NULL;
button = CLTR_BUTTON(cltr_button_new(-1, -1));
return CLTR_WIDGET(button);
}
static void
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:
/* ??? */
break;
}
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(CLTR_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;
}
return TRUE;
}
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(cltr_widget_abs_x(widget),
cltr_widget_abs_y(widget),
cltr_widget_abs_x2(widget),
cltr_widget_abs_y2(widget),
2, 5,
NULL);
glDisable(GL_BLEND);
glPopMatrix();
}