mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 19:15:14 -04:00
Port MenuInputWidget to C client.
This commit is contained in:
parent
e4310342bb
commit
b79d42e3fa
@ -10,9 +10,7 @@ namespace ClassicalSharp.Gui.Widgets {
|
||||
|
||||
public abstract bool IsValidString(string s);
|
||||
|
||||
public virtual bool IsValidValue(string s) {
|
||||
return IsValidString(s);
|
||||
}
|
||||
public abstract bool IsValidValue(string s);
|
||||
|
||||
protected void MakeRange(string min, string max) {
|
||||
Range = "&7(" + min + " - " + max + ")";
|
||||
@ -119,6 +117,7 @@ namespace ClassicalSharp.Gui.Widgets {
|
||||
}
|
||||
|
||||
public override bool IsValidString(string s) { return true; }
|
||||
public override bool IsValidValue(string s) { return true; }
|
||||
}
|
||||
|
||||
public sealed class BooleanValidator : MenuInputValidator {
|
||||
@ -161,5 +160,9 @@ namespace ClassicalSharp.Gui.Widgets {
|
||||
public override bool IsValidString(string s) {
|
||||
return s.Length <= Utils.StringLength;
|
||||
}
|
||||
|
||||
public override bool IsValidValue(string s) {
|
||||
return s.Length <= Utils.StringLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,8 @@
|
||||
Copyright 2017 ClassicalSharp | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
/* returns a bit mask for the nth bit in an integer */
|
||||
#define bit(x) (1 << (x))
|
||||
/* returns smallest of two numbers */
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
/* returns largest of two numbers */
|
||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
/* returns number of elements in given array. */
|
||||
#define Array_NumElements(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
#define QuickSort_Swap_Maybe()\
|
||||
|
@ -7,10 +7,7 @@
|
||||
*/
|
||||
|
||||
Int32 Utils_AccumulateWheelDelta(Real32* accmulator, Real32 delta);
|
||||
|
||||
UInt32 Utils_ParseEnum(STRING_PURE String* text, UInt32 defValue, const UInt8** names, UInt32 namesCount);
|
||||
|
||||
bool Utils_IsValidInputChar(UInt8 c, bool supportsCP437);
|
||||
|
||||
#define Utils_AdjViewDist(value) ((Int32)(1.4142135f * (value)))
|
||||
#endif
|
@ -503,13 +503,6 @@ Int32 Table_Height(TableWidget* widget) {
|
||||
return min(widget->RowsCount, TABLE_MAX_ROWS_DISPLAYED) * widget->BlockSize + 10 + 40;
|
||||
}
|
||||
|
||||
/* These were sourced by taking a screenshot of vanilla
|
||||
Then using paint to extract the colour components
|
||||
Then using wolfram alpha to solve the glblendfunc equation */
|
||||
PackedCol Table_TopBackCol = PACKEDCOL_CONST( 34, 34, 34, 168);
|
||||
PackedCol Table_BottomBackCol = PACKEDCOL_CONST( 57, 57, 104, 202);
|
||||
PackedCol Table_TopSelCol = PACKEDCOL_CONST(255, 255, 255, 142);
|
||||
PackedCol Table_BottomSelCol = PACKEDCOL_CONST(255, 255, 255, 192);
|
||||
#define TABLE_MAX_VERTICES (8 * 10 * ISOMETRICDRAWER_MAXVERTICES)
|
||||
|
||||
bool TableWidget_GetCoords(TableWidget* widget, Int32 i, Int32* winX, Int32* winY) {
|
||||
@ -631,10 +624,19 @@ void TableWidget_Init(GuiElement* elem) {
|
||||
elem->Recreate(elem);
|
||||
}
|
||||
|
||||
void TableWidget_Render(GuiElement* elem, Real64 delta) {
|
||||
void TableWidget_Render(GuiElement* elem, Real64 delta) {
|
||||
/* These were sourced by taking a screenshot of vanilla
|
||||
Then using paint to extract the colour components
|
||||
Then using wolfram alpha to solve the glblendfunc equation */
|
||||
PackedCol topBackCol = PACKEDCOL_CONST( 34, 34, 34, 168);
|
||||
PackedCol bottomBackCol = PACKEDCOL_CONST( 57, 57, 104, 202);
|
||||
PackedCol topSelCol = PACKEDCOL_CONST(255, 255, 255, 142);
|
||||
PackedCol bottomSelCol = PACKEDCOL_CONST(255, 255, 255, 192);
|
||||
|
||||
TableWidget* widget = (TableWidget*)elem;
|
||||
GfxCommon_Draw2DGradient(Table_X(widget), Table_Y(widget),
|
||||
Table_Width(widget), Table_Height(widget), Table_TopBackCol, Table_BottomBackCol);
|
||||
Table_Width(widget), Table_Height(widget), topBackCol, bottomBackCol);
|
||||
|
||||
if (widget->RowsCount > TABLE_MAX_ROWS_DISPLAYED) {
|
||||
GuiElement* scroll = &widget->Scroll.Base.Base;
|
||||
scroll->Render(scroll, delta);
|
||||
@ -647,7 +649,7 @@ void TableWidget_Render(GuiElement* elem, Real64 delta) {
|
||||
Real32 off = blockSize * 0.1f;
|
||||
Int32 size = (Int32)(blockSize + off * 2);
|
||||
GfxCommon_Draw2DGradient((Int32)(x - off), (Int32)(y - off),
|
||||
size, size, Table_TopSelCol, Table_BottomSelCol);
|
||||
size, size, topSelCol, bottomSelCol);
|
||||
}
|
||||
Gfx_SetTexturing(true);
|
||||
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B);
|
||||
@ -1236,7 +1238,7 @@ void InputWidget_Clear(InputWidget* widget) {
|
||||
Gfx_DeleteTexture(&widget->InputTex.ID);
|
||||
}
|
||||
|
||||
bool InputWidget_AllowedChar(InputWidget* widget, UInt8 c) {
|
||||
bool InputWidget_AllowedChar(GuiElement* elem, UInt8 c) {
|
||||
return Utils_IsValidInputChar(c, ServerConnection_SupportsFullCP437);
|
||||
}
|
||||
|
||||
@ -1253,7 +1255,7 @@ void InputWidget_AppendChar(InputWidget* widget, UInt8 c) {
|
||||
bool InputWidget_TryAppendChar(InputWidget* widget, UInt8 c) {
|
||||
Int32 maxChars = widget->GetMaxLines() * widget->MaxCharsPerLine;
|
||||
if (widget->Text.length >= maxChars) return false;
|
||||
if (!InputWidget_AllowedChar(widget, c)) return false;
|
||||
if (!widget->AllowedChar(&widget->Base.Base, c)) return false;
|
||||
|
||||
InputWidget_AppendChar(widget, c);
|
||||
return true;
|
||||
@ -1510,6 +1512,7 @@ void InputWidget_Create(InputWidget* widget, FontDesc* font, STRING_REF String*
|
||||
widget->Prefix = *prefix;
|
||||
widget->CaretPos = -1;
|
||||
widget->MaxCharsPerLine = STRING_SIZE;
|
||||
widget->AllowedChar = InputWidget_AllowedChar;
|
||||
|
||||
widget->Base.Base.Init = InputWidget_Init;
|
||||
widget->Base.Base.Free = InputWidget_Free;
|
||||
@ -1535,13 +1538,104 @@ void InputWidget_Create(InputWidget* widget, FontDesc* font, STRING_REF String*
|
||||
widget->PrefixHeight = (UInt16)size.Height; widget->Base.Height = size.Height;
|
||||
}
|
||||
|
||||
void MenuInputWidget_Render(GuiElement* elem, Real64 delta) {
|
||||
Widget* elemW = (Widget*)elem;
|
||||
PackedCol backCol = PACKEDCOL_CONST(30, 30, 30, 200);
|
||||
Gfx_SetTexturing(false);
|
||||
GfxCommon_Draw2DFlat(elemW->X, elemW->Y, elemW->Width, elemW->Height, backCol);
|
||||
Gfx_SetTexturing(true);
|
||||
|
||||
InputWidget* widget = (InputWidget*)elem;
|
||||
Texture_Render(&widget->InputTex);
|
||||
InputWidget_RenderCaret(&widget, delta);
|
||||
}
|
||||
|
||||
void MenuInputWidget_RemakeTexture(GuiElement* elem) {
|
||||
Widget* elemW = (Widget*)elem;
|
||||
MenuInputWidget* widget = (MenuInputWidget*)elem;
|
||||
|
||||
DrawTextArgs args;
|
||||
DrawTextArgs_Make(&args, &widget->Base.Lines[0], &widget->Base.Font, false);
|
||||
Size2D size = Drawer2D_MeasureText(&args);
|
||||
widget->Base.CaretAccumulator = 0.0;
|
||||
|
||||
UInt8 rangeBuffer[String_BufferSize(STRING_SIZE)];
|
||||
String range = String_InitAndClearArray(rangeBuffer);
|
||||
widget->Validator.GetRange(&range);
|
||||
|
||||
/* Ensure we don't have 0 text height */
|
||||
if (size.Height == 0) {
|
||||
args.Text = range;
|
||||
size.Height = Drawer2D_MeasureText(&args).Height;
|
||||
args.Text = widget->Base.Lines[0];
|
||||
}
|
||||
|
||||
elemW->Width = max(size.Width, widget->MinWidth);
|
||||
elemW->Height = max(size.Height, widget->MinHeight);
|
||||
Size2D adjSize = size; adjSize.Width = elemW->Width;
|
||||
|
||||
Bitmap bmp; Bitmap_AllocatePow2(&bmp, adjSize.Width, adjSize.Height);
|
||||
Drawer2D_Begin(&bmp);
|
||||
Drawer2D_DrawText(&args, widget->Base.Padding, 0);
|
||||
|
||||
args.Text = range;
|
||||
Size2D hintSize = Drawer2D_MeasureText(&args);
|
||||
Int32 hintX = adjSize.Width - hintSize.Width;
|
||||
if (size.Width + 3 < hintX) {
|
||||
Drawer2D_DrawText(&args, hintX, 0);
|
||||
}
|
||||
|
||||
Drawer2D_End();
|
||||
Texture* tex = &widget->Base.InputTex;
|
||||
*tex = Drawer2D_Make2DTexture(&bmp, adjSize, 0, 0);
|
||||
|
||||
Reposition();
|
||||
tex->X = elemW->X; tex->Y = elemW->Y;
|
||||
if (size.Height < widget->MinHeight) {
|
||||
tex->Y += widget->MinHeight / 2 - size.Height / 2;
|
||||
}
|
||||
}
|
||||
|
||||
bool MenuInputWidget_AllowedChar(GuiElement* elem, UInt8 c) {
|
||||
if (c == '&' || !Utils_IsValidInputChar(c, true)) return false;
|
||||
MenuInputWidget* widget = (MenuInputWidget*)elem;
|
||||
InputWidget* elemW = (InputWidget*)elem;
|
||||
|
||||
if (!widget->Validator.IsValidChar(c)) return false;
|
||||
Int32 maxChars = elemW->GetMaxLines() * elemW->MaxCharsPerLine;
|
||||
if (elemW->Text.length == maxChars) return false;
|
||||
|
||||
/* See if the new string is in valid format */
|
||||
InputWidget_AppendChar(elemW, c);
|
||||
bool valid = widget->Validator.IsValidString(&elemW->Text);
|
||||
InputWidget_DeleteChar(elemW);
|
||||
return valid;
|
||||
}
|
||||
|
||||
Int32 MenuInputWidget_GetMaxLines(void) { return 1; }
|
||||
void MenuInputWidget_Create(MenuInputWidget* widget, Int32 width, Int32 height, STRING_PURE String* text, FontDesc* font, MenuInputValidator* validator) {
|
||||
InputWidget_Create(&widget->Base, font, NULL);
|
||||
widget->MinWidth = width;
|
||||
widget->MinHeight = height;
|
||||
widget->Validator = *validator;
|
||||
|
||||
widget->Base.Padding = 3;
|
||||
widget->Base.Text = String_InitAndClearArray(widget->TextBuffer);
|
||||
widget->Base.GetMaxLines = MenuInputWidget_GetMaxLines;
|
||||
widget->Base.AllowedChar = MenuInputWidget_AllowedChar;
|
||||
widget->Base.RemakeTexture = MenuInputWidget_RemakeTexture;
|
||||
|
||||
GuiElement* elem = &widget->Base.Base.Base;
|
||||
elem->Render = MenuInputWidget_Render;
|
||||
elem->Init(elem);
|
||||
InputWidget_AppendString(&widget->Base, text);
|
||||
}
|
||||
|
||||
|
||||
#define GROUP_NAME_ID UInt16_MaxValue
|
||||
#define LIST_COLUMN_PADDING 5
|
||||
#define LIST_BOUNDS_SIZE 10
|
||||
#define LIST_NAMES_PER_COLUMN 16
|
||||
PackedCol list_topCol = PACKEDCOL_CONST(0, 0, 0, 180);
|
||||
PackedCol list_bottomCol = PACKEDCOL_CONST(50, 50, 50, 205);
|
||||
|
||||
Texture PlayerListWidget_DrawName(PlayerListWidget* widget, STRING_PURE String* name) {
|
||||
UInt8 tmpBuffer[String_BufferSize(STRING_SIZE)];
|
||||
@ -1864,11 +1958,13 @@ void PlayerListWidget_Render(GuiElement* elem, Real64 delta) {
|
||||
PlayerListWidget* widget = (PlayerListWidget*)elem;
|
||||
Widget* elemW = &widget->Base;
|
||||
TextWidget* overview = &widget->Overview;
|
||||
PackedCol topCol = PACKEDCOL_CONST(0, 0, 0, 180);
|
||||
PackedCol bottomCol = PACKEDCOL_CONST(50, 50, 50, 205);
|
||||
|
||||
Gfx_SetTexturing(false);
|
||||
Int32 offset = overview->Base.Height + 10;
|
||||
Int32 height = max(300, elemW->Height + overview->Base.Height);
|
||||
GfxCommon_Draw2DGradient(elemW->X, elemW->Y - offset, elemW->Width, elemW->Height, list_topCol, list_bottomCol);
|
||||
GfxCommon_Draw2DGradient(elemW->X, elemW->Y - offset, elemW->Width, elemW->Height, topCol, bottomCol);
|
||||
|
||||
Gfx_SetTexturing(true);
|
||||
overview->Base.YOffset = elemW->Y - offset + 5;
|
||||
|
@ -129,6 +129,7 @@ typedef struct InputWidget_ {
|
||||
Int32 Padding, MaxCharsPerLine;
|
||||
void (*RemakeTexture)(GuiElement* elem); /* Remakes the raw texture containing all the chat lines. Also updates dimensions. */
|
||||
void (*OnPressedEnter)(GuiElement* elem); /* Invoked when the user presses enter. */
|
||||
bool (*AllowedChar)(GuiElement* elem, UInt8 c);
|
||||
|
||||
String Text;
|
||||
String Lines[INPUTWIDGET_MAX_LINES]; /* raw text of each line */
|
||||
@ -160,6 +161,22 @@ void InputWidget_AppendString(InputWidget* widget, STRING_PURE String* text);
|
||||
void InputWidget_Append(InputWidget* widget, UInt8 c);
|
||||
|
||||
|
||||
typedef struct MenuInputValidator_ {
|
||||
void (*GetRange)(STRING_TRANSIENT String* range);
|
||||
bool (*IsValidChar)(UInt8 c);
|
||||
bool (*IsValidString)(STRING_PURE String* s);
|
||||
bool (*IsValidValue)(STRING_PURE String* s);
|
||||
} MenuInputValidator;
|
||||
typedef struct MenuInputWidget_ {
|
||||
InputWidget Base;
|
||||
Int32 MinWidth, MinHeight;
|
||||
MenuInputValidator Validator;
|
||||
UInt8 TextBuffer[String_BufferSize(STRING_SIZE)];
|
||||
} MenuInputWidget;
|
||||
|
||||
void MenuInputWidget_Create(MenuInputWidget* widget, Int32 width, Int32 height, STRING_PURE String* text, FontDesc* font, MenuInputValidator* validator);
|
||||
|
||||
|
||||
/* "part1" "> part2" type urls */
|
||||
#define LINK_FLAG_CONTINUE 2
|
||||
/* used for internally combining "part1" and "part2" */
|
||||
|
@ -481,7 +481,7 @@ void Window_GetClipboardText(STRING_TRANSIENT String* value) {
|
||||
}
|
||||
} else {
|
||||
UInt8* text = (UInt8*)src;
|
||||
while (*text != 0) {
|
||||
while (*text != NULL) {
|
||||
String_Append(value, *text); text++;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user