~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to WINGs/wtabview.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "WINGsP.h"
 
3
 
 
4
 
 
5
typedef struct W_TabView {
 
6
    W_Class widgetClass;
 
7
    W_View *view;
 
8
 
 
9
    struct W_TabViewItem **items;
 
10
    int itemCount;
 
11
    int maxItems;              /* size of items array, can be increased */
 
12
 
 
13
    int selectedItem;
 
14
    int firstVisible;
 
15
 
 
16
    int visibleTabs;
 
17
 
 
18
    WMFont *font;
 
19
 
 
20
    WMColor *lightGray;
 
21
    WMColor *tabColor;
 
22
 
 
23
    WMTabViewDelegate *delegate;
 
24
 
 
25
    short tabHeight;
 
26
 
 
27
    struct {
 
28
        WMReliefType relief:4;
 
29
        WMTitlePosition titlePosition:4;
 
30
        WMTabViewType type:2;
 
31
 
 
32
        unsigned enabled:1;
 
33
        unsigned tabbed:1;
 
34
        unsigned dontFitAll:1;
 
35
        unsigned bordered:1;
 
36
        unsigned uniformTabs:1;
 
37
    } flags;
 
38
} TabView;
 
39
 
 
40
 
 
41
typedef struct W_TabViewItem {
 
42
    WMTabView *tabView;
 
43
 
 
44
    W_View *view;
 
45
 
 
46
    char *label;
 
47
 
 
48
    short tabWidth;
 
49
    int identifier;
 
50
 
 
51
    struct {
 
52
        unsigned visible:1;
 
53
        unsigned enabled:1;
 
54
    } flags;
 
55
} W_TabViewItem;
 
56
 
 
57
 
 
58
 
 
59
 
 
60
 
 
61
 
 
62
#define DEFAULT_WIDTH   40
 
63
#define DEFAULT_HEIGHT  40
 
64
 
 
65
#define NORMAL_SIDE_OFFSET 8
 
66
#define BUTTONED_SIDE_OFFSET 15
 
67
 
 
68
 
 
69
static void destroyTabView(TabView *tPtr);
 
70
static void paintTabView(TabView *tPtr);
 
71
 
 
72
 
 
73
static void W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent);
 
74
 
 
75
static void W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect,
 
76
                        Bool enabled);
 
77
 
 
78
static void W_UnmapTabViewItem(WMTabViewItem *item);
 
79
 
 
80
static void W_MapTabViewItem(WMTabViewItem *item);
 
81
 
 
82
static WMView *W_TabViewItemView(WMTabViewItem *item);
 
83
 
 
84
static int W_TabViewItemTabWidth(WMTabViewItem *item);
 
85
 
 
86
static void W_SetTabViewItemTabWidth(WMTabViewItem *item, int width);
 
87
 
 
88
 
 
89
static void recalcTabWidth(TabView *tPtr);
 
90
static void rearrange(TabView *tPtr);
 
91
 
 
92
static void didResize(struct W_ViewDelegate*, WMView*);
 
93
 
 
94
static W_ViewDelegate delegate = {
 
95
    NULL,
 
96
    NULL,
 
97
    didResize,
 
98
    NULL,
 
99
    NULL
 
100
};
 
101
 
 
102
 
 
103
static int
 
104
positionOfTab(WMTabView *tabView, int tab)
 
105
{
 
106
    int i;
 
107
    int offs;
 
108
 
 
109
    if (tab < tabView->firstVisible)
 
110
        return -1;
 
111
 
 
112
    if (tab > tabView->firstVisible + tabView->visibleTabs)
 
113
        return -1;
 
114
 
 
115
    if (tabView->flags.dontFitAll)
 
116
        offs = BUTTONED_SIDE_OFFSET;
 
117
    else
 
118
        offs = NORMAL_SIDE_OFFSET;
 
119
 
 
120
    for (i = tabView->firstVisible; i < tab; i++)
 
121
        offs += W_TabViewItemTabWidth(tabView->items[i]) - 10;
 
122
 
 
123
    return offs;
 
124
}
 
125
 
 
126
 
 
127
static int
 
128
countVisibleTabs(TabView *tPtr, int first)
 
129
{
 
130
    int i;
 
131
    int width;
 
132
 
 
133
    if (first < 0) {
 
134
        width = W_VIEW_WIDTH(tPtr->view) - 2 * NORMAL_SIDE_OFFSET;
 
135
        first = 0;
 
136
    } else {
 
137
        width = W_VIEW_WIDTH(tPtr->view) - 2 * BUTTONED_SIDE_OFFSET;
 
138
    }
 
139
 
 
140
    for (i = first; i < tPtr->itemCount; i++) {
 
141
        width -= W_TabViewItemTabWidth(tPtr->items[i]) - 10;
 
142
        if (width <= 0) {
 
143
            return i - first;
 
144
        }
 
145
    }
 
146
    return i - first;
 
147
}
 
