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