5 typedef struct W_TabView
{
9 struct W_TabViewItem
**items
;
11 int maxItems
; /* size of items array */
20 WMTabViewDelegate
*delegate
;
26 WMReliefType relief
:4;
27 WMTitlePosition titlePosition
:4;
28 WMTabViewTypes type
:2;
31 unsigned allowsTruncatedLabels
:1;
37 struct W_ViewProcedureTable _TabViewViewProcedures
= {
44 #define DEFAULT_WIDTH 40
45 #define DEFAULT_HEIGHT 40
48 static void destroyTabView(TabView
*tPtr
);
49 static void paintTabView(TabView
*tPtr
);
52 static void W_SetTabViewItemParent(WMTabViewItem
*item
, WMTabView
*parent
);
54 static void W_DrawLabel(WMTabViewItem
*item
, Drawable d
, WMRect rect
);
56 static void W_UnmapTabViewItem(WMTabViewItem
*item
);
58 static void W_MapTabViewItem(WMTabViewItem
*item
);
60 static WMView
*W_TabViewItemView(WMTabViewItem
*item
);
62 static void recalcTabWidth(TabView
*tPtr
);
66 handleEvents(XEvent
*event
, void *data
)
68 TabView
*tPtr
= (TabView
*)data
;
70 CHECK_CLASS(data
, WC_TabView
);
72 switch (event
->type
) {
74 if (event
->xexpose
.count
!=0)
81 WMTabViewItem
*item
= WMTabViewItemAtPoint(tPtr
,
85 WMSelectTabViewItem(tPtr
, item
);
99 WMCreateTabView(WMWidget
*parent
)
102 WMScreen
*scr
= WMWidgetScreen(parent
);
104 tPtr
= wmalloc(sizeof(TabView
));
105 memset(tPtr
, 0, sizeof(TabView
));
107 tPtr
->widgetClass
= WC_TabView
;
109 tPtr
->view
= W_CreateView(W_VIEW(parent
));
114 tPtr
->view
->self
= tPtr
;
116 tPtr
->lightGray
= WMCreateRGBColor(scr
, 0xd9d9, 0xd9d9, 0xd9d9, False
);
117 tPtr
->tabColor
= WMCreateRGBColor(scr
, 0x8420, 0x8420, 0x8420, False
);
119 tPtr
->font
= WMRetainFont(scr
->normalFont
);
121 WMCreateEventHandler(tPtr
->view
, ExposureMask
|StructureNotifyMask
122 |ButtonPressMask
, handleEvents
, tPtr
);
124 WMResizeWidget(tPtr
, DEFAULT_WIDTH
, DEFAULT_HEIGHT
);
126 tPtr
->tabHeight
= WMFontHeight(tPtr
->font
) + 3;
133 WMSetTabViewDelegate(WMTabView
*tPtr
, WMTabViewDelegate
*delegate
)
135 tPtr
->delegate
= delegate
;
140 WMAddItemInTabView(WMTabView
*tPtr
, WMTabViewItem
*item
)
142 WMInsertItemInTabView(tPtr
, tPtr
->itemCount
, item
);
147 WMInsertItemInTabView(WMTabView
*tPtr
, int index
, WMTabViewItem
*item
)
149 wassertr(W_TabViewItemView(item
) != NULL
);
151 if (tPtr
->maxItems
== tPtr
->itemCount
) {
152 WMTabViewItem
**items
;
154 items
= wrealloc(tPtr
->items
,
155 sizeof(WMTabViewItem
*) * (tPtr
->maxItems
+ 10));
157 wwarning("out of memory allocating memory for tabview");
160 memset(&items
[tPtr
->maxItems
], 0, sizeof(WMTabViewItem
*) * 10);
162 tPtr
->maxItems
+= 10;
165 if (index
> tPtr
->itemCount
)
166 index
= tPtr
->itemCount
;
168 if (index
== 0 && tPtr
->items
[0]) {
169 W_UnmapTabViewItem(tPtr
->items
[0]);
172 if (index
< tPtr
->itemCount
) {
173 memmove(&tPtr
->items
[index
+ 1], &tPtr
->items
[index
],
174 tPtr
->itemCount
- index
);
177 tPtr
->items
[index
] = item
;
181 recalcTabWidth(tPtr
);
183 W_SetTabViewItemParent(item
, tPtr
);
185 W_UnmapTabViewItem(item
);
187 W_ReparentView(W_TabViewItemView(item
), tPtr
->view
, 1,
188 tPtr
->tabHeight
+ 1);
190 W_ResizeView(W_TabViewItemView(item
), tPtr
->view
->size
.width
- 3,
191 tPtr
->view
->size
.height
- tPtr
->tabHeight
- 3);
194 W_MapTabViewItem(item
);
196 if (tPtr
->delegate
&& tPtr
->delegate
->didChangeNumberOfItems
)
197 (*tPtr
->delegate
->didChangeNumberOfItems
)(tPtr
->delegate
, tPtr
);
202 WMRemoveTabViewItem(WMTabView
*tPtr
, WMTabViewItem
*item
)
206 for (i
= 0; i
< tPtr
->itemCount
; i
++) {
207 if (tPtr
->items
[i
] == item
) {
208 if (i
< tPtr
->itemCount
- 1)
209 memmove(&tPtr
->items
[i
], &tPtr
->items
[i
+ 1],
210 tPtr
->itemCount
- i
- 1);
212 tPtr
->items
[i
] = NULL
;
214 W_SetTabViewItemParent(item
, NULL
);
220 if (tPtr
->delegate
&& tPtr
->delegate
->didChangeNumberOfItems
)
221 (*tPtr
->delegate
->didChangeNumberOfItems
)(tPtr
->delegate
, tPtr
);
227 isInside(int x
, int y
, int width
, int height
, int px
, int py
)
229 if (py
>= y
+ height
- 3 && py
<= y
+ height
230 && px
>= x
+ py
- (y
+ height
- 3)
231 && px
<= x
+ width
- (py
- (y
+ height
- 3))) {
235 if (py
>= y
+ 3 && py
< y
+ height
- 3
236 && px
>= x
+ 3 + ((y
+ 3) - py
)*3/7
237 && px
<= x
+ width
- 3 - ((y
+ 3) - py
)*3/7) {
241 if (py
>= y
&& py
< y
+ 3
242 && px
>= x
+ 7 + py
- y
243 && px
<= x
+ width
- 7 - (py
- y
)) {
252 WMTabViewItemAtPoint(WMTabView
*tPtr
, int x
, int y
)
256 i
= tPtr
->selectedItem
;
257 if (isInside(8 + (tPtr
->tabWidth
-10)*i
, 0, tPtr
->tabWidth
,
258 tPtr
->tabHeight
, x
, y
)) {
259 return tPtr
->items
[i
];
262 for (i
= 0; i
< tPtr
->itemCount
; i
++) {
263 if (isInside(8 + (tPtr
->tabWidth
-10)*i
, 0, tPtr
->tabWidth
,
264 tPtr
->tabHeight
, x
, y
)) {
265 return tPtr
->items
[i
];
273 WMSelectFirstTabViewItem(WMTabView
*tPtr
)
275 WMSelectTabViewItemAtIndex(tPtr
, 0);
280 WMSelectLastTabViewItem(WMTabView
*tPtr
)
282 WMSelectTabViewItemAtIndex(tPtr
, tPtr
->itemCount
);
287 WMSelectNextTabViewItem(WMTabView
*tPtr
)
289 WMSelectTabViewItemAtIndex(tPtr
, tPtr
->selectedItem
+ 1);
294 WMSelectPreviousTabViewItem(WMTabView
*tPtr
)
296 WMSelectTabViewItemAtIndex(tPtr
, tPtr
->selectedItem
- 1);
301 WMGetSelectedTabViewItem(WMTabView
*tPtr
)
303 return tPtr
->items
[tPtr
->selectedItem
];
308 WMSelectTabViewItem(WMTabView
*tPtr
, WMTabViewItem
*item
)
312 for (i
= 0; i
< tPtr
->itemCount
; i
++) {
313 if (tPtr
->items
[i
] == item
) {
314 WMSelectTabViewItemAtIndex(tPtr
, i
);
322 WMSelectTabViewItemAtIndex(WMTabView
*tPtr
, int index
)
326 if (index
== tPtr
->selectedItem
)
331 else if (index
>= tPtr
->itemCount
)
332 index
= tPtr
->itemCount
- 1;
334 item
= tPtr
->items
[tPtr
->selectedItem
];
336 if (tPtr
->delegate
&& tPtr
->delegate
->shouldSelectItem
)
337 if (!(*tPtr
->delegate
->shouldSelectItem
)(tPtr
->delegate
, tPtr
,
341 if (tPtr
->delegate
&& tPtr
->delegate
->willSelectItem
)
342 (*tPtr
->delegate
->willSelectItem
)(tPtr
->delegate
, tPtr
,
345 W_UnmapTabViewItem(item
);
348 item
= tPtr
->items
[index
];
350 W_MapTabViewItem(item
);
352 tPtr
->selectedItem
= index
;
354 if (tPtr
->delegate
&& tPtr
->delegate
->didSelectItem
)
355 (*tPtr
->delegate
->didSelectItem
)(tPtr
->delegate
, tPtr
,
361 recalcTabWidth(TabView
*tPtr
)
364 int twidth
= W_VIEW(tPtr
)->size
.width
;
368 for (i
= 0; i
< tPtr
->itemCount
; i
++) {
369 char *str
= WMGetTabViewItemLabel(tPtr
->items
[i
]);
372 width
= WMWidthOfString(tPtr
->font
, str
, strlen(str
));
373 if (width
> tPtr
->tabWidth
)
374 tPtr
->tabWidth
= width
;
377 tPtr
->tabWidth
+= 30;
378 if (tPtr
->tabWidth
> twidth
- 10 * tPtr
->itemCount
379 && tPtr
->tabWidth
< twidth
- 16)
380 tPtr
->tabWidth
= (twidth
- 16) / tPtr
->itemCount
;
385 drawRelief(W_Screen
*scr
, Drawable d
, int x
, int y
, unsigned int width
,
388 Display
*dpy
= scr
->display
;
389 GC bgc
= WMColorGC(scr
->black
);
390 GC wgc
= WMColorGC(scr
->white
);
391 GC dgc
= WMColorGC(scr
->darkGray
);
393 XDrawLine(dpy
, d
, wgc
, x
, y
, x
, y
+height
-1);
395 XDrawLine(dpy
, d
, bgc
, x
, y
+height
-1, x
+width
-1, y
+height
-1);
396 XDrawLine(dpy
, d
, dgc
, x
+1, y
+height
-2, x
+width
-2, y
+height
-2);
398 XDrawLine(dpy
, d
, bgc
, x
+width
-1, y
, x
+width
-1, y
+height
-1);
399 XDrawLine(dpy
, d
, dgc
, x
+width
-2, y
+1, x
+width
-2, y
+height
-2);
404 drawTab(TabView
*tPtr
, Drawable d
, int x
, int y
,
405 unsigned width
, unsigned height
, Bool selected
)
407 WMScreen
*scr
= W_VIEW(tPtr
)->screen
;
408 Display
*dpy
= scr
->display
;
409 GC white
= WMColorGC(selected
? scr
->white
: tPtr
->lightGray
);
410 GC black
= WMColorGC(scr
->black
);
411 GC dark
= WMColorGC(scr
->darkGray
);
412 GC light
= WMColorGC(scr
->gray
);
415 trap
[0].x
= x
+ (selected
? 0 : 1);
416 trap
[0].y
= y
+ height
- (selected
? 0 : 1);
419 trap
[1].y
= y
+ height
- 3;
421 trap
[2].x
= x
+ 10 - 3;
427 trap
[4].x
= x
+ width
- 10;
430 trap
[5].x
= x
+ width
- 10 + 3;
433 trap
[6].x
= x
+ width
- 3;
434 trap
[6].y
= y
+ height
- 3;
436 trap
[7].x
= x
+ width
- (selected
? 0 : 1);
437 trap
[7].y
= y
+ height
- (selected
? 0 : 1);
439 XFillPolygon(dpy
, d
, selected
? light
: WMColorGC(tPtr
->tabColor
), trap
, 8,
440 Convex
, CoordModeOrigin
);
442 XDrawLine(dpy
, d
, white
, trap
[0].x
, trap
[0].y
, trap
[1].x
, trap
[1].y
);
443 XDrawLine(dpy
, d
, white
, trap
[1].x
, trap
[1].y
, trap
[2].x
, trap
[2].y
);
444 XDrawLine(dpy
, d
, white
, trap
[2].x
, trap
[2].y
, trap
[3].x
, trap
[3].y
);
445 XDrawLine(dpy
, d
, white
, trap
[3].x
, trap
[3].y
, trap
[4].x
, trap
[4].y
);
446 XDrawLine(dpy
, d
, dark
, trap
[4].x
, trap
[4].y
, trap
[5].x
, trap
[5].y
);
447 XDrawLine(dpy
, d
, black
, trap
[5].x
, trap
[5].y
, trap
[6].x
, trap
[6].y
);
448 XDrawLine(dpy
, d
, black
, trap
[6].x
, trap
[6].y
, trap
[7].x
, trap
[7].y
);
450 XDrawLine(dpy
, d
, selected
? light
: WMColorGC(scr
->white
),
451 trap
[0].x
, trap
[0].y
, trap
[7].x
, trap
[7].y
);
456 paintTabView(TabView
*tPtr
)
459 WMScreen
*scr
= W_VIEW(tPtr
)->screen
;
460 Display
*dpy
= scr
->display
;
461 GC white
= WMColorGC(scr
->white
);
465 if (tPtr
->flags
.type
== WTTopTabsBevelBorder
) {
466 buffer
= XCreatePixmap(dpy
, W_VIEW(tPtr
)->window
,
467 W_VIEW(tPtr
)->size
.width
, tPtr
->tabHeight
,
468 W_VIEW(tPtr
)->screen
->depth
);
470 XFillRectangle(dpy
, buffer
, WMColorGC(W_VIEW(tPtr
)->backColor
),
471 0, 0, W_VIEW(tPtr
)->size
.width
, tPtr
->tabHeight
);
475 rect
.size
.width
= tPtr
->tabWidth
;
476 rect
.size
.height
= tPtr
->tabHeight
;
478 for (i
= tPtr
->itemCount
- 1; i
>= 0; i
--) {
479 if (i
!= tPtr
->selectedItem
) {
480 drawTab(tPtr
, buffer
, 8 + (rect
.size
.width
-10)*i
, 0,
481 rect
.size
.width
, rect
.size
.height
, False
);
484 drawTab(tPtr
, buffer
, 8 + (rect
.size
.width
-10) * tPtr
->selectedItem
,
485 0, rect
.size
.width
, rect
.size
.height
, True
);
487 XDrawLine(dpy
, buffer
, white
, 0, tPtr
->tabHeight
- 1,
488 8, tPtr
->tabHeight
- 1);
490 XDrawLine(dpy
, buffer
, white
,
491 8 + 10 + (rect
.size
.width
-10) * tPtr
->itemCount
,
492 tPtr
->tabHeight
- 1, W_VIEW(tPtr
)->size
.width
- 1,
493 tPtr
->tabHeight
- 1);
496 for (i
= 0; i
< tPtr
->itemCount
; i
++) {
497 W_DrawLabel(tPtr
->items
[i
], buffer
, rect
);
499 rect
.pos
.x
+= rect
.size
.width
- 10;
502 XCopyArea(dpy
, buffer
, W_VIEW(tPtr
)->window
, scr
->copyGC
, 0, 0,
503 W_VIEW(tPtr
)->size
.width
, tPtr
->tabHeight
, 0, 0);
505 XFreePixmap(dpy
, buffer
);
507 switch (tPtr
->flags
.type
) {
508 case WTTopTabsBevelBorder
:
509 drawRelief(scr
, W_VIEW(tPtr
)->window
, 0, tPtr
->tabHeight
- 1,
510 W_VIEW(tPtr
)->size
.width
,
511 W_VIEW(tPtr
)->size
.height
- tPtr
->tabHeight
+ 1);
514 case WTNoTabsBevelBorder
:
515 W_DrawRelief(scr
, W_VIEW(tPtr
)->window
, 0, 0, W_VIEW(tPtr
)->size
.width
,
516 W_VIEW(tPtr
)->size
.height
, WRRaised
);
519 case WTNoTabsLineBorder
:
520 W_DrawRelief(scr
, W_VIEW(tPtr
)->window
, 0, 0, W_VIEW(tPtr
)->size
.width
,
521 W_VIEW(tPtr
)->size
.height
, WRSimple
);
524 case WTNoTabsNoBorder
:
531 destroyTabView(TabView
*tPtr
)
535 for (i
= 0; i
< tPtr
->itemCount
; i
++) {
536 WMSetTabViewItemView(tPtr
->items
[i
], NULL
);
537 WMDestroyTabViewItem(tPtr
->items
[i
]);
541 WMReleaseColor(tPtr
->lightGray
);
542 WMReleaseColor(tPtr
->tabColor
);
543 WMReleaseFont(tPtr
->font
);
548 /******************************************************************/
551 typedef struct W_TabViewItem
{
567 W_SetTabViewItemParent(WMTabViewItem
*item
, WMTabView
*parent
)
569 item
->tabView
= parent
;
574 W_DrawLabel(WMTabViewItem
*item
, Drawable d
, WMRect rect
)
576 WMScreen
*scr
= W_VIEW(item
->tabView
)->screen
;
581 WMDrawString(scr
, d
, WMColorGC(scr
->black
), item
->tabView
->font
,
582 rect
.pos
.x
, rect
.pos
.y
, item
->label
, strlen(item
->label
));
587 W_UnmapTabViewItem(WMTabViewItem
*item
)
589 wassertr(item
->view
);
591 W_UnmapView(item
->view
);
593 item
->flags
.visible
= 0;
598 W_MapTabViewItem(WMTabViewItem
*item
)
600 wassertr(item
->view
);
602 W_MapView(item
->view
);
604 item
->flags
.visible
= 1;
609 W_TabViewItemView(WMTabViewItem
*item
)
616 WMCreateTabViewItemWithIdentifier(int identifier
)
620 item
= wmalloc(sizeof(WMTabViewItem
));
621 memset(item
, 0, sizeof(WMTabViewItem
));
623 item
->identifier
= identifier
;
630 WMGetTabViewItemIdentifier(WMTabViewItem
*item
)
632 return item
->identifier
;
637 WMSetTabViewFont(WMTabView
*tPtr
, WMFont
*font
)
640 WMReleaseFont(tPtr
->font
);
642 tPtr
->font
= WMRetainFont(font
);
643 tPtr
->tabHeight
= WMFontHeight(tPtr
->font
) + 3;
644 recalcTabWidth(tPtr
);
649 WMSetTabViewItemLabel(WMTabViewItem
*item
, char *label
)
654 item
->label
= wstrdup(label
);
657 recalcTabWidth(item
->tabView
);
662 WMGetTabViewItemLabel(WMTabViewItem
*item
)
669 WMSetTabViewItemView(WMTabViewItem
*item
, WMView
*view
)
676 WMGetTabViewItemView(WMTabViewItem
*item
)
683 WMDestroyTabViewItem(WMTabViewItem
*item
)
689 W_DestroyView(item
->view
);