148
 
 
149
 
 
150
 
 
151
static void
 
152
handleEvents(XEvent *event, void *data)
 
153
{
 
154
    TabView *tPtr = (TabView*)data;
 
155
 
 
156
    CHECK_CLASS(data, WC_TabView);
 
157
 
 
158
    switch (event->type) {
 
159
    case Expose:
 
160
        if (event->xexpose.count!=0)
 
161
            break;
 
162
        paintTabView(tPtr);
 
163
        break;
 
164
 
 
165
    case ButtonPress:
 
166
        if (tPtr->flags.enabled) {
 
167
            WMTabViewItem *item = WMTabViewItemAtPoint(tPtr,
 
168
                                                       event->xbutton.x,
 
169
                                                       event->xbutton.y);
 
170
            /*if (item && !item->flags.enabled)
 
171
             break;*/
 
172
 
 
173
            if (item && item->flags.enabled) {
 
174
                WMSelectTabViewItem(tPtr, item);
 
175
            } else if (tPtr->flags.dontFitAll) {
 
176
                int redraw = 0;
 
177
                int lastVisible = tPtr->firstVisible+tPtr->visibleTabs-1;
 
178
 
 
179
                if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
 
180
                    if (tPtr->firstVisible > 0) {
 
181
                        redraw = 1;
 
182
                        tPtr->firstVisible--;
 
183
                    }
 
184
                } else if (event->xbutton.x > positionOfTab(tPtr,lastVisible)){
 
185
 
 
186
                    if (lastVisible < tPtr->itemCount-1) {
 
187
                        redraw = 1;
 
188
                        tPtr->firstVisible++;
 
189
                    }
 
190
                }
 
191
                tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
 
192
                if (redraw) {
 
193
                    paintTabView(tPtr);
 
194
                }
 
195
            }
 
196
        }
 
197
        break;
 
198
 
 
199
    case DestroyNotify:
 
200
        destroyTabView(tPtr);
 
201
        break;
 
202
    }
 
203
}
 
204
 
 
205
 
 
206
 
 
207
WMTabView*
 
208
WMCreateTabView(WMWidget *parent)
 
209
{
 
210
    TabView *tPtr;
 
211
    WMScreen *scr = WMWidgetScreen(parent);
 
212
 
 
213
    tPtr = wmalloc(sizeof(TabView));
 
214
    memset(tPtr, 0, sizeof(TabView));
 
215
 
 
216
    tPtr->widgetClass = WC_TabView;
 
217
 
 
218
    tPtr->view = W_CreateView(W_VIEW(parent));
 
219
    if (!tPtr->view) {
 
220
        wfree(tPtr);
 
221
        return NULL;
 
222
    }
 
223
    tPtr->view->self = tPtr;
 
224
    tPtr->view->delegate = &delegate;
 
225
 
 
226
    tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
 
227
    tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
 
228
 
 
229
    tPtr->font = WMRetainFont(scr->normalFont);
 
230
 
 
231
    tPtr->flags.type = WTTopTabsBevelBorder;
 
232
    tPtr->flags.bordered = 1;
 
233
    tPtr->flags.uniformTabs = 0;
 
234
    tPtr->flags.enabled = 1;
 
235
 
 
236
    WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
 
237
                         |ButtonPressMask, handleEvents, tPtr);
 
238
 
 
239
    WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
 
240
 
 
241
    tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
 
242
 
 
243
    return tPtr;
 
244
}
 
245
 
 
246
 
 
247
void
 
248
WMSetTabViewDelegate(WMTabView *tPtr, WMTabViewDelegate *delegate)
 
249
{
 
250
    tPtr->delegate = delegate;
 
251
}
 
252
 
 
253
 
 
254
WMTabViewItem*
 
255
WMAddTabViewItemWithView(WMTabView *tPtr, WMView *view, int identifier,
 
256
                         char *label)
 
257
{
 
258
    WMTabViewItem *item;
 
259
 
 
260
    item = WMCreateTabViewItemWithIdentifier(identifier);
 
261
    WMSetTabViewItemView(item, view);
 
262
    WMAddItemInTabView(tPtr, item);
 
263
    WMSetTabViewItemLabel(item, label);
 
264
 
 
265
    return item;
 
266
}
 
267
 
 
268
 
 
269
void
 
270
WMAddItemInTabView(WMTabView *tPtr, WMTabViewItem *item)
 
271
{
 
272
    WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
 
273
}
 
274
 
 
275
 
 
276
void
 
277
WMSetTabViewEnabled(WMTabView *tPtr, Bool flag)
 
