1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 12:28:22 +01:00
Files
wmaker/WINGs/wtabview.c
dan 33cc542e85 - Finished moving to the new proplist handling code in WINGs.
- Also tested the backward compatibility ability of the WINGs proplist code
  which seems to work quite well.

Starting with this moment, Window Maker no longer needs libPropList and is
now using the better and much more robust proplist code from WINGs. Also the
WINGs based proplist code is actively maintained while the old libPropList
code is practically dead and flawed by the fact that it borrowed concepts
from the UserDefaults which conflicted with the retain/release mechanism,
making some problems that libPropList had, practically unsolvable without a
complete redesign (which can be found in the more robust WINGs code).
2001-10-04 03:07:34 +00:00

1027 lines
22 KiB
C

#include "WINGsP.h"
typedef struct W_TabView {
W_Class widgetClass;
W_View *view;
struct W_TabViewItem **items;
int itemCount;
int maxItems; /* size of items array, can be increased */
int selectedItem;
int firstVisible;
int visibleTabs;
WMFont *font;
WMColor *lightGray;
WMColor *tabColor;
WMTabViewDelegate *delegate;
short tabHeight;
struct {
WMReliefType relief:4;
WMTitlePosition titlePosition:4;
WMTabViewType type:2;
unsigned enabled:1;
unsigned tabbed:1;
unsigned dontFitAll:1;
unsigned bordered:1;
unsigned uniformTabs:1;
} flags;
} TabView;
#define DEFAULT_WIDTH 40
#define DEFAULT_HEIGHT 40
#define NORMAL_SIDE_OFFSET 8
#define BUTTONED_SIDE_OFFSET 15
static void destroyTabView(TabView *tPtr);
static void paintTabView(TabView *tPtr);
static void W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent);
static void W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect,
Bool enabled);
static void W_UnmapTabViewItem(WMTabViewItem *item);
static void W_MapTabViewItem(WMTabViewItem *item);
static WMView *W_TabViewItemView(WMTabViewItem *item);
static int W_TabViewItemTabWidth(WMTabViewItem *item);
static void W_SetTabViewItemTabWidth(WMTabViewItem *item, int width);
static void recalcTabWidth(TabView *tPtr);
static void rearrange(TabView *tPtr);
static void didResize(struct W_ViewDelegate*, WMView*);
static W_ViewDelegate delegate = {
NULL,
NULL,
didResize,
NULL,
NULL
};
static int
positionOfTab(WMTabView *tabView, int tab)
{
int i;
int offs;
if (tab < tabView->firstVisible)
return -1;
if (tab > tabView->firstVisible + tabView->visibleTabs)
return -1;
if (tabView->flags.dontFitAll)
offs = BUTTONED_SIDE_OFFSET;
else
offs = NORMAL_SIDE_OFFSET;
for (i = tabView->firstVisible; i < tab; i++)
offs += W_TabViewItemTabWidth(tabView->items[i]) - 10;
return offs;
}
static int
countVisibleTabs(TabView *tPtr, int first)
{
int i;
int width;
if (first < 0) {
width = W_VIEW_WIDTH(tPtr->view) - 2 * NORMAL_SIDE_OFFSET;
first = 0;
} else {
width = W_VIEW_WIDTH(tPtr->view) - 2 * BUTTONED_SIDE_OFFSET;
}
for (i = first; i < tPtr->itemCount; i++) {
width -= W_TabViewItemTabWidth(tPtr->items[i]) - 10;
if (width <= 0) {
return i - first;
}
}
return i - first;
}
static void
handleEvents(XEvent *event, void *data)
{
TabView *tPtr = (TabView*)data;
CHECK_CLASS(data, WC_TabView);
switch (event->type) {
case Expose:
if (event->xexpose.count!=0)
break;
paintTabView(tPtr);
break;
case ButtonPress:
if (tPtr->flags.enabled) {
WMTabViewItem *item = WMTabViewItemAtPoint(tPtr,
event->xbutton.x,
event->xbutton.y);
if (item) {
WMSelectTabViewItem(tPtr, item);
} else if (tPtr->flags.dontFitAll) {
int redraw = 0;
int lastVisible = tPtr->firstVisible+tPtr->visibleTabs-1;
if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
if (tPtr->firstVisible > 0) {
redraw = 1;
tPtr->firstVisible--;
}
} else if (event->xbutton.x > positionOfTab(tPtr,lastVisible)){
if (lastVisible < tPtr->itemCount-1) {
redraw = 1;
tPtr->firstVisible++;
}
}
tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
if (redraw) {
paintTabView(tPtr);
}
}
}
break;
case DestroyNotify:
destroyTabView(tPtr);
break;
}
}
WMTabView*
WMCreateTabView(WMWidget *parent)
{
TabView *tPtr;
WMScreen *scr = WMWidgetScreen(parent);
tPtr = wmalloc(sizeof(TabView));
memset(tPtr, 0, sizeof(TabView));
tPtr->widgetClass = WC_TabView;
tPtr->view = W_CreateView(W_VIEW(parent));
if (!tPtr->view) {
wfree(tPtr);
return NULL;
}
tPtr->view->self = tPtr;
tPtr->view->delegate = &delegate;
tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
tPtr->font = WMRetainFont(scr->normalFont);
tPtr->flags.type = WTTopTabsBevelBorder;
tPtr->flags.bordered = 1;
tPtr->flags.uniformTabs = 0;
tPtr->flags.enabled = 1;
WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
|ButtonPressMask, handleEvents, tPtr);
WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
return tPtr;
}
void
WMSetTabViewDelegate(WMTabView *tPtr, WMTabViewDelegate *delegate)
{
tPtr->delegate = delegate;
}
WMTabViewItem*
WMAddTabViewItemWithView(WMTabView *tPtr, WMView *view, int identifier,
char *label)
{
WMTabViewItem *item;
item = WMCreateTabViewItemWithIdentifier(identifier);
WMSetTabViewItemView(item, view);
WMAddItemInTabView(tPtr, item);
WMSetTabViewItemLabel(item, label);
return item;
}
void
WMAddItemInTabView(WMTabView *tPtr, WMTabViewItem *item)
{
WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
}
void
WMSetTabViewEnabled(WMTabView *tPtr, Bool flag)
{
tPtr->flags.enabled = flag;
if (W_VIEW_REALIZED(tPtr->view))
paintTabView(tPtr);
}
void
WMInsertItemInTabView(WMTabView *tPtr, int index, WMTabViewItem *item)
{
wassertr(W_TabViewItemView(item) != NULL);
if (tPtr->maxItems == tPtr->itemCount) {
WMTabViewItem **items;
items = wrealloc(tPtr->items,
sizeof(WMTabViewItem*) * (tPtr->maxItems + 10));
memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem*) * 10);
tPtr->items = items;
tPtr->maxItems += 10;
}
if (index > tPtr->itemCount)
index = tPtr->itemCount;
if (index == 0 && tPtr->items[0]) {
W_UnmapTabViewItem(tPtr->items[0]);
}
if (index < tPtr->itemCount) {
memmove(tPtr->items + index + 1, tPtr->items + index,
(tPtr->itemCount - index) * sizeof(WMTabViewItem*));
}
tPtr->items[index] = item;
tPtr->itemCount++;
recalcTabWidth(tPtr);
W_SetTabViewItemParent(item, tPtr);
W_UnmapTabViewItem(item);
if (tPtr->flags.bordered) {
W_ReparentView(W_TabViewItemView(item), tPtr->view, 1,
tPtr->tabHeight + 1);
W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width - 3,
tPtr->view->size.height - tPtr->tabHeight - 3);
} else {
W_ReparentView(W_TabViewItemView(item), tPtr->view, 0,
tPtr->tabHeight);
W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width,
tPtr->view->size.height - tPtr->tabHeight);
}
if (index == 0) {
W_MapTabViewItem(item);
}
if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
(*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
if (W_VIEW_REALIZED(tPtr->view))
paintTabView(tPtr);
}
void
WMRemoveTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
{
int i;
for (i = 0; i < tPtr->itemCount; i++) {
if (tPtr->items[i] == item) {
if (i < tPtr->itemCount - 1)
memmove(&tPtr->items[i], &tPtr->items[i + 1],
tPtr->itemCount - i - 1);
else
tPtr->items[i] = NULL;
W_SetTabViewItemParent(item, NULL);
tPtr->itemCount--;
break;
}
}
if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
(*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
}
static Bool
isInside(int x, int y, int width, int height, int px, int py)
{
if (py >= y + height - 3 && py <= y + height
&& px >= x + py - (y + height - 3)
&& px <= x + width - (py - (y + height - 3))) {
return True;
}
if (py >= y + 3 && py < y + height - 3
&& px >= x + 3 + ((y + 3) - py)*3/7
&& px <= x + width - 3 - ((y + 3) - py)*3/7) {
return True;
}
if (py >= y && py < y + 3
&& px >= x + 7 + py - y
&& px <= x + width - 7 - (py - y)) {
return True;
}
return False;
}
WMTabViewItem*
WMTabViewItemAtPoint(WMTabView *tPtr, int x, int y)
{
int i;
int count = tPtr->visibleTabs;
int first = tPtr->firstVisible;
if (tPtr->flags.dontFitAll) {
i = tPtr->selectedItem - tPtr->firstVisible;
if (i >= 0 && i < tPtr->visibleTabs
&& isInside(positionOfTab(tPtr, tPtr->selectedItem), 0,
W_TabViewItemTabWidth(tPtr->items[tPtr->selectedItem]),
tPtr->tabHeight, x, y)) {
return tPtr->items[tPtr->selectedItem];
}
} else {
i = tPtr->selectedItem;
if (isInside(positionOfTab(tPtr, i), 0,
W_TabViewItemTabWidth(tPtr->items[i]),
tPtr->tabHeight, x, y)) {
return tPtr->items[i];
}
}
for (i = first; i < first + count; i++) {
int pos;
pos = positionOfTab(tPtr, i);
if (isInside(pos, 0, W_TabViewItemTabWidth(tPtr->items[i]),
tPtr->tabHeight, x, y)) {
return tPtr->items[i];
}
}
return NULL;
}
void
WMSetTabViewType(WMTabView *tPtr, WMTabViewType type)
{
tPtr->flags.type = type;
if (type != WTTopTabsBevelBorder)
tPtr->tabHeight = 0;
else
tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
if (type == WTNoTabsNoBorder)
tPtr->flags.bordered = 0;
else
tPtr->flags.bordered = 1;
rearrange(tPtr);
}
void
WMSelectFirstTabViewItem(WMTabView *tPtr)
{
WMSelectTabViewItemAtIndex(tPtr, 0);
}
void
WMSelectLastTabViewItem(WMTabView *tPtr)
{
WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
}
void
WMSelectNextTabViewItem(WMTabView *tPtr)
{
WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
}
void
WMSelectPreviousTabViewItem(WMTabView *tPtr)
{
WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
}
WMTabViewItem*
WMGetSelectedTabViewItem(WMTabView *tPtr)
{
return tPtr->items[tPtr->selectedItem];
}
void
WMSelectTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
{
int i;
for (i = 0; i < tPtr->itemCount; i++) {
if (tPtr->items[i] == item) {
WMSelectTabViewItemAtIndex(tPtr, i);
break;
}
}
}
void
WMSelectTabViewItemAtIndex(WMTabView *tPtr, int index)
{
WMTabViewItem *item;
if (index == tPtr->selectedItem) {
return;
}
if (index < 0)
index = 0;
else if (index >= tPtr->itemCount)
index = tPtr->itemCount - 1;
item = tPtr->items[tPtr->selectedItem];
if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
if (!(*tPtr->delegate->shouldSelectItem)(tPtr->delegate, tPtr,
tPtr->items[index]))
return;
if (tPtr->delegate && tPtr->delegate->willSelectItem)
(*tPtr->delegate->willSelectItem)(tPtr->delegate, tPtr,
tPtr->items[index]);
W_UnmapTabViewItem(item);
item = tPtr->items[index];
W_MapTabViewItem(item);
tPtr->selectedItem = index;
if (tPtr->delegate && tPtr->delegate->didSelectItem)
(*tPtr->delegate->didSelectItem)(tPtr->delegate, tPtr,
tPtr->items[index]);
paintTabView(tPtr);
}
static void
recalcTabWidth(TabView *tPtr)
{
int i;
/*int twidth = W_VIEW(tPtr)->size.width;*/
int width;
if (tPtr->flags.uniformTabs) {
int tabWidth;
tabWidth = 0;
for (i = 0; i < tPtr->itemCount; i++) {
char *str = WMGetTabViewItemLabel(tPtr->items[i]);
if (str) {
width = WMWidthOfString(tPtr->font, str, strlen(str));
if (width > tabWidth)
tabWidth = width;
}
}
tabWidth = tabWidth + 30;
for (i = 0; i < tPtr->itemCount; i++)
W_SetTabViewItemTabWidth(tPtr->items[i], tabWidth);
tPtr->firstVisible = 0;
tPtr->visibleTabs = countVisibleTabs(tPtr, -1);
if (tPtr->visibleTabs < tPtr->itemCount)
tPtr->flags.dontFitAll = 1;
else
tPtr->flags.dontFitAll = 0;
} else {
for (i = 0; i < tPtr->itemCount; i++) {
char *str = WMGetTabViewItemLabel(tPtr->items[i]);
if (!str)
continue;
width = WMWidthOfString(tPtr->font, str, strlen(str)) + 30;
W_SetTabViewItemTabWidth(tPtr->items[i], width);
}
if (countVisibleTabs(tPtr, -1) < tPtr->itemCount) {
tPtr->flags.dontFitAll = 1;
tPtr->firstVisible = 0;
tPtr->visibleTabs = countVisibleTabs(tPtr, tPtr->firstVisible);
} else {
tPtr->flags.dontFitAll = 0;
tPtr->firstVisible = 0;
tPtr->visibleTabs = tPtr->itemCount;
}
}
}
static void
drawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
unsigned int height)
{
Display *dpy = scr->display;
GC bgc = WMColorGC(scr->black);
GC wgc = WMColorGC(scr->white);
GC dgc = WMColorGC(scr->darkGray);
XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
}
static void
drawTab(TabView *tPtr, Drawable d, int x, int y,
unsigned width, unsigned height, Bool selected)
{
WMScreen *scr = W_VIEW(tPtr)->screen;
Display *dpy = scr->display;
GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
GC black = WMColorGC(scr->black);
GC dark = WMColorGC(scr->darkGray);
GC light = WMColorGC(scr->gray);
XPoint trap[8];
trap[0].x = x + (selected ? 0 : 1);
trap[0].y = y + height - (selected ? 0 : 1);
trap[1].x = x + 3;
trap[1].y = y + height - 3;
trap[2].x = x + 10 - 3;
trap[2].y = y + 3;
trap[3].x = x + 10;
trap[3].y = y;
trap[4].x = x + width - 10;
trap[4].y = y;
trap[5].x = x + width - 10 + 3;
trap[5].y = y + 3;
trap[6].x = x + width - 3;
trap[6].y = y + height - 3;
trap[7].x = x + width - (selected ? 0 : 1);
trap[7].y = y + height - (selected ? 0 : 1);
XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8,
Convex, CoordModeOrigin);
XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
XDrawLine(dpy, d, dark, trap[4].x, trap[4].y, trap[5].x, trap[5].y);
XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white),
trap[0].x, trap[0].y, trap[7].x, trap[7].y);
}
static void
paintDot(TabView *tPtr, Drawable d, int x, int y)
{
WMScreen *scr = W_VIEW(tPtr)->screen;
Display *dpy = scr->display;
GC white = WMColorGC(scr->white);
GC black = WMColorGC(scr->black);
XFillRectangle(dpy, d, black, x, y, 2, 2);
XDrawPoint(dpy, d, white, x, y);
}
static void
paintTabView(TabView *tPtr)
{
Pixmap buffer;
WMScreen *scr = W_VIEW(tPtr)->screen;
Display *dpy = scr->display;
GC white = WMColorGC(scr->white);
int i;
if (tPtr->flags.type == WTTopTabsBevelBorder) {
int count = tPtr->visibleTabs;
int first = tPtr->firstVisible;
int moreAtLeft;
int moreAtRight;
int selectedIsVisible;
int ty;
int twidth, theight;
ty = 2;
theight = tPtr->tabHeight;
buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
W_VIEW(tPtr)->size.width, theight,
W_VIEW(tPtr)->screen->depth);
XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
if (tPtr->flags.dontFitAll) {
moreAtLeft = first > 0;
moreAtRight = (first + count) < tPtr->itemCount;
if (tPtr->selectedItem >= first
&& tPtr->selectedItem < first + count)
selectedIsVisible = 1;
else
selectedIsVisible = 0;
} else {
moreAtLeft = 0;
moreAtRight = 0;
selectedIsVisible = 1;
}
if (moreAtRight) {
drawTab(tPtr, buffer, positionOfTab(tPtr, first+count), 0,
W_VIEW_WIDTH(tPtr->view), theight, False);
}
for (i = first + count-1; i >= first; i--) {
if (!selectedIsVisible || i != tPtr->selectedItem) {
twidth = W_TabViewItemTabWidth(tPtr->items[i]);
drawTab(tPtr, buffer, positionOfTab(tPtr, i), 0,
twidth, theight, False);
}
}
if (moreAtLeft) {
drawTab(tPtr, buffer, positionOfTab(tPtr, 0)-2*BUTTONED_SIDE_OFFSET,
0, BUTTONED_SIDE_OFFSET*4, theight, False);
}
if (selectedIsVisible) {
int idx = tPtr->selectedItem;
drawTab(tPtr, buffer, positionOfTab(tPtr, idx),
0, W_TabViewItemTabWidth(tPtr->items[idx]),
theight, True);
XDrawLine(dpy, buffer, white, 0, theight - 1,
positionOfTab(tPtr, idx), theight - 1);
XDrawLine(dpy, buffer, white,
positionOfTab(tPtr, idx) + W_TabViewItemTabWidth(tPtr->items[idx]),
tPtr->tabHeight - 1, W_VIEW_WIDTH(tPtr->view) - 1,
tPtr->tabHeight - 1);
} else {
XDrawLine(dpy, buffer, white, 0, theight - 1,
W_VIEW_WIDTH(tPtr->view), theight - 1);
}
for (i = 0; i < count; i++) {
WMRect rect;
rect.pos.x = 15 + positionOfTab(tPtr, first+i);
rect.pos.y = ty;
rect.size.width = W_TabViewItemTabWidth(tPtr->items[first+i]);
rect.size.height = theight;
W_DrawLabel(tPtr->items[first+i], buffer, rect,
tPtr->flags.enabled);
}
if (moreAtLeft) {
paintDot(tPtr, buffer, 4, 10);
paintDot(tPtr, buffer, 7, 10);
paintDot(tPtr, buffer, 10, 10);
}
if (moreAtRight) {
int x;
x = positionOfTab(tPtr, tPtr->firstVisible + tPtr->visibleTabs);
x = x + (W_VIEW_WIDTH(tPtr->view) - x)/2;
paintDot(tPtr, buffer, x + 5, 10);
paintDot(tPtr, buffer, x + 8, 10);
paintDot(tPtr, buffer, x + 11, 10);
}
XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
W_VIEW_WIDTH(tPtr->view), theight, 0, 0);
XFreePixmap(dpy, buffer);
}
switch (tPtr->flags.type) {
case WTTopTabsBevelBorder:
drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
W_VIEW(tPtr)->size.width,
W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
break;
case WTNoTabsBevelBorder:
W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
W_VIEW(tPtr)->size.height, WRRaised);
break;
case WTNoTabsLineBorder:
W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
W_VIEW(tPtr)->size.height, WRSimple);
break;
case WTNoTabsNoBorder:
break;
}
}
static void
rearrange(TabView *tPtr)
{
int i;
int width, height;
int bordered = tPtr->flags.bordered;
recalcTabWidth(tPtr);
width = tPtr->view->size.width - (bordered ? 3 : 0);
height = tPtr->view->size.height - tPtr->tabHeight - (bordered ? 3 : 0);
for (i = 0; i < tPtr->itemCount; i++) {
W_MoveView(W_TabViewItemView(tPtr->items[i]),
1*bordered, tPtr->tabHeight + 1*bordered);
W_ResizeView(W_TabViewItemView(tPtr->items[i]), width, height);
}
if (W_VIEW_MAPPED(tPtr->view) && W_VIEW_REALIZED(tPtr->view))
paintTabView(tPtr);
}
static void
didResize(struct W_ViewDelegate *deleg, WMView *view)
{
rearrange(view->self);
}
static void
destroyTabView(TabView *tPtr)
{
int i;
for (i = 0; i < tPtr->itemCount; i++) {
WMSetTabViewItemView(tPtr->items[i], NULL);
WMDestroyTabViewItem(tPtr->items[i]);
}
wfree(tPtr->items);
WMReleaseColor(tPtr->lightGray);
WMReleaseColor(tPtr->tabColor);
WMReleaseFont(tPtr->font);
wfree(tPtr);
}
/******************************************************************/
typedef struct W_TabViewItem {
WMTabView *tabView;
W_View *view;
char *label;
short tabWidth;
int identifier;
struct {
unsigned visible:1;
} flags;
} TabViewItem;
static void
W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent)
{
item->tabView = parent;
}
static void
W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect, Bool enabled)
{
WMScreen *scr = W_VIEW(item->tabView)->screen;
if (!item->label)
return;
WMDrawString(scr, d, WMColorGC(enabled ? scr->black : scr->darkGray),
item->tabView->font, rect.pos.x, rect.pos.y,
item->label, strlen(item->label));
}
static void
W_UnmapTabViewItem(WMTabViewItem *item)
{
wassertr(item->view);
W_UnmapView(item->view);
item->flags.visible = 0;
}
static void
W_MapTabViewItem(WMTabViewItem *item)
{
wassertr(item->view);
W_MapView(item->view);
W_RaiseView(item->view);
item->flags.visible = 1;
}
static WMView*
W_TabViewItemView(WMTabViewItem *item)
{
return item->view;
}
static int
W_TabViewItemTabWidth(WMTabViewItem *item)
{
return item->tabWidth;
}
static void
W_SetTabViewItemTabWidth(WMTabViewItem *item, int width)
{
item->tabWidth = width;
}
WMTabViewItem*
WMCreateTabViewItemWithIdentifier(int identifier)
{
WMTabViewItem *item;
item = wmalloc(sizeof(WMTabViewItem));
memset(item, 0, sizeof(WMTabViewItem));
item->identifier = identifier;
return item;
}
WMTabViewItem*
WMCreateTabViewItem(int identifier, char *label)
{
WMTabViewItem *item;
item = wmalloc(sizeof(WMTabViewItem));
memset(item, 0, sizeof(WMTabViewItem));
item->identifier = identifier;
WMSetTabViewItemLabel(item, label);
return item;
}
int
WMGetTabViewItemIdentifier(WMTabViewItem *item)
{
return item->identifier;
}
void
WMSetTabViewFont(WMTabView *tPtr, WMFont *font)
{
if (tPtr->font)
WMReleaseFont(tPtr->font);
tPtr->font = WMRetainFont(font);
tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
recalcTabWidth(tPtr);
}
void
WMSetTabViewItemLabel(WMTabViewItem *item, char *label)
{
if (item->label)
wfree(item->label);
if (label)
item->label = wstrdup(label);
else
item->label = NULL;
if (item->tabView)
recalcTabWidth(item->tabView);
}
char*
WMGetTabViewItemLabel(WMTabViewItem *item)
{
return item->label;
}
void
WMSetTabViewItemView(WMTabViewItem *item, WMView *view)
{
item->view = view;
}
WMView*
WMGetTabViewItemView(WMTabViewItem *item)
{
return item->view;
}
void
WMDestroyTabViewItem(WMTabViewItem *item)
{
if (item->label)
wfree(item->label);
if (item->view)
W_DestroyView(item->view);
wfree(item);
}