/* * Twin - A Tiny Window System * Copyright © 2004 Keith Packard * 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)); } static twin_path_t * _twin_path_bevel_shape (twin_shape_t shape, twin_bool_t upper, twin_coord_t left, twin_coord_t top, twin_coord_t right, twin_coord_t bottom, twin_fixed_t radius, twin_fixed_t bw) { return 0; } 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); }