278
{
 
279
    tPtr->flags.enabled = ((flag==0) ? 0 : 1);
 
280
    if (W_VIEW_REALIZED(tPtr->view))
 
281
        paintTabView(tPtr);
 
282
}
 
283
 
 
284
 
 
285
void
 
286
WMInsertItemInTabView(WMTabView *tPtr, int index, WMTabViewItem *item)
 
287
{
 
288
    wassertr(W_TabViewItemView(item) != NULL);
 
289
 
 
290
    if (tPtr->maxItems == tPtr->itemCount) {
 
291
        WMTabViewItem **items;
 
292
 
 
293
        items = wrealloc(tPtr->items,
 
294
                         sizeof(WMTabViewItem*) * (tPtr->maxItems + 10));
 
295
        memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem*) * 10);
 
296
        tPtr->items = items;
 
297
        tPtr->maxItems += 10;
 
298
    }
 
299
 
 
300
    if (index > tPtr->itemCount)
 
301
        index = tPtr->itemCount;
 
302
 
 
303
    if (index == 0 && tPtr->items[0]) {
 
304
        W_UnmapTabViewItem(tPtr->items[0]);
 
305
    }
 
306
 
 
307
    if (index < tPtr->itemCount) {
 
308
        memmove(tPtr->items + index + 1, tPtr->items + index,
 
309
                (tPtr->itemCount - index) * sizeof(WMTabViewItem*));
 
310
    }
 
311
 
 
312
    tPtr->items[index] = item;
 
313
 
 
314
    tPtr->itemCount++;
 
315
 
 
316
    recalcTabWidth(tPtr);
 
317
 
 
318
    W_SetTabViewItemParent(item, tPtr);
 
319
 
 
320
    W_UnmapTabViewItem(item);
 
321
 
 
322
    if (tPtr->flags.bordered) {
 
323
        W_ReparentView(W_TabViewItemView(item), tPtr->view, 1,
 
324
                       tPtr->tabHeight + 1);
 
325
 
 
326
        W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width - 3,
 
327
                     tPtr->view->size.height - tPtr->tabHeight - 3);
 
328
    } else {
 
329
        W_ReparentView(W_TabViewItemView(item), tPtr->view, 0,
 
330
                       tPtr->tabHeight);
 
331
 
 
332
        W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width,
 
333
                     tPtr->view->size.height - tPtr->tabHeight);
 
334
    }
 
335
 
 
336
    if (index == 0) {
 
337
        W_MapTabViewItem(item);
 
338
    }
 
339
    if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
 
340
        (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
 
341
 
 
342
    if (W_VIEW_REALIZED(tPtr->view))
 
343
        paintTabView(tPtr);
 
344
}
 
345
 
 
346
 
 
347
void
 
348
WMRemoveTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
 
