- Finished moving to the new proplist handling code in WINGs.
[wmaker-crm.git] / WINGs / wtabview.c
blob3cad8c8a80bc6d48a31c6f81af647cf09d548a8d
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 = 0;
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 count = tPtr->visibleTabs;
382 int first = tPtr->firstVisible;
384 if (tPtr->flags.dontFitAll) {
385 i = tPtr->selectedItem - tPtr->firstVisible;
386 if (i >= 0 && i < tPtr->visibleTabs
387 && isInside(positionOfTab(tPtr, tPtr->selectedItem), 0,
388 W_TabViewItemTabWidth(tPtr->items[tPtr->selectedItem]),
389 tPtr->tabHeight, x, y)) {
390 return tPtr->items[tPtr->selectedItem];
392 } else {
393 i = tPtr->selectedItem;
394 if (isInside(positionOfTab(tPtr, i), 0,
395 W_TabViewItemTabWidth(tPtr->items[i]),
396 tPtr->tabHeight, x, y)) {
397 return tPtr->items[i];
401 for (i = first; i < first + count; i++) {
402 int pos;
404 pos = positionOfTab(tPtr, i);
405 if (isInside(pos, 0, W_TabViewItemTabWidth(tPtr->items[i]),
406 tPtr->tabHeight, x, y)) {
407 return tPtr->items[i];
410 return NULL;
414 void
415 WMSetTabViewType(WMTabView *tPtr, WMTabViewType type)
417 tPtr->flags.type = type;
419 if (type != WTTopTabsBevelBorder)
420 tPtr->tabHeight = 0;
421 else
422 tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
424 if (type == WTNoTabsNoBorder)
425 tPtr->flags.bordered = 0;
426 else
427 tPtr->flags.bordered = 1;
429 rearrange(tPtr);
432 void
433 WMSelectFirstTabViewItem(WMTabView *tPtr)
435 WMSelectTabViewItemAtIndex(tPtr, 0);
439 void
440 WMSelectLastTabViewItem(WMTabView *tPtr)
442 WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
446 void
447 WMSelectNextTabViewItem(WMTabView *tPtr)
449 WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
453 void
454 WMSelectPreviousTabViewItem(WMTabView *tPtr)
456 WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
460 WMTabViewItem*
461 WMGetSelectedTabViewItem(WMTabView *tPtr)
463 return tPtr->items[tPtr->selectedItem];
467 void
468 WMSelectTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
470 int i;
472 for (i = 0; i < tPtr->itemCount; i++) {
473 if (tPtr->items[i] == item) {
474 WMSelectTabViewItemAtIndex(tPtr, i);
475 break;
481 void
482 WMSelectTabViewItemAtIndex(WMTabView *tPtr, int index)
484 WMTabViewItem *item;
486 if (index == tPtr->selectedItem) {
487 return;
490 if (index < 0)
491 index = 0;
492 else if (index >= tPtr->itemCount)
493 index = tPtr->itemCount - 1;
495 item = tPtr->items[tPtr->selectedItem];
497 if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
498 if (!(*tPtr->delegate->shouldSelectItem)(tPtr->delegate, tPtr,
499 tPtr->items[index]))
500 return;
502 if (tPtr->delegate && tPtr->delegate->willSelectItem)
503 (*tPtr->delegate->willSelectItem)(tPtr->delegate, tPtr,
504 tPtr->items[index]);
506 W_UnmapTabViewItem(item);
509 item = tPtr->items[index];
511 W_MapTabViewItem(item);
513 tPtr->selectedItem = index;
515 if (tPtr->delegate && tPtr->delegate->didSelectItem)
516 (*tPtr->delegate->didSelectItem)(tPtr->delegate, tPtr,
517 tPtr->items[index]);
519 paintTabView(tPtr);
524 static void
525 recalcTabWidth(TabView *tPtr)
527 int i;
528 /*int twidth = W_VIEW(tPtr)->size.width;*/
529 int width;
531 if (tPtr->flags.uniformTabs) {
532 int tabWidth;
534 tabWidth = 0;
536 for (i = 0; i < tPtr->itemCount; i++) {
537 char *str = WMGetTabViewItemLabel(tPtr->items[i]);
539 if (str) {
540 width = WMWidthOfString(tPtr->font, str, strlen(str));
541 if (width > tabWidth)
542 tabWidth = width;
546 tabWidth = tabWidth + 30;
548 for (i = 0; i < tPtr->itemCount; i++)
549 W_SetTabViewItemTabWidth(tPtr->items[i], tabWidth);
551 tPtr->firstVisible = 0;
552 tPtr->visibleTabs = countVisibleTabs(tPtr, -1);
553 if (tPtr->visibleTabs < tPtr->itemCount)
554 tPtr->flags.dontFitAll = 1;
555 else
556 tPtr->flags.dontFitAll = 0;
557 } else {
558 for (i = 0; i < tPtr->itemCount; i++) {
559 char *str = WMGetTabViewItemLabel(tPtr->items[i]);
560 if (!str)
561 continue;
563 width = WMWidthOfString(tPtr->font, str, strlen(str)) + 30;
565 W_SetTabViewItemTabWidth(tPtr->items[i], width);
568 if (countVisibleTabs(tPtr, -1) < tPtr->itemCount) {
569 tPtr->flags.dontFitAll = 1;
570 tPtr->firstVisible = 0;
571 tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
572 } else {
573 tPtr->flags.dontFitAll = 0;
574 tPtr->firstVisible = 0;
575 tPtr->visibleTabs = tPtr->itemCount;
581 static void
582 drawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
583 unsigned int height)
585 Display *dpy = scr->display;
586 GC bgc = WMColorGC(scr->black);
587 GC wgc = WMColorGC(scr->white);
588 GC dgc = WMColorGC(scr->darkGray);
590 XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
592 XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
593 XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
595 XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
596 XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
600 static void
601 drawTab(TabView *tPtr, Drawable d, int x, int y,
602 unsigned width, unsigned height, Bool selected)
604 WMScreen *scr = W_VIEW(tPtr)->screen;
605 Display *dpy = scr->display;
606 GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
607 GC black = WMColorGC(scr->black);
608 GC dark = WMColorGC(scr->darkGray);
609 GC light = WMColorGC(scr->gray);
610 XPoint trap[8];
612 trap[0].x = x + (selected ? 0 : 1);
613 trap[0].y = y + height - (selected ? 0 : 1);
615 trap[1].x = x + 3;
616 trap[1].y = y + height - 3;
618 trap[2].x = x + 10 - 3;
619 trap[2].y = y + 3;
621 trap[3].x = x + 10;
622 trap[3].y = y;
624 trap[4].x = x + width - 10;
625 trap[4].y = y;
627 trap[5].x = x + width - 10 + 3;
628 trap[5].y = y + 3;
630 trap[6].x = x + width - 3;
631 trap[6].y = y + height - 3;
633 trap[7].x = x + width - (selected ? 0 : 1);
634 trap[7].y = y + height - (selected ? 0 : 1);
636 XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8,
637 Convex, CoordModeOrigin);
639 XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
640 XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
641 XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
642 XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
643 XDrawLine(dpy, d, dark, trap[4].x, trap[4].y, trap[5].x, trap[5].y);
644 XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
645 XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
647 XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white),
648 trap[0].x, trap[0].y, trap[7].x, trap[7].y);
652 static void
653 paintDot(TabView *tPtr, Drawable d, int x, int y)
655 WMScreen *scr = W_VIEW(tPtr)->screen;
656 Display *dpy = scr->display;
657 GC white = WMColorGC(scr->white);
658 GC black = WMColorGC(scr->black);
660 XFillRectangle(dpy, d, black, x, y, 2, 2);
661 XDrawPoint(dpy, d, white, x, y);
666 static void
667 paintTabView(TabView *tPtr)
669 Pixmap buffer;
670 WMScreen *scr = W_VIEW(tPtr)->screen;
671 Display *dpy = scr->display;
672 GC white = WMColorGC(scr->white);
673 int i;
675 if (tPtr->flags.type == WTTopTabsBevelBorder) {
676 int count = tPtr->visibleTabs;
677 int first = tPtr->firstVisible;
678 int moreAtLeft;
679 int moreAtRight;
680 int selectedIsVisible;
681 int ty;
682 int twidth, theight;
684 ty = 2;
685 theight = tPtr->tabHeight;
687 buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
688 W_VIEW(tPtr)->size.width, theight,
689 W_VIEW(tPtr)->screen->depth);
691 XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
692 0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
694 if (tPtr->flags.dontFitAll) {
695 moreAtLeft = first > 0;
696 moreAtRight = (first + count) < tPtr->itemCount;
697 if (tPtr->selectedItem >= first
698 && tPtr->selectedItem < first + count)
699 selectedIsVisible = 1;
700 else
701 selectedIsVisible = 0;
702 } else {
703 moreAtLeft = 0;
704 moreAtRight = 0;
705 selectedIsVisible = 1;
708 if (moreAtRight) {
709 drawTab(tPtr, buffer, positionOfTab(tPtr, first+count), 0,
710 W_VIEW_WIDTH(tPtr->view), theight, False);
712 for (i = first + count-1; i >= first; i--) {
713 if (!selectedIsVisible || i != tPtr->selectedItem) {
714 twidth = W_TabViewItemTabWidth(tPtr->items[i]);
716 drawTab(tPtr, buffer, positionOfTab(tPtr, i), 0,
717 twidth, theight, False);
720 if (moreAtLeft) {
721 drawTab(tPtr, buffer, positionOfTab(tPtr, 0)-2*BUTTONED_SIDE_OFFSET,
722 0, BUTTONED_SIDE_OFFSET*4, theight, False);
725 if (selectedIsVisible) {
726 int idx = tPtr->selectedItem;
728 drawTab(tPtr, buffer, positionOfTab(tPtr, idx),
729 0, W_TabViewItemTabWidth(tPtr->items[idx]),
730 theight, True);
732 XDrawLine(dpy, buffer, white, 0, theight - 1,
733 positionOfTab(tPtr, idx), theight - 1);
735 XDrawLine(dpy, buffer, white,
736 positionOfTab(tPtr, idx) + W_TabViewItemTabWidth(tPtr->items[idx]),
737 tPtr->tabHeight - 1, W_VIEW_WIDTH(tPtr->view) - 1,
738 tPtr->tabHeight - 1);
739 } else {
740 XDrawLine(dpy, buffer, white, 0, theight - 1,
741 W_VIEW_WIDTH(tPtr->view), theight - 1);
744 for (i = 0; i < count; i++) {
745 WMRect rect;
747 rect.pos.x = 15 + positionOfTab(tPtr, first+i);
748 rect.pos.y = ty;
749 rect.size.width = W_TabViewItemTabWidth(tPtr->items[first+i]);
750 rect.size.height = theight;
751 W_DrawLabel(tPtr->items[first+i], buffer, rect,
752 tPtr->flags.enabled);
755 if (moreAtLeft) {
756 paintDot(tPtr, buffer, 4, 10);
757 paintDot(tPtr, buffer, 7, 10);
758 paintDot(tPtr, buffer, 10, 10);
760 if (moreAtRight) {
761 int x;
763 x = positionOfTab(tPtr, tPtr->firstVisible + tPtr->visibleTabs);
765 x = x + (W_VIEW_WIDTH(tPtr->view) - x)/2;
766 paintDot(tPtr, buffer, x + 5, 10);
767 paintDot(tPtr, buffer, x + 8, 10);
768 paintDot(tPtr, buffer, x + 11, 10);
771 XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
772 W_VIEW_WIDTH(tPtr->view), theight, 0, 0);
774 XFreePixmap(dpy, buffer);
776 switch (tPtr->flags.type) {
777 case WTTopTabsBevelBorder:
778 drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
779 W_VIEW(tPtr)->size.width,
780 W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
781 break;
783 case WTNoTabsBevelBorder:
784 W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
785 W_VIEW(tPtr)->size.height, WRRaised);
786 break;
788 case WTNoTabsLineBorder:
789 W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
790 W_VIEW(tPtr)->size.height, WRSimple);
791 break;
793 case WTNoTabsNoBorder:
794 break;
799 static void
800 rearrange(TabView *tPtr)
802 int i;
803 int width, height;
804 int bordered = tPtr->flags.bordered;
806 recalcTabWidth(tPtr);
808 width = tPtr->view->size.width - (bordered ? 3 : 0);
809 height = tPtr->view->size.height - tPtr->tabHeight - (bordered ? 3 : 0);
811 for (i = 0; i < tPtr->itemCount; i++) {
812 W_MoveView(W_TabViewItemView(tPtr->items[i]),
813 1*bordered, tPtr->tabHeight + 1*bordered);
814 W_ResizeView(W_TabViewItemView(tPtr->items[i]), width, height);
816 if (W_VIEW_MAPPED(tPtr->view) && W_VIEW_REALIZED(tPtr->view))
817 paintTabView(tPtr);
821 static void
822 didResize(struct W_ViewDelegate *deleg, WMView *view)
824 rearrange(view->self);
828 static void
829 destroyTabView(TabView *tPtr)
831 int i;
833 for (i = 0; i < tPtr->itemCount; i++) {
834 WMSetTabViewItemView(tPtr->items[i], NULL);
835 WMDestroyTabViewItem(tPtr->items[i]);
837 wfree(tPtr->items);
839 WMReleaseColor(tPtr->lightGray);
840 WMReleaseColor(tPtr->tabColor);
841 WMReleaseFont(tPtr->font);
843 wfree(tPtr);
846 /******************************************************************/
849 typedef struct W_TabViewItem {
850 WMTabView *tabView;
852 W_View *view;
854 char *label;
856 short tabWidth;
857 int identifier;
859 struct {
860 unsigned visible:1;
861 } flags;
862 } TabViewItem;
865 static void
866 W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent)
868 item->tabView = parent;
872 static void
873 W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect, Bool enabled)
875 WMScreen *scr = W_VIEW(item->tabView)->screen;
877 if (!item->label)
878 return;
880 WMDrawString(scr, d, WMColorGC(enabled ? scr->black : scr->darkGray),
881 item->tabView->font, rect.pos.x, rect.pos.y,
882 item->label, strlen(item->label));
886 static void
887 W_UnmapTabViewItem(WMTabViewItem *item)
889 wassertr(item->view);
891 W_UnmapView(item->view);
893 item->flags.visible = 0;
897 static void
898 W_MapTabViewItem(WMTabViewItem *item)
900 wassertr(item->view);
902 W_MapView(item->view);
903 W_RaiseView(item->view);
905 item->flags.visible = 1;
909 static WMView*
910 W_TabViewItemView(WMTabViewItem *item)
912 return item->view;
916 static int
917 W_TabViewItemTabWidth(WMTabViewItem *item)
919 return item->tabWidth;
923 static void
924 W_SetTabViewItemTabWidth(WMTabViewItem *item, int width)
926 item->tabWidth = width;
930 WMTabViewItem*
931 WMCreateTabViewItemWithIdentifier(int identifier)
933 WMTabViewItem *item;
935 item = wmalloc(sizeof(WMTabViewItem));
936 memset(item, 0, sizeof(WMTabViewItem));
938 item->identifier = identifier;
940 return item;
944 WMTabViewItem*
945 WMCreateTabViewItem(int identifier, char *label)
947 WMTabViewItem *item;
949 item = wmalloc(sizeof(WMTabViewItem));
950 memset(item, 0, sizeof(WMTabViewItem));
952 item->identifier = identifier;
953 WMSetTabViewItemLabel(item, label);
955 return item;
961 WMGetTabViewItemIdentifier(WMTabViewItem *item)
963 return item->identifier;
967 void
968 WMSetTabViewFont(WMTabView *tPtr, WMFont *font)
970 if (tPtr->font)
971 WMReleaseFont(tPtr->font);
973 tPtr->font = WMRetainFont(font);
974 tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
975 recalcTabWidth(tPtr);
979 void
980 WMSetTabViewItemLabel(WMTabViewItem *item, char *label)
982 if (item->label)
983 wfree(item->label);
985 if (label)
986 item->label = wstrdup(label);
987 else
988 item->label = NULL;
990 if (item->tabView)
991 recalcTabWidth(item->tabView);
995 char*
996 WMGetTabViewItemLabel(WMTabViewItem *item)
998 return item->label;
1002 void
1003 WMSetTabViewItemView(WMTabViewItem *item, WMView *view)
1005 item->view = view;
1009 WMView*
1010 WMGetTabViewItemView(WMTabViewItem *item)
1012 return item->view;
1016 void
1017 WMDestroyTabViewItem(WMTabViewItem *item)
1019 if (item->label)
1020 wfree(item->label);
1022 if (item->view)
1023 W_DestroyView(item->view);
1025 wfree(item);