panel and scroll_view
This commit is contained in:
2
dependencies/tim
vendored
2
dependencies/tim
vendored
Submodule dependencies/tim updated: 2a685dfcd0...ee6375f553
@@ -18,9 +18,9 @@ void ClientCLI_construct(ClientCLI* self){
|
||||
zeroStruct(self);
|
||||
|
||||
self->style.common = (TimStyle){
|
||||
.brd = Color256_MidGray,
|
||||
.brd = Color256_LightGray,
|
||||
.bg = Color256_NavyBlue,
|
||||
.fg = Color256_MidGray
|
||||
.fg = Color256_LightGray
|
||||
};
|
||||
self->style.focused = (TimStyle){
|
||||
.brd = Color256_White,
|
||||
@@ -28,7 +28,7 @@ void ClientCLI_construct(ClientCLI* self){
|
||||
.fg = Color256_White
|
||||
};
|
||||
self->style.error = (TimStyle){
|
||||
.brd = Color256_MidGray,
|
||||
.brd = Color256_LightGray,
|
||||
.bg = Color256_DarkRed,
|
||||
.fg = Color256_White
|
||||
};
|
||||
|
||||
@@ -35,8 +35,10 @@ void ClientCLI_run(ClientCLI* self);
|
||||
|
||||
|
||||
enum {
|
||||
Color256_White = 0xe7,
|
||||
Color256_Black = 0x10,
|
||||
Color256_MidGray = 0xf8,
|
||||
Color256_LightGray = 0xfb,
|
||||
Color256_White = 0xe7,
|
||||
Color256_NavyBlue = 0x11,
|
||||
Color256_DeepSkyBlue = 0x18,
|
||||
Color256_DarkRed = 0x58,
|
||||
@@ -59,22 +61,22 @@ void TextInputState_construct(TextInputState* ctx, cstr label,
|
||||
/// tim_edit with tim_label over its upper border.
|
||||
void text_input(TextInputState* ctx, i32 x, i32 y, i32 w, TimStyle style);
|
||||
|
||||
void TimScrollItem_fromTextInputState(TimScrollItem* item, TextInputState* input);
|
||||
void TimPanelItem_fromTextInputState(TimPanelItem* item, TextInputState* input);
|
||||
|
||||
/// Intended to use in TimScrollItem
|
||||
/// Intended to use in TimPanelItem
|
||||
/// @param data TextInputState*
|
||||
void draw_item_text_input(bool is_selected, TimRect place, void* data);
|
||||
void draw_item_text_input(void* data, TimRect place, bool is_selected);
|
||||
|
||||
|
||||
List_declare(TimScrollItem);
|
||||
List_declare(TimPanelItem);
|
||||
|
||||
typedef struct StartScreenContext {
|
||||
ClientCLI* client;
|
||||
char* err_msg; // heap only
|
||||
TextInputState input_username;
|
||||
TextInputState input_password;
|
||||
List(TimScrollItem) scroll_list;
|
||||
TimScrollState scroll_state;
|
||||
TimPanel central_panel;
|
||||
TimPanel central_buttons_panel;
|
||||
} StartScreenContext;
|
||||
|
||||
void StartScreenContext_construct(StartScreenContext* ctx, ClientCLI* client);
|
||||
@@ -84,6 +86,8 @@ void start_screen(StartScreenContext* ctx);
|
||||
|
||||
typedef struct MainScreenContext {
|
||||
ClientCLI* client;
|
||||
TimPanel central_panel;
|
||||
TimScrollView central_scroll_view;
|
||||
} MainScreenContext;
|
||||
|
||||
void MainScreenContext_construct(MainScreenContext* ctx, ClientCLI* client);
|
||||
|
||||
@@ -19,6 +19,8 @@ static const str farewell_art = STR(
|
||||
);
|
||||
|
||||
|
||||
static void draw_test_label(void* data, TimRect place, bool is_selected);
|
||||
static void draw_central_panel(void* data, TimRect place);
|
||||
static Result(SavedServer*) joinNewServer(ClientCLI* self);
|
||||
static Result(SavedServer*) selectServerFromCache(ClientCLI* self);
|
||||
static Result(void) showSavedServer(ClientCLI* self, SavedServer* server);
|
||||
@@ -29,23 +31,64 @@ static Result(void) loginAtServer(ClientCLI* self);
|
||||
void MainScreenContext_construct(MainScreenContext* ctx, ClientCLI* client){
|
||||
zeroStruct(ctx);
|
||||
ctx->client = client;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// central_panel //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
List(TimPanelItem) items = List_TimPanelItem_alloc(4);
|
||||
|
||||
TimPanelItem item_test_label = {
|
||||
.w = A, .h = 12, .data = ctx, .draw = draw_test_label
|
||||
};
|
||||
List_TimPanelItem_push(&items, item_test_label);
|
||||
List_TimPanelItem_push(&items, item_test_label);
|
||||
List_TimPanelItem_push(&items, item_test_label);
|
||||
List_TimPanelItem_push(&items, item_test_label);
|
||||
|
||||
ctx->central_panel.items = items.data;
|
||||
ctx->central_panel.len = items.len;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// central_scroll_view //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
ctx->central_scroll_view.content_h = 50;
|
||||
ctx->central_scroll_view.data = ctx;
|
||||
ctx->central_scroll_view.draw = draw_central_panel;
|
||||
}
|
||||
}
|
||||
|
||||
void MainScreenContext_destroy(MainScreenContext* ctx){
|
||||
|
||||
free(ctx->central_panel.items);
|
||||
}
|
||||
|
||||
void main_screen(MainScreenContext* ctx){
|
||||
tim_frame(0, 0, ~0, ~0, ctx->client->style.common);
|
||||
if (tim->event.type == TimEvent_Draw) {
|
||||
tim_fill(tim_cell(" ", ctx->client->style.common.fg, ctx->client->style.common.bg), 0, 0, A, A);
|
||||
}
|
||||
|
||||
if(tim_button("[Esc/Q] Quit", A, A, A, A, ctx->client->style.common)
|
||||
if(tim_button_noborder("[Esc/Q] Exit", 1, 0, 14, 1, ctx->client->style.common)
|
||||
|| tim_is_key_press('q')
|
||||
|| tim_is_key_press(TimKey_Escape))
|
||||
{
|
||||
ctx->client->state = ClientCLIState_Exit;
|
||||
}
|
||||
|
||||
tim_scroll_view(&ctx->central_scroll_view, 0, 1, ~0, ~0, ctx->client->style.common);
|
||||
}
|
||||
|
||||
static void draw_test_label(void* data, TimRect place, bool is_selected){
|
||||
MainScreenContext* ctx = data;
|
||||
TimStyle style = is_selected ? ctx->client->style.focused : ctx->client->style.common;
|
||||
tim_frame(place.x, place.y, place.w, place.h, style);
|
||||
tim_label("0\n1\n2\n3\n4\n5\n6\n7\n8\n9",
|
||||
place.x + 1, place.y + 1, place.w - 2, place.h - 2, style);
|
||||
}
|
||||
|
||||
static void draw_central_panel(void* data, TimRect place){
|
||||
MainScreenContext* ctx = data;
|
||||
tim_panel(&ctx->central_panel, false, place.x, place.y, place.w, place.h);
|
||||
}
|
||||
|
||||
/*
|
||||
static Result(void) ClientCLI_execCommand(ClientCLI* self, str command, bool* stop){
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#include "network/tcp-chat-protocol/v1.h"
|
||||
#include "tlibc/filesystem.h"
|
||||
|
||||
static void draw_buttons(bool is_selected, TimRect place, void* data);
|
||||
static void draw_central_buttons_panel(void* data, TimRect place, bool is_selected);
|
||||
static void draw_start_button(void* data, TimRect place, bool is_selected);
|
||||
static void draw_exit_button(void* data, TimRect place, bool is_selected);
|
||||
static Result(void) openUserDB(StartScreenContext* ctx);
|
||||
|
||||
|
||||
@@ -21,77 +23,101 @@ static void clearError(StartScreenContext* ctx){
|
||||
void StartScreenContext_construct(StartScreenContext* ctx, ClientCLI* client){
|
||||
zeroStruct(ctx);
|
||||
ctx->client = client;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// input_username //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
Array(char) username_buf = Array_char_alloc(USERNAME_SIZE_MAX + 1);
|
||||
TextInputState_construct(&ctx->input_username, "[username]",
|
||||
username_buf, NULL, false,
|
||||
ctx->client->style.common, ctx->client->style.focused);
|
||||
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// input_password //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
Array(char) password_buf = Array_char_alloc(PASSWORD_SIZE_MAX + 1);
|
||||
TextInputState_construct(&ctx->input_password, "[password]",
|
||||
password_buf, NULL, true,
|
||||
ctx->client->style.common, ctx->client->style.focused);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// central_panel //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
List(TimPanelItem) items = List_TimPanelItem_alloc(4);
|
||||
|
||||
ctx->scroll_list = List_TimScrollItem_alloc(8);
|
||||
TimPanelItem item_username_input;
|
||||
TimPanelItem_fromTextInputState(&item_username_input, &ctx->input_username);
|
||||
List_TimPanelItem_push(&items, item_username_input);
|
||||
|
||||
TimScrollItem item_input_username;
|
||||
TimScrollItem_fromTextInputState(&item_input_username, &ctx->input_username);
|
||||
List_TimScrollItem_push(&ctx->scroll_list, item_input_username);
|
||||
TimPanelItem item_password_input;
|
||||
TimPanelItem_fromTextInputState(&item_password_input, &ctx->input_password);
|
||||
List_TimPanelItem_push(&items, item_password_input);
|
||||
|
||||
TimScrollItem item_input_password;
|
||||
TimScrollItem_fromTextInputState(&item_input_password, &ctx->input_password);
|
||||
List_TimScrollItem_push(&ctx->scroll_list, item_input_password);
|
||||
|
||||
TimScrollItem item_buttons = {
|
||||
.data = ctx,
|
||||
.focus_target = NULL,
|
||||
.h = 3,
|
||||
.draw = draw_buttons
|
||||
TimPanelItem item_central_buttons_panel = {
|
||||
.w = A, .h = 3, .data = ctx, .draw = draw_central_buttons_panel
|
||||
};
|
||||
List_TimScrollItem_push(&ctx->scroll_list, item_buttons);
|
||||
List_TimPanelItem_push(&items, item_central_buttons_panel);
|
||||
|
||||
ctx->scroll_state = (TimScrollState){ .items = ctx->scroll_list.data, .len = ctx->scroll_list.len };
|
||||
ctx->central_panel.items = items.data;
|
||||
ctx->central_panel.len = items.len;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// central_buttons_panel //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
List(TimPanelItem) items = List_TimPanelItem_alloc(4);
|
||||
|
||||
TimPanelItem item_start_button = {
|
||||
.w = A, .h = 3, .data = ctx, .draw = draw_start_button
|
||||
};
|
||||
List_TimPanelItem_push(&items, item_start_button);
|
||||
|
||||
TimPanelItem item_exit_button = {
|
||||
.w = A, .h = 3, .data = ctx, .draw = draw_exit_button
|
||||
};
|
||||
List_TimPanelItem_push(&items, item_exit_button);
|
||||
|
||||
ctx->central_buttons_panel.items = items.data;
|
||||
ctx->central_buttons_panel.len = items.len;
|
||||
ctx->central_buttons_panel.is_horizontal = true;
|
||||
}
|
||||
}
|
||||
|
||||
void StartScreenContext_destroy(StartScreenContext* ctx){
|
||||
free(ctx->input_username.edit.s);
|
||||
free(ctx->input_password.edit.s);
|
||||
free(ctx->err_msg);
|
||||
List_TimScrollItem_destroy(&ctx->scroll_list);
|
||||
free(ctx->central_panel.items);
|
||||
free(ctx->central_buttons_panel.items);
|
||||
}
|
||||
|
||||
void start_screen(StartScreenContext* ctx)
|
||||
{
|
||||
if (tim->event.type == TimEvent_Draw) {
|
||||
tim_fill(tim_cell(" ", ctx->client->style.common.fg, ctx->client->style.common.bg), 0, 0, A, A);
|
||||
tim_scope(A, A, 40, 13) {
|
||||
tim_scroll(&ctx->scroll_state, 1, 1, ~1, ~1, ctx->client->style.common);
|
||||
}
|
||||
|
||||
tim_frame(A, A, 40, 11, ctx->client->style.common);
|
||||
tim_panel(&ctx->central_panel, true, A, A, 38, 9);
|
||||
|
||||
if(ctx->err_msg){
|
||||
i32 below_scroll = tim->scopes[tim->scope].h/2 + 6;
|
||||
tim_label("ERROR: ", A, below_scroll, A, A, ctx->client->style.error);
|
||||
tim_label(ctx->err_msg, A, below_scroll + 1, A, A, ctx->client->style.error);
|
||||
i32 below_list = tim->scopes[tim->scope].h/2 + 6;
|
||||
tim_label("ERROR: ", A, below_list, A, A, ctx->client->style.error);
|
||||
tim_label(ctx->err_msg, A, below_list + 1, A, A, ctx->client->style.error);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_central_buttons_panel(void* data, TimRect place, bool is_selected){
|
||||
StartScreenContext* ctx = data;
|
||||
tim_panel(&ctx->central_buttons_panel, is_selected, place.x, place.y, place.w, place.h);
|
||||
}
|
||||
|
||||
|
||||
static void draw_buttons(bool is_selected, TimRect place, void* data){
|
||||
static void draw_start_button(void* data, TimRect place, bool is_selected){
|
||||
StartScreenContext* ctx = data;
|
||||
TimStyle style = is_selected ? ctx->client->style.focused : ctx->client->style.common;
|
||||
i32 start_w = place.w / 2;
|
||||
i32 dist = 1;
|
||||
i32 quit_x = place.x + start_w + dist;
|
||||
i32 quit_w = place.w - start_w - dist;
|
||||
if(tim_button("[Esc/Q] Quit", quit_x, place.y, quit_w, A, ctx->client->style.common)
|
||||
|| tim_is_key_press('q')
|
||||
|| ctx->input_username.result_key == TimKey_Escape
|
||||
|| ctx->input_password.result_key == TimKey_Escape)
|
||||
{
|
||||
ctx->client->state = ClientCLIState_Exit;
|
||||
return;
|
||||
}
|
||||
if(tim_button("[Enter] Start", place.x, place.y, start_w, A, style)
|
||||
if(tim_button("[Enter] Start", place.x, place.y, place.w, A, style)
|
||||
|| tim_is_key_press(TimKey_Enter))
|
||||
{
|
||||
clearError(ctx);
|
||||
@@ -116,21 +142,32 @@ static void draw_buttons(bool is_selected, TimRect place, void* data){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// create client
|
||||
try_handle(ctx->client->client, p, Client_create(username, password), handleError);
|
||||
|
||||
// init user DB
|
||||
try_handle_void(openUserDB(ctx), handleError);
|
||||
|
||||
// erase password from memory
|
||||
memset(ctx->input_password.edit.s, 0, ctx->input_password.edit.capacity);
|
||||
|
||||
// switch to next screen
|
||||
ctx->client->state = ClientCLIState_MainScreen;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_exit_button(void* data, TimRect place, bool is_selected){
|
||||
StartScreenContext* ctx = data;
|
||||
TimStyle style = is_selected ? ctx->client->style.focused : ctx->client->style.common;
|
||||
if(tim_button("[Esc/Q] Exit", place.x, place.y, place.w, A, style)
|
||||
|| tim_is_key_press('q')
|
||||
|| tim_is_key_press(TimKey_Escape)
|
||||
|| ctx->input_username.result_key == TimKey_Escape
|
||||
|| ctx->input_password.result_key == TimKey_Escape)
|
||||
{
|
||||
ctx->client->state = ClientCLIState_Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static Result(void) openUserDB(StartScreenContext* ctx){
|
||||
Deferral(8);
|
||||
|
||||
|
||||
@@ -16,15 +16,16 @@ void text_input(TextInputState* ctx, i32 x, i32 y, i32 w, TimStyle style){
|
||||
tim_label(ctx->label, x + 3, y, A, 1, style);
|
||||
}
|
||||
|
||||
void TimScrollItem_fromTextInputState(TimScrollItem* item, TextInputState* input){
|
||||
void TimPanelItem_fromTextInputState(TimPanelItem* item, TextInputState* input){
|
||||
zeroStruct(item);
|
||||
item->w = A;
|
||||
item->h = 3;
|
||||
item->data = input;
|
||||
item->focus_target = &input->edit;
|
||||
item->h = 3;
|
||||
item->draw = draw_item_text_input;
|
||||
}
|
||||
|
||||
void draw_item_text_input(bool is_selected, TimRect place, void* data){
|
||||
void draw_item_text_input(void* data, TimRect place, bool is_selected){
|
||||
TextInputState* ctx = data;
|
||||
TimStyle style = is_selected ? ctx->style.focused : ctx->style.common;
|
||||
text_input(ctx, place.x, place.y, place.w, style);
|
||||
|
||||
Reference in New Issue
Block a user