349
{
 
350
    int i;
 
351
 
 
352
    for (i = 0; i < tPtr->itemCount; i++) {
 
353
        if (tPtr->items[i] == item) {
 
354
            if (i < tPtr->itemCount - 1)
 
355
                memmove(&tPtr->items[i], &tPtr->items[i + 1],
 
356
                        tPtr->itemCount - i - 1);
 
357
            else
 
358
                tPtr->items[i] = NULL;
 
359
 
 
360
            W_SetTabViewItemParent(item, NULL);
 
361
 
 
362
            tPtr->itemCount--;
 
363
            break;
 
364
        }
 
365
    }
 
366
    if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
 
367
        (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
 
368
}
 
369
 
 
370
 
 
371
 
 
372
static Bool
 
373
isInside(int x, int y, int width, int height, int px, int py)
 
374
{
 
375
    if (py >= y + height - 3 && py <= y + height
 
376
        && px >= x + py - (y + height - 3)
 
377
        && px <= x + width - (py - (y + height - 3))) {
 
378
 
 
379
        return True;
 
380
    }
 
381
    if (py >= y + 3 && py < y + height - 3
 
382
        && px >= x + 3 + ((y + 3) - py)*3/7
 
383
        && px <= x + width - 3 - ((y + 3) - py)*3/7) {
 
384
 
 
385
        return True;
 
386
    }
 
387
    if (py >= y && py < y + 3
 
388
        && px >= x + 7 + py - y
 
389
        && px <= x + width - 7 - (py - y)) {
 
390
 
 
391
        return True;
 
392
    }
 
393
    return False;
 
394
}
 
395
 
 
396
 
 
397
WMTabViewItem*
 
398
WMTabViewItemAtPoint(WMTabView *tPtr, int x, int y)
 
399
{
 
400
    int i;
 
401
    int count = tPtr->visibleTabs;
 
402
    int first = tPtr->firstVisible;
 
403
 
 
404
    if (tPtr->flags.dontFitAll) {
 
405
        i = tPtr->selectedItem - tPtr->firstVisible;
 
406
        if (i >= 0 && i < tPtr->visibleTabs
 
407
            && isInside(positionOfTab(tPtr, tPtr->selectedItem), 0,
 
408
                        W_TabViewItemTabWidth(tPtr->items[tPtr->selectedItem]),
 
409
                        tPtr->tabHeight, x, y)) {
 
410
            return tPtr->items[tPtr->selectedItem];
 
411
        }
 
412
    } else {
 
413
        i = tPtr->selectedItem;
 
414
        if (isInside(positionOfTab(tPtr, i), 0,
 
415
                     W_TabViewItemTabWidth(tPtr->items[i]),
 
416
                     tPtr->tabHeight, x, y)) {
 
417
            return tPtr->items[i];
 
418
        }
 
419
    }
 
420
 
 
421
    for (i = first; i < first + count; i++) {
 
422
        int pos;
 
423
 
 
424
        pos = positionOfTab(tPtr, i);
 
425
        if (isInside(pos, 0, W_TabViewItemTabWidth(tPtr->items[i]),
 
426
                     tPtr->tabHeight, x, y)) {
 
427
            return tPtr->items[i];
 
428
        }
 
429
    }
 
430
    return NULL;
 
431
}
 
432
 
 
433
 
 
434
void
 
435
WMSetTabViewType(WMTabView *tPtr, WMTabViewType type)
 
436
{
 
437
    tPtr->flags.type = type;
 
438
 
 
439
    if (type != WTTopTabsBevelBorder)
 
440
        tPtr->tabHeight = 0;
 
441
    else
 
442
        tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
 
443
 
 
444
    if (type == WTNoTabsNoBorder)
 
445
        tPtr->flags.bordered = 0;
 
446
    else
 
447
        tPtr->flags.bordered = 1;
 
448
 
 
449
    rearrange(tPtr);
 
450
}
 
451
 
 
452
void
 
453
WMSelectFirstTabViewItem(WMTabView *tPtr)
 
454
{
 
455
    WMSelectTabViewItemAtIndex(tPtr, 0);
 
456
}
 
457
 
 
458
 
 
459
void
 
460
WMSelectLastTabViewItem(WMTabView *tPtr)
 
461
{
 
462
    WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
 
463
}
 
464
 
 
465
 
 
466
void
 
467
WMSelectNextTabViewItem(WMTabView *tPtr)
 
468
{
 
469
    WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
 
470
}
 
471
 
 
472
 
 
473
void
 
474
WMSelectPreviousTabViewItem(WMTabView *tPtr)
 
475
{
 
476
    WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
 
477
}
 
478
 
 
479
 
 
480
WMTabViewItem*
 
481
WMGetSelectedTabViewItem(WMTabView *tPtr)
 
482
{
 
483
    return tPtr->items[tPtr->selectedItem];
 
484
}
 
485
 
 
486
 
 
487
void
 
488
WMSelectTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
 
489
{
 
490
    int i;
 
491
 
 
492
    for (i = 0; i < tPtr->itemCount; i++) {
 
493
        if (tPtr->items[i] == item) {
 
494
            WMSelectTabViewItemAtIndex(tPtr, i);
 
495
            break;
 
496
        }
 
497
    }
 
498
}
 
499
 
 
500
 
 
501
void
 
502
WMSelectTabViewItemAtIndex(WMTabView *tPtr, int index)
 
503
{
 
504
    WMTabViewItem *item;
 
505
 
 
506
    if (index == tPtr->selectedItem) {
 
507
        return;
 
508
    }
 
509
 
 
510
    if (index < 0)
 
511
        index = 0;
 
512
    else if (index >= tPtr->itemCount)
 
513
        index = tPtr->itemCount - 1;
 
514
 
 
515
    item = tPtr->items[tPtr->selectedItem];
 
516
 
 
517
    if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
 
518
        if (!(*tPtr->delegate->shouldSelectItem)(tPtr->delegate, tPtr,
 
519
                                                 tPtr->items[index]))
 
520
            return;
 
521
 
 
522
    if (tPtr->delegate && tPtr->delegate->willSelectItem)
 
523
        (*tPtr->delegate->willSelectItem)(tPtr->delegate, tPtr,
 
524
                                          tPtr->items[index]);
 
525
 
 
526
    W_UnmapTabViewItem(item);
 
527
 
 
528
 
 
529
    item = tPtr->items[index];
 
530
 
 
531
    W_MapTabViewItem(item);
 
532
 
 
533
    tPtr->selectedItem = index;
 
534
 
 
535
    if (tPtr->delegate && tPtr->delegate->didSelectItem)
 
536
        (*tPtr->delegate->didSelectItem)(tPtr->delegate, tPtr,
 
537
                                         tPtr->items[index]);
 
538
 
 
539
    paintTabView(tPtr);
 
540
}
 
541
 
 
542
 
 
543
 
 
544
static void
 
545
recalcTabWidth(TabView *tPtr)
 
546
{
 
547
    int i;
 
548
    /*int twidth = W_VIEW(tPtr)->size.width;*/
 
549
    int width;
 
550
 
 
551
    if (tPtr->flags.uniformTabs) {
 
552
        int tabWidth;
 
553
 
 
554
        tabWidth = 0;
 
555
 
 
556
        for (i = 0; i < tPtr->itemCount; i++) {
 
557
            char *str = WMGetTabViewItemLabel(tPtr->items[i]);
 
558
 
 
559
            if (str) {
 
560
                width = WMWidthOfString(tPtr->font, str, strlen(str));
 
561
                if (width > tabWidth)
 
562
                    tabWidth = width;
 
563
            }
 
564
        }
 
565
 
 
566
        tabWidth = tabWidth + 30;
 
567
 
 
568
        for (i = 0; i < tPtr->itemCount; i++)
 
569
            W_SetTabViewItemTabWidth(tPtr->items[i], tabWidth);
 
570
 
 
571
        tPtr->firstVisible = 0;
 
572
        tPtr->visibleTabs = countVisibleTabs(tPtr, -1);
 
573
        if (tPtr->visibleTabs < tPtr->itemCount)
 
574
            tPtr->flags.dontFitAll = 1;
 
575
        else
 
576
            tPtr->flags.dontFitAll = 0;
 
577
    } else {
 
578
        for (i = 0; i < tPtr->itemCount; i++) {
 
579
            char *str = WMGetTabViewItemLabel(tPtr->items[i]);
 
580
            if (!str)
 
581
                continue;
 
582
 
 
583
            width = WMWidthOfString(tPtr->font, str, strlen(str)) + 30;
 
584
 
 
585
            W_SetTabViewItemTabWidth(tPtr->items[i], width);
 
586
        }
 
587
 
 
588
        if (countVisibleTabs(tPtr, -1) < tPtr->itemCount) {
 
589
            tPtr->flags.dontFitAll = 1;
 
590
            tPtr->firstVisible = 0;
 
591
            tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
 
592
        } else {
 
593
            tPtr->flags.dontFitAll = 0;
 
594
            tPtr->firstVisible = 0;
 
595
            tPtr->visibleTabs = tPtr->itemCount;
 
596
        }
 
597
    }
 
598
}
 
599
 
 
600
 
 
601
static void
 
602
drawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
 
603
           unsigned int height)
 
