Line data Source code
1 : /* Copyright (C) 2007-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include "gdraw.h"
28 : #include "gkeysym.h"
29 : #include "gresource.h"
30 : #include "gwidget.h"
31 : #include "ggadgetP.h"
32 : #include <string.h>
33 :
34 : static GBox gdrawable_box = GBOX_EMPTY; /* Don't initialize here */
35 : static FontInstance *gdrawable_font = NULL;
36 : static int gdrawable_inited = false;
37 :
38 : static GResInfo gdrawable_ri = {
39 : NULL, &ggadget_ri, NULL,NULL,
40 : &gdrawable_box,
41 : NULL,
42 : NULL,
43 : NULL,
44 : N_("Drawing Area"),
45 : N_("A canvas (sub-window) wrapped up in a gadget, for drawing"),
46 : "GDrawable",
47 : "Gdraw",
48 : false,
49 : omf_border_width|omf_padding|omf_border_type,
50 : NULL,
51 : GBOX_EMPTY,
52 : NULL,
53 : NULL,
54 : NULL
55 : };
56 :
57 0 : static void GDrawableInit() {
58 :
59 0 : GGadgetInit();
60 0 : _GGadgetCopyDefaultBox(&gdrawable_box);
61 0 : gdrawable_box.border_width = gdrawable_box.padding = 0;
62 0 : gdrawable_box.border_type = bt_none;
63 0 : gdrawable_font = _GGadgetInitDefaultBox("GDrawable.",&gdrawable_box,NULL);
64 0 : gdrawable_inited = true;
65 0 : }
66 :
67 0 : static int gdrawable_expose(GWindow pixmap, GGadget *g, GEvent *event) {
68 : GRect old;
69 :
70 0 : if ( g->state == gs_invisible )
71 0 : return( false );
72 :
73 0 : GDrawPushClip(pixmap,&g->r,&old);
74 0 : GBoxDrawBorder(pixmap,&g->r,g->box,g->state,false);
75 :
76 0 : GDrawPopClip(pixmap,&old);
77 0 : return( true );
78 : }
79 :
80 0 : static int gdrawable_mouse(GGadget *g, GEvent *event) {
81 0 : return( event->type==et_mousedown || event->type==et_mouseup );
82 : }
83 :
84 0 : static int gdrawable_key(GGadget *g, GEvent *event) {
85 0 : return(false);
86 : }
87 :
88 0 : static void gdrawable_redraw(GGadget *g ) {
89 0 : GDrawable *gd = (GDrawable *) g;
90 0 : if ( gd->gw!=NULL )
91 0 : GDrawRequestExpose(gd->gw,NULL,true);
92 0 : _ggadget_redraw(g);
93 0 : }
94 :
95 0 : static void gdrawable_move(GGadget *g, int32 x, int32 y) {
96 0 : GDrawable *gd = (GDrawable *) g;
97 :
98 0 : if ( gd->gw!=NULL )
99 0 : GDrawMove(gd->gw,x+(g->inner.x-g->r.x),y+(g->inner.y-g->r.y));
100 0 : _ggadget_move(g,x,y);
101 0 : }
102 :
103 0 : static void gdrawable_resize(GGadget *g, int32 width, int32 height ) {
104 0 : GDrawable *gd = (GDrawable *) g;
105 0 : int bp = GBoxBorderWidth(g->base,g->box);
106 :
107 0 : if ( gd->gw!=NULL )
108 0 : GDrawResize(gd->gw,width - 2*bp, height - 2*bp);
109 0 : _ggadget_resize(g,width, height);
110 0 : }
111 :
112 0 : static void gdrawable_setvisible(GGadget *g, int visible ) {
113 0 : GDrawable *gd = (GDrawable *) g;
114 :
115 0 : if ( gd->gw!=NULL )
116 0 : GDrawSetVisible(gd->gw,visible);
117 0 : _ggadget_setvisible(g,visible);
118 0 : }
119 :
120 0 : static void gdrawable_destroy(GGadget *g) {
121 0 : GDrawable *gd = (GDrawable *) g;
122 :
123 0 : if ( gd->gw!=NULL ) {
124 0 : GDrawSetUserData(gd->gw,NULL);
125 0 : GDrawDestroyWindow(gd->gw);
126 : }
127 :
128 0 : _ggadget_destroy(g);
129 0 : }
130 :
131 0 : static void GDrawableGetDesiredSize(GGadget *g, GRect *outer, GRect *inner) {
132 0 : int bp = GBoxBorderWidth(g->base,g->box);
133 :
134 0 : if ( outer!=NULL ) {
135 0 : *outer = g->r;
136 0 : outer->width = g->desired_width; outer->height = g->desired_height;
137 : }
138 0 : if ( inner!=NULL ) {
139 0 : *inner = g->inner;
140 0 : inner->width = g->desired_width-2*bp; inner->height = g->desired_height-2*bp;
141 : }
142 0 : }
143 :
144 0 : static int gdrawable_FillsWindow(GGadget *g) {
145 0 : return( g->prev==NULL && _GWidgetGetGadgets(g->base)==g );
146 : }
147 :
148 : struct gfuncs gdrawable_funcs = {
149 : 0,
150 : sizeof(struct gfuncs),
151 :
152 : gdrawable_expose,
153 : gdrawable_mouse,
154 : gdrawable_key,
155 : NULL,
156 : NULL,
157 : NULL,
158 : NULL,
159 :
160 : gdrawable_redraw,
161 : gdrawable_move,
162 : gdrawable_resize,
163 : gdrawable_setvisible,
164 : _ggadget_setenabled,
165 : _ggadget_getsize,
166 : _ggadget_getinnersize,
167 :
168 : gdrawable_destroy,
169 :
170 : NULL,
171 : NULL,
172 : NULL,
173 : NULL,
174 : NULL,
175 : NULL,
176 : NULL,
177 :
178 : NULL,
179 : NULL,
180 : NULL,
181 : NULL,
182 : NULL,
183 : NULL,
184 : NULL,
185 : NULL,
186 : NULL,
187 : NULL,
188 : NULL,
189 :
190 : GDrawableGetDesiredSize,
191 : _ggadget_setDesiredSize,
192 : gdrawable_FillsWindow,
193 : NULL
194 : };
195 :
196 0 : static int drawable_e_h(GWindow pixmap, GEvent *event) {
197 0 : GWindow gw = event->type==et_expose ? event->w : pixmap;
198 0 : GGadget *g = _GWidgetGetGadgets(GDrawGetParentWindow(gw));
199 0 : GDrawable *gdr = NULL;
200 :
201 : /* Figure out our ggadget */
202 0 : while ( g!=NULL ) {
203 0 : if ( g->funcs == &gdrawable_funcs && ((GDrawable *) g)->gw==gw ) {
204 0 : gdr = (GDrawable *) g;
205 0 : break;
206 : }
207 0 : g = g->prev;
208 : }
209 0 : if ( gdr==NULL )
210 0 : return( false );
211 0 : if ( event->type == et_destroy ) {
212 0 : gdr->gw = NULL;
213 : }
214 0 : if ( gdr->e_h!=NULL )
215 0 : return( (gdr->e_h)(pixmap,event));
216 :
217 0 : return( false );
218 : }
219 :
220 0 : GGadget *GDrawableCreate(struct gwindow *base, GGadgetData *gd,void *data) {
221 0 : GDrawable *gdr = calloc(1,sizeof(GTabSet));
222 : int bp;
223 : GRect r;
224 : GWindowAttrs childattrs;
225 :
226 0 : if ( !gdrawable_inited )
227 0 : GDrawableInit();
228 0 : gdr->g.funcs = &gdrawable_funcs;
229 0 : _GGadget_Create(&gdr->g,base,gd,data,&gdrawable_box);
230 :
231 0 : gdr->g.takes_input = false; gdr->g.takes_keyboard = false; gdr->g.focusable = false;
232 :
233 0 : GDrawGetSize(base,&r);
234 0 : if ( gd->pos.x <= 0 )
235 0 : gdr->g.r.x = GDrawPointsToPixels(base,2);
236 0 : if ( gd->pos.y <= 0 )
237 0 : gdr->g.r.y = GDrawPointsToPixels(base,2);
238 0 : if ( gd->pos.width<=0 )
239 0 : gdr->g.r.width = r.width - gdr->g.r.x - GDrawPointsToPixels(base,2);
240 0 : if ( gd->pos.height<=0 ) {
241 0 : gdr->g.r.height = r.height - gdr->g.r.y - GDrawPointsToPixels(base,26);
242 : }
243 :
244 0 : bp = GBoxBorderWidth(base,gdr->g.box);
245 0 : gdr->g.inner = gdr->g.r;
246 0 : gdr->g.inner.x += bp; gdr->g.inner.width -= 2*bp;
247 0 : gdr->g.inner.y += bp; gdr->g.inner.height -= 2*bp;
248 :
249 0 : gdr->g.desired_width = gdr->g.r.width;
250 0 : gdr->g.desired_height = gdr->g.r.height;
251 0 : gdr->e_h = gd->u.drawable_e_h;
252 :
253 0 : memset(&childattrs,0,sizeof(childattrs));
254 0 : childattrs.mask = wam_events|wam_backcol;
255 0 : childattrs.event_masks = -1;
256 0 : childattrs.background_color = gdr->g.box->main_background;
257 :
258 0 : if ( !(gd->flags&gg_tabset_nowindow) ) {
259 0 : gdr->gw = GWidgetCreateSubWindow(base,&gdr->g.inner,drawable_e_h,GDrawGetUserData(base),&childattrs);
260 0 : if ( gd->flags&gg_visible )
261 0 : GDrawSetVisible(gdr->gw,true);
262 : }
263 :
264 0 : if ( gd->flags & gg_group_end )
265 0 : _GGadgetCloseGroup(&gdr->g);
266 :
267 0 : return( &gdr->g );
268 : }
269 :
270 0 : GWindow GDrawableGetWindow(GGadget *g) {
271 0 : GDrawable *gd = (GDrawable *) g;
272 0 : return( gd->gw );
273 : }
274 :
275 0 : GResInfo *_GDrawableRIHead(void) {
276 :
277 0 : if ( !gdrawable_inited )
278 0 : GDrawableInit();
279 0 : return( &gdrawable_ri );
280 : }
|