1 /* Copyright (C) 2000-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 
28 #include <fontforge-config.h>
29 
30 #include "gdraw.h"
31 #include "ggadgetP.h"
32 #include "gresource.h"
33 
34 GBox _GGroup_LineBox = GBOX_EMPTY; /* Don't initialize here */
35 static GBox group_box = GBOX_EMPTY; /* Don't initialize here */
36 static int ggroup_inited = false;
37 
38 static GGadgetCreateData gline_gcd[] = {
39     { GLineCreate, { { 0, 0, 100, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { NULL }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
40 };
41 static GGadgetCreateData *larray[] = { GCD_Glue, &gline_gcd[0], GCD_Glue, NULL, NULL };
42 static GGadgetCreateData linebox =
43     { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) larray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
44 GResInfo gline_ri = {
45     NULL, &ggadget_ri, NULL, NULL,
46     &_GGroup_LineBox,
47     NULL,
48     &linebox,
49     NULL,
50     N_("Line"),
51     N_("A separator line drawn across a dialog or in a menu"),
52     "GLine",
53     "Gdraw",
54     false,
55     omf_border_type|omf_border_shape|omf_padding,
56     NULL,
57     GBOX_EMPTY,
58     NULL,
59     NULL,
60     NULL
61 };
62 
_GGroup_Init(void)63 void _GGroup_Init(void) {
64     if ( ggroup_inited )
65 return;
66     _GGadgetCopyDefaultBox(&_GGroup_LineBox);
67     _GGadgetCopyDefaultBox(&group_box);
68     group_box.border_type = _GGroup_LineBox.border_type = bt_engraved;
69     group_box.border_shape = _GGroup_LineBox.border_shape = bs_rect;
70     group_box.padding = _GGroup_LineBox.padding = 0;
71     /*group_box.flags = _GGroup_LineBox.flags = 0;*/
72     group_box.main_background = COLOR_TRANSPARENT;
73     group_box.disabled_background = COLOR_TRANSPARENT;
74     _GGadgetInitDefaultBox("GLine.",&_GGroup_LineBox,NULL);
75     _GGadgetInitDefaultBox("GGroup.",&group_box,NULL);
76     ggroup_inited = true;
77 }
78 
ggroup_expose(GWindow pixmap,GGadget * g,GEvent * event)79 static int ggroup_expose(GWindow pixmap, GGadget *g, GEvent *event) {
80     GRect old1, border;
81 
82     if ( g->state == gs_invisible )
83 return( false );
84 
85     GDrawPushClip(pixmap,&g->r,&old1);
86     /* Background should be transpearant */
87     /*GBoxDrawBackground(pixmap,&g->r,g->box, g->state,false);*/
88     border = g->r;
89     if ( g->prevlabel ) {
90 	int off = (g->prev->r.height-GBoxBorderWidth(g->base,g->box))/2;
91 	border.y += off; border.height -= off;
92     }
93     GBoxDrawBorder(pixmap,&border,g->box,g->state,false);
94 
95     GDrawPopClip(pixmap,&old1);
96 return( true );
97 }
98 
gline_expose(GWindow pixmap,GGadget * g,GEvent * event)99 static int gline_expose(GWindow pixmap, GGadget *g, GEvent *event) {
100     GRect old1;
101 
102     if ( g->state == gs_invisible )
103 return( false );
104 
105     GDrawPushClip(pixmap,&g->r,&old1);
106     if ( g->vert )
107 	GBoxDrawVLine(pixmap,&g->r,g->box);
108     else
109 	GBoxDrawHLine(pixmap,&g->r,g->box);
110     GDrawPopClip(pixmap,&old1);
111 return( true );
112 }
113 
GGroupGetDesiredSize(GGadget * g,GRect * outer,GRect * inner)114 static void GGroupGetDesiredSize(GGadget *g, GRect *outer, GRect *inner) {
115     if ( outer!=NULL ) {
116 	int bp = GBoxBorderWidth(g->base,g->box);
117 	outer->x = outer->y = 0;
118 	outer->width = outer->height = 2*bp+2;
119 	if ( g->desired_width>0 ) outer->width = g->desired_width;
120 	if ( g->desired_height>0 ) outer->height = g->desired_height;
121     }
122     if ( inner!=NULL ) {
123 	inner->x = inner->y = 0;
124 	inner->width = inner->height = 1;
125     }
126 }
127 
128 struct gfuncs gline_funcs = {
129     0,
130     sizeof(struct gfuncs),
131 
132     gline_expose,
133     _ggadget_noop,
134     _ggadget_noop,
135     NULL,
136     NULL,
137     NULL,
138     NULL,
139 
140     _ggadget_redraw,
141     _ggadget_move,
142     _ggadget_resize,
143     _ggadget_setvisible,
144     _ggadget_setenabled,
145     _ggadget_getsize,
146     _ggadget_getinnersize,
147 
148     _ggadget_destroy,
149 
150     NULL,
151     NULL,
152     NULL,
153     NULL,
154     NULL,
155 
156     NULL,
157     NULL,
158 
159     NULL,
160     NULL,
161     NULL,
162     NULL,
163     NULL,
164     NULL,
165     NULL,
166     NULL,
167     NULL,
168     NULL,
169     NULL,
170 
171     GGroupGetDesiredSize,
172     _ggadget_setDesiredSize,
173     NULL,
174     NULL
175 };
176 
177 struct gfuncs ggroup_funcs = {
178     0,
179     sizeof(struct gfuncs),
180 
181     ggroup_expose,
182     _ggadget_noop,
183     _ggadget_noop,
184     NULL,
185     NULL,
186     NULL,
187     NULL,
188 
189     _ggadget_redraw,
190     _ggadget_move,
191     _ggadget_resize,
192     _ggadget_setvisible,
193     _ggadget_setenabled,
194     _ggadget_getsize,
195     _ggadget_getinnersize,
196 
197     _ggadget_destroy,
198 
199     NULL,
200     NULL,
201     NULL,
202     NULL,
203     NULL,
204 
205     NULL,
206     NULL,
207 
208     NULL,
209     NULL,
210     NULL,
211     NULL,
212     NULL,
213     NULL,
214     NULL,
215     NULL,
216     NULL,
217     NULL,
218     NULL,
219 
220     GGroupGetDesiredSize,
221     _ggadget_setDesiredSize,
222     NULL,
223     NULL
224 };
225 
GLineFit(GGadget * g)226 static void GLineFit(GGadget *g) {
227     int bp = GBoxBorderWidth(g->base,g->box);
228 
229     if ( g->r.width==0 && !g->vert ) {
230 	GRect size;
231 	GDrawGetSize(g->base,&size);
232 	g->r.width = size.width - g->r.x - GDrawPointsToPixels(g->base,_GGadget_Skip);
233     }
234     if ( g->r.height==0 && !g->vert )
235 	g->r.height = bp;
236     if ( g->r.width==0 && g->vert )
237 	g->r.width = bp;
238     g->inner = g->r;
239     g->inner.width = g->inner.height = 0;
240 }
241 
GGroupFit(GGadget * g)242 static void GGroupFit(GGadget *g) {
243     int bp = GBoxBorderWidth(g->base,g->box);
244 
245     if ( g->r.width==0 || g->r.height==0 )
246 	g->opengroup = true;
247     g->inner = g->r;
248     g->inner.x += bp;
249     if ( g->prevlabel )
250 	g->inner.y += (g->prev->r.height-bp)/2 + bp;
251     else
252 	g->inner.y += bp;
253     if ( g->r.width != 0 )
254 	g->inner.width = g->r.width - 2*bp;
255     if ( g->r.height != 0 )
256 	g->inner.height = g->r.y + g->r.height - bp - g->inner.y;
257 }
258 
GLineCreate(struct gwindow * base,GGadgetData * gd,void * data)259 GGadget *GLineCreate(struct gwindow *base, GGadgetData *gd,void *data) {
260     GGadget *g = calloc(1,sizeof(GLine));
261 
262     if ( !ggroup_inited )
263 	_GGroup_Init();
264     g->funcs = &gline_funcs;
265     _GGadget_Create(g,base,gd,data,&_GGroup_LineBox);
266     if ( gd->flags & gg_line_vert )
267 	g->vert = true;
268 
269     GLineFit(g);
270     _GGadget_FinalPosition(g,base,gd);
271 return( g );
272 }
273 
GGroupCreate(struct gwindow * base,GGadgetData * gd,void * data)274 GGadget *GGroupCreate(struct gwindow *base, GGadgetData *gd,void *data) {
275     GGadget *g = calloc(1,sizeof(GGroup));
276 
277     if ( !ggroup_inited )
278 	_GGroup_Init();
279     g->funcs = &ggroup_funcs;
280     _GGadget_Create(g,base,gd,data,&group_box);
281 
282     if ( (gd->flags&gg_group_prevlabel) && g->prev!=NULL )
283 	g->prevlabel = true;
284     if ( g->prevlabel && gd->pos.x==0 )
285 	g->r.x = g->prev->r.x - GDrawPointsToPixels(base,_GGadget_Skip);
286     GGroupFit(g);
287     _GGadget_FinalPosition(g,base,gd);
288 return( g );
289 }
290 
_GLineRIHead(void)291 GResInfo *_GLineRIHead(void) {
292 
293     _GGroup_Init();
294 return( &gline_ri );
295 }
296