604
{
 
605
    Display *dpy = scr->display;
 
606
    GC bgc = WMColorGC(scr->black);
 
607
    GC wgc = WMColorGC(scr->white);
 
608
    GC dgc = WMColorGC(scr->darkGray);
 
609
 
 
610
    XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
 
611
 
 
612
    XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
 
613
    XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
 
614
 
 
615
    XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
 
616
    XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
 
617
}
 
618
 
 
619
 
 
620
static void
 
621
drawTab(TabView *tPtr, Drawable d, int x, int y,
 
622
        unsigned width, unsigned height, Bool selected)
 
623
{
 
624
    WMScreen *scr = W_VIEW(tPtr)->screen;
 
625
    Display *dpy = scr->display;
 
626
    GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
 
627
    GC black = WMColorGC(scr->black);
 
628
    GC dark = WMColorGC(scr->darkGray);
 
629
    GC light = WMColorGC(scr->gray);
 
630
    XPoint trap[8];
 
631
 
 
632
    trap[0].x = x + (selected ? 0 : 1);
 
633
    trap[0].y = y + height - (selected ? 0 : 1);
 
634
 
 
635
    trap[1].x = x + 3;
 
636
    trap[1].y = y + height - 3;
 
637
 
 
638
    trap[2].x = x + 10 - 3;
 
639
    trap[2].y = y + 3;
 
640
 
 
641
    trap[3].x = x + 10;
 
642
    trap[3].y = y;
 
643
 
 
644
    trap[4].x = x + width - 10;
 
645
    trap[4].y = y;
 
646
 
 
647
    trap[5].x = x + width - 10 + 3;
 
648
    trap[5].y = y + 3;
 
649
 
 
650
    trap[6].x = x + width - 3;
 
651
    trap[6].y = y + height - 3;
 
652
 
 
653
    trap[7].x = x + width - (selected ? 0 : 1);
 
654
    trap[7].y = y + height - (selected ? 0 : 1);
 
655
 
 
656
    XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8,
 
657
                 Convex, CoordModeOrigin);
 
658
 
 
659
    XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
 
660
    XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
 
661
    XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
 
662
    XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
 
