diff --git a/ClassicalSharp/Utils/Camera.cs b/ClassicalSharp/Utils/Camera.cs index 22396c58b..19f929bb5 100644 --- a/ClassicalSharp/Utils/Camera.cs +++ b/ClassicalSharp/Utils/Camera.cs @@ -92,7 +92,7 @@ namespace ClassicalSharp { float sensitivity = sensiFactor * game.MouseSensitivity; if (game.SmoothCamera) { - speedX += delta.X * adjust; + speedX += delta.X * adjust; game.LocalPlayer.ModelScale.XYZ speedX *= slippery; speedY += delta.Y * adjust; speedY *= slippery; diff --git a/src/LScreens.c b/src/LScreens.c index 84a4d5b7a..090ba3e58 100644 --- a/src/LScreens.c +++ b/src/LScreens.c @@ -1152,7 +1152,7 @@ static void ServersScreen_HashFilter(String* str) { static void ServersScreen_SearchChanged(struct LInput* w) { struct ServersScreen* s = &ServersScreen_Instance; - LTable_Filter(&s->Table, &w->Text); + LTable_ApplyFilter(&s->Table); LWidget_Draw(&s->Table); } @@ -1175,6 +1175,9 @@ static void ServersScreen_InitWidgets(struct LScreen* s_) { s->IptHash.ClipboardFilter = ServersScreen_HashFilter; LTable_Init(&s->Table, &Launcher_TextFont, &s->RowFont); + s->Table.Filter = &s->IptSearch.Text; + s->Table.SelectedHash = &s->IptHash.Text; + s->Widgets[s->NumWidgets++] = (struct LWidget*)&s->Table; } diff --git a/src/LWidgets.c b/src/LWidgets.c index 8daae6175..4b0f2e2ac 100644 --- a/src/LWidgets.c +++ b/src/LWidgets.c @@ -660,7 +660,7 @@ static int SoftwareColumn_Sort(struct ServerInfo* a, struct ServerInfo* b) { } static struct LTableColumn tableColumns[5] = { - { "", 20, FlagColumn_Draw, NULL, false }, + { "", 15, FlagColumn_Draw, NULL, false }, { "Name", 320, NameColumn_Draw, NameColumn_Sort, true }, { "Players", 65, PlayersColumn_Draw, PlayersColumn_Sort, true }, { "Uptime", 65, UptimeColumn_Draw, UptimeColumn_Sort, true }, @@ -669,38 +669,99 @@ static struct LTableColumn tableColumns[5] = { #define GRIDLINE_SIZE 2 #define SCROLLBAR_WIDTH 10 -#define CELL_YPADDING 3 -#define CELL_XPADDING 3 - - +#define HDR_YPADDING 3 +#define ROW_YPADDING 1 +#define CELL_XPADDING 5 #define LTable_Get(row) &FetchServersTask.Servers[FetchServersTask.Servers[row]._order] -void LTable_DrawHeaders(struct LTable* w) { + +static void LTable_DrawHeaderBackground(struct LTable* w) { BitmapCol gridCol = BITMAPCOL_CONST(20, 20, 10, 255); - struct DrawTextArgs args; - int i, x, y; + if (Launcher_ClassicBackground) return; - if (!Launcher_ClassicBackground) { - Drawer2D_Clear(&Launcher_Framebuffer, gridCol, - w->X, w->Y, w->Width, w->HdrHeight); - Drawer2D_Clear(&Launcher_Framebuffer, Launcher_BackgroundCol, - w->X, w->Y + w->HdrHeight, w->Width, GRIDLINE_SIZE); + Drawer2D_Clear(&Launcher_Framebuffer, gridCol, + w->X, w->Y, w->Width, w->HdrHeight); +} + +static BitmapCol LTable_RowCol(struct LTable* w, struct ServerInfo* row) { + BitmapCol emptyCol = BITMAPCOL_CONST(0, 0, 0, 0); + BitmapCol gridCol = BITMAPCOL_CONST(20, 20, 10, 255); + BitmapCol featSelCol = BITMAPCOL_CONST( 50, 53, 0, 255); + BitmapCol featuredCol = BITMAPCOL_CONST(101, 107, 0, 255); + BitmapCol selectedCol = BITMAPCOL_CONST( 40, 40, 40, 255); + bool selected; + + if (row) { + selected = String_Equals(&row->Hash, w->SelectedHash); + if (row->Featured) { + return selected ? featSelCol : featuredCol; + } else if (selected) { + return selectedCol; + } } + return Launcher_ClassicBackground ? emptyCol : gridCol; +} - DrawTextArgs_MakeEmpty(&args, &w->HdrFont, true); - x = w->X; - y = w->Y + CELL_YPADDING; +static void LTable_DrawRowsBackground(struct LTable* w) { + struct ServerInfo* entry; + BitmapCol col; + int y, row, height; - for (i = 0; i < w->NumColumns; i++) { - x += CELL_XPADDING; - args.Text = String_FromReadonly(w->Columns[i].Name); + y = w->RowsBegY; + for (row = 0; row < w->VisibleRows; row++, y += w->RowHeight) { + entry = row < w->RowsCount ? LTable_Get(row) : NULL; + col = LTable_RowCol(w, entry); - Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args, - x, y, w->Columns[i].Width); - x += w->Columns[i].Width + CELL_XPADDING; + if (!col.A) continue; + /* last row may get chopped off */ + height = min(y + w->RowHeight, w->RowsEndY) - y; + + Drawer2D_Clear(&Launcher_Framebuffer, col, + w->X, y, w->Width, height); } } -void LTable_DrawRows(struct LTable* w) { +static void LTable_DrawGridlines(struct LTable* w) { + int i, x; + if (Launcher_ClassicBackground) return; + + x = w->X; + Drawer2D_Clear(&Launcher_Framebuffer, Launcher_BackgroundCol, + x, w->Y + w->HdrHeight, w->Width, GRIDLINE_SIZE); + + for (i = 0; i < w->NumColumns; i++) { + x += w->Columns[i].Width; + if (!w->Columns[i].ColumnGridline) continue; + + Drawer2D_Clear(&Launcher_Framebuffer, Launcher_BackgroundCol, + x, w->Y, GRIDLINE_SIZE, w->Height); + x += GRIDLINE_SIZE; + } +} + +static void LTable_DrawBackground(struct LTable* w) { + LTable_DrawHeaderBackground(w); + LTable_DrawRowsBackground(w); + LTable_DrawGridlines(w); +} + +static void LTable_DrawHeaders(struct LTable* w) { + struct DrawTextArgs args; + int i, x, y; + + DrawTextArgs_MakeEmpty(&args, &w->HdrFont, true); + x = w->X; y = w->Y; + + for (i = 0; i < w->NumColumns; i++) { + args.Text = String_FromReadonly(w->Columns[i].Name); + Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args, + x + CELL_XPADDING, y + HDR_YPADDING, w->Columns[i].Width); + + x += w->Columns[i].Width; + if (w->Columns[i].ColumnGridline) x += GRIDLINE_SIZE; + } +} + +static void LTable_DrawRows(struct LTable* w) { BitmapCol gridCol = BITMAPCOL_CONST(20, 20, 10, 255); String str; char strBuffer[STRING_SIZE]; struct ServerInfo* entry; @@ -714,30 +775,21 @@ void LTable_DrawRows(struct LTable* w) { for (row = 0; row < w->VisibleRows; row++, y += w->RowHeight) { x = w->X; - if (!Launcher_ClassicBackground) { - Drawer2D_Clear(&Launcher_Framebuffer, gridCol, - x, y, w->Width, w->RowHeight); - } - - if (row >= w->RowsCount) continue; + if (row >= w->RowsCount) break; + if (y + w->RowHeight > w->RowsEndY) break; entry = LTable_Get(row); for (i = 0; i < w->NumColumns; i++) { - x += CELL_XPADDING; args.Text = str; w->Columns[i].DrawRow(entry, &args, x, y); if (args.Text.length) { Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args, - x, y, w->Columns[i].Width); + x + CELL_XPADDING, y + ROW_YPADDING, w->Columns[i].Width); } - x += w->Columns[i].Width; - if (!Launcher_ClassicBackground && w->Columns[i].ColumnGridline) { - Drawer2D_Clear(&Launcher_Framebuffer, Launcher_BackgroundCol, - x, y, GRIDLINE_SIZE, w->RowHeight); - } - x += CELL_XPADDING; + x += w->Columns[i].Width; + if (w->Columns[i].ColumnGridline) x += GRIDLINE_SIZE; } } } @@ -1074,16 +1126,18 @@ static void LTable_StopDragging(struct LTable* table) { void LTable_Reposition(struct LTable* w) { int rowsHeight; - w->HdrHeight = Drawer2D_FontHeight(&w->HdrFont, true) + CELL_YPADDING * 2; - w->RowHeight = Drawer2D_FontHeight(&w->RowFont, true) + CELL_YPADDING * 2; + w->HdrHeight = Drawer2D_FontHeight(&w->HdrFont, true) + HDR_YPADDING * 2; + w->RowHeight = Drawer2D_FontHeight(&w->RowFont, true) + ROW_YPADDING * 2; w->RowsBegY = w->Y + w->HdrHeight + GRIDLINE_SIZE; - rowsHeight = w->Height - (w->RowsBegY - w->Y); + w->RowsEndY = w->Y + w->Height; + rowsHeight = w->Height - (w->RowsBegY - w->Y); w->VisibleRows = Math_CeilDiv(rowsHeight, w->RowHeight); } static void LTable_Draw(void* widget) { struct LTable* w = widget; + LTable_DrawBackground(w); LTable_DrawHeaders(w); LTable_DrawRows(w); Launcher_MarkAllDirty(); @@ -1107,16 +1161,20 @@ void LTable_Init(struct LTable* w, const FontDesc* hdrFont, const FontDesc* rowF void LTable_Reset(struct LTable* w) { LTable_StopDragging(w); LTable_Reposition(w); - w->Sorter = LTable_DefaultSort; - LTable_Filter(w, &String_Empty); + + w->Sorter = LTable_DefaultSort; + w->SelectedHash->length = 0; + w->Filter->length = 0; + LTable_CalcSortOrder(w); + LTable_ApplyFilter(w); } -void LTable_Filter(struct LTable* w, const String* filter) { +void LTable_ApplyFilter(struct LTable* w) { int i, j, count; count = FetchServersTask.NumServers; for (i = 0, j = 0; i < count; i++) { - if (String_CaselessContains(&FetchServersTask.Servers[i].Name, filter)) { + if (String_CaselessContains(&FetchServersTask.Servers[i].Name, w->Filter)) { FetchServersTask.Servers[j++]._order = i; } } @@ -1127,4 +1185,8 @@ void LTable_Filter(struct LTable* w, const String* filter) { } /* TODO: preserve selected server */ /* TODO: Resort entries again */ +} + +void LTable_CalcSortOrder(struct LTable* table) { + /* TODO: Implement */ } \ No newline at end of file diff --git a/src/LWidgets.h b/src/LWidgets.h index aa3a58e5e..2d91a8e55 100644 --- a/src/LWidgets.h +++ b/src/LWidgets.h @@ -143,8 +143,8 @@ struct LTable { int NumColumns; /* Fonts for text in header and rows. */ FontDesc RowFont, HdrFont; - /* Y start of rows and height of each row. */ - int RowsBegY, RowHeight; + /* Y start and end of rows and height of each row. */ + int RowsBegY, RowsEndY, RowHeight; /* Y height of headers. */ int HdrHeight; /* Maximum number of rows visible. */ @@ -154,6 +154,11 @@ struct LTable { /* Comparison function used to sort rows. */ LTableSorter Sorter; + /* Hash of the currently selected server. */ + String* SelectedHash; + /* Filter for which server names to show. */ + String* Filter; + /* Index of column currently being dragged. */ int DraggingColumn; /* Whether scrollbar is currently being dragged up or down. */ @@ -167,10 +172,11 @@ void LTable_Init(struct LTable* table, const FontDesc* hdrFont, const FontDesc* void LTable_Reset(struct LTable* table); /* Adjusts Y position of rows and number of visible rows. */ void LTable_Reposition(struct LTable* table); -/* Filters rows to only show those containing 'filter' in the name. */ -void LTable_Filter(struct LTable* table, const String* filter); +/* Filters rows to only show those containing 'w->Filter' in the name. */ +void LTable_ApplyFilter(struct LTable* table); +/* Calculates the sorted order of rows in the table. */ +/* NOTE: You must use ApplyFilter to actually update visible row order. */ +void LTable_CalcSortOrder(struct LTable* table); /* Attempts to select the row whose hash equals the given hash. Scrolls table if needed. */ void LTable_SetSelected(struct LTable* table, const String* hash); -/* Attempts to get the hash of the currently selected row. */ -void LTable_GetSelected(struct LTable* table, String* hash); #endif