New wkdemenu.pl from Malcolm Cowe
[wmaker-crm.git] / WINGs / wtabview.c
blobfb24506c712a3cfa4f7175b32ead1511e238f813
2 #include "WINGsP.h"
5 typedef struct W_TabView {
6 W_Class widgetClass;
7 W_View *view;
9 struct W_TabViewItem **items;
10 int itemCount;
11 int maxItems; /* size of items array, can be increased */
13 int selectedItem;
14 int firstVisible;
16 int visibleTabs;
18 WMFont *font;
20 WMColor *lightGray;
21 WMColor *tabColor;
23 WMTabViewDelegate *delegate;
25 short tabHeight;
27 struct {
28 WMReliefType relief:4;
29 WMTitlePosition titlePosition:4;
30 WMTabViewType type:2;
32 unsigned enabled:1;
33 unsigned tabbed:1;
34 unsigned dontFitAll:1;
35 unsigned bordered:1;
36 unsigned uniformTabs:1;
37 } flags;
38 } TabView;
45 #define DEFAULT_WIDTH 40
46 #define DEFAULT_HEIGHT 40
48 #define NORMAL_SIDE_OFFSET 8
49 #define BUTTONED_SIDE_OFFSET 15
52 static void destroyTabView(TabView *tPtr);
53 static void paintTabView(TabView *tPtr);
56 static void W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent);
58 static void W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect,
59 Bool enabled);
61 static void W_UnmapTabViewItem(WMTabViewItem *item);
63 static void W_MapTabViewItem(WMTabViewItem *item);
65 static WMView *W_TabViewItemView(WMTabViewItem *item);
67 static int W_TabViewItemTabWidth(WMTabViewItem *item);
69 static void W_SetTabViewItemTabWidth(WMTabViewItem *item, int width);
72 static void recalcTabWidth(TabView *tPtr);
73 static void rearrange(TabView *tPtr);
75 static void didResize(struct W_ViewDelegate*, WMView*);
77 static W_ViewDelegate delegate = {
78 NULL,
79 NULL,
80 didResize,
81 NULL,
82 NULL
86 static int
87 positionOfTab(WMTabView *tabView, int tab)
89 int i;
90 int offs;
92 if (tab < tabView->firstVisible)
93 return -1;
95 if (tab > tabView->firstVisible + tabView->visibleTabs)
96 return -1;
98 if (tabView->flags.dontFitAll)
99 offs = BUTTONED_SIDE_OFFSET;
100 else
101 offs = NORMAL_SIDE_OFFSET;
103 for (i = tabView->firstVisible; i < tab; i++)
104 offs += W_TabViewItemTabWidth(tabView->items[i]) - 10;
106 return offs;
110 static int
111 countVisibleTabs(TabView *tPtr, int first)
113 int i;
114 int width;
116 if (first < 0) {
117 width = W_VIEW_WIDTH(tPtr->view) - 2 * NORMAL_SIDE_OFFSET;
118 first = 0;
119 } else {
120 width = W_VIEW_WIDTH(tPtr->view) - 2 * BUTTONED_SIDE_OFFSET;
123 for (i = first; i < tPtr->itemCount; i++) {
124 width -= W_TabViewItemTabWidth(tPtr->items[i]) - 10;
125 if (width <= 0) {
126 return i - first;
129 return i - first;
134 static void
135 handleEvents(XEvent *event, void *data)
137 TabView *tPtr = (TabView*)data;
139 CHECK_CLASS(data, WC_TabView);
141 switch (event->type) {
142 case Expose:
143 if (event->xexpose.count!=0)
144 break;
145 paintTabView(tPtr);
146 break;
148 case ButtonPress:
149 if (tPtr->flags.enabled) {
150 WMTabViewItem *item = WMTabViewItemAtPoint(tPtr,
151 event->xbutton.x,
152 event->xbutton.y);
153 if (item) {
154 WMSelectTabViewItem(tPtr, item);
155 } else if (tPtr->flags.dontFitAll) {
156 int redraw;
157 int lastVisible = tPtr->firstVisible+tPtr->visibleTabs-1;
159 if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
160 if (tPtr->firstVisible > 0) {
161 redraw = 1;
162 tPtr->firstVisible--;
164 } else if (event->xbutton.x > positionOfTab(tPtr,lastVisible)){
166 if (lastVisible < tPtr->itemCount-1) {
167 redraw = 1;
168 tPtr->firstVisible++;
171 tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
172 if (redraw) {
173 paintTabView(tPtr);
177 break;
179 case DestroyNotify:
180 destroyTabView(tPtr);
181 break;
187 WMTabView*
188 WMCreateTabView(WMWidget *parent)
190 TabView *tPtr;
191 WMScreen *scr = WMWidgetScreen(parent);
193 tPtr = wmalloc(sizeof(TabView));
194 memset(tPtr, 0, sizeof(TabView));
196 tPtr->widgetClass = WC_TabView;
198 tPtr->view = W_CreateView(W_VIEW(parent));
199 if (!tPtr->view) {
200 wfree(tPtr);
201 return NULL;
203 tPtr->view->self = tPtr;
204 tPtr->view->delegate = &delegate;
206 tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
207 tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
209 tPtr->font = WMRetainFont(scr->normalFont);
211 tPtr->flags.type = WTTopTabsBevelBorder;
212 tPtr->flags.bordered = 1;
213 tPtr->flags.uniformTabs = 0;
214 tPtr->flags.enabled = 1;
216 WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
217 |ButtonPressMask, handleEvents, tPtr);
219 WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
221 tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
223 return tPtr;
227 void
228 WMSetTabViewDelegate(WMTabView *tPtr, WMTabViewDelegate *delegate)
230 tPtr->delegate = delegate;
234 WMTabViewItem*
235 WMAddTabViewItemWithView(WMTabView *tPtr, WMView *view, int identifier,
236 char *label)
238 WMTabViewItem *item;
240 item = WMCreateTabViewItemWithIdentifier(identifier);
241 WMSetTabViewItemView(item, view);
242 WMAddItemInTabView(tPtr, item);
243 WMSetTabViewItemLabel(item, label);
245 return item;
249 void
250 WMAddItemInTabView(WMTabView *tPtr, WMTabViewItem *item)
252 WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
256 void
257 WMSetTabViewEnabled(WMTabView *tPtr, Bool flag)
259 tPtr->flags.enabled = flag;
260 if (W_VIEW_REALIZED(tPtr->view))
261 paintTabView(tPtr);
265 void
266 WMInsertItemInTabView(WMTabView *tPtr, int index, WMTabViewItem *item)
268 wassertr(W_TabViewItemView(item) != NULL);
270 if (tPtr->maxItems == tPtr->itemCount) {
271 WMTabViewItem **items;
273 items = wrealloc(tPtr->items,
274 sizeof(WMTabViewItem*) * (tPtr->maxItems + 10));
275 memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem*) * 10);
276 tPtr->items = items;
277 tPtr->maxItems += 10;
280 if (index > tPtr->itemCount)
281 index = tPtr->itemCount;
283 if (index == 0 && tPtr->items[0]) {
284 W_UnmapTabViewItem(tPtr->items[0]);
287 if (index < tPtr->itemCount) {
288 memmove(tPtr->items + index + 1, tPtr->items + index,
289 (tPtr->itemCount - index) * sizeof(WMTabViewItem*));
292 tPtr->items[index] = item;
294 tPtr->itemCount++;
296 recalcTabWidth(tPtr);
298 W_SetTabViewItemParent(item, tPtr);
300 W_UnmapTabViewItem(item);
302 if (tPtr->flags.bordered) {
303 W_ReparentView(W_TabViewItemView(item), tPtr->view, 1,
304 tPtr->tabHeight + 1);
306 W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width - 3,
307 tPtr->view->size.height - tPtr->tabHeight - 3);
308 } else {
309 W_ReparentView(W_TabViewItemView(item), tPtr->view, 0,
310 tPtr->tabHeight);
312 W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width,
313 tPtr->view->size.height - tPtr->tabHeight);
316 if (index == 0) {
317 W_MapTabViewItem(item);
319 if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
320 (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
322 if (W_VIEW_REALIZED(tPtr->view))
323 paintTabView(tPtr);
327 void
328 WMRemoveTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
330 int i;
332 for (i = 0; i < tPtr->itemCount; i++) {
333 if (tPtr->items[i] == item) {
334 if (i < tPtr->itemCount - 1)
335 memmove(&tPtr->items[i], &tPtr->items[i + 1],
336 tPtr->itemCount - i - 1);
337 else
338 tPtr->items[i] = NULL;
340 W_SetTabViewItemParent(item, NULL);
342 tPtr->itemCount--;
343 break;
346 if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
347 (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
352 static Bool
353 isInside(int x, int y, int width, int height, int px, int py)
355 if (py >= y + height - 3 && py <= y + height
356 && px >= x + py - (y + height - 3)
357 && px <= x + width - (py - (y + height - 3))) {
359 return True;
361 if (py >= y + 3 && py < y + height - 3
362 && px >= x + 3 + ((y + 3) - py)*3/7
363 && px <= x + width - 3 - ((y + 3) - py)*3/7) {
365 return True;
367 if (py >= y && py < y + 3
368 && px >= x + 7 + py - y
369 && px <= x + width - 7 - (py - y)) {
371 return True;
373 return False;
377 WMTabViewItem*
378 WMTabViewItemAtPoint(WMTabView *tPtr, int x, int y)
380 int i;
381 int offset;
382 int count = tPtr->visibleTabs;
383 int first = tPtr->firstVisible;
385 if (tPtr->flags.dontFitAll) {
386 i = tPtr->selectedItem - tPtr->firstVisible;
387 if (i >= 0 && i < tPtr->visibleTabs
388 && isInside(positionOfTab(tPtr, tPtr->selectedItem), 0,
389 W_TabViewItemTabWidth(tPtr->items[tPtr->selectedItem]),
390 tPtr->tabHeight, x, y)) {
391 return tPtr->items[tPtr->selectedItem];
393 } else {
394 i = tPtr->selectedItem;
395 if (isInside(positionOfTab(tPtr, i), 0,
396 W_TabViewItemTabWidth(tPtr->items[i]),
397 tPtr->tabHeight, x, y)) {
398 return tPtr->items[i];
402 for (i = first; i < first + count; i++) {
403 int pos;
405 pos = positionOfTab(tPtr, i);
406 if (isInside(pos, 0, W_TabViewItemTabWidth(tPtr->items[i]),
407 tPtr->tabHeight, x, y)) {
408 return tPtr->items[i];
411 return NULL;
415 void
416 WMSetTabViewType(WMTabView *tPtr, WMTabViewType type)
418 tPtr->flags.type = type;
420 if (type != WTTopTabsBevelBorder)
421 tPtr->tabHeight = 0;
422 else
423 tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
425 if (type == WTNoTabsNoBorder)
426 tPtr->flags.bordered = 0;
427 else
428 tPtr->flags.bordered = 1;
430 rearrange(tPtr);
433 void
434 WMSelectFirstTabViewItem(WMTabView *tPtr)
436 WMSelectTabViewItemAtIndex(tPtr, 0);
440 void
441 WMSelectLastTabViewItem(WMTabView *tPtr)
443 WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
447 void
448 WMSelectNextTabViewItem(WMTabView *tPtr)
450 WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
454 void
455 WMSelectPreviousTabViewItem(WMTabView *tPtr)
457 WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
461 WMTabViewItem*
462 WMGetSelectedTabViewItem(WMTabView *tPtr)
464 return tPtr->items[tPtr->selectedItem];
468 void
469 WMSelectTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
471 int i;
473 for (i = 0; i < tPtr->itemCount; i++) {
474 if (tPtr->items[i] == item) {
475 WMSelectTabViewItemAtIndex(tPtr, i);
476 break;
482 void
483 WMSelectTabViewItemAtIndex(WMTabView *tPtr, int index)
485 WMTabViewItem *item;
487 if (index == tPtr->selectedItem) {
488 return;
491 if (index < 0)
492 index = 0;
493 else if (index >= tPtr->itemCount)
494 index = tPtr->itemCount - 1;
496 item = tPtr->items[tPtr->selectedItem];
498 if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
499 if (!(*tPtr->delegate->shouldSelectItem)(tPtr->delegate, tPtr,
500 tPtr->items[index]))
501 return;
503 if (tPtr->delegate && tPtr->delegate->willSelectItem)
504 (*tPtr->delegate->willSelectItem)(tPtr->delegate, tPtr,
505 tPtr->items[index]);
507 W_UnmapTabViewItem(item);
510 item = tPtr->items[index];
512 W_MapTabViewItem(item);
514 tPtr->selectedItem = index;
516 if (tPtr->delegate && tPtr->delegate->didSelectItem)
517 (*tPtr->delegate->didSelectItem)(tPtr->delegate, tPtr,
518 tPtr->items[index]);
520 paintTabView(tPtr);
525 static void
526 recalcTabWidth(TabView *tPtr)
528 int i;
529 int twidth = W_VIEW(tPtr)->size.width;
530 int width;
532 if (tPtr->flags.uniformTabs) {
533 int tabWidth;
535 tabWidth = 0;
537 for (i = 0; i < tPtr->itemCount; i++) {
538 char *str = WMGetTabViewItemLabel(tPtr->items[i]);
540 if (str) {
541 width = WMWidthOfString(tPtr->font, str, strlen(str));
542 if (width > tabWidth)
543 tabWidth = width;
547 tabWidth = tabWidth + 30;
549 for (i = 0; i < tPtr->itemCount; i++)
550 W_SetTabViewItemTabWidth(tPtr->items[i], tabWidth);
552 tPtr->firstVisible = 0;
553 tPtr->visibleTabs = countVisibleTabs(tPtr, -1);
554 if (tPtr->visibleTabs < tPtr->itemCount)
555 tPtr->flags.dontFitAll = 1;
556 else
557 tPtr->flags.dontFitAll = 0;
558 } else {
559 for (i = 0; i < tPtr->itemCount; i++) {
560 char *str = WMGetTabViewItemLabel(tPtr->items[i]);
561 if (!str)
562 continue;
564 width = WMWidthOfString(tPtr->font, str, strlen(str)) + 30;
566 W_SetTabViewItemTabWidth(tPtr->items[i], width);
569 if (countVisibleTabs(tPtr, -1) < tPtr->itemCount) {
570 tPtr->flags.dontFitAll = 1;
571 tPtr->firstVisible = 0;
572 tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
573 } else {
574 tPtr->flags.dontFitAll = 0;
575 tPtr->firstVisible = 0;
576 tPtr->visibleTabs = tPtr->itemCount;
582 static void
583 drawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
584 unsigned int height)
586 Display *dpy = scr->display;
587 GC bgc = WMColorGC(scr->black);
588 GC wgc = WMColorGC(scr->white);
589 GC dgc = WMColorGC(scr->darkGray);
591 XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
593 XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
594 XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
596 XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
597 XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
601 static void
602 drawTab(TabView *tPtr, Drawable d, int x, int y,
603 unsigned width, unsigned height, Bool selected)
605 WMScreen *scr = W_VIEW(tPtr)->screen;
606 Display *dpy = scr->display;
607 GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
608 GC black = WMColorGC(scr->black);
609 GC dark = WMColorGC(scr->darkGray);
610 GC light = WMColorGC(scr->gray);
611 XPoint trap[8];
613 trap[0].x = x + (selected ? 0 : 1);
614 trap[0].y = y + height - (selected ? 0 : 1);
616 trap[1].x = x + 3;
617 trap[1].y = y + height - 3;
619 trap[2].x = x + 10 - 3;
620 trap[2].y = y + 3;
622 trap[3].x = x + 10;
623 trap[3].y = y;
625 trap[4].x = x + width - 10;
626 trap[4].y = y;
628 trap[5].x = x + width - 10 + 3;
629 trap[5].y = y + 3;
631 trap[6].x = x + width - 3;
632 trap[6].y = y + height - 3;
634 trap[7].x = x + width - (selected ? 0 : 1);
635 trap[7].y = y + height - (selected ? 0 : 1);
637 XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8,
638 Convex, CoordModeOrigin);
640 XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
641 XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
642 XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
643 XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
644 XDrawLine(dpy, d, dark, trap[4].x, trap[4].y, trap[5].x, trap[5].y);
645 XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
646 XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
648 XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white),
649 trap[0].x, trap[0].y, trap[7].x, trap[7].y);
653 static void
654 paintDot(TabView *tPtr, Drawable d, int x, int y)
656 WMScreen *scr = W_VIEW(tPtr)->screen;
657 Display *dpy = scr->display;
658 GC white = WMColorGC(scr->white);
659 GC black = WMColorGC(scr->black);
661 XFillRectangle(dpy, d, black, x, y, 2, 2);
662 XDrawPoint(dpy, d, white, x, y);
667 static void
668 paintTabView(TabView *tPtr)
670 Pixmap buffer;
671 WMScreen *scr = W_VIEW(tPtr)->screen;
672 Display *dpy = scr->display;
673 GC white = WMColorGC(scr->white);
674 int i;
676 if (tPtr->flags.type == WTTopTabsBevelBorder) {
677 int count = tPtr->visibleTabs;
678 int first = tPtr->firstVisible;
679 int moreAtLeft;
680 int moreAtRight;
681 int selectedIsVisible;
682 int tx, ty;
683 int twidth, theight;
685 ty = 2;
686 theight = tPtr->tabHeight;
688 buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
689 W_VIEW(tPtr)->size.width, theight,
690 W_VIEW(tPtr)->screen->depth);
692 XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
693 0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
695 if (tPtr->flags.dontFitAll) {
696 moreAtLeft = first > 0;
697 moreAtRight = (first + count) < tPtr->itemCount;
698 if (tPtr->selectedItem >= first
699 && tPtr->selectedItem < first + count)
700 selectedIsVisible = 1;
701 else
702 selectedIsVisible = 0;
703 } else {
704 moreAtLeft = 0;
705 moreAtRight = 0;
706 selectedIsVisible = 1;
709 if (moreAtRight) {
710 drawTab(tPtr, buffer, positionOfTab(tPtr, first+count), 0,
711 W_VIEW_WIDTH(tPtr->view), theight, False);
713 for (i = first + count-1; i >= first; i--) {
714 if (!selectedIsVisible || i != tPtr->selectedItem) {
715 twidth = W_TabViewItemTabWidth(tPtr->items[i]);
717 drawTab(tPtr, buffer, positionOfTab(tPtr, i), 0,
718 twidth, theight, False);
721 if (moreAtLeft) {
722 drawTab(tPtr, buffer, positionOfTab(tPtr, 0)-2*BUTTONED_SIDE_OFFSET,
723 0, BUTTONED_SIDE_OFFSET*4, theight, False);
726 if (selectedIsVisible) {
727 int idx = tPtr->selectedItem;
729 drawTab(tPtr, buffer, positionOfTab(tPtr, idx),
730 0, W_TabViewItemTabWidth(tPtr->items[idx]),
731 theight, True);
733 XDrawLine(dpy, buffer, white, 0, theight - 1,
734 positionOfTab(tPtr, idx), theight - 1);
736 XDrawLine(dpy, buffer, white,
737 positionOfTab(tPtr, idx) + W_TabViewItemTabWidth(tPtr->items[idx]),
738 tPtr->tabHeight - 1, W_VIEW_WIDTH(tPtr->view) - 1,
739 tPtr->tabHeight - 1);
740 } else {
741 XDrawLine(dpy, buffer, white, 0, theight - 1,
742 W_VIEW_WIDTH(tPtr->view), theight - 1);
745 for (i = 0; i < count; i++) {
746 WMRect rect;
748 rect.pos.x = 15 + positionOfTab(tPtr, first+i);
749 rect.pos.y = ty;
750 rect.size.width = W_TabViewItemTabWidth(tPtr->items[first+i]);
751 rect.size.height = theight;
752 W_DrawLabel(tPtr->items[first+i], buffer, rect,
753 tPtr->flags.enabled);
756 if (moreAtLeft) {
757 paintDot(tPtr, buffer, 4, 10);
758 paintDot(tPtr, buffer, 7, 10);
759 paintDot(tPtr, buffer, 10, 10);
761 if (moreAtRight) {
762 int x;
764 x = positionOfTab(tPtr, tPtr->firstVisible + tPtr->visibleTabs);
766 x = x + (W_VIEW_WIDTH(tPtr->view) - x)/2;
767 paintDot(tPtr, buffer, x + 5, 10);
768 paintDot(tPtr, buffer, x + 8, 10);
769 paintDot(tPtr, buffer, x + 11, 10);
772 XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
773 W_VIEW_WIDTH(tPtr->view), theight, 0, 0);
775 XFreePixmap(dpy, buffer);
777 switch (tPtr->flags.type) {
778 case WTTopTabsBevelBorder:
779 drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
780 W_VIEW(tPtr)->size.width,
781 W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
782 break;
784 case WTNoTabsBevelBorder:
785 W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
786 W_VIEW(tPtr)->size.height, WRRaised);
787 break;
789 case WTNoTabsLineBorder:
790 W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
791 W_VIEW(tPtr)->size.height, WRSimple);
792 break;
794 case WTNoTabsNoBorder:
795 break;
800 static void
801 rearrange(TabView *tPtr)
803 int i;
804 int width, height;
805 int bordered = tPtr->flags.bordered;
807 recalcTabWidth(tPtr);
809 width = tPtr->view->size.width - (bordered ? 3 : 0);
810 height = tPtr->view->size.height - tPtr->tabHeight - (bordered ? 3 : 0);
812 for (i = 0; i < tPtr->itemCount; i++) {
813 W_MoveView(W_TabViewItemView(tPtr->items[i]),
814 1*bordered, tPtr->tabHeight + 1*bordered);
815 W_ResizeView(W_TabViewItemView(tPtr->items[i]), width, height);
817 if (W_VIEW_MAPPED(tPtr->view) && W_VIEW_REALIZED(tPtr->view))
818 paintTabView(tPtr);
822 static void
823 didResize(struct W_ViewDelegate *deleg, WMView *view)
825 rearrange(view->self);
829 static void
830 destroyTabView(TabView *tPtr)
832 int i;
834 for (i = 0; i < tPtr->itemCount; i++) {
835 WMSetTabViewItemView(tPtr->items[i], NULL);
836 WMDestroyTabViewItem(tPtr->items[i]);
838 wfree(tPtr->items);
840 WMReleaseColor(tPtr->lightGray);
841 WMReleaseColor(tPtr->tabColor);
842 WMReleaseFont(tPtr->font);
844 wfree(tPtr);
847 /******************************************************************/
850 typedef struct W_TabViewItem {
851 WMTabView *tabView;
853 W_View *view;
855 char *label;
857 short tabWidth;
858 int identifier;
860 struct {
861 unsigned visible:1;
862 } flags;
863 } TabViewItem;
866 static void
867 W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent)
869 item->tabView = parent;
873 static void
874 W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect, Bool enabled)
876 WMScreen *scr = W_VIEW(item->tabView)->screen;
878 if (!item->label)
879 return;
881 WMDrawString(scr, d, WMColorGC(enabled ? scr->black : scr->darkGray),
882 item->tabView->font, rect.pos.x, rect.pos.y,
883 item->label, strlen(item->label));
887 static void
888 W_UnmapTabViewItem(WMTabViewItem *item)
890 wassertr(item->view);
892 W_UnmapView(item->view);
894 item->flags.visible = 0;
898 static void
899 W_MapTabViewItem(WMTabViewItem *item)
901 wassertr(item->view);
903 W_MapView(item->view);
904 W_RaiseView(item->view);
906 item->flags.visible = 1;
910 static WMView*
911 W_TabViewItemView(WMTabViewItem *item)
913 return item->view;
917 static int
918 W_TabViewItemTabWidth(WMTabViewItem *item)
920 return item->tabWidth;
924 static void
925 W_SetTabViewItemTabWidth(WMTabViewItem *item, int width)
927 item->tabWidth = width;
931 WMTabViewItem*
932 WMCreateTabViewItemWithIdentifier(int identifier)
934 WMTabViewItem *item;
936 item = wmalloc(sizeof(WMTabViewItem));
937 memset(item, 0, sizeof(WMTabViewItem));
939 item->identifier = identifier;
941 return item;
945 WMTabViewItem*
946 WMCreateTabViewItem(int identifier, char *label)
948 WMTabViewItem *item;
950 item = wmalloc(sizeof(WMTabViewItem));
951 memset(item, 0, sizeof(WMTabViewItem));
953 item->identifier = identifier;
954 WMSetTabViewItemLabel(item, label);
956 return item;
962 WMGetTabViewItemIdentifier(WMTabViewItem *item)
964 return item->identifier;
968 void
969 WMSetTabViewFont(WMTabView *tPtr, WMFont *font)
971 if (tPtr->font)
972 WMReleaseFont(tPtr->font);
974 tPtr->font = WMRetainFont(font);
975 tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
976 recalcTabWidth(tPtr);
980 void
981 WMSetTabViewItemLabel(WMTabViewItem *item, char *label)
983 if (item->label)
984 wfree(item->label);
986 if (label)
987 item->label = wstrdup(label);
988 else
989 item->label = NULL;
991 if (item->tabView)
992 recalcTabWidth(item->tabView);
996 char*
997 WMGetTabViewItemLabel(WMTabViewItem *item)
999 return item->label;
1003 void
1004 WMSetTabViewItemView(WMTabViewItem *item, WMView *view)
1006 item->view = view;
1010 WMView*
1011 WMGetTabViewItemView(WMTabViewItem *item)
1013 return item->view;
1017 void
1018 WMDestroyTabViewItem(WMTabViewItem *item)
1020 if (item->label)
1021 wfree(item->label);
1023 if (item->view)
1024 W_DestroyView(item->view);
1026 wfree(item);