663
    XDrawLine(dpy, d, dark,  trap[4].x, trap[4].y, trap[5].x, trap[5].y);
 
664
    XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
 
665
    XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
 
666
 
 
667
    XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white),
 
668
              trap[0].x, trap[0].y, trap[7].x, trap[7].y);
 
669
}
 
670
 
 
671
 
 
672
static void
 
673
paintDot(TabView *tPtr, Drawable d, int x, int y)
 
674
{
 
675
    WMScreen *scr = W_VIEW(tPtr)->screen;
 
676
    Display *dpy = scr->display;
 
677
    GC white = WMColorGC(scr->white);
 
678
    GC black = WMColorGC(scr->black);
 
679
 
 
680
    XFillRectangle(dpy, d, black, x, y, 2, 2);
 
681
    XDrawPoint(dpy, d, white, x, y);
 
682
}
 
683
 
 
684
 
 
685
 
 
686
static void
 
687
paintTabView(TabView *tPtr)
 
688
{
 
689
    Pixmap buffer;
 
690
    WMScreen *scr = W_VIEW(tPtr)->screen;
 
691
    Display *dpy = scr->display;
 
692
    GC white = WMColorGC(scr->white);
 
693
    int i;
 
694
 
 
695
    if (tPtr->flags.type == WTTopTabsBevelBorder) {
 
696
        int count = tPtr->visibleTabs;
 
697
        int first = tPtr->firstVisible;
 
698
        int moreAtLeft;
 
699
        int moreAtRight;
 
700
        int selectedIsVisible;
 
701
        int ty;
 
702
        int twidth, theight;
 
703
 
 
704
        ty = 2;
 
705
        theight = tPtr->tabHeight;
 
706
 
 
707
        buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
 
708
                               W_VIEW(tPtr)->size.width, theight,
 
709
                               W_VIEW(tPtr)->screen->depth);
 
710
 
 
711
        XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
 
712
                       0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
 
713
 
 
714
        if (tPtr->flags.dontFitAll) {
 
715
            moreAtLeft = first > 0;
 
716
            moreAtRight = (first + count) < tPtr->itemCount;
 
717
            if (tPtr->selectedItem >= first
 
718
                && tPtr->selectedItem < first + count)
 
719
                selectedIsVisible = 1;
 
720
            else
 
721
                selectedIsVisible = 0;
 
722
        } else {
 
723
            moreAtLeft = 0;
 
724
            moreAtRight = 0;
 
725
            selectedIsVisible = 1;
 
726
        }
 
727
 
 
728
        if (moreAtRight) {
 
729
            drawTab(tPtr, buffer, positionOfTab(tPtr, first+count), 0,
 
730
                    W_VIEW_WIDTH(tPtr->view), theight, False);
 
731
        }
 
732
        for (i = first + count-1; i >= first; i--) {
 
733
            if (!selectedIsVisible || i != tPtr->selectedItem) {
 
734
                twidth = W_TabViewItemTabWidth(tPtr->items[i]);
 
735
 
 
736
                drawTab(tPtr, buffer, positionOfTab(tPtr, i), 0,
 
737
                        twidth, theight, False);
 
738
            }
 
739
        }
 
740
        if (moreAtLeft) {
 
741
            drawTab(tPtr, buffer, positionOfTab(tPtr, 0)-2*BUTTONED_SIDE_OFFSET,
 
742
                    0, BUTTONED_SIDE_OFFSET*4, theight, False);
 
743
        }
 
744
 
 
745
        if (selectedIsVisible) {
 
746
            int idx = tPtr->selectedItem;
 
747
 
 
748
            drawTab(tPtr, buffer, positionOfTab(tPtr, idx),
 
749
                    0, W_TabViewItemTabWidth(tPtr->items[idx]),
 
750
                    theight, True);
 
751
 
 
752
            XDrawLine(dpy, buffer, white, 0, theight - 1,
 
753
                      positionOfTab(tPtr, idx), theight - 1);
 
754
 
 
755
            XDrawLine(dpy, buffer, white,
 
756
                      positionOfTab(tPtr, idx) + W_TabViewItemTabWidth(tPtr->items[idx]),
 
757
                      tPtr->tabHeight - 1, W_VIEW_WIDTH(tPtr->view) - 1,
 
758
                      tPtr->tabHeight - 1);
 
759
        } else {
 
760
            XDrawLine(dpy, buffer, white, 0, theight - 1,
 
761
                      W_VIEW_WIDTH(tPtr->view), theight - 1);
 
762
        }
 
763
 
 
764
        for (i = 0; i < count; i++) {
 
765
            WMRect rect;
 
766
 
 
767
            rect.pos.x = 15 + positionOfTab(tPtr, first+i);
 
768
            rect.pos.y = ty;
 
769
            rect.size.width = W_TabViewItemTabWidth(tPtr->items[first+i]);
 
770
            rect.size.height = theight;
 
771
            W_DrawLabel(tPtr->items[first+i], buffer, rect,
 
772
                        tPtr->flags.enabled &&
 
773
                        tPtr->items[first+i]->flags.enabled);
 
774
        }
 
775
 
 
776
        if (moreAtLeft) {
 
777
            paintDot(tPtr, buffer, 4, 10);
 
778
            paintDot(tPtr, buffer, 7, 10);
 
779
            paintDot(tPtr, buffer, 10, 10);
 
780
        }
 
781
        if (moreAtRight) {
 
782
            int x;
 
783
 
 
784
            x = positionOfTab(tPtr, tPtr->firstVisible + tPtr->visibleTabs);
 
785
 
 
786
            x = x + (W_VIEW_WIDTH(tPtr->view) - x)/2;
 
787
            paintDot(tPtr, buffer, x + 5, 10);
 
788
            paintDot(tPtr, buffer, x + 8, 10);
 
789
            paintDot(tPtr, buffer, x + 11, 10);
 
790
        }
 
791
 
 
792
        XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
 
793
                  W_VIEW_WIDTH(tPtr->view), theight, 0, 0);
 
