Files
wmaker/WINGs/wtabview.c
T

903 lines
21 KiB
C
Raw Normal View History

1999-05-15 17:38:05 +00:00
#include "WINGsP.h"
typedef struct W_TabView {
2009-08-20 00:59:40 +02:00
W_Class widgetClass;
W_View *view;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
struct W_TabViewItem **items;
int itemCount;
int maxItems; /* size of items array, can be increased */
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
int selectedItem;
int firstVisible;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
int visibleTabs;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
WMFont *font;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
WMColor *lightGray;
WMColor *tabColor;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
WMTabViewDelegate *delegate;
1999-05-17 03:55:35 +00:00
2009-08-20 00:59:40 +02:00
short tabHeight;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
struct {
WMReliefType relief:4;
WMTitlePosition titlePosition:4;
WMTabViewType type:2;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
unsigned enabled:1;
unsigned tabbed:1;
unsigned dontFitAll:1;
unsigned bordered:1;
unsigned uniformTabs:1;
} flags;
1999-05-15 17:38:05 +00:00
} TabView;
typedef struct W_TabViewItem {
2009-08-20 00:59:40 +02:00
WMTabView *tabView;
2009-08-20 00:59:40 +02:00
W_View *view;
2009-08-20 00:59:40 +02:00
char *label;
2009-08-20 00:59:40 +02:00
short tabWidth;
int identifier;
2009-08-20 00:59:40 +02:00
struct {
unsigned visible:1;
unsigned enabled:1;
} flags;
} W_TabViewItem;
1999-05-15 17:38:05 +00:00
#define DEFAULT_WIDTH 40
#define DEFAULT_HEIGHT 40
2000-03-04 00:18:13 +00:00
#define NORMAL_SIDE_OFFSET 8
2001-01-02 14:17:26 +00:00
#define BUTTONED_SIDE_OFFSET 15
2000-03-04 00:18:13 +00:00
2009-08-20 00:59:40 +02:00
static void destroyTabView(TabView * tPtr);
static void paintTabView(TabView * tPtr);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
static void W_SetTabViewItemParent(WMTabViewItem * item, WMTabView * parent);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
static void W_DrawLabel(WMTabViewItem * item, Drawable d, WMRect rect, Bool enabled);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
static void W_UnmapTabViewItem(WMTabViewItem * item);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
static void W_MapTabViewItem(WMTabViewItem * item);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
static WMView *W_TabViewItemView(WMTabViewItem * item);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
static int W_TabViewItemTabWidth(WMTabViewItem * item);
2001-01-02 14:17:26 +00:00
2009-08-20 00:59:40 +02:00
static void W_SetTabViewItemTabWidth(WMTabViewItem * item, int width);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
static void recalcTabWidth(TabView * tPtr);
static void rearrange(TabView * tPtr);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
static void didResize(struct W_ViewDelegate *, WMView *);
2000-11-11 18:08:10 +00:00
static W_ViewDelegate delegate = {
2009-08-20 00:59:40 +02:00
NULL,
NULL,
didResize,
NULL,
NULL
2000-11-11 18:08:10 +00:00
};
2009-08-20 00:59:40 +02:00
static int positionOfTab(WMTabView * tabView, int tab)
2001-01-02 14:17:26 +00:00
{
2009-08-20 00:59:40 +02:00
int i;
int offs;
2004-10-12 21:28:27 +00:00
2010-10-08 15:08:30 -04:00
if (tab < 0 || tab < tabView->firstVisible)
2009-08-20 00:59:40 +02:00
return -1;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
if (tab > tabView->firstVisible + tabView->visibleTabs)
return -1;
2001-01-02 14:17:26 +00:00
2009-08-20 00:59:40 +02:00
if (tabView->flags.dontFitAll)
offs = BUTTONED_SIDE_OFFSET;
else
offs = NORMAL_SIDE_OFFSET;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
for (i = tabView->firstVisible; i < tab; i++)
offs += W_TabViewItemTabWidth(tabView->items[i]) - 10;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
return offs;
2001-01-02 14:17:26 +00:00
}
2009-08-20 00:59:40 +02:00
static int countVisibleTabs(TabView * tPtr, int first)
2001-01-02 14:17:26 +00:00
{
2009-08-20 00:59:40 +02:00
int i;
int width;
2001-01-02 14:17:26 +00:00
2009-08-20 00:59:40 +02:00
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;
}
2000-11-11 18:08:10 +00:00
2009-08-20 00:59:40 +02:00
for (i = first; i < tPtr->itemCount; i++) {
width -= W_TabViewItemTabWidth(tPtr->items[i]) - 10;
if (width <= 0) {
return i - first;
}
}
return i - first;
}
2000-11-11 18:08:10 +00:00
2009-08-20 00:59:40 +02:00
static void handleEvents(XEvent * event, void *data)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
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 && !item->flags.enabled)
break; */
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (item && item->flags.enabled) {
WMSelectTabViewItem(tPtr, item);
} else if (tPtr->flags.dontFitAll) {
int redraw = 0;
int lastVisible = tPtr->firstVisible + tPtr->visibleTabs - 1;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
if (tPtr->firstVisible > 0) {
redraw = 1;
tPtr->firstVisible--;
}
} else if (event->xbutton.x > positionOfTab(tPtr, lastVisible)) {
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
TabView *tPtr;
WMScreen *scr = WMWidgetScreen(parent);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
tPtr = wmalloc(sizeof(TabView));
tPtr->widgetClass = WC_TabView;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
tPtr->view = W_CreateView(W_VIEW(parent));
if (!tPtr->view) {
wfree(tPtr);
return NULL;
}
tPtr->view->self = tPtr;
tPtr->view->delegate = &delegate;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
tPtr->font = WMRetainFont(scr->normalFont);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
tPtr->flags.type = WTTopTabsBevelBorder;
tPtr->flags.bordered = 1;
tPtr->flags.uniformTabs = 0;
tPtr->flags.enabled = 1;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
WMCreateEventHandler(tPtr->view, ExposureMask | StructureNotifyMask | ButtonPressMask, handleEvents, tPtr);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
return tPtr;
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSetTabViewDelegate(WMTabView * tPtr, WMTabViewDelegate * delegate)
1999-05-17 03:55:35 +00:00
{
2009-08-20 00:59:40 +02:00
tPtr->delegate = delegate;
1999-05-17 03:55:35 +00:00
}
WMTabViewItem *WMAddTabViewItemWithView(WMTabView * tPtr, WMView * view, int identifier, const char *label)
2000-11-09 14:07:48 +00:00
{
2009-08-20 00:59:40 +02:00
WMTabViewItem *item;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
item = WMCreateTabViewItemWithIdentifier(identifier);
WMSetTabViewItemView(item, view);
WMAddItemInTabView(tPtr, item);
WMSetTabViewItemLabel(item, label);
2000-11-09 14:07:48 +00:00
2009-08-20 00:59:40 +02:00
return item;
2000-11-09 14:07:48 +00:00
}
2009-08-20 00:59:40 +02:00
void WMAddItemInTabView(WMTabView * tPtr, WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSetTabViewEnabled(WMTabView * tPtr, Bool flag)
2001-01-10 21:10:39 +00:00
{
2009-08-20 00:59:40 +02:00
tPtr->flags.enabled = ((flag == 0) ? 0 : 1);
if (W_VIEW_REALIZED(tPtr->view))
paintTabView(tPtr);
2001-01-10 21:10:39 +00:00
}
2009-08-20 00:59:40 +02:00
void WMInsertItemInTabView(WMTabView * tPtr, int index, WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
wassertr(W_TabViewItemView(item) != NULL);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (tPtr->maxItems == tPtr->itemCount) {
WMTabViewItem **items;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
items = wrealloc(tPtr->items, sizeof(WMTabViewItem *) * (tPtr->maxItems + 10));
memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem *) * 10); /* XXX */
2009-08-20 00:59:40 +02:00
tPtr->items = items;
tPtr->maxItems += 10;
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (index > tPtr->itemCount)
index = tPtr->itemCount;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (index == 0 && tPtr->items[0]) {
W_UnmapTabViewItem(tPtr->items[0]);
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (index < tPtr->itemCount) {
memmove(tPtr->items + index + 1, tPtr->items + index,
(tPtr->itemCount - index) * sizeof(WMTabViewItem *));
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
tPtr->items[index] = item;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
tPtr->itemCount++;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
recalcTabWidth(tPtr);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
W_SetTabViewItemParent(item, tPtr);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
W_UnmapTabViewItem(item);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (tPtr->flags.bordered) {
W_ReparentView(W_TabViewItemView(item), tPtr->view, 1, tPtr->tabHeight + 1);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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);
2001-01-02 14:17:26 +00:00
2009-08-20 00:59:40 +02:00
W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width,
tPtr->view->size.height - tPtr->tabHeight);
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (index == 0) {
W_MapTabViewItem(item);
}
if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
(*tPtr->delegate->didChangeNumberOfItems) (tPtr->delegate, tPtr);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
if (W_VIEW_REALIZED(tPtr->view))
paintTabView(tPtr);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
void WMRemoveTabViewItem(WMTabView * tPtr, WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
int i;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
W_SetTabViewItemParent(item, NULL);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
tPtr->itemCount--;
break;
}
}
if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
(*tPtr->delegate->didChangeNumberOfItems) (tPtr->delegate, tPtr);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
static Bool isInside(int x, int y, int width, int height, int px, int py)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
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) {
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
return True;
}
if (py >= y && py < y + 3 && px >= x + 7 + py - y && px <= x + width - 7 - (py - y)) {
return True;
}
return False;
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
WMTabViewItem *WMTabViewItemAtPoint(WMTabView * tPtr, int x, int y)
2000-11-13 13:22:22 +00:00
{
2009-08-20 00:59:40 +02:00
int i;
int count = tPtr->visibleTabs;
int first = tPtr->firstVisible;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
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];
}
}
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
for (i = first; i < first + count; i++) {
int pos;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
pos = positionOfTab(tPtr, i);
if (isInside(pos, 0, W_TabViewItemTabWidth(tPtr->items[i]), tPtr->tabHeight, x, y)) {
return tPtr->items[i];
}
}
return NULL;
2000-11-13 13:22:22 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSetTabViewType(WMTabView * tPtr, WMTabViewType type)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
tPtr->flags.type = type;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (type != WTTopTabsBevelBorder)
tPtr->tabHeight = 0;
else
tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (type == WTNoTabsNoBorder)
tPtr->flags.bordered = 0;
else
tPtr->flags.bordered = 1;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
rearrange(tPtr);
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
void WMSelectFirstTabViewItem(WMTabView * tPtr)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
WMSelectTabViewItemAtIndex(tPtr, 0);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSelectLastTabViewItem(WMTabView * tPtr)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSelectNextTabViewItem(WMTabView * tPtr)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSelectPreviousTabViewItem(WMTabView * tPtr)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
WMTabViewItem *WMGetSelectedTabViewItem(WMTabView * tPtr)
{
return tPtr->items[tPtr->selectedItem];
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
void WMSelectTabViewItem(WMTabView * tPtr, WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
int i;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
for (i = 0; i < tPtr->itemCount; i++) {
if (tPtr->items[i] == item) {
WMSelectTabViewItemAtIndex(tPtr, i);
break;
}
}
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
void WMSelectTabViewItemAtIndex(WMTabView * tPtr, int index)
{
WMTabViewItem *item;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (index == tPtr->selectedItem) {
return;
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (index < 0)
index = 0;
else if (index >= tPtr->itemCount)
index = tPtr->itemCount - 1;
1999-05-17 03:55:35 +00:00
2009-08-20 00:59:40 +02:00
item = tPtr->items[tPtr->selectedItem];
1999-05-17 03:55:35 +00:00
2009-08-20 00:59:40 +02:00
if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
if (!(*tPtr->delegate->shouldSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]))
return;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (tPtr->delegate && tPtr->delegate->willSelectItem)
(*tPtr->delegate->willSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
W_UnmapTabViewItem(item);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
item = tPtr->items[index];
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
W_MapTabViewItem(item);
1999-05-17 03:55:35 +00:00
2009-08-20 00:59:40 +02:00
tPtr->selectedItem = index;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
if (tPtr->delegate && tPtr->delegate->didSelectItem)
(*tPtr->delegate->didSelectItem) (tPtr->delegate, tPtr, tPtr->items[index]);
paintTabView(tPtr);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
static void recalcTabWidth(TabView * tPtr)
{
int i;
/*int twidth = W_VIEW(tPtr)->size.width; */
int width;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (tPtr->flags.uniformTabs) {
int tabWidth;
2001-01-02 14:17:26 +00:00
2009-08-20 00:59:40 +02:00
tabWidth = 0;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
for (i = 0; i < tPtr->itemCount; i++) {
char *str = WMGetTabViewItemLabel(tPtr->items[i]);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (str) {
width = WMWidthOfString(tPtr->font, str, strlen(str));
if (width > tabWidth)
tabWidth = width;
}
}
tabWidth = tabWidth + 30;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
for (i = 0; i < tPtr->itemCount; i++)
W_SetTabViewItemTabWidth(tPtr->items[i], tabWidth);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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;
}
}
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
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);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
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];
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
trap[0].x = x + (selected ? 0 : 1);
trap[0].y = y + height - (selected ? 0 : 1);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
trap[1].x = x + 3;
trap[1].y = y + height - 3;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
trap[2].x = x + 10 - 3;
trap[2].y = y + 3;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
trap[3].x = x + 10;
trap[3].y = y;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
trap[4].x = x + width - 10;
trap[4].y = y;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
trap[5].x = x + width - 10 + 3;
trap[5].y = y + 3;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
trap[6].x = x + width - 3;
trap[6].y = y + height - 3;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
trap[7].x = x + width - (selected ? 0 : 1);
trap[7].y = y + height - (selected ? 0 : 1);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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]);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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);
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (selectedIsVisible) {
int idx = tPtr->selectedItem;
2000-03-04 00:18:13 +00:00
2009-08-20 00:59:40 +02:00
drawTab(tPtr, buffer, positionOfTab(tPtr, idx),
0, W_TabViewItemTabWidth(tPtr->items[idx]), theight, True);
2000-03-04 00:18:13 +00:00
2009-08-20 00:59:40 +02:00
XDrawLine(dpy, buffer, white, 0, theight - 1, positionOfTab(tPtr, idx), theight - 1);
2000-03-04 00:18:13 +00:00
2009-08-20 00:59:40 +02:00
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);
}
2000-03-04 00:18:13 +00:00
2009-08-20 00:59:40 +02:00
for (i = 0; i < count; i++) {
WMRect rect;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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 && tPtr->items[first + i]->flags.enabled);
}
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
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;
}
2000-11-11 18:08:10 +00:00
}
2009-08-20 00:59:40 +02:00
static void rearrange(TabView * tPtr)
{
int i;
int width, height;
int bordered = tPtr->flags.bordered;
recalcTabWidth(tPtr);
2000-11-11 18:08:10 +00:00
2009-08-20 00:59:40 +02:00
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);
2000-11-11 18:08:10 +00:00
}
2009-08-20 00:59:40 +02:00
static void didResize(struct W_ViewDelegate *deleg, WMView * view)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) deleg;
2009-08-20 00:59:40 +02:00
rearrange(view->self);
}
2000-11-11 18:08:10 +00:00
2009-08-20 00:59:40 +02:00
static void destroyTabView(TabView * tPtr)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
int i;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
for (i = 0; i < tPtr->itemCount; i++) {
WMSetTabViewItemView(tPtr->items[i], NULL);
WMDestroyTabViewItem(tPtr->items[i]);
}
wfree(tPtr->items);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
WMReleaseColor(tPtr->lightGray);
WMReleaseColor(tPtr->tabColor);
WMReleaseFont(tPtr->font);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
wfree(tPtr);
1999-05-15 17:38:05 +00:00
}
/******************************************************************/
2009-08-20 00:59:40 +02:00
static void W_SetTabViewItemParent(WMTabViewItem * item, WMTabView * parent)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
item->tabView = parent;
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
static void W_DrawLabel(WMTabViewItem * item, Drawable d, WMRect rect, Bool enabled)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
WMScreen *scr = W_VIEW(item->tabView)->screen;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (!item->label)
return;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
WMDrawString(scr, d, enabled ? scr->black : scr->darkGray,
item->tabView->font, rect.pos.x, rect.pos.y, item->label, strlen(item->label));
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
static void W_UnmapTabViewItem(WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
wassertr(item->view);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
W_UnmapView(item->view);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
item->flags.visible = 0;
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
static void W_MapTabViewItem(WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
wassertr(item->view);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
W_MapView(item->view);
W_RaiseView(item->view);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
item->flags.visible = 1;
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
static WMView *W_TabViewItemView(WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
return item->view;
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
static int W_TabViewItemTabWidth(WMTabViewItem * item)
2001-01-02 14:17:26 +00:00
{
2009-08-20 00:59:40 +02:00
return item->tabWidth;
2001-01-02 14:17:26 +00:00
}
2009-08-20 00:59:40 +02:00
static void W_SetTabViewItemTabWidth(WMTabViewItem * item, int width)
2001-01-02 14:17:26 +00:00
{
2009-08-20 00:59:40 +02:00
item->tabWidth = width;
2001-01-02 14:17:26 +00:00
}
2009-08-20 00:59:40 +02:00
WMTabViewItem *WMCreateTabViewItemWithIdentifier(int identifier)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
WMTabViewItem *item;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
item = wmalloc(sizeof(WMTabViewItem));
item->identifier = identifier;
item->flags.enabled = 1;
2009-08-20 00:59:40 +02:00
return item;
1999-05-15 17:38:05 +00:00
}
WMTabViewItem *WMCreateTabViewItem(int identifier, const char *label)
2000-07-10 22:37:39 +00:00
{
2009-08-20 00:59:40 +02:00
WMTabViewItem *item;
2000-07-10 22:37:39 +00:00
2009-08-20 00:59:40 +02:00
item = wmalloc(sizeof(WMTabViewItem));
item->identifier = identifier;
item->flags.enabled = 1;
2009-08-20 00:59:40 +02:00
WMSetTabViewItemLabel(item, label);
2000-07-10 22:37:39 +00:00
2009-08-20 00:59:40 +02:00
return item;
2000-07-10 22:37:39 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSetTabViewItemEnabled(WMTabViewItem * tPtr, Bool flag)
{
2009-08-20 00:59:40 +02:00
tPtr->flags.enabled = ((flag == 0) ? 0 : 1);
if (tPtr->tabView && W_VIEW_REALIZED(tPtr->tabView->view))
paintTabView(tPtr->tabView);
}
2009-08-20 00:59:40 +02:00
int WMGetTabViewItemIdentifier(WMTabViewItem * item)
1999-05-17 03:55:35 +00:00
{
2009-08-20 00:59:40 +02:00
return item->identifier;
1999-05-17 03:55:35 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSetTabViewFont(WMTabView * tPtr, WMFont * font)
1999-05-16 15:11:13 +00:00
{
2009-08-20 00:59:40 +02:00
if (tPtr->font)
WMReleaseFont(tPtr->font);
1999-05-16 15:11:13 +00:00
2009-08-20 00:59:40 +02:00
tPtr->font = WMRetainFont(font);
tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
recalcTabWidth(tPtr);
1999-05-16 15:11:13 +00:00
}
void WMSetTabViewItemLabel(WMTabViewItem * item, const char *label)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
if (item->label)
wfree(item->label);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (label)
item->label = wstrdup(label);
else
item->label = NULL;
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (item->tabView)
recalcTabWidth(item->tabView);
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
char *WMGetTabViewItemLabel(WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
return item->label;
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSetTabViewItemView(WMTabViewItem * item, WMView * view)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
item->view = view;
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
WMView *WMGetTabViewItemView(WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
return item->view;
1999-05-15 17:38:05 +00:00
}
2009-08-20 00:59:40 +02:00
void WMDestroyTabViewItem(WMTabViewItem * item)
1999-05-15 17:38:05 +00:00
{
2009-08-20 00:59:40 +02:00
if (item->label)
wfree(item->label);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
if (item->view)
W_DestroyView(item->view);
1999-05-15 17:38:05 +00:00
2009-08-20 00:59:40 +02:00
wfree(item);
1999-05-15 17:38:05 +00:00
}