mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 09:30:45 -05:00
295 lines
6.3 KiB
C
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();
|
|
}
|
|
|
|
|