summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ui_demos.c25
-rw-r--r--src/ui_local.h9
-rw-r--r--src/ui_menu.c260
-rw-r--r--src/ui_multiplayer.c4
4 files changed, 227 insertions, 71 deletions
diff --git a/src/ui_demos.c b/src/ui_demos.c
index cec1608..b4edf45 100644
--- a/src/ui_demos.c
+++ b/src/ui_demos.c
@@ -339,7 +339,7 @@ static void BuildList(void)
if (m_demos.list.numItems) {
Change(&m_demos.list.generic);
if (m_demos.list.sortdir) {
- m_demos.list.sort(&m_demos.list, m_demos.list.sortcol);
+ m_demos.list.sort(&m_demos.list);
}
}
@@ -475,9 +475,9 @@ static int namecmp(const void *p1, const void *p2)
return Q_stricmp(s1, s2) * m_demos.list.sortdir;
}
-static menuSound_t Sort(menuList_t *self, int column)
+static menuSound_t Sort(menuList_t *self)
{
- switch (column) {
+ switch (m_demos.list.sortcol) {
case COL_NAME:
case COL_MAP:
case COL_POV:
@@ -504,21 +504,21 @@ static void Size(menuFrameWork_t *self)
m_demos.list.generic.height = uis.height - CHAR_HEIGHT * 2 - 1;
w1 = 17 + m_demos.widest_map + m_demos.widest_pov;
- w2 = uis.width - (w1 + 2) * CHAR_WIDTH - MLIST_SCROLLBAR_WIDTH;
+ w2 = uis.width - w1 * CHAR_WIDTH - MLIST_PADDING * 4 - MLIST_SCROLLBAR_WIDTH;
if (w2 > 8 * CHAR_WIDTH) {
// everything fits
m_demos.list.columns[0].width = w2;
- m_demos.list.columns[1].width = 12 * CHAR_WIDTH + CHAR_WIDTH / 2;
- m_demos.list.columns[2].width = 5 * CHAR_WIDTH + CHAR_WIDTH / 2;
- m_demos.list.columns[3].width = m_demos.widest_map * CHAR_WIDTH + CHAR_WIDTH / 2;
- m_demos.list.columns[4].width = m_demos.widest_pov * CHAR_WIDTH + CHAR_WIDTH / 2;
+ m_demos.list.columns[1].width = 12 * CHAR_WIDTH + MLIST_PADDING;
+ m_demos.list.columns[2].width = 5 * CHAR_WIDTH + MLIST_PADDING;
+ m_demos.list.columns[3].width = m_demos.widest_map * CHAR_WIDTH + MLIST_PADDING;
+ m_demos.list.columns[4].width = m_demos.widest_pov * CHAR_WIDTH + MLIST_PADDING;
m_demos.list.numcolumns = COL_MAX;
} else {
// map and pov don't fit
- w2 = uis.width - (17 + 1) * CHAR_WIDTH - MLIST_SCROLLBAR_WIDTH;
+ w2 = uis.width - 17 * CHAR_WIDTH - MLIST_PADDING * 2 - MLIST_SCROLLBAR_WIDTH;
m_demos.list.columns[0].width = w2;
- m_demos.list.columns[1].width = 12 * CHAR_WIDTH + CHAR_WIDTH / 2;
- m_demos.list.columns[2].width = 5 * CHAR_WIDTH + CHAR_WIDTH / 2;
+ m_demos.list.columns[1].width = 12 * CHAR_WIDTH + MLIST_PADDING;
+ m_demos.list.columns[2].width = 5 * CHAR_WIDTH + MLIST_PADDING;
m_demos.list.columns[3].width = 0;
m_demos.list.columns[4].width = 0;
m_demos.list.numcolumns = COL_MAX - 2;
@@ -588,7 +588,7 @@ static void ui_sortdemos_changed(cvar_t *self)
}
if (m_demos.list.items && m_demos.list.sortdir) {
- m_demos.list.sort(&m_demos.list, m_demos.list.sortcol);
+ m_demos.list.sort(&m_demos.list);
}
}
@@ -622,6 +622,7 @@ void M_Menu_Demos(void)
m_demos.list.sortcol = COL_NAME;
m_demos.list.extrasize = DEMO_EXTRASIZE;
m_demos.list.sort = Sort;
+ m_demos.list.mlFlags = MLF_HEADER | MLF_SCROLLBAR;
m_demos.list.columns[0].name = m_demos.browse;
m_demos.list.columns[0].uiFlags = UI_LEFT;
diff --git a/src/ui_local.h b/src/ui_local.h
index 8b80f66..34826de 100644
--- a/src/ui_local.h
+++ b/src/ui_local.h
@@ -166,11 +166,10 @@ typedef struct menuSlider_s {
#define MLIST_BORDER_WIDTH 1
#define MLIST_SCROLLBAR_WIDTH GENERIC_SPACING(CHAR_WIDTH)
#define MLIST_PRESTEP 3
+#define MLIST_PADDING (MLIST_PRESTEP*2)
-#define MLF_HIDE_SCROLLBAR (1<<0)
-#define MLF_HIDE_SCROLLBAR_EMPTY (1<<1)
-#define MLF_HIDE_BACKGROUND (1<<2)
-#define MLF_HIDE_HEADER (1<<3)
+#define MLF_HEADER 0x00000001
+#define MLF_SCROLLBAR 0x00000002
typedef struct menuListColumn_s {
char *name;
@@ -199,7 +198,7 @@ typedef struct menuList_s {
int numcolumns;
int sortdir, sortcol;
- menuSound_t (*sort)(struct menuList_s *, int column);
+ menuSound_t (*sort)(struct menuList_s *);
} menuList_t;
typedef struct menuSpinControl_s {
diff --git a/src/ui_menu.c b/src/ui_menu.c
index a931620..02c0bd1 100644
--- a/src/ui_menu.c
+++ b/src/ui_menu.c
@@ -744,7 +744,7 @@ static void MenuList_ValidatePrestep(menuList_t *l)
static void MenuList_AdjustPrestep(menuList_t *l)
{
- if (l->numItems > l->maxItems) {
+ if (l->numItems > l->maxItems && l->curvalue > 0) {
if (l->prestep > l->curvalue) {
l->prestep = l->curvalue;
} else if (l->prestep < l->curvalue - l->maxItems + 1) {
@@ -766,13 +766,13 @@ void MenuList_Init(menuList_t *l)
int i;
height = l->generic.height;
- if (!(l->mlFlags & MLF_HIDE_HEADER)) {
+ if (l->mlFlags & MLF_HEADER) {
height -= MLIST_SPACING;
}
l->maxItems = height / MLIST_SPACING;
- clamp(l->curvalue, 0, l->numItems - 1);
+ //clamp(l->curvalue, 0, l->numItems - 1);
MenuList_ValidatePrestep(l);
@@ -784,14 +784,14 @@ void MenuList_Init(menuList_t *l)
l->generic.rect.width += l->columns[i].width;
}
-// if( !( l->mlFlags & MLF_HIDE_SCROLLBAR ) ) {
-// rc->width += MLIST_SCROLLBAR_WIDTH;
-// }
+ if (l->mlFlags & MLF_SCROLLBAR) {
+ l->generic.rect.width += MLIST_SCROLLBAR_WIDTH;
+ }
l->generic.rect.height = l->generic.height;
if (l->sortdir && l->sort) {
- l->sort(l, l->sortcol);
+ l->sort(l);
}
}
@@ -814,7 +814,7 @@ void MenuList_SetValue(menuList_t *l, int value)
MenuList_AdjustPrestep(l);
}
-static int MenuList_SetColumn(menuList_t *l, int value)
+static menuSound_t MenuList_SetColumn(menuList_t *l, int value)
{
if (l->sortcol == value) {
l->sortdir = -l->sortdir;
@@ -823,18 +823,88 @@ static int MenuList_SetColumn(menuList_t *l, int value)
l->sortdir = 1;
}
if (l->sort) {
- l->sort(l, l->sortcol);
+ l->sort(l);
}
return QMS_SILENT;
}
+// finds a visible column by number, with numeration starting at 1
+static menuSound_t MenuList_FindColumn(menuList_t *l, int rel)
+{
+ int i, j;
+
+ if (!l->sortdir)
+ return QMS_NOTHANDLED;
+
+ for (i = 0, j = 0; i < l->numcolumns; i++) {
+ if (!l->columns[i].width)
+ continue;
+
+ if (++j == rel)
+ return MenuList_SetColumn(l, i);
+ }
+
+ return QMS_NOTHANDLED;
+}
+
+static menuSound_t MenuList_PrevColumn(menuList_t *l)
+{
+ int col;
+
+ if (!l->sortdir || !l->numcolumns) {
+ return QMS_NOTHANDLED;
+ }
+
+ col = l->sortcol;
+ if (col < 0)
+ return MenuList_FindColumn(l, 1);
+
+ do {
+ if (col < 0) {
+ col = l->numcolumns - 1;
+ } else {
+ col--;
+ }
+ if (col == l->sortcol) {
+ return QMS_SILENT;
+ }
+ } while (!l->columns[col].width);
+
+ return MenuList_SetColumn(l, col);
+}
+
+static menuSound_t MenuList_NextColumn(menuList_t *l)
+{
+ int col;
+
+ if (!l->sortdir || !l->numcolumns) {
+ return QMS_NOTHANDLED;
+ }
+
+ col = l->sortcol;
+ if (col < 0)
+ return MenuList_FindColumn(l, 1);
+
+ do {
+ if (col == l->numcolumns - 1) {
+ col = 0;
+ } else {
+ col++;
+ }
+ if (col == l->sortcol) {
+ return QMS_SILENT;
+ }
+ } while (!l->columns[col].width);
+
+ return MenuList_SetColumn(l, col);
+}
/*
=================
MenuList_Click
=================
*/
-static int MenuList_Click(menuList_t *l)
+static menuSound_t MenuList_Click(menuList_t *l)
{
int i, j;
vrect_t rect;
@@ -843,15 +913,62 @@ static int MenuList_Click(menuList_t *l)
return QMS_SILENT;
}
+ // click on scroll bar
+ if ((l->mlFlags & MLF_SCROLLBAR) && l->numItems > l->maxItems) {
+ int x = l->generic.rect.x + l->generic.rect.width - MLIST_SCROLLBAR_WIDTH;
+ int y = l->generic.rect.y + MLIST_SPACING;
+ int h = l->generic.height;
+ int barHeight;
+ float pageFrac, prestepFrac;
+
+ if (l->mlFlags & MLF_HEADER) {
+ y += MLIST_SPACING;
+ h -= MLIST_SPACING;
+ }
+
+ barHeight = h - MLIST_SPACING * 2;
+ pageFrac = (float)l->maxItems / l->numItems;
+ prestepFrac = (float)l->prestep / l->numItems;
+
+ // click above thumb
+ rect.x = x;
+ rect.y = y;
+ rect.width = MLIST_SCROLLBAR_WIDTH;
+ rect.height = Q_rint(barHeight * prestepFrac);
+ if (UI_CursorInRect(&rect)) {
+ l->prestep -= l->maxItems;
+ MenuList_ValidatePrestep(l);
+ return QMS_MOVE;
+ }
+
+ h = rect.height + Q_rint(barHeight * pageFrac);
+
+ // click below thumb
+ rect.y = y + h;
+ rect.height = barHeight - h;
+ if (UI_CursorInRect(&rect)) {
+ l->prestep += l->maxItems;
+ MenuList_ValidatePrestep(l);
+ return QMS_MOVE;
+ }
+ }
+
rect.x = l->generic.rect.x;
rect.y = l->generic.rect.y;
rect.width = l->generic.rect.width;
rect.height = MLIST_SPACING;
+ if (l->mlFlags & MLF_SCROLLBAR) {
+ rect.width -= MLIST_SCROLLBAR_WIDTH;
+ }
+
// click on header
- if (!(l->mlFlags & MLF_HIDE_HEADER)) {
+ if (l->mlFlags & MLF_HEADER) {
if (l->sortdir && UI_CursorInRect(&rect)) {
for (j = 0; j < l->numcolumns; j++) {
+ if (!l->columns[j].width) {
+ continue;
+ }
rect.width = l->columns[j].width;
if (UI_CursorInRect(&rect)) {
return MenuList_SetColumn(l, j);
@@ -892,7 +1009,7 @@ static int MenuList_Click(menuList_t *l)
MenuList_Key
=================
*/
-static int MenuList_Key(menuList_t *l, int key)
+static menuSound_t MenuList_Key(menuList_t *l, int key)
{
//int i;
@@ -901,11 +1018,7 @@ static int MenuList_Key(menuList_t *l, int key)
}
if (Key_IsDown(K_ALT) && Q_isdigit(key)) {
- int col = key == '0' ? 9 : key - '0' - 1;
- if (l->sortdir && col < l->numcolumns) {
- return MenuList_SetColumn(l, col);
- }
- return QMS_NOTHANDLED;
+ return MenuList_FindColumn(l, key - '0');
}
#if 0
@@ -946,25 +1059,18 @@ static int MenuList_Key(menuList_t *l, int key)
switch (key) {
case K_LEFTARROW:
case 'h':
- if (l->sortdir) {
- if (l->sortcol > 0) {
- return MenuList_SetColumn(l, l->sortcol - 1);
- }
- return MenuList_SetColumn(l, l->numcolumns - 1);
- }
- break;
+ return MenuList_PrevColumn(l);
+
case K_RIGHTARROW:
case 'l':
- if (l->sortdir) {
- if (l->sortcol < l->numcolumns - 1) {
- return MenuList_SetColumn(l, l->sortcol + 1);
- }
- return MenuList_SetColumn(l, 0);
- }
- break;
+ return MenuList_NextColumn(l);
+
case K_UPARROW:
case K_KP_UPARROW:
case 'k':
+ if (l->curvalue < 0) {
+ goto home;
+ }
if (l->curvalue > 0) {
l->curvalue--;
if (l->generic.change) {
@@ -978,6 +1084,9 @@ static int MenuList_Key(menuList_t *l, int key)
case K_DOWNARROW:
case K_KP_DOWNARROW:
case 'j':
+ if (l->curvalue < 0) {
+ goto home;
+ }
if (l->curvalue < l->numItems - 1) {
l->curvalue++;
if (l->generic.change) {
@@ -990,6 +1099,7 @@ static int MenuList_Key(menuList_t *l, int key)
case K_HOME:
case K_KP_HOME:
+ home:
l->prestep = 0;
l->curvalue = 0;
if (l->generic.change) {
@@ -1028,15 +1138,39 @@ static int MenuList_Key(menuList_t *l, int key)
case K_PGUP:
case K_KP_PGUP:
- l->prestep -= l->maxItems;
- MenuList_ValidatePrestep(l);
- return QMS_SILENT;
+ if (l->curvalue < 0) {
+ goto home;
+ }
+ if (l->curvalue > 0) {
+ l->curvalue -= l->maxItems - 1;
+ if (l->curvalue < 0) {
+ l->curvalue = 0;
+ }
+ if (l->generic.change) {
+ l->generic.change(&l->generic);
+ }
+ MenuList_AdjustPrestep(l);
+ return QMS_MOVE;
+ }
+ return QMS_BEEP;
case K_PGDN:
case K_KP_PGDN:
- l->prestep += l->maxItems;
- MenuList_ValidatePrestep(l);
- return QMS_SILENT;
+ if (l->curvalue < 0) {
+ goto home;
+ }
+ if (l->curvalue < l->numItems - 1) {
+ l->curvalue += l->maxItems - 1;
+ if (l->curvalue > l->numItems - 1) {
+ l->curvalue = l->numItems - 1;
+ }
+ if (l->generic.change) {
+ l->generic.change(&l->generic);
+ }
+ MenuList_AdjustPrestep(l);
+ return QMS_MOVE;
+ }
+ return QMS_BEEP;
case K_MOUSE1:
case K_MOUSE2:
@@ -1064,7 +1198,7 @@ static void MenuList_DrawString(int x, int y, int flags,
rc.bottom = 0;
if ((column->uiFlags & UI_CENTER) == UI_CENTER) {
- x += column->width / 2;
+ x += column->width / 2 - 1;
} else if (column->uiFlags & UI_RIGHT) {
x += column->width - MLIST_PRESTEP;
} else {
@@ -1100,12 +1234,16 @@ static void MenuList_Draw(menuList_t *l)
height = l->generic.rect.height;
// draw header
- if (!(l->mlFlags & MLF_HIDE_HEADER)) {
+ if (l->mlFlags & MLF_HEADER) {
xx = x;
for (j = 0; j < l->numcolumns; j++) {
int flags = UI_ALTCOLOR;
uint32_t color = uis.color.normal.u32;
+ if (!l->columns[j].width) {
+ continue;
+ }
+
if (l->sortcol == j && l->sortdir) {
flags = 0;
if (l->generic.flags & QMF_HASFOCUS) {
@@ -1125,16 +1263,14 @@ static void MenuList_Draw(menuList_t *l)
height -= MLIST_SPACING;
}
- if (!(l->mlFlags & MLF_HIDE_SCROLLBAR) &&
- (!(l->mlFlags & MLF_HIDE_SCROLLBAR_EMPTY) || l->numItems > l->maxItems)) {
+ if (l->mlFlags & MLF_SCROLLBAR) {
barHeight = height - MLIST_SPACING * 2;
yy = y + MLIST_SPACING;
// draw scrollbar background
- if (!(l->mlFlags & MLF_HIDE_BACKGROUND)) {
- R_DrawFill32(x + width, yy, MLIST_SCROLLBAR_WIDTH - 1,
- barHeight, uis.color.normal.u32);
- }
+ R_DrawFill32(x + width - MLIST_SCROLLBAR_WIDTH, yy,
+ MLIST_SCROLLBAR_WIDTH - 1, barHeight,
+ uis.color.normal.u32);
if (l->numItems > l->maxItems) {
pageFrac = (float)l->maxItems / l->numItems;
@@ -1145,17 +1281,22 @@ static void MenuList_Draw(menuList_t *l)
}
// draw scrollbar thumb
- R_DrawFill32(x + width,
+ R_DrawFill32(x + width - MLIST_SCROLLBAR_WIDTH,
yy + Q_rint(barHeight * prestepFrac),
MLIST_SCROLLBAR_WIDTH - 1,
Q_rint(barHeight * pageFrac),
uis.color.selection.u32);
}
+ // draw background
xx = x;
for (j = 0; j < l->numcolumns; j++) {
uint32_t color = uis.color.normal.u32;
+ if (!l->columns[j].width) {
+ continue;
+ }
+
if (l->sortcol == j && l->sortdir) {
if (l->generic.flags & QMF_HASFOCUS) {
color = uis.color.active.u32;
@@ -1174,6 +1315,9 @@ static void MenuList_Draw(menuList_t *l)
if (!(l->generic.flags & QMF_DISABLED) && i == l->curvalue) {
xx = x;
for (j = 0; j < l->numcolumns; j++) {
+ if (!l->columns[j].width) {
+ continue;
+ }
R_DrawFill32(xx, yy, l->columns[j].width - 1,
MLIST_SPACING, uis.color.selection.u32);
xx += l->columns[j].width;
@@ -1188,9 +1332,10 @@ static void MenuList_Draw(menuList_t *l)
break;
}
- MenuList_DrawString(xx, yy, 0, &l->columns[j], s);
-
- xx += l->columns[j].width;
+ if (l->columns[j].width) {
+ MenuList_DrawString(xx, yy, 0, &l->columns[j], s);
+ xx += l->columns[j].width;
+ }
s += strlen(s) + 1;
}
@@ -1203,11 +1348,19 @@ void MenuList_Sort(menuList_t *l, int offset, int (*cmpfunc)(const void *, const
void *n;
int i;
- if (!l->items) {
+ if (!l->items)
+ return;
+
+ if (offset >= l->numItems)
return;
- }
- n = l->items[l->curvalue];
+ if (l->sortcol < 0 || l->sortcol >= l->numcolumns)
+ return;
+
+ if (l->curvalue < 0 || l->curvalue >= l->numItems)
+ n = NULL;
+ else
+ n = l->items[l->curvalue];
qsort(l->items + offset, l->numItems - offset, sizeof(char *), cmpfunc);
@@ -1218,7 +1371,8 @@ void MenuList_Sort(menuList_t *l, int offset, int (*cmpfunc)(const void *, const
}
}
- MenuList_AdjustPrestep(l);
+ if (n)
+ MenuList_AdjustPrestep(l);
}
/*
diff --git a/src/ui_multiplayer.c b/src/ui_multiplayer.c
index 43434c4..a15d14b 100644
--- a/src/ui_multiplayer.c
+++ b/src/ui_multiplayer.c
@@ -414,6 +414,7 @@ void M_Menu_Servers(void)
m_join.list.generic.change = Change;
m_join.list.items = (void **)m_join.names;
m_join.list.numcolumns = 3;
+ m_join.list.mlFlags = MLF_HEADER | MLF_SCROLLBAR;
m_join.list.columns[0].uiFlags = UI_LEFT;
m_join.list.columns[0].name = "Hostname";
@@ -428,6 +429,7 @@ void M_Menu_Servers(void)
m_join.info.generic.type = MTYPE_LIST;
m_join.info.generic.flags = QMF_LEFT_JUSTIFY | QMF_HIDDEN;
m_join.info.numcolumns = 2;
+ m_join.info.mlFlags = MLF_HEADER | MLF_SCROLLBAR;
m_join.info.columns[0].uiFlags = UI_LEFT;
m_join.info.columns[0].name = "Key";
@@ -439,8 +441,8 @@ void M_Menu_Servers(void)
//
m_join.players.generic.type = MTYPE_LIST;
m_join.players.generic.flags = QMF_LEFT_JUSTIFY | QMF_HIDDEN | QMF_DISABLED;
- m_join.players.mlFlags = MLF_HIDE_SCROLLBAR;
m_join.players.numcolumns = 3;
+ m_join.players.mlFlags = MLF_HEADER;
m_join.players.columns[0].uiFlags = UI_CENTER;
m_join.players.columns[0].name = "Frg";