strncpy's third argument should be the length of the dest buffer, not the source.
[wmaker-crm.git] / WINGs / wtabview.c
blob57a458c59b75af23b1eacd177b38a26c0a435fb7
2 #include "WINGsP.h"
4 typedef struct W_TabView {
5 W_Class widgetClass;
6 W_View *view;
8 struct W_TabViewItem **items;
9 int itemCount;
10 int maxItems; /* size of items array, can be increased */
12 int selectedItem;
13 int firstVisible;
15 int visibleTabs;
17 WMFont *font;
19 WMColor *lightGray;
20 WMColor *tabColor;
22 WMTabViewDelegate *delegate;
24 short tabHeight;
26 struct {
27 WMReliefType relief:4;
28 WMTitlePosition titlePosition:4;
29 WMTabViewType type:2;
31 unsigned enabled:1;
32 unsigned tabbed:1;
33 unsigned dontFitAll:1;
34 unsigned bordered:1;
35 unsigned uniformTabs:1;
36 } flags;
37 } TabView;
39 typedef struct W_TabViewItem {
40 WMTabView *tabView;
42 W_View *view;
44 char *label;
46 short tabWidth;
47 int identifier;
49 struct {
50 unsigned visible:1;
51 unsigned enabled:1;
52 } flags;
53 } W_TabViewItem;
55 #define DEFAULT_WIDTH 40
56 #define DEFAULT_HEIGHT 40
58 #define NORMAL_SIDE_OFFSET 8
59 #define BUTTONED_SIDE_OFFSET 15
61 static void destroyTabView(TabView * tPtr);
62 static void paintTabView(TabView * tPtr);
64 static void W_SetTabViewItemParent(WMTabViewItem * item, WMTabView * parent);
66 static void W_DrawLabel(WMTabViewItem * item, Drawable d, WMRect rect, Bool enabled);
68 static void W_UnmapTabViewItem(WMTabViewItem * item);
70 static void W_MapTabViewItem(WMTabViewItem * item);
72 static WMView *W_TabViewItemView(WMTabViewItem * item);
74 static int W_TabViewItemTabWidth(WMTabViewItem * item);
76 static void W_SetTabViewItemTabWidth(WMTabViewItem * item, int width);
78 static void recalcTabWidth(TabView * tPtr);
79 static void rearrange(TabView * tPtr);
81 static void didResize(struct W_ViewDelegate *, WMView *);
83 static W_ViewDelegate delegate = {
84 NULL,
85 NULL,
86 didResize,
87 NULL,
88 NULL
91 static int positionOfTab(WMTabView * tabView, int tab)
93 int i;
94 int offs;
96 if (tab < 0 || tab < tabView->firstVisible)
97 return -1;
99 if (tab > tabView->firstVisible + tabView->visibleTabs)
100 return -1;
102 if (tabView->flags.dontFitAll)
103 offs = BUTTONED_SIDE_OFFSET;
104 else
105 offs = NORMAL_SIDE_OFFSET;
107 for (i = tabView->firstVisible; i < tab; i++)
108 offs += W_TabViewItemTabWidth(tabView->items[i]) - 10;
110 return offs;
113 static int countVisibleTabs(TabView * tPtr, int first)
115 int i;
116 int width;
118 if (first < 0) {
119 width = W_VIEW_WIDTH(tPtr->view) - 2 * NORMAL_SIDE_OFFSET;
120 first = 0;
121 } else {
122 width = W_VIEW_WIDTH(tPtr->view) - 2 * BUTTONED_SIDE_OFFSET;
125 for (i = first; i < tPtr->itemCount; i++) {
126 width -= W_TabViewItemTabWidth(tPtr->items[i]) - 10;
127 if (width <= 0) {
128 return i - first;
131 return i - first;
134 static void handleEvents(XEvent * event, void *data)
136 TabView *tPtr = (TabView *) data;
138 CHECK_CLASS(data, WC_TabView);
140 switch (event->type) {
141 case Expose:
142 if (event->xexpose.count != 0)
143 break;
144 paintTabView(tPtr);
145 break;
147 case ButtonPress:
148 if (tPtr->flags.enabled) {
149 WMTabViewItem *item = WMTabViewItemAtPoint(tPtr,
150 event->xbutton.x,
151 event->xbutton.y);
152 /*if (item && !item->flags.enabled)
153 break; */
155 if (item && item->flags.enabled) {
156 WMSelectTabViewItem(tPtr, item);
157 } else if (tPtr->flags.dontFitAll) {
158 int redraw = 0;
159 int lastVisible = tPtr->firstVisible + tPtr->visibleTabs - 1;
161 if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
162 if (tPtr->firstVisible > 0) {
163 redraw = 1;
164 tPtr->firstVisible--;
166 } else if (event->xbutton.x > positionOfTab(tPtr, lastVisible)) {
168 if (lastVisible < tPtr->itemCount - 1) {
169 redraw = 1;
170 tPtr->firstVisible++;
173 tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
174 if (redraw) {
175 paintTabView(tPtr);
179 break;
181 case DestroyNotify:
182 destroyTabView(tPtr);
183 break;
187 WMTabView *WMCreateTabView(WMWidget * parent)
189 TabView *tPtr;
190 WMScreen *scr = WMWidgetScreen(parent);
192 tPtr = wmalloc(sizeof(TabView));
193 tPtr->widgetClass = WC_TabView;
195 tPtr->view = W_CreateView(W_VIEW(parent));
196 if (!tPtr->view) {
197 wfree(tPtr);
198 return NULL;
200 tPtr->view->self = tPtr;
201 tPtr->view->delegate = &delegate;
203 tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
204 tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
206 tPtr->font = WMRetainFont(scr->normalFont);
208 tPtr->flags.type = WTTopTabsBevelBorder;
209 tPtr->flags.bordered = 1;
210 tPtr->flags.uniformTabs = 0;
211 tPtr->flags.enabled = 1;
213 WMCreateEventHandler(tPtr->view, ExposureMask | StructureNotifyMask | ButtonPressMask, handleEvents, tPtr);
215 WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
217 tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
219 return tPtr;
222 void WMSetTabViewDelegate(WMTabView * tPtr, WMTabViewDelegate * delegate)
224 tPtr->delegate = delegate;
227 WMTabViewItem *WMAddTabViewItemWithView(WMTabView * tPtr, WMView * view, int identifier, const char *label)
229 WMTabViewItem *item;
231 item = WMCreateTabViewItemWithIdentifier(identifier);
232 WMSetTabViewItemView(item, view);
233 WMAddItemInTabView(tPtr, item);
234 WMSetTabViewItemLabel(item, label);
236 return item;
239 void WMAddItemInTabView(WMTabView * tPtr, WMTabViewItem * item)
241 WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
244 void WMSetTabViewEnabled(WMTabView * tPtr, Bool flag)
246 tPtr->flags.enabled = ((flag == 0) ? 0 : 1);
247 if (W_VIEW_REALIZED(tPtr->view))
248 paintTabView(tPtr);
251 void WMInsertItemInTabView(WMTabView * tPtr, int index, WMTabViewItem * item)
253 wassertr(W_TabViewItemView(item) != NULL);
255 if (tPtr->maxItems == tPtr->itemCount) {
256 WMTabViewItem **items;
258 items = wrealloc(tPtr->items, sizeof(WMTabViewItem *) * (tPtr->maxItems + 10));
259 memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem *) * 10); /* XXX */
260 tPtr->items = items;
261 tPtr->maxItems += 10;
264 if (index > tPtr->itemCount)
265 index = tPtr->itemCount;
267 if (index == 0 && tPtr->items[0]) {
268 W_UnmapTabViewItem(tPtr->items[0]);
271 if (index < tPtr->itemCount) {
272 memmove(tPtr->items + index + 1, tPtr->items + index,
273 (tPtr->itemCount - index) * sizeof(WMTabViewItem *));
276 tPtr->items[index] = item;
278 tPtr->itemCount++;
280 recalcTabWidth(tPtr);
282 W_SetTabViewItemParent(item, tPtr);
284 W_UnmapTabViewItem(item);
286 if (tPtr->flags.bordered) {
287 W_ReparentView(W_TabViewItemView(item), tPtr->view, 1, tPtr->tabHeight + 1);
289 W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width - 3,
290 tPtr->view->size.height - tPtr->tabHeight - 3);
291 } else {
292 W_ReparentView(W_TabViewItemView(item), tPtr->view, 0, tPtr->tabHeight);
294 W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width,
295 tPtr->view->size.height - tPtr->tabHeight);
298 if (index == 0) {
299 W_MapTabViewItem(item);
301 if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
302 (*tPtr->delegate->didChangeNumberOfItems) (tPtr->delegate, tPtr);
304 if (W_VIEW_REALIZED(tPtr->view))
305 paintTabView(tPtr);
308 void WMRemoveTabViewItem(WMTabView * tPtr, WMTabViewItem * item)
310 int i;
312 for (i = 0; i < tPtr->itemCount; i++) {
313 if (tPtr->items[i] == item) {
314 if (i < tPtr->itemCount - 1)
315 memmove(&tPtr->items[i], &tPtr->items[i + 1], tPtr->itemCount - i - 1);
316 else
317 tPtr->items[i] = NULL;
319 W_SetTabViewItemParent(item, NULL);
321 tPtr->itemCount--;
322 break;
325 if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
326 (*tPtr->delegate->didChangeNumberOfItems) (tPtr->delegate, tPtr);
329 static Bool isInside(int x, int y, int width, int height, int px, int py)
331 if (py >= y + height - 3 && py <= y + height && px >= x + py - (y + height - 3)
332 && px <= x + width - (py - (y + height - 3))) {
334 return True;
336 if (py >= y + 3 && py < y + height - 3
337 && px >= x + 3 + ((y + 3) - py) * 3 / 7 && px <= x + width - 3 - ((y + 3) - py) * 3 / 7) {
339 return True;
341 if (py >= y && py < y + 3 && px >= x + 7 + py - y && px <= x + width - 7 - (py - y)) {
343 return True;
345 return False;
348 WMTabViewItem *WMTabViewItemAtPoint(WMTabView * tPtr, int x, int y)
350 int i;
351 int count = tPtr->visibleTabs;
352 int first = tPtr->firstVisible;
354 if (tPtr->flags.dontFitAll) {
355 i = tPtr->selectedItem - tPtr->firstVisible;
356 if (i >= 0 && i < tPtr->visibleTabs
357 && isInside(positionOfTab(tPtr, tPtr->selectedItem), 0,
358 W_TabViewItemTabWidth(tPtr->items[tPtr->selectedItem]), tPtr->tabHeight, x, y)) {
359 return tPtr->items[tPtr->selectedItem];
361 } else {
362 i = tPtr->selectedItem;
363 if (isInside(positionOfTab(tPtr, i), 0,
364 W_TabViewItemTabWidth(tPtr->items[i]), tPtr->tabHeight, x, y)) {
365 return tPtr->items[i];
369 for (i = first; i < first + count; i++) {
370 int pos;
372 pos = positionOfTab(tPtr, i);
373 if (isInside(pos, 0, W_TabViewItemTabWidth(tPtr->items[i]), tPtr->tabHeight, x, y)) {
374 return tPtr->items[i];
377 return NULL;
380 void WMSetTabViewType(WMTabView * tPtr, WMTabViewType type)
382 tPtr->flags.type = type;
384 if (type != WTTopTabsBevelBorder)
385 tPtr->tabHeight = 0;
386 else
387 tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
389 if (type == WTNoTabsNoBorder)
390 tPtr->flags.bordered = 0;
391 else
392 tPtr->flags.bordered = 1;
394 rearrange(tPtr);
397 void WMSelectFirstTabViewItem(WMTabView * tPtr)
399 WMSelectTabViewItemAtIndex(tPtr, 0);
402 void WMSelectLastTabViewItem(WMTabView * tPtr)
404 WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
407 void WMSelectNextTabViewItem(WMTabView * tPtr)
409 WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
412 void WMSelectPreviousTabViewItem(WMTabView * tPtr)
414 WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
417 WMTabViewItem *WMGetSelectedTabViewItem(WMTabView * tPtr)
419 return tPtr->items[tPtr->selectedItem];
422 void WMSelectTabViewItem(WMTabView * tPtr, WMTabViewItem * item)
424 int i;
426 for (i = 0; i < tPtr->itemCount; i++) {
427 if (tPtr->items[i] == item) {
428 WMSelectTabViewItemAtIndex(tPtr, i);
429 break;
434 void WMSelectTabViewItemAtIndex(WMTabView * tPtr, int index)
436 WMTabViewItem *item;
438 if (index == tPtr->selectedItem) {
439 return;
442 if (index < 0)
443 index = 0;
444 else if (index >= tPtr->itemCount)
445 index = tPtr->itemCount - 1;
447 item = tPtr->items[tPtr->selectedItem];
449 if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
450 if (!(*tPtr->delegate->shouldSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]))
451 return;
453 if (tPtr->delegate && tPtr->delegate->willSelectItem)
454 (*tPtr->delegate->willSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]);
456 W_UnmapTabViewItem(item);
458 item = tPtr->items[index];
460 W_MapTabViewItem(item);
462 tPtr->selectedItem = index;
464 if (tPtr->delegate && tPtr->delegate->didSelectItem)
465 (*tPtr->delegate->didSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]);
467 paintTabView(tPtr);
470 static void recalcTabWidth(TabView * tPtr)
472 int i;
473 /*int twidth = W_VIEW(tPtr)->size.width; */
474 int width;
476 if (tPtr->flags.uniformTabs) {
477 int tabWidth;
479 tabWidth = 0;
481 for (i = 0; i < tPtr->itemCount; i++) {
482 char *str = WMGetTabViewItemLabel(tPtr->items[i]);
484 if (str) {
485 width = WMWidthOfString(tPtr->font, str, strlen(str));
486 if (width > tabWidth)
487 tabWidth = width;
491 tabWidth = tabWidth + 30;
493 for (i = 0; i < tPtr->itemCount; i++)
494 W_SetTabViewItemTabWidth(tPtr->items[i], tabWidth);
496 tPtr->firstVisible = 0;
497 tPtr->visibleTabs = countVisibleTabs(tPtr, -1);
498 if (tPtr->visibleTabs < tPtr->itemCount)
499 tPtr->flags.dontFitAll = 1;
500 else
501 tPtr->flags.dontFitAll = 0;
502 } else {
503 for (i = 0; i < tPtr->itemCount; i++) {
504 char *str = WMGetTabViewItemLabel(tPtr->items[i]);
505 if (!str)
506 continue;
508 width = WMWidthOfString(tPtr->font, str, strlen(str)) + 30;
510 W_SetTabViewItemTabWidth(tPtr->items[i], width);
513 if (countVisibleTabs(tPtr, -1) < tPtr->itemCount) {
514 tPtr->flags.dontFitAll = 1;
515 tPtr->firstVisible = 0;
516 tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
517 } else {
518 tPtr->flags.dontFitAll = 0;
519 tPtr->firstVisible = 0;
520 tPtr->visibleTabs = tPtr->itemCount;
525 static void drawRelief(W_Screen * scr, Drawable d, int x, int y, unsigned int width, unsigned int height)
527 Display *dpy = scr->display;
528 GC bgc = WMColorGC(scr->black);
529 GC wgc = WMColorGC(scr->white);
530 GC dgc = WMColorGC(scr->darkGray);
532 XDrawLine(dpy, d, wgc, x, y, x, y + height - 1);
534 XDrawLine(dpy, d, bgc, x, y + height - 1, x + width - 1, y + height - 1);
535 XDrawLine(dpy, d, dgc, x + 1, y + height - 2, x + width - 2, y + height - 2);
537 XDrawLine(dpy, d, bgc, x + width - 1, y, x + width - 1, y + height - 1);
538 XDrawLine(dpy, d, dgc, x + width - 2, y + 1, x + width - 2, y + height - 2);
541 static void drawTab(TabView * tPtr, Drawable d, int x, int y, unsigned width, unsigned height, Bool selected)
543 WMScreen *scr = W_VIEW(tPtr)->screen;
544 Display *dpy = scr->display;
545 GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
546 GC black = WMColorGC(scr->black);
547 GC dark = WMColorGC(scr->darkGray);
548 GC light = WMColorGC(scr->gray);
549 XPoint trap[8];
551 trap[0].x = x + (selected ? 0 : 1);
552 trap[0].y = y + height - (selected ? 0 : 1);
554 trap[1].x = x + 3;
555 trap[1].y = y + height - 3;
557 trap[2].x = x + 10 - 3;
558 trap[2].y = y + 3;
560 trap[3].x = x + 10;
561 trap[3].y = y;
563 trap[4].x = x + width - 10;
564 trap[4].y = y;
566 trap[5].x = x + width - 10 + 3;
567 trap[5].y = y + 3;
569 trap[6].x = x + width - 3;
570 trap[6].y = y + height - 3;
572 trap[7].x = x + width - (selected ? 0 : 1);
573 trap[7].y = y + height - (selected ? 0 : 1);
575 XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8, Convex, CoordModeOrigin);
577 XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
578 XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
579 XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
580 XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
581 XDrawLine(dpy, d, dark, trap[4].x, trap[4].y, trap[5].x, trap[5].y);
582 XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
583 XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
585 XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white), trap[0].x, trap[0].y, trap[7].x, trap[7].y);
588 static void paintDot(TabView * tPtr, Drawable d, int x, int y)
590 WMScreen *scr = W_VIEW(tPtr)->screen;
591 Display *dpy = scr->display;
592 GC white = WMColorGC(scr->white);
593 GC black = WMColorGC(scr->black);
595 XFillRectangle(dpy, d, black, x, y, 2, 2);
596 XDrawPoint(dpy, d, white, x, y);
599 static void paintTabView(TabView * tPtr)
601 Pixmap buffer;
602 WMScreen *scr = W_VIEW(tPtr)->screen;
603 Display *dpy = scr->display;
604 GC white = WMColorGC(scr->white);
605 int i;
607 if (tPtr->flags.type == WTTopTabsBevelBorder) {
608 int count = tPtr->visibleTabs;
609 int first = tPtr->firstVisible;
610 int moreAtLeft;
611 int moreAtRight;
612 int selectedIsVisible;
613 int ty;
614 int twidth, theight;
616 ty = 2;
617 theight = tPtr->tabHeight;
619 buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
620 W_VIEW(tPtr)->size.width, theight, W_VIEW(tPtr)->screen->depth);
622 XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
623 0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
625 if (tPtr->flags.dontFitAll) {
626 moreAtLeft = first > 0;
627 moreAtRight = (first + count) < tPtr->itemCount;
628 if (tPtr->selectedItem >= first && tPtr->selectedItem < first + count)
629 selectedIsVisible = 1;
630 else
631 selectedIsVisible = 0;
632 } else {
633 moreAtLeft = 0;
634 moreAtRight = 0;
635 selectedIsVisible = 1;
638 if (moreAtRight) {
639 drawTab(tPtr, buffer, positionOfTab(tPtr, first + count), 0,
640 W_VIEW_WIDTH(tPtr->view), theight, False);
642 for (i = first + count - 1; i >= first; i--) {
643 if (!selectedIsVisible || i != tPtr->selectedItem) {
644 twidth = W_TabViewItemTabWidth(tPtr->items[i]);
646 drawTab(tPtr, buffer, positionOfTab(tPtr, i), 0, twidth, theight, False);
649 if (moreAtLeft) {
650 drawTab(tPtr, buffer, positionOfTab(tPtr, 0) - 2 * BUTTONED_SIDE_OFFSET,
651 0, BUTTONED_SIDE_OFFSET * 4, theight, False);
654 if (selectedIsVisible) {
655 int idx = tPtr->selectedItem;
657 drawTab(tPtr, buffer, positionOfTab(tPtr, idx),
658 0, W_TabViewItemTabWidth(tPtr->items[idx]), theight, True);
660 XDrawLine(dpy, buffer, white, 0, theight - 1, positionOfTab(tPtr, idx), theight - 1);
662 XDrawLine(dpy, buffer, white,
663 positionOfTab(tPtr, idx) + W_TabViewItemTabWidth(tPtr->items[idx]),
664 tPtr->tabHeight - 1, W_VIEW_WIDTH(tPtr->view) - 1, tPtr->tabHeight - 1);
665 } else {
666 XDrawLine(dpy, buffer, white, 0, theight - 1, W_VIEW_WIDTH(tPtr->view), theight - 1);
669 for (i = 0; i < count; i++) {
670 WMRect rect;
672 rect.pos.x = 15 + positionOfTab(tPtr, first + i);
673 rect.pos.y = ty;
674 rect.size.width = W_TabViewItemTabWidth(tPtr->items[first + i]);
675 rect.size.height = theight;
676 W_DrawLabel(tPtr->items[first + i], buffer, rect,
677 tPtr->flags.enabled && tPtr->items[first + i]->flags.enabled);
680 if (moreAtLeft) {
681 paintDot(tPtr, buffer, 4, 10);
682 paintDot(tPtr, buffer, 7, 10);
683 paintDot(tPtr, buffer, 10, 10);
685 if (moreAtRight) {
686 int x;
688 x = positionOfTab(tPtr, tPtr->firstVisible + tPtr->visibleTabs);
690 x = x + (W_VIEW_WIDTH(tPtr->view) - x) / 2;
691 paintDot(tPtr, buffer, x + 5, 10);
692 paintDot(tPtr, buffer, x + 8, 10);
693 paintDot(tPtr, buffer, x + 11, 10);
696 XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
697 W_VIEW_WIDTH(tPtr->view), theight, 0, 0);
699 XFreePixmap(dpy, buffer);
701 switch (tPtr->flags.type) {
702 case WTTopTabsBevelBorder:
703 drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
704 W_VIEW(tPtr)->size.width, W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
705 break;
707 case WTNoTabsBevelBorder:
708 W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
709 W_VIEW(tPtr)->size.height, WRRaised);
710 break;
712 case WTNoTabsLineBorder:
713 W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
714 W_VIEW(tPtr)->size.height, WRSimple);
715 break;
717 case WTNoTabsNoBorder:
718 break;
722 static void rearrange(TabView * tPtr)
724 int i;
725 int width, height;
726 int bordered = tPtr->flags.bordered;
728 recalcTabWidth(tPtr);
730 width = tPtr->view->size.width - (bordered ? 3 : 0);
731 height = tPtr->view->size.height - tPtr->tabHeight - (bordered ? 3 : 0);
733 for (i = 0; i < tPtr->itemCount; i++) {
734 W_MoveView(W_TabViewItemView(tPtr->items[i]), 1 * bordered, tPtr->tabHeight + 1 * bordered);
735 W_ResizeView(W_TabViewItemView(tPtr->items[i]), width, height);
737 if (W_VIEW_MAPPED(tPtr->view) && W_VIEW_REALIZED(tPtr->view))
738 paintTabView(tPtr);
741 static void didResize(struct W_ViewDelegate *deleg, WMView * view)
743 /* Parameter not used, but tell the compiler that it is ok */
744 (void) deleg;
746 rearrange(view->self);
749 static void destroyTabView(TabView * tPtr)
751 int i;
753 for (i = 0; i < tPtr->itemCount; i++) {
754 WMSetTabViewItemView(tPtr->items[i], NULL);
755 WMDestroyTabViewItem(tPtr->items[i]);
757 wfree(tPtr->items);
759 WMReleaseColor(tPtr->lightGray);
760 WMReleaseColor(tPtr->tabColor);
761 WMReleaseFont(tPtr->font);
763 wfree(tPtr);
766 /******************************************************************/
768 static void W_SetTabViewItemParent(WMTabViewItem * item, WMTabView * parent)
770 item->tabView = parent;
773 static void W_DrawLabel(WMTabViewItem * item, Drawable d, WMRect rect, Bool enabled)
775 WMScreen *scr = W_VIEW(item->tabView)->screen;
777 if (!item->label)
778 return;
780 WMDrawString(scr, d, enabled ? scr->black : scr->darkGray,
781 item->tabView->font, rect.pos.x, rect.pos.y, item->label, strlen(item->label));
784 static void W_UnmapTabViewItem(WMTabViewItem * item)
786 wassertr(item->view);
788 W_UnmapView(item->view);
790 item->flags.visible = 0;
793 static void W_MapTabViewItem(WMTabViewItem * item)
795 wassertr(item->view);
797 W_MapView(item->view);
798 W_RaiseView(item->view);
800 item->flags.visible = 1;
803 static WMView *W_TabViewItemView(WMTabViewItem * item)
805 return item->view;
808 static int W_TabViewItemTabWidth(WMTabViewItem * item)
810 return item->tabWidth;
813 static void W_SetTabViewItemTabWidth(WMTabViewItem * item, int width)
815 item->tabWidth = width;
818 WMTabViewItem *WMCreateTabViewItemWithIdentifier(int identifier)
820 WMTabViewItem *item;
822 item = wmalloc(sizeof(WMTabViewItem));
823 item->identifier = identifier;
824 item->flags.enabled = 1;
826 return item;
829 WMTabViewItem *WMCreateTabViewItem(int identifier, const char *label)
831 WMTabViewItem *item;
833 item = wmalloc(sizeof(WMTabViewItem));
834 item->identifier = identifier;
835 item->flags.enabled = 1;
837 WMSetTabViewItemLabel(item, label);
839 return item;
842 void WMSetTabViewItemEnabled(WMTabViewItem * tPtr, Bool flag)
844 tPtr->flags.enabled = ((flag == 0) ? 0 : 1);
845 if (tPtr->tabView && W_VIEW_REALIZED(tPtr->tabView->view))
846 paintTabView(tPtr->tabView);
849 int WMGetTabViewItemIdentifier(WMTabViewItem * item)
851 return item->identifier;
854 void WMSetTabViewFont(WMTabView * tPtr, WMFont * font)
856 if (tPtr->font)
857 WMReleaseFont(tPtr->font);
859 tPtr->font = WMRetainFont(font);
860 tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
861 recalcTabWidth(tPtr);
864 void WMSetTabViewItemLabel(WMTabViewItem * item, const char *label)
866 if (item->label)
867 wfree(item->label);
869 if (label)
870 item->label = wstrdup(label);
871 else
872 item->label = NULL;
874 if (item->tabView)
875 recalcTabWidth(item->tabView);
878 char *WMGetTabViewItemLabel(WMTabViewItem * item)
880 return item->label;
883 void WMSetTabViewItemView(WMTabViewItem * item, WMView * view)
885 item->view = view;
888 WMView *WMGetTabViewItemView(WMTabViewItem * item)
890 return item->view;
893 void WMDestroyTabViewItem(WMTabViewItem * item)
895 if (item->label)
896 wfree(item->label);
898 if (item->view)
899 W_DestroyView(item->view);
901 wfree(item);