blob: 3906de3d681651875e4fbbe6d68ddbacd04cc6b6 [file] [log] [blame]
/*
* Twin - A Tiny Window System
* Copyright © 2004 Keith Packard <keithp@keithp.com>
* All rights reserved.
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with the Twin Library; see the file COPYING. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "twinint.h"
static twin_path_t *
_twin_path_shape (twin_shape_t shape,
twin_coord_t left,
twin_coord_t top,
twin_coord_t right,
twin_coord_t bottom,
twin_fixed_t radius)
{
twin_path_t *path = twin_path_create ();
twin_fixed_t x = twin_int_to_fixed (left);
twin_fixed_t y = twin_int_to_fixed (top);
twin_fixed_t w = twin_int_to_fixed (right - left);
twin_fixed_t h = twin_int_to_fixed (bottom - top);
if (!path)
return 0;
switch (shape) {
case TwinShapeRectangle:
twin_path_rectangle (path, x, y, w, h);
break;
case TwinShapeRoundedRectangle:
twin_path_rounded_rectangle (path, x, h, w, y, radius, radius);
break;
case TwinShapeLozenge:
twin_path_lozenge (path, x, y, w, h);
break;
case TwinShapeTab:
twin_path_tab (path, x, y, w, h, radius, radius);
break;
case TwinShapeEllipse:
twin_path_ellipse (path, x + w/2, y + h/2, w/2, h/2);
break;
}
return path;
}
void
_twin_widget_paint_shape (twin_widget_t *widget,
twin_shape_t shape,
twin_coord_t left,
twin_coord_t top,
twin_coord_t right,
twin_coord_t bottom,
twin_fixed_t radius)
{
twin_pixmap_t *pixmap = widget->window->pixmap;
if (shape == TwinShapeRectangle)
twin_fill (pixmap, widget->background, TWIN_SOURCE,
left, top, right, bottom);
else
{
twin_path_t *path = _twin_path_shape (shape, left, top,
right, bottom, radius);
if (path)
{
twin_paint_path (pixmap, widget->background, path);
twin_path_destroy (path);
}
}
}
static void
_twin_widget_paint (twin_widget_t *widget)
{
_twin_widget_paint_shape (widget, widget->shape, 0, 0,
_twin_widget_width (widget),
_twin_widget_height (widget), widget->radius);
}
twin_dispatch_result_t
_twin_widget_dispatch (twin_widget_t *widget, twin_event_t *event)
{
switch (event->kind) {
case TwinEventQueryGeometry:
widget->layout = TWIN_FALSE;
if (widget->copy_geom)
{
twin_widget_t *copy = widget->copy_geom;
if (copy->layout)
(*copy->dispatch) (copy, event);
widget->preferred = copy->preferred;
return TwinDispatchDone;
}
break;
case TwinEventConfigure:
widget->extents = event->u.configure.extents;
break;
case TwinEventPaint:
_twin_widget_paint (widget);
widget->paint = TWIN_FALSE;
break;
default:
break;
}
return TwinDispatchContinue;
}
void
_twin_widget_init (twin_widget_t *widget,
twin_box_t *parent,
twin_window_t *window,
twin_widget_layout_t preferred,
twin_dispatch_proc_t dispatch)
{
if (parent)
{
twin_widget_t **prev;
for (prev = &parent->children; *prev; prev = &(*prev)->next);
widget->next = *prev;
*prev = widget;
window = parent->widget.window;
}
else
widget->next = NULL;
widget->window = window;
widget->parent = parent;
widget->copy_geom = NULL;
widget->paint = TWIN_TRUE;
widget->layout = TWIN_TRUE;
widget->want_focus = TWIN_FALSE;
widget->background = 0x00000000;
widget->extents.left = widget->extents.top = 0;
widget->extents.right = widget->extents.bottom = 0;
widget->preferred = preferred;
widget->dispatch = dispatch;
widget->shape = TwinShapeRectangle;
widget->radius = twin_int_to_fixed (12);
}
void
_twin_widget_queue_paint (twin_widget_t *widget)
{
while (widget->parent)
{
if (widget->paint)
return;
widget->paint = TWIN_TRUE;
widget = &widget->parent->widget;
}
_twin_toplevel_queue_paint (widget);
}
void
_twin_widget_queue_layout (twin_widget_t *widget)
{
while (widget->parent)
{
if (widget->layout)
return;
widget->layout = TWIN_TRUE;
widget->paint = TWIN_TRUE;
widget = &widget->parent->widget;
}
_twin_toplevel_queue_layout (widget);
}
twin_bool_t
_twin_widget_contains (twin_widget_t *widget,
twin_coord_t x,
twin_coord_t y)
{
return (0 <= x && x < _twin_widget_width(widget) &&
0 <= y && y < _twin_widget_height(widget));
}
void
_twin_widget_bevel (twin_widget_t *widget,
twin_fixed_t b,
twin_bool_t down)
{
twin_path_t *path = twin_path_create ();
twin_fixed_t w = twin_int_to_fixed (_twin_widget_width (widget));
twin_fixed_t h = twin_int_to_fixed (_twin_widget_height (widget));
twin_argb32_t top_color, bot_color;
twin_pixmap_t *pixmap = widget->window->pixmap;
if (path)
{
if (down)
{
top_color = 0x80000000;
bot_color = 0x80808080;
}
else
{
top_color = 0x80808080;
bot_color = 0x80000000;
}
twin_path_move (path, 0, 0);
twin_path_draw (path, w, 0);
twin_path_draw (path, w-b, b);
twin_path_draw (path, b, b);
twin_path_draw (path, b, h-b);
twin_path_draw (path, 0, h);
twin_path_close (path);
twin_paint_path (pixmap, top_color, path);
twin_path_empty (path);
twin_path_move (path, b, h-b);
twin_path_draw (path, w-b, h-b);
twin_path_draw (path, w-b, b);
twin_path_draw (path, w, 0);
twin_path_draw (path, w, h);
twin_path_draw (path, 0, h);
twin_path_close (path);
twin_paint_path (pixmap, bot_color, path);
twin_path_destroy (path);
}
}
twin_widget_t *
twin_widget_create (twin_box_t *parent,
twin_argb32_t background,
twin_coord_t width,
twin_coord_t height,
twin_stretch_t stretch_width,
twin_stretch_t stretch_height)
{
twin_widget_t *widget = malloc (sizeof (twin_widget_t));
twin_widget_layout_t preferred;
if (!widget)
return NULL;
preferred.width = width;
preferred.height = height;
preferred.stretch_width = stretch_width;
preferred.stretch_height = stretch_height;
_twin_widget_init (widget, parent, 0, preferred, _twin_widget_dispatch);
widget->background = background;
return widget;
}
void
twin_widget_set (twin_widget_t *widget, twin_argb32_t background)
{
widget->background = background;
_twin_widget_queue_paint (widget);
}