diff --git a/dependencies/tim b/dependencies/tim index 2a685df..ee6375f 160000 --- a/dependencies/tim +++ b/dependencies/tim @@ -1 +1 @@ -Subproject commit 2a685dfcd052ed3ed57d2b006be25f081e8ec8b8 +Subproject commit ee6375f553e13871a85c0a33567483dbbb39ef1c diff --git a/src/cli/ClientCLI/ClientCLI.c b/src/cli/ClientCLI/ClientCLI.c index c5cdce3..9b0b79e 100644 --- a/src/cli/ClientCLI/ClientCLI.c +++ b/src/cli/ClientCLI/ClientCLI.c @@ -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 }; diff --git a/src/cli/ClientCLI/ClientCLI.h b/src/cli/ClientCLI/ClientCLI.h index 202e8b2..37c4cfd 100644 --- a/src/cli/ClientCLI/ClientCLI.h +++ b/src/cli/ClientCLI/ClientCLI.h @@ -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); diff --git a/src/cli/ClientCLI/main_screen.c b/src/cli/ClientCLI/main_screen.c index 6017f2b..ec67ba4 100644 --- a/src/cli/ClientCLI/main_screen.c +++ b/src/cli/ClientCLI/main_screen.c @@ -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){ diff --git a/src/cli/ClientCLI/start_screen.c b/src/cli/ClientCLI/start_screen.c index 09f944f..a58de4c 100644 --- a/src/cli/ClientCLI/start_screen.c +++ b/src/cli/ClientCLI/start_screen.c @@ -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; - - 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); - - 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); + /////////////////////////////////////////////////////////////////////////// + // 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); + + TimPanelItem item_username_input; + TimPanelItem_fromTextInputState(&item_username_input, &ctx->input_username); + List_TimPanelItem_push(&items, item_username_input); - ctx->scroll_list = List_TimScrollItem_alloc(8); - - 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); + TimPanelItem item_central_buttons_panel = { + .w = A, .h = 3, .data = ctx, .draw = draw_central_buttons_panel + }; + List_TimPanelItem_push(&items, item_central_buttons_panel); - TimScrollItem item_buttons = { - .data = ctx, - .focus_target = NULL, - .h = 3, - .draw = draw_buttons - }; - List_TimScrollItem_push(&ctx->scroll_list, item_buttons); - - 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) { - 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); + 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_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); diff --git a/src/cli/ClientCLI/widgets.c b/src/cli/ClientCLI/widgets.c index d3fbf62..456e37c 100644 --- a/src/cli/ClientCLI/widgets.c +++ b/src/cli/ClientCLI/widgets.c @@ -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);