1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/tdgtbrow.c,v 1.7 2011/05/16 16:22:00 william Exp $
19 */
20
21 #define _INCLUDE_FROM_TDGTBROW_C_
22
23 #include "tgifdefs.h"
24 #include "patchlvl.h"
25 #include "tidget.h"
26
27 #include "menu.e"
28 #include "msg.e"
29 #include "raster.e"
30 #include "rect.e"
31 #include "setup.e"
32 #include "tdgtbrow.e"
33 #include "tdgtbtn.e"
34 #include "tidget.e"
35 #include "util.e"
36
37 static void RedrawTdgtBtnRow ARGS_DECL((TidgetInfo *pti));
38 static int TdgtBtnRowEventHandler ARGS_DECL((TidgetInfo *pti, XEvent *input,
39 TidgetInfo *handling_pti));
40 static int IsTdgtBtnRowEvent ARGS_DECL((TidgetInfo *pti, XEvent *input,
41 TidgetInfo **ppti_handler_tidget_return));
42 static void DestroyTdgtBtnRow ARGS_DECL((TidgetInfo *pti));
43 static void MapTdgtBtnRow ARGS_DECL((TidgetInfo *pti));
44 static void TdgtBtnRowMoveResize ARGS_DECL((TidgetInfo *pti, int x, int y,
45 int w, int h));
46 static int TdgtBtnRowSendCmd ARGS_DECL((TidgetInfo *pti, int cmd_type,
47 int cmd_arg, void *pv_cmd_userdata));
48
49 /* --------------------- Utility Functions --------------------- */
50
51 static
GetContentWH(pTdgtBtnRow,pn_content_w,pn_content_h)52 void GetContentWH(pTdgtBtnRow, pn_content_w, pn_content_h)
53 TdgtBtnRow *pTdgtBtnRow;
54 int *pn_content_w, *pn_content_h;
55 {
56 int w=0, h=0;
57
58 if (ListLength(&pTdgtBtnRow->pti->tci.clist) > 0) {
59 CVListElem *pElem=NULL;
60
61 for (pElem=ListFirst(&pTdgtBtnRow->pti->tci.clist); pElem != NULL;
62 pElem=ListNext(&pTdgtBtnRow->pti->tci.clist, pElem)) {
63 TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
64
65 w += pti->tci.win_info.w + pTdgtBtnRow->h_gap;
66 if (pti->tci.win_info.h > h) {
67 h = pti->tci.win_info.h;
68 }
69 }
70 w -= pTdgtBtnRow->h_gap;
71 }
72 if (pn_content_w != NULL) *pn_content_w = w;
73 if (pn_content_h != NULL) *pn_content_h = h;
74 }
75
76 /* --------------------- RedrawTdgtBtnRow() --------------------- */
77
78 static
RedrawTdgtBtnRow(pti)79 void RedrawTdgtBtnRow(pti)
80 TidgetInfo *pti;
81 {
82 TdgtBtnRow *pTdgtBtnRow=(TdgtBtnRow*)(pti->tidget);
83 CVListElem *pElem=NULL;
84
85 XClearWindow(mainDisplay, pTdgtBtnRow->pti->tci.win);
86
87 if (threeDLook) {
88 struct BBRec bbox;
89
90 SetBBRec(&bbox, 0, 0, pTdgtBtnRow->pti->tci.win_info.w,
91 pTdgtBtnRow->pti->tci.win_info.h);
92 switch (pTdgtBtnRow->pti->tci.state) {
93 case TGBS_NORMAL: break;
94 default:
95 TgDrawThreeDButton(mainDisplay, pTdgtBtnRow->pti->tci.win,
96 gTidgetManager.gc, &bbox, pTdgtBtnRow->pti->tci.state, 2, TRUE);
97 TidgetManagerResetGC();
98 break;
99 }
100 } else {
101 /*
102 * XDrawRectangle(mainDisplay, pTdgtBtnRow->pti->tci.win,
103 * gTidgetManager.gc, 0, 0, pTdgtBtnRow->pti->tci.win_info.w,
104 * pTdgtBtnRow->pti->tci.win_info.h);
105 */
106 }
107 for (pElem=ListFirst(&pTdgtBtnRow->pti->tci.clist); pElem != NULL;
108 pElem=ListNext(&pTdgtBtnRow->pti->tci.clist, pElem)) {
109 TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
110
111 if (pti != NULL && pti->tidget != NULL) {
112 RedrawTidget(pti);
113 }
114 }
115 }
116
117 /* --------------------- TdgtBtnRowEventHandler() --------------------- */
118
119 static
TdgtBtnRowEventHandler(pti,input,handling_pti)120 int TdgtBtnRowEventHandler(pti, input, handling_pti)
121 TidgetInfo *pti, *handling_pti;
122 XEvent *input;
123 {
124 TdgtBtnRow *pTdgtBtnRow=(TdgtBtnRow*)(pti->tidget);
125 CVListElem *pElem=NULL;
126
127 if (pti == handling_pti) {
128 if (input->type == Expose && input->xany.window ==
129 pTdgtBtnRow->pti->tci.win) {
130 XEvent ev;
131
132 RedrawTdgtBtnRow(pTdgtBtnRow->pti);
133 while (XCheckWindowEvent(mainDisplay, pTdgtBtnRow->pti->tci.win,
134 ExposureMask, &ev)) ;
135 }
136 }
137 for (pElem=ListFirst(&pTdgtBtnRow->pti->tci.clist); pElem != NULL;
138 pElem=ListNext(&pTdgtBtnRow->pti->tci.clist, pElem)) {
139 TidgetInfo *child_pti=(TidgetInfo*)(pElem->obj);
140
141 if (TidgetEventHandler(child_pti, input, handling_pti)) {
142 return TRUE;
143 }
144 }
145 return FALSE;
146 }
147
148 /* --------------------- IsTdgtBtnRowEvent() --------------------- */
149
150 static
IsTdgtBtnRowEvent(pti,input,ppti_handler_tidget_return)151 int IsTdgtBtnRowEvent(pti, input, ppti_handler_tidget_return)
152 TidgetInfo *pti, **ppti_handler_tidget_return;
153 XEvent *input;
154 {
155 TdgtBtnRow *pTdgtBtnRow=(TdgtBtnRow*)(pti->tidget);
156 CVListElem *pElem=NULL;
157
158 if (input->xany.window == pTdgtBtnRow->pti->tci.win) return TRUE;
159
160 for (pElem=ListFirst(&pTdgtBtnRow->pti->tci.clist); pElem != NULL;
161 pElem=ListNext(&pTdgtBtnRow->pti->tci.clist, pElem)) {
162 TidgetInfo *child_pti=(TidgetInfo*)(pElem->obj);
163
164 if (IsTidgetEvent(child_pti, input, ppti_handler_tidget_return)) {
165 return TRUE;
166 }
167 }
168 return FALSE;
169 }
170
171 /* --------------------- DestroyTdgtBtnRow() --------------------- */
172
173 static
DestroyTdgtBtnRow(pti)174 void DestroyTdgtBtnRow(pti)
175 TidgetInfo *pti;
176 {
177 TdgtBtnRow *pTdgtBtnRow=(TdgtBtnRow*)(pti->tidget);
178
179 TdgtBtnRowReset(pTdgtBtnRow);
180
181 free(pTdgtBtnRow);
182 }
183
184 /* --------------------- MapTdgtBtnRow() --------------------- */
185
186 static
MapTdgtBtnRow(pti)187 void MapTdgtBtnRow(pti)
188 TidgetInfo *pti;
189 {
190 TdgtBtnRow *pTdgtBtnRow=(TdgtBtnRow*)(pti->tidget);
191
192 CVListElem *pElem=NULL;
193
194 #ifdef MAPBEFORESELECT
195 XMapWindow(mainDisplay, pTdgtBtnRow->pti->tci.win);
196 XSelectInput(mainDisplay, pTdgtBtnRow->pti->tci.win,
197 ButtonReleaseMask | ButtonPressMask | KeyPressMask | ExposureMask |
198 EnterWindowMask | LeaveWindowMask);
199 #else
200 XSelectInput(mainDisplay, pTdgtBtnRow->pti->tci.win,
201 ButtonReleaseMask | ButtonPressMask | KeyPressMask | ExposureMask |
202 EnterWindowMask | LeaveWindowMask);
203 XMapWindow(mainDisplay, pTdgtBtnRow->pti->tci.win);
204 #endif
205 for (pElem=ListFirst(&pTdgtBtnRow->pti->tci.clist); pElem != NULL;
206 pElem=ListNext(&pTdgtBtnRow->pti->tci.clist, pElem)) {
207 TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
208
209 if (pti != NULL) {
210 MapTidget(pti);
211 }
212 }
213 }
214
215 /* --------------------- TdgtBtnRowMoveResize() --------------------- */
216
217 static
TdgtBtnRowMoveResize(pti,x,y,w,h)218 void TdgtBtnRowMoveResize(pti, x, y, w, h)
219 TidgetInfo *pti;
220 int x, y, w, h;
221 {
222 TdgtBtnRow *pTdgtBtnRow=(TdgtBtnRow*)(pti->tidget);
223
224 /* there should be no need to resize a button */
225 pTdgtBtnRow->pti->tci.win_info.x = x;
226 pTdgtBtnRow->pti->tci.win_info.y = y;
227 pTdgtBtnRow->pti->tci.win_info.w = w;
228 pTdgtBtnRow->pti->tci.win_info.h = h;
229 XMoveResizeWindow(mainDisplay, pTdgtBtnRow->pti->tci.win, x, y, w, h);
230
231 if (ListLength(&pTdgtBtnRow->pti->tci.clist) > 0) {
232 int x=0;
233 CVListElem *pElem=NULL;
234
235 switch (pTdgtBtnRow->just) {
236 case JUST_L: x = windowPadding+pti->tci.h_pad; break;
237 case JUST_C: x = ((w-pTdgtBtnRow->content_w)>>1); break;
238 case JUST_R:
239 x = w-pTdgtBtnRow->content_w-windowPadding-pti->tci.h_pad;
240 break;
241 }
242 for (pElem=ListFirst(&pTdgtBtnRow->pti->tci.clist); pElem != NULL;
243 pElem=ListNext(&pTdgtBtnRow->pti->tci.clist, pElem)) {
244 TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
245
246 TidgetMoveResize(pti, x, pti->tci.win_info.y, pti->tci.win_info.w,
247 pti->tci.win_info.h);
248 x += pti->tci.win_info.w + pTdgtBtnRow->h_gap;
249 }
250 }
251 }
252
253 /* --------------------- TdgtBtnRowSendCmd() --------------------- */
254
255 static
TdgtBtnRowSendCmd(pti,cmd_type,cmd_arg,pv_cmd_userdata)256 int TdgtBtnRowSendCmd(pti, cmd_type, cmd_arg, pv_cmd_userdata)
257 TidgetInfo *pti;
258 int cmd_type, cmd_arg;
259 void *pv_cmd_userdata;
260 {
261 TdgtBtnRow *pTdgtBtnRow=(TdgtBtnRow*)(pti->tidget);
262
263 if (pTdgtBtnRow != NULL) {
264 }
265 return FALSE;
266 }
267
268 /* --------------------- TdgtBtnRowReset() --------------------- */
269
TdgtBtnRowReset(pTdgtBtnRow)270 void TdgtBtnRowReset(pTdgtBtnRow)
271 TdgtBtnRow *pTdgtBtnRow;
272 {
273 CVListElem *pElem=NULL;
274
275 for (pElem=ListFirst(&pTdgtBtnRow->pti->tci.clist); pElem != NULL;
276 pElem=ListNext(&pTdgtBtnRow->pti->tci.clist, pElem)) {
277 TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
278
279 DestroyTidget(&pti);
280 }
281 ListUnlinkAll(&pTdgtBtnRow->pti->tci.clist);
282 CVListInit(&pTdgtBtnRow->pti->tci.clist);
283 }
284
285 /* --------------------- CreateTdgtBtnRow() --------------------- */
286
287 static
TdgtBtnRowCalcGeom(pTdgtBtnRow,pn_content_w,pn_content_h)288 void TdgtBtnRowCalcGeom(pTdgtBtnRow, pn_content_w, pn_content_h)
289 TdgtBtnRow *pTdgtBtnRow;
290 int *pn_content_w, *pn_content_h;
291 {
292 int btn_w=0, btn_h=0;
293
294 if (pTdgtBtnRow != NULL) {
295 }
296 CalcTdgtBtnDim("Ok", 8, TDGTBTN_DEF_H_PAD, TDGTBTN_DEF_V_PAD, &btn_w,
297 &btn_h);
298
299 if (pn_content_w != NULL) *pn_content_w = btn_w;
300 if (pn_content_h != NULL) *pn_content_h = btn_h;
301 }
302
CreateTdgtBtnRow(parent_win,parent_tidgetinfo,ctl_id,x,y,h_pad,v_pad,state,h_gap,just)303 TdgtBtnRow *CreateTdgtBtnRow(parent_win, parent_tidgetinfo, ctl_id, x, y, h_pad,
304 v_pad, state, h_gap, just)
305 Window parent_win;
306 TidgetInfo *parent_tidgetinfo;
307 int ctl_id, x, y, h_pad, v_pad, state, h_gap, just;
308 {
309 int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel), w=0, h=0;
310 int content_w=0, content_h=0;
311 TdgtBtnRow *pTdgtBtnRow=NULL;
312
313 TdgtBtnRowCalcGeom(NULL, &content_w, &content_h);
314 w = content_w + (windowPadding<<1) + (h_pad<<1);
315 h = content_h + (windowPadding<<1) + (v_pad<<1);
316
317 pTdgtBtnRow = (TdgtBtnRow*)malloc(sizeof(TdgtBtnRow));
318 if (pTdgtBtnRow == NULL) FailAllocMessage();
319 memset(pTdgtBtnRow, 0, sizeof(TdgtBtnRow));
320
321 pTdgtBtnRow->pti = NewTidgetInfo(parent_tidgetinfo, TIDGET_TYPE_BROW,
322 pTdgtBtnRow, ctl_id, NULL);
323 if ((pTdgtBtnRow->pti->tci.win=XCreateSimpleWindow(mainDisplay, parent_win,
324 x, y, w, h, brdrW, myBorderPixel, bg_pixel)) == 0) {
325 FailToCreateWindowMessage("CreateTdgtBtnRow()", NULL, TRUE);
326 }
327 XSelectInput(mainDisplay, pTdgtBtnRow->pti->tci.win,
328 ButtonReleaseMask | ButtonPressMask | KeyPressMask | ExposureMask |
329 EnterWindowMask | LeaveWindowMask);
330 SetTidgetInfoBasic(pTdgtBtnRow->pti, TIDGET_TYPE_BROW, pTdgtBtnRow,
331 parent_win, x, y, w, h, h_pad, v_pad, state, NULL);
332 TidgetCanHaveChildren(pTdgtBtnRow->pti, TRUE);
333 TidgetSetCallbacks(pTdgtBtnRow->pti,
334 RedrawTdgtBtnRow, TdgtBtnRowEventHandler, IsTdgtBtnRowEvent,
335 DestroyTdgtBtnRow, MapTdgtBtnRow, TdgtBtnRowMoveResize,
336 TdgtBtnRowSendCmd);
337
338 pTdgtBtnRow->client_area.x = windowPadding + h_pad;
339 pTdgtBtnRow->client_area.y = windowPadding + v_pad;
340 pTdgtBtnRow->client_area.w = w-(windowPadding<<1)-(h_pad<<1);
341 pTdgtBtnRow->client_area.h = h-(windowPadding<<1)-(v_pad<<1);
342
343 pTdgtBtnRow->content_w = content_w;
344 pTdgtBtnRow->content_h = content_h;
345 pTdgtBtnRow->h_gap = h_gap;
346 pTdgtBtnRow->just = just;
347
348 return pTdgtBtnRow;
349 }
350
351 /* --------------------- TdgtBtnRowAddBtn() --------------------- */
352
TdgtBtnRowAddBtn(pTdgtBtnRow,pTdgtBtn)353 int TdgtBtnRowAddBtn(pTdgtBtnRow, pTdgtBtn)
354 TdgtBtnRow *pTdgtBtnRow;
355 TdgtBtn *pTdgtBtn;
356 {
357 int x=0, content_w=0, content_h=0;
358 int this_btn_w=pTdgtBtn->pti->tci.win_info.w;
359 int this_btn_h=pTdgtBtn->pti->tci.win_info.h;
360
361 GetContentWH(pTdgtBtnRow, &content_w, &content_h);
362 if (this_btn_h > content_h) content_h = this_btn_h;
363 if (content_w != 0) {
364 x = content_w+pTdgtBtnRow->h_gap;
365 }
366 content_w = x+this_btn_w;
367
368 pTdgtBtnRow->content_w = content_w;
369 pTdgtBtnRow->content_h = content_h;
370
371 /*
372 * Set the client_area to be as small as possible -- just big enough
373 * to include all the buttons.
374 */
375 pTdgtBtnRow->client_area.w = content_w;
376 pTdgtBtnRow->client_area.h = content_h;
377
378 pTdgtBtnRow->pti->tci.win_info.w =
379 content_w + (windowPadding<<1) + ((pTdgtBtnRow->pti->tci.h_pad)<<1);
380 pTdgtBtnRow->pti->tci.win_info.h =
381 content_h + (windowPadding<<1) + ((pTdgtBtnRow->pti->tci.v_pad)<<1);
382
383 TdgtBtnRowMoveResize(pTdgtBtnRow->pti, pTdgtBtnRow->pti->tci.win_info.x,
384 pTdgtBtnRow->pti->tci.win_info.y, pTdgtBtnRow->pti->tci.win_info.w,
385 pTdgtBtnRow->pti->tci.win_info.h);
386
387 TdgtBtnRowMoveResize(pTdgtBtn->pti,
388 x+windowPadding+pTdgtBtnRow->pti->tci.h_pad,
389 windowPadding+pTdgtBtnRow->pti->tci.v_pad, this_btn_w, this_btn_h);
390
391 return ListAppend(&pTdgtBtnRow->pti->tci.clist, pTdgtBtn->pti);
392 }
393
394 /* --------------------- Init & Clean Up --------------------- */
395
InitTdgtBtnRow()396 int InitTdgtBtnRow()
397 {
398 return TRUE;
399 }
400
CleanUpTdgtBtnRow()401 void CleanUpTdgtBtnRow()
402 {
403 }
404
405