-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathplumbing.c
124 lines (116 loc) · 3.02 KB
/
plumbing.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
atg - a tiny GUI toolkit for SDL
Copyright (C) 2012 Edward Cree
See atg.h for license information
plumbing.c: implements generic-to-specific plumbing
*/
#include "atg.h"
#include "atg_internals.h"
SDL_Surface *atg_render_element(atg_element *e)
{
if(!e) return(NULL);
if(e->hidden) return(NULL);
if(e->cache&&e->cached)
{
e->cached->refcount++;
return(e->cached);
}
SDL_Surface *rv=NULL;
if(e->render_callback)
rv=e->render_callback(e);
if(e->cache)
{
e->cached=rv;
if(rv) rv->refcount++;
}
return(rv);
}
int atg__push_event(struct atg_event_list *list, atg_event event)
{
if(!list) return(1);
if(list->last)
{
if(!(list->last->next=malloc(sizeof(atg__event_list))))
return(1);
*(list->last=list->last->next)=(atg__event_list){.event=event, .next=NULL};
return(0);
}
else if(list->list)
{
list->last=list->list;
while(list->last->next) list->last=list->last->next;
if(!(list->last->next=malloc(sizeof(atg__event_list))))
return(1);
*(list->last=list->last->next)=(atg__event_list){.event=event, .next=NULL};
return(0);
}
else
{
if(!(list->last=list->list=malloc(sizeof(atg__event_list))))
return(1);
*list->last=(atg__event_list){.event=event, .next=NULL};
return(0);
}
}
void atg__match_click_recursive(struct atg_event_list *list, atg_element *element, SDL_MouseButtonEvent button, unsigned int xoff, unsigned int yoff)
{
if(!element) return;
if(element->hidden) return;
if(
(button.x>=(int)(element->display.x+xoff))
&&(button.x<(int)(element->display.x+xoff+element->display.w))
&&(button.y>=(int)(element->display.y+yoff))
&&(button.y<(int)(element->display.y+yoff+element->display.h))
)
{
if(element->cached) // Catching clicks clears cache. It's only prudent
{
SDL_FreeSurface(element->cached);
element->cached=NULL;
}
if(element->clickable)
{
atg_ev_click click;
click.e=element;
click.pos=(atg_pos){.x=button.x-element->display.x-xoff, .y=button.y-element->display.y-yoff};
click.button=button.button;
atg__push_event(list, (atg_event){.type=ATG_EV_CLICK, .event.click=click});
}
if(element->match_click_callback)
element->match_click_callback(list, element, button, xoff, yoff);
}
}
void atg__match_click(struct atg_event_list *list, atg_canvas *canvas, SDL_MouseButtonEvent button)
{
if(!canvas) return;
atg__match_click_recursive(list, canvas->content, button, 0, 0);
}
atg_element *atg_copy_element(const atg_element *e)
{
if(!e) return(NULL);
if(e->copy_callback)
return(e->copy_callback(e));
return(NULL);
}
int atg_value_event(atg_element *e, struct atg_event *ev)
{
struct atg_event event;
if(!e) return(1);
if(!e->value_callback) return(1);
event=e->value_callback(e);
if(ev)
*ev=event;
return(0);
}
void atg_free_element(atg_element *element)
{
if(element)
{
if(element->free_callback)
element->free_callback(element);
else /* Bad things */
fprintf(stderr, "Don't know how to free element of type %s at %p, very bad things!\n", element->type, (void *)element);
SDL_FreeSurface(element->cached);
}
free(element);
}