794
 
 
795
        XFreePixmap(dpy, buffer);
 
796
    }
 
797
    switch (tPtr->flags.type) {
 
798
    case WTTopTabsBevelBorder:
 
799
        drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
 
800
                   W_VIEW(tPtr)->size.width,
 
801
                   W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
 
802
        break;
 
803
 
 
804
    case WTNoTabsBevelBorder:
 
805
        W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
 
806
                     W_VIEW(tPtr)->size.height, WRRaised);
 
807
        break;
 
808
 
 
809
    case WTNoTabsLineBorder:
 
810
        W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
 
811
                     W_VIEW(tPtr)->size.height, WRSimple);
 
812
        break;
 
813
 
 
814
    case WTNoTabsNoBorder:
 
815
        break;
 
816
    }
 
817
}
 
818
 
 
819
 
 
820
static void
 
821
rearrange(TabView *tPtr)
 
822
{
 
823
    int i;
 
824
    int width, height;
 
825
    int bordered = tPtr->flags.bordered;
 
826
 
 
827
    recalcTabWidth(tPtr);
 
828
 
 
829
    width = tPtr->view->size.width - (bordered ? 3 : 0);
 
830
    height = tPtr->view->size.height - tPtr->tabHeight - (bordered ? 3 : 0);
 
831
 
 
832
    for (i = 0; i < tPtr->itemCount; i++) {
 
833
        W_MoveView(W_TabViewItemView(tPtr->items[i]),
 
834
                   1*bordered, tPtr->tabHeight + 1*bordered);
 
835
        W_ResizeView(W_TabViewItemView(tPtr->items[i]), width, height);
 
836
    }
 
837
    if (W_VIEW_MAPPED(tPtr->view) && W_VIEW_REALIZED(tPtr->view))
 
838
        paintTabView(tPtr);
 
839
}
 
840
 
 
841
 
 
842
static void
 
843
didResize(struct W_ViewDelegate *deleg, WMView *view)
 
844
{
 
845
    rearrange(view->self);
 
846
}
 
847
 
 
848
 
 
849
static void
 
850
destroyTabView(TabView *tPtr)
 
851
{
 
852
    int i;
 
853
 
 
854
    for (i = 0; i < tPtr->itemCount; i++) {
 
855
        WMSetTabViewItemView(tPtr->items[i], NULL);
 
856
        WMDestroyTabViewItem(tPtr->items[i]);
 
857
    }
 
858
    wfree(tPtr->items);
 
859
 
 
860
    WMReleaseColor(tPtr->lightGray);
 
861
    WMReleaseColor(tPtr->tabColor);
 
862
    WMReleaseFont(tPtr->font);
 
863
 
 
864
    wfree(tPtr);
 
865
}
 
866
 
 
867
/******************************************************************/
 
868
 
 
869
 
 
870
static void
 
871
W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent)
 
872
{
 
873
    item->tabView = parent;
 
874
}
 
875
 
 
876
 
 
877
static void
 
878
W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect, Bool enabled)
 
879
{
 
880
    WMScreen *scr = W_VIEW(item->tabView)->screen;
 
881
 
 
882
    if (!item->label)
 
883
        return;
 
884
 
 
885
    WMDrawString(scr, d, enabled ? scr->black : scr->darkGray,
 
886
                 item->tabView->font, rect.pos.x, rect.pos.y,
 
887
                 item->label, strlen(item->label));
 
888
}
 
889
 
 
890
 
 
891
static void
 
