aseprite/jinete/src/jtheme.c

375 lines
7.6 KiB
C
Raw Normal View History

2007-09-18 23:57:02 +00:00
/* jinete - a GUI library
* Copyright (C) 2003-2005, 2007 by David A. Capello
*
* Jinete is gift-ware.
*/
#include <allegro.h>
#include <allegro/internal/aintern.h>
#include "jinete/font.h"
#include "jinete/manager.h"
#include "jinete/rect.h"
#include "jinete/system.h"
#include "jinete/theme.h"
#include "jinete/view.h"
#include "jinete/widget.h"
static JTheme ji_current_theme = NULL;
static JTheme ji_standard_theme = NULL;
static void draw_text(BITMAP *bmp, FONT *f, const char *text, int x, int y,
int fg_color, int bg_color, bool fill_bg);
int _ji_theme_init(void)
{
return 0;
}
void _ji_theme_exit(void)
{
if (ji_standard_theme) {
jtheme_free(ji_standard_theme);
ji_standard_theme = NULL;
}
}
JTheme jtheme_new(void)
{
JTheme theme;
theme = jmalloc(sizeof (struct jtheme));
if (!theme)
return NULL;
theme->name = "Theme";
theme->default_font = font; /* default Allegro font */
theme->desktop_color = 0;
theme->textbox_fg_color = 0;
theme->textbox_bg_color = 0;
theme->check_icon_size = 0;
theme->radio_icon_size = 0;
theme->scrollbar_size = 0;
theme->destroy = NULL;
theme->regen = NULL;
theme->set_cursor = NULL;
theme->init_widget = NULL;
theme->get_window_mask = NULL;
theme->map_decorative_widget = NULL;
theme->nmethods = 0;
theme->methods = NULL;
return theme;
}
void jtheme_free(JTheme theme)
{
if (theme->destroy)
(*theme->destroy)();
if (ji_current_theme == theme)
ji_set_theme(NULL);
if (theme->methods)
jfree(theme->methods);
jfree(theme);
}
void jtheme_set_method(JTheme theme, int widget_type, JDrawFunc draw_widget)
{
if (widget_type >= theme->nmethods) {
int c, old_nmethods = theme->nmethods;
theme->nmethods = widget_type+1;
theme->methods = jrealloc(theme->methods,
sizeof (JDrawFunc) * theme->nmethods);
for (c=old_nmethods; c<theme->nmethods; c++)
theme->methods[c] = NULL;
}
theme->methods[widget_type] = draw_widget;
}
JDrawFunc jtheme_get_method(JTheme theme, int widget_type)
{
if (theme->methods && widget_type >= 0 && widget_type < theme->nmethods)
return theme->methods[widget_type];
else
return NULL;
}
/**********************************************************************/
void ji_set_theme(JTheme theme)
{
JWidget manager = ji_get_default_manager();
ji_current_theme = theme;
if (ji_current_theme) {
ji_regen_theme();
/* XXX any better idea? */
if (manager && jwidget_get_theme(manager) == NULL)
jwidget_set_theme(manager, theme);
}
}
void ji_set_standard_theme(void)
{
if (!ji_standard_theme) {
ji_standard_theme = jtheme_new_standard();
/* ji_standard_theme = jtheme_new_simple(); */
if (!ji_standard_theme)
return;
}
ji_set_theme(ji_standard_theme);
}
JTheme ji_get_theme(void)
{
return ji_current_theme;
}
void ji_regen_theme(void)
{
if (ji_current_theme) {
/* hide the cursor */
show_mouse(NULL);
set_mouse_sprite(NULL);
if (ji_current_theme->regen)
(*ji_current_theme->regen)();
/* ok, reset the mouse cursor */
ji_mouse_set_cursor(ji_mouse_get_cursor());
}
}
void _ji_theme_draw_sprite_color(BITMAP *bmp, BITMAP *sprite,
int x, int y, int color)
{
int u, v, mask = bitmap_mask_color(sprite);
for (v=0; v<sprite->h; v++)
for (u=0; u<sprite->w; u++)
if (getpixel(sprite, u, v) != mask)
putpixel(bmp, x+u, y+v, color);
}
void _ji_theme_rectedge(BITMAP *bmp,
int x1, int y1, int x2, int y2, int c1, int c2)
{
vline(bmp, x1, y1, y2, c1);
vline(bmp, x2, y1, y2, c2);
hline(bmp, x1+1, y1, x2-1, c1);
hline(bmp, x1+1, y2, x2-1, c2);
}
void _ji_theme_rectfill_exclude(BITMAP *bmp,
int x1, int y1, int x2, int y2,
int ex1, int ey1, int ex2, int ey2, int color)
{
if ((ex1 > x2) || (ex2 < x1) ||
(ey1 > y2) || (ey2 < y1))
rectfill(bmp, x1, y1, x2, y2, color);
else {
int y, my1, my2;
my1 = MAX(y1, ey1);
my2 = MIN(y2, ey2);
/* top */
for (y=y1; y<ey1; y++)
hline(bmp, x1, y, x2, color);
/* left */
if (x1 < ex1)
for (y=my1; y<=my2; y++)
hline(bmp, x1, y, ex1-1, color);
/* right */
if (x2 > ex2)
for (y=my1; y<=my2; y++)
hline(bmp, ex2+1, y, x2, color);
/* bottom */
for (y=ey2+1; y<=y2; y++)
hline(bmp, x1, y, x2, color);
}
}
void _ji_theme_textbox_draw(BITMAP *bmp, JWidget widget, int *w, int *h)
{
JWidget view = jwidget_get_view(widget);
char *text = widget->text;
int x1, y1, x2, y2;
int x, y, chr, len;
char *beg, *end;
int bg = widget->theme->textbox_bg_color;
int fg = widget->theme->textbox_fg_color;
int scroll_x, scroll_y;
int viewport_w, viewport_h;
int textheight = jwidget_get_text_height(widget);
FONT *font = widget->text_font;
char *beg_end, *old_end;
int width;
if (view) {
JRect vp = jview_get_viewport_position (view);
x1 = vp->x1;
y1 = vp->y1;
viewport_w = jrect_w(vp);
viewport_h = jrect_h(vp);
jview_get_scroll(view, &scroll_x, &scroll_y);
jrect_free(vp);
}
else {
x1 = widget->rc->x1;
y1 = widget->rc->y1;
viewport_w = jrect_w(widget->rc);
viewport_h = jrect_h(widget->rc);
scroll_x = scroll_y = 0;
}
x2 = x1+viewport_w-1;
y2 = y1+viewport_h-1;
chr = 0;
/* without word-wrap */
if (!(widget->align & JI_WORDWRAP)) {
width = jrect_w(widget->rc);
}
/* with word-wrap */
else {
if (w) {
width = *w;
*w = 0;
}
else {
/* XXX modificable option? I don't think so, this is very internal stuff */
#if 0
/* shows more information in x-scroll 0 */
width = viewport_w;
#else
/* make good use of the complete text-box */
if (view) {
int w, h;
jview_get_max_size(view, &w, &h);
width = MAX(viewport_w, w);
}
else {
width = viewport_w;
}
#endif
}
}
/* draw line-by-line */
y = y1 - scroll_y;
for (beg=end=text; end; ) {
x = x1 - scroll_x;
/* without word-wrap */
if (!(widget->align & JI_WORDWRAP)) {
end = ustrchr (beg, '\n');
if (end) {
chr = *end;
*end = 0;
}
}
/* with word-wrap */
else {
old_end = NULL;
for (beg_end=beg;;) {
end = ustrpbrk(beg_end, " \n");
if (end) {
chr = *end;
*end = 0;
}
/* to here we can print */
if ((old_end) && (x+text_length(font, beg) > x1-scroll_x+width)) {
if (end)
*end = chr;
end = old_end;
chr = *end;
*end = 0;
break;
}
/* we can print one word more */
else if (end) {
/* force break */
if (chr == '\n')
break;
*end = chr;
beg_end = end+1;
}
/* we are in the end of text */
else
break;
old_end = end;
}
}
len = text_length(font, beg);
/* render the text in the "bmp" */
if (bmp) {
int xout;
if (widget->align & JI_CENTER)
xout = x + width/2 - len/2;
else if (widget->align & JI_RIGHT)
xout = x + width - len;
else /* left */
xout = x;
draw_text(bmp, font, beg, xout, y, fg, bg, TRUE);
_ji_theme_rectfill_exclude
(bmp,
x1, y, x2, y+textheight-1,
xout, y, xout+len-1, y+textheight-1, bg);
}
/* width */
if (w)
*w = MAX (*w, len);
y += textheight;
if (end) {
*end = chr;
beg = end+1;
}
}
/* height */
if (h)
*h = (y-y1+scroll_y);
if (bmp) {
/* fill bottom area */
if (y <= y2)
rectfill(bmp, x1, y, x2, y2, bg);
}
}
static void draw_text(BITMAP *bmp, FONT *f, const char *text, int x, int y,
int fg_color, int bg_color, bool fill_bg)
{
/* XXXX optional anti-aliased textout */
ji_font_set_aa_mode(f, bg_color);
text_mode(fill_bg ? bg_color: -1);
textout(bmp, f, text, x, y, fg_color);
/* XXXX */
}