892
W_UnmapTabViewItem(WMTabViewItem *item)
 
893
{
 
894
    wassertr(item->view);
 
895
 
 
896
    W_UnmapView(item->view);
 
897
 
 
898
    item->flags.visible = 0;
 
899
}
 
900
 
 
901
 
 
902
static void
 
903
W_MapTabViewItem(WMTabViewItem *item)
 
904
{
 
905
    wassertr(item->view);
 
906
 
 
907
    W_MapView(item->view);
 
908
    W_RaiseView(item->view);
 
909
 
 
910
    item->flags.visible = 1;
 
911
}
 
912
 
 
913
 
 
914
static WMView*
 
915
W_TabViewItemView(WMTabViewItem *item)
 
916
{
 
917
    return item->view;
 
918
}
 
919
 
 
920
 
 
921
static int
 
922
W_TabViewItemTabWidth(WMTabViewItem *item)
 
923
{
 
924
    return item->tabWidth;
 
925
}
 
926
 
 
927
 
 
928
static void
 
929
W_SetTabViewItemTabWidth(WMTabViewItem *item, int width)
 
930
{
 
931
    item->tabWidth = width;
 
932
}
 
933
 
 
934
 
 
935
WMTabViewItem*
 
936
WMCreateTabViewItemWithIdentifier(int identifier)
 
937
{
 
938
    WMTabViewItem *item;
 
939
 
 
940
    item = wmalloc(sizeof(WMTabViewItem));
 
941
    memset(item, 0, sizeof(WMTabViewItem));
 
942
 
 
943
    item->identifier = identifier;
 
944
 
 
945
    item->flags.enabled = 1;
 
946
 
 
947
    return item;
 
948
}
 
949
 
 
950
 
 
951
WMTabViewItem*
 
952
WMCreateTabViewItem(int identifier, char *label)
 
953
{
 
954
    WMTabViewItem *item;
 
955
 
 
956
    item = wmalloc(sizeof(WMTabViewItem));
 
957
    memset(item, 0, sizeof(WMTabViewItem));
 
958
 
 
959
    item->identifier = identifier;
 
960
 
 
961
    item->flags.enabled = 1;
 
962
 
 
963
    WMSetTabViewItemLabel(item, label);
 
964
 
 
965
    return item;
 
966
}
 
967
 
 
968
 
 
969
void
 
970
WMSetTabViewItemEnabled(WMTabViewItem *tPtr, Bool flag)
 
971
{
 
972
    tPtr->flags.enabled = ((flag==0) ? 0 : 1);
 
973
    if (tPtr->tabView && W_VIEW_REALIZED(tPtr->tabView->view))
 
974
        paintTabView(tPtr->tabView);
 
975
}
 
976
 
 
977
 
 
978
int
 
979
WMGetTabViewItemIdentifier(WMTabViewItem *item)
 
980
{
 
981
    return item->identifier;
 
982
}
 
983
 
 
984
 
 
985
void
 
986
WMSetTabViewFont(WMTabView *tPtr, WMFont *font)
 
987
{
 
988
    if (tPtr->font)
 
989
        WMReleaseFont(tPtr->font);
 
990
 
 
991
    tPtr->font = WMRetainFont(font);
 
992
    tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
 
993
    recalcTabWidth(tPtr);
 
994
}
 
995
 
 
996
 
 
997
void
 
998
WMSetTabViewItemLabel(WMTabViewItem *item, char *label)
 
999
{
 
1000
    if (item->label)
 
1001
        wfree(item->label);
 
1002
 
 
1003
    if (label)
 
1004
        item->label = wstrdup(label);
 
1005
    else
 
1006
        item->label = NULL;
 
1007
 
 
1008
    if (item->tabView)
 
1009
        recalcTabWidth(item->tabView);
 
1010
}
 
1011
 
 
1012
 
 
1013
char*
 
1014
WMGetTabViewItemLabel(WMTabViewItem *item)
 
1015
{
 
1016
    return item->label;
 
1017
}
 
1018
 
 
1019
 
 
1020
void
 
1021
WMSetTabViewItemView(WMTabViewItem *item, WMView *view)
 
1022
{
 
1023
    item->view = view;
 
1024
}
 
1025
 
 
1026
 
 
1027
WMView*
 
1028
WMGetTabViewItemView(WMTabViewItem *item)
 
1029
{
 
1030
    return item->view;
 
1031
}
 
1032
 
 
1033
 
 
1034
void
 
1035
WMDestroyTabViewItem(WMTabViewItem *item)
 
1036
{
 
1037
    if (item->label)
 
1038
        wfree(item->label);
 
1039
 
 
1040
    if (item->view)
 
1041
        W_DestroyView(item->view);
 
1042
 
 
1043
    wfree(item);
 
1044
}
 
1045