From 85b36cdce3e5d60a64274067160a919503291896 Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Sat, 22 Feb 2020 19:55:55 +0100 Subject: licensing --- src/mo_edit.c | 1904 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 949 insertions(+), 955 deletions(-) (limited to 'src') diff --git a/src/mo_edit.c b/src/mo_edit.c index ded4c05..c54dae7 100644 --- a/src/mo_edit.c +++ b/src/mo_edit.c @@ -1,956 +1,950 @@ -/* -* BSD 2-Clause “Simplified” License -* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com -* All rights reserved. -*/ - -#include "config.h" -#include "project_base.h" - -// TODO(Aldrik): delete file of language when deleting language - -s32 global_language_id = 1; -char project_path[MAX_INPUT_LENGTH]; - -typedef struct t_language -{ - char *name; - s32 id; -} language; - -typedef struct t_translation -{ - s32 language_id; - char *value; -} translation; - -typedef struct t_term -{ - char *name; - array translations; -} term; - -typedef struct t_translation_project -{ - array languages; - array terms; - int selected_term_index; -} translation_project; - -translation_project *current_project = 0; -array tb_translation_list; - -#include "save.h" -#include "save.c" - -#include "settings.h" -#include "settings.c" - -scroll_state term_scroll; -scroll_state lang_scroll; -scroll_state trans_scroll; -button_state btn_new_project; -button_state btn_new_language; -button_state btn_summary; -button_state btn_set_term_name; -dropdown_state dd_available_countries; -textbox_state tb_filter; -textbox_state tb_new_term; -textbox_state tb_new_language; - -image *set_img; -image *add_img; -image *list_img; -image *exclaim_img; -image *delete_img; -image *logo_small_img; - -font *font_medium; -font *font_small; -font *font_mini; - -static void load_assets() -{ - list_img = assets_load_image(_binary____data_imgs_list_png_start, - _binary____data_imgs_list_png_end, false); - exclaim_img = assets_load_image(_binary____data_imgs_exclaim_png_start, - _binary____data_imgs_exclaim_png_end, false); - logo_small_img = assets_load_image(_binary____data_imgs_logo_64_png_start, - _binary____data_imgs_logo_64_png_end, true); - delete_img = assets_load_image(_binary____data_imgs_delete_png_start, - _binary____data_imgs_delete_png_end, false); - add_img = assets_load_image(_binary____data_imgs_add_png_start, - _binary____data_imgs_add_png_end, false); - set_img = assets_load_image(_binary____data_imgs_set_png_start, - _binary____data_imgs_set_png_end, false); - - font_medium = assets_load_font(_binary____data_fonts_mono_ttf_start, - _binary____data_fonts_mono_ttf_end, 18); - font_small = assets_load_font(_binary____data_fonts_mono_ttf_start, - _binary____data_fonts_mono_ttf_end, 15); - font_mini = assets_load_font(_binary____data_fonts_mono_ttf_start, - _binary____data_fonts_mono_ttf_end, 12); -} - -bool term_has_missing_translations(term *t) -{ - for (s32 i = 0; i < t->translations.length; i++) - { - translation *tr = array_at(&t->translations, i); - if (string_equals(tr->value, "")) return true; - } - - return false; -} - -s32 get_translated_count_for_language(s32 language_id) -{ - s32 count = 0; - for (s32 i = 0; i < current_project->terms.length; i++) - { - term *t = array_at(¤t_project->terms, i); - - for (s32 x = 0; x < t->translations.length; x++) - { - translation *tr = array_at(&t->translations, x); - - if (tr->language_id == language_id && !string_equals(tr->value, "")) - { - count++; - break; - } - } - } - - return count; -} - -bool term_name_is_available(char *name) -{ - for (s32 i = 0; i < current_project->terms.length; i++) - { - term *tr = array_at(¤t_project->terms, i); - - if (string_equals(tr->name, name)) - { - return false; - } - } - - return true; -} - -language* get_language_by_id(s32 language_id) -{ - for (s32 i = 0; i < current_project->languages.length; i++) - { - language *l = array_at(¤t_project->languages, i); - if (l->id == language_id) - { - return l; - } - } - return 0; -} - -s32 add_language_to_project(char *buffer) -{ - if (string_equals(buffer, "")) - { - // TODO(Aldrik): localize - platform_show_message(main_window, "Language name cannot be empty", "Invalid info"); - return -1; - } - - for (s32 i = 0; i < current_project->languages.length; i++) - { - language *lang = array_at(¤t_project->languages, i); - if (string_equals(lang->name, buffer)) - { - // TODO(Aldrik): localize - platform_show_message(main_window, "Language already added", "Invalid info"); - return -1; - } - } - - char *val = mem_alloc(MAX_INPUT_LENGTH); - string_copyn(val, buffer, MAX_INPUT_LENGTH); - - language l; - l.name = val; - l.id = global_language_id++; - - s32 index = array_push(¤t_project->languages, &l); - - textbox_state new_tb; - new_tb = ui_create_textbox(MAX_INPUT_LENGTH); - new_tb.accept_newline = true; - new_tb.deselect_on_enter = false; - array_push(&tb_translation_list, &new_tb); - - for (s32 x = 0; x < current_project->terms.length; x++) - { - term *t = array_at(¤t_project->terms, x); - - translation new_t; - new_t.value = mem_alloc(MAX_INPUT_LENGTH); - string_copyn(new_t.value, "", MAX_INPUT_LENGTH); - new_t.language_id = l.id; - - array_push(&t->translations, &new_t); - } - - return l.id; -} - -void set_term_name(s32 index, char *name) -{ - if (strlen(name) > 0) - { - term *t = array_at(¤t_project->terms, index); - string_copyn(t->name, name, MAX_TERM_NAME_LENGTH); - } - else - { - platform_show_message(main_window, localize("term_name_cannot_be_empty"), localize("invalid_input")); - } -} - -void remove_term_from_project(s32 index) -{ - term *t = array_at(¤t_project->terms, index); - mem_free(t->name); - for (s32 i = 0; i < t->translations.length; i++) - { - translation *tr = array_at(&t->translations, i); - mem_free(tr->value); - } - array_destroy(&t->translations); - array_remove_at(¤t_project->terms, index); -} - -void remove_language_from_project(s32 language_id) -{ - for (s32 i = 0; i < current_project->languages.length; i++) - { - language *l = array_at(¤t_project->languages, i); - if (l->id == language_id) - { - char fullpath[MAX_INPUT_LENGTH]; - fullpath[0] = 0; - string_appendn(fullpath, project_path, MAX_INPUT_LENGTH); -#ifdef OS_WIN - string_appendn(fullpath, "\\", MAX_INPUT_LENGTH); -#endif -#ifdef OS_LINUX - string_appendn(fullpath, "/", MAX_INPUT_LENGTH); -#endif - string_appendn(fullpath, l->name, MAX_INPUT_LENGTH); - string_appendn(fullpath, ".mo", MAX_INPUT_LENGTH); - if (platform_file_exists(fullpath)) - { - platform_delete_file(fullpath); - } - - array_remove_at(¤t_project->languages, i); - textbox_state *st = array_at(&tb_translation_list, i); - mem_free(st->buffer); - array_remove_at(&tb_translation_list, i); - break; - } - } - - for (s32 x = 0; x < current_project->terms.length; x++) - { - term *tr = array_at(¤t_project->terms, x); - - for (s32 i = 0; i < tr->translations.length; i++) - { - translation *t = array_at(&tr->translations, i); - - if (t->language_id == language_id) - { - mem_free(t->value); - array_remove_at(&tr->translations, i); - break; - } - } - } -} - -void select_term(s32 index) -{ - current_project->selected_term_index = index; - term *t = array_at(¤t_project->terms, index); - ui_set_textbox_text(&tb_new_term, t->name); - - for (s32 i = 0; i < current_project->languages.length; i++) - { - translation *tr = array_at(&t->translations, i); - textbox_state *tb = array_at(&tb_translation_list, i); - tb->state = false; - - if (tr->value) - { - ui_set_textbox_text(tb, tr->value); - } - else - { - ui_set_textbox_text(tb, ""); - } - } -} - -s32 add_term_to_project() -{ - tb_filter.state = 0; - ui_set_textbox_text(&tb_filter, ""); - - term t; - t.name = mem_alloc(MAX_TERM_NAME_LENGTH); - - s32 count = 0; - do - { - char buffer[MAX_TERM_NAME_LENGTH]; - sprintf(buffer, "term_%d", count); - string_copyn(t.name, buffer, MAX_TERM_NAME_LENGTH); - count++; - } - while(!term_name_is_available(t.name)); - - t.translations = array_create(sizeof(translation)); - array_reserve(&t.translations, current_project->languages.length); - - for (s32 i = 0; i < current_project->languages.length; i++) - { - language *l = array_at(¤t_project->languages, i); - - translation tr; - tr.value = mem_alloc(MAX_INPUT_LENGTH); - string_copyn(tr.value, "", MAX_INPUT_LENGTH); - tr.language_id = l->id; - array_push(&t.translations, &tr); - } - - ui_set_textbox_active(&tb_new_term); - - return array_push(¤t_project->terms, &t); -} - -void save_term_changes() -{ - set_term_name(current_project->selected_term_index, tb_new_term.buffer); - - term *t = array_at(¤t_project->terms, current_project->selected_term_index); - - for (s32 i = 0; i < current_project->languages.length; i++) - { - translation *tr = array_at(&t->translations, i); - textbox_state *tb = array_at(&tb_translation_list, i); - - string_copyn(tr->value, tb->buffer, MAX_INPUT_LENGTH); - } -} - -void start_new_project() -{ - global_language_id = 1; - current_project = mem_alloc(sizeof(translation_project)); - - current_project->terms = array_create(sizeof(term)); - array_reserve(¤t_project->terms, 100); - current_project->terms.reserve_jump = 100; - - current_project->languages = array_create(sizeof(language)); - array_reserve(¤t_project->languages, 100); - current_project->languages.reserve_jump = 100; - - current_project->selected_term_index = -1; -} - -void load_config(settings_config *config) -{ - char *path = settings_config_get_string(config, "ACTIVE_PROJECT"); - char *locale_id = settings_config_get_string(config, "LOCALE"); - - if (path) - { - string_copyn(project_path, path, MAX_INPUT_LENGTH); - - if (platform_directory_exists(project_path)) - { - load_project_from_folder(project_path); - } - else - { - string_copyn(project_path, "", MAX_INPUT_LENGTH); - } - } - - if (locale_id) - set_locale(locale_id); - else - set_locale("en"); -} - -#if defined(OS_LINUX) || defined(OS_WIN) -int main(int argc, char **argv) -{ - platform_init(argc, argv); - - char config_path_buffer[PATH_MAX]; - get_config_save_location(config_path_buffer); - - // load config - settings_config config = settings_config_load_from_file(config_path_buffer); - - s32 window_w = settings_config_get_number(&config, "WINDOW_WIDTH"); - s32 window_h = settings_config_get_number(&config, "WINDOW_HEIGHT"); - if (window_w < 800 || window_h < 600) - { - window_w = 800; - window_h = 600; - } - - platform_window window = platform_open_window("mo-edit", window_w, window_h, 0, 0, 800, 600); - main_window = &window; - - validate_license(); - - settings_page_create(); - - load_available_localizations(); - set_locale("en"); - - load_assets(); - - keyboard_input keyboard = keyboard_input_create(); - mouse_input mouse = mouse_input_create(); - - camera camera; - camera.x = 0; - camera.y = 0; - camera.rotation = 0; - - ui_create(&window, &keyboard, &mouse, &camera, font_small); - term_scroll = ui_create_scroll(1); - lang_scroll = ui_create_scroll(1); - trans_scroll = ui_create_scroll(1); - btn_summary = ui_create_button(); - btn_set_term_name = ui_create_button(); - btn_new_project = ui_create_button(); - btn_new_language = ui_create_button(); - tb_filter = ui_create_textbox(MAX_INPUT_LENGTH); - tb_new_term = ui_create_textbox(MAX_TERM_NAME_LENGTH); - tb_new_language = ui_create_textbox(MAX_INPUT_LENGTH); - - // asset worker - thread asset_queue_worker1 = thread_start(assets_queue_worker, NULL); - thread asset_queue_worker2 = thread_start(assets_queue_worker, NULL); - thread_detach(&asset_queue_worker1); - thread_detach(&asset_queue_worker2); - - tb_translation_list = array_create(sizeof(textbox_state)); - load_config(&config); - - while(window.is_open) { - u64 last_stamp = platform_get_time(TIME_FULL, TIME_US); - platform_handle_events(&window, &mouse, &keyboard); - platform_set_cursor(&window, CURSOR_DEFAULT); - - settings_page_update_render(); - - platform_window_make_current(&window); - - if (!license_is_valid) - { - char message[200]; - sprintf(message, localize("invalid_license"), license_key); - platform_show_message(main_window, message, localize("license_error")); - window.is_open = false; - } - - static bool icon_loaded = false; - if (!icon_loaded && logo_small_img->loaded) - { - icon_loaded = true; - platform_set_icon(&window, logo_small_img); - } - - if (global_asset_collection.queue.queue.length == 0 && !global_asset_collection.done_loading_assets) - { - global_asset_collection.done_loading_assets = true; - } - - global_ui_context.layout.active_window = &window; - global_ui_context.keyboard = &keyboard; - global_ui_context.mouse = &mouse; - - render_clear(); - camera_apply_transformations(&window, &camera); - - global_ui_context.layout.width = global_ui_context.layout.active_window->width; - // begin ui - - ui_begin(1); - { - render_rectangle(0, 0, main_window->width, main_window->height, global_ui_context.style.background); - - ui_begin_menu_bar(); - { - if (ui_push_menu(localize("file"))) - { - if (ui_push_menu_item(localize("load_project"), "Ctrl + O")) - { - load_project(); - } - if (ui_push_menu_item(localize("save_project"), "Ctrl + S")) - { - if (current_project) - { - if (string_equals(project_path, "")) - save_project(); - else - save_project_to_folder(project_path); - } - else - { - platform_show_message(main_window, localize("no_project_to_save"), localize("error_saving_project")); - } - } - if (ui_push_menu_item(localize("save_project_as"), "Ctrl + A")) - { - if (current_project) - { - save_project(); - } - else - { - platform_show_message(main_window, localize("no_project_to_save"), localize("error_saving_project")); - } - } - if (ui_push_menu_item(localize("close_project"), "")) - { - current_project = 0; - project_path[0] = 0; - } - ui_push_menu_item_separator(); - if (ui_push_menu_item(localize("quit"), "Ctrl + Q")) - { - window.is_open = false; - } - } - if (ui_push_menu(localize("options"))) - { - if (ui_push_menu_item(localize("settings"), "")) - { - settings_page_show(); - } - } - } - ui_end_menu_bar(); - ui_push_separator(); - - global_ui_context.layout.width = 300; - ui_push_vertical_dragbar(); - - if (current_project) - { - ui_block_begin(LAYOUT_HORIZONTAL); - { - if (ui_push_button_image(&btn_summary, "", list_img)) - { - current_project->selected_term_index = -1; - } - - ui_push_textf_width(font_medium, localize("terms"), global_ui_context.layout.width-106); - - if (ui_push_button_image(&btn_summary, "", add_img)) - { - select_term(add_term_to_project()); - } - - //ui_push_button_image(&btn_summary, "", delete_img); - - } - ui_block_end(); - - ui_block_begin(LAYOUT_HORIZONTAL); - { - TEXTBOX_WIDTH = 280; - ui_push_textbox(&tb_filter, localize("filter_terms")); - } - ui_block_end(); - - ui_push_separator(); - - // reset scroll if filter text changed - if (tb_filter.state && keyboard.text_changed) - { - term_scroll.scroll = 0; - } - - term_scroll.height = main_window->height-global_ui_context.layout.offset_y+8; - ui_scroll_begin(&term_scroll); - { - for (s32 i = 0; i < current_project->terms.length; i++) - { - term *t = array_at(¤t_project->terms, i); - - if (!strlen(tb_filter.buffer) || string_contains(t->name, tb_filter.buffer)) - { - bool removed = false; - if (ui_push_button_image_with_confirmation(&btn_summary, "", delete_img)) - { - removed = true; - } - - //ui_push_image(exclaim_img, 14, 14, 1, rgb(255,255,255)); - - if (i == current_project->selected_term_index) - { - ui_push_rect(10, global_ui_context.style.textbox_active_border); - } - else if (term_has_missing_translations(t)) - { - ui_push_rect(10, MISSING_TRANSLATION_COLOR); - } - else - { - ui_push_rect(10, global_ui_context.style.background); - } - - if (ui_push_text_width(t->name, global_ui_context.layout.width-100, true)) - { - select_term(i); - } - - ui_block_end(); - - if (removed) - { - remove_term_from_project(i); - --i; - if (i >= 0) select_term(i); - } - } - } - } - ui_scroll_end(); - } - else - { - if (ui_push_button(&btn_new_project, localize("create_new_project"))) - { - start_new_project(); - } - } - - global_ui_context.layout.width = main_window->width - 310; - - global_ui_context.layout.offset_x = 310; - global_ui_context.layout.offset_y = MENU_BAR_HEIGHT + WIDGET_PADDING; - - if (current_project && current_project->selected_term_index >= 0) - { - if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_S)) - { - save_term_changes(); - } - - term *t = array_at(¤t_project->terms, - current_project->selected_term_index); - - ui_block_begin(LAYOUT_HORIZONTAL); - { - // editor - - if (string_equals(tb_new_term.buffer, t->name)) - ui_push_rect(10, global_ui_context.style.background); - else - ui_push_rect(10, UNSAVED_CHANGES_COLOR); - - ui_push_textbox(&tb_new_term, localize("term_name")); - - if (ui_push_button_image(&btn_set_term_name, "", set_img)) - { - save_term_changes(); - } - } - ui_block_end(); - - global_ui_context.layout.offset_x = 310; - ui_push_separator(); - - trans_scroll.height = main_window->height-global_ui_context.layout.offset_y+WIDGET_PADDING; - - ui_scroll_begin(&trans_scroll); - { - if (!current_project->languages.length) - { - ui_push_text(localize("no_languages_added")); - } - else - { - for (s32 i = 0; i < t->translations.length; i++) - { - translation *tr = array_at(&t->translations, i); - - TEXTBOX_WIDTH = global_ui_context.layout.width - 130; - - textbox_state *tbs = array_at(&tb_translation_list, i); - if (!strlen(tbs->buffer)) - { - ui_push_rect(10, MISSING_TRANSLATION_COLOR); - } - else if (string_equals(tbs->buffer, - tr->value)) - { - ui_push_rect(10, global_ui_context.style.background); - } - else - { - ui_push_rect(10, UNSAVED_CHANGES_COLOR); - } - - ui_push_textbox(tbs, ""); - - language *l = get_language_by_id(tr->language_id); - ui_push_text(l->name); - - global_ui_context.layout.offset_y += TEXTBOX_HEIGHT + WIDGET_PADDING; - global_ui_context.layout.offset_x = 310; - - if (keyboard_is_key_pressed(&keyboard, KEY_TAB) && tbs->state) - { - keyboard.input_keys[KEY_TAB] = false; - tbs->state = false; - - if (i+1 < t->translations.length) - { - ui_set_textbox_active(array_at(&tb_translation_list, i+1)); - } - else - { - ui_set_textbox_active(array_at(&tb_translation_list, 0)); - } - } - } - } - } - ui_scroll_end(); - } - else if (current_project) - { - // overview - ui_block_begin(LAYOUT_HORIZONTAL); - { - ui_push_textf_width(font_medium, localize("overview"), 100); - - char info_text[60]; - sprintf(info_text, localize("info_text"), current_project->terms.length, current_project->languages.length); - - color c = global_ui_context.style.foreground; - global_ui_context.style.foreground = rgb(110,110,110); - ui_push_textf(font_small, info_text); - global_ui_context.style.foreground = c; - } - ui_block_end(); - - ui_push_separator(); - - ui_block_begin(LAYOUT_HORIZONTAL); - { - bool selected = tb_new_language.state; - ui_push_textbox(&tb_new_language, localize("add_language")); - - if (keyboard_is_key_pressed(&keyboard, KEY_ENTER) && selected) - { - add_language_to_project(tb_new_language.buffer); - ui_set_textbox_text(&tb_new_language, ""); - keyboard_set_input_text(&keyboard, ""); - tb_new_language.state = true; - } - - if (ui_push_button(&btn_new_language, localize("add"))) - { - add_language_to_project(tb_new_language.buffer); - ui_set_textbox_text(&tb_new_language, ""); - keyboard_set_input_text(&keyboard, ""); - tb_new_language.state = true; - } - - if (!string_equals(tb_new_language.buffer, "")) - { - ui_block_end(); - char filename_buffer[MAX_INPUT_LENGTH]; - filename_buffer[0] = 0; - string_appendn(filename_buffer, localize("filename"), MAX_INPUT_LENGTH); - string_appendn(filename_buffer, ": ", MAX_INPUT_LENGTH); - string_appendn(filename_buffer, tb_new_language.buffer, MAX_INPUT_LENGTH); - string_appendn(filename_buffer, ".mo", MAX_INPUT_LENGTH); - color c = global_ui_context.style.foreground; - global_ui_context.style.foreground = rgb(110,110,110); - ui_push_textf(font_mini, filename_buffer); - global_ui_context.style.foreground = c; - } - } - ui_block_end(); - - if (dd_available_countries.selected_index >= 0) - ui_push_separator(); - - // languages - lang_scroll.height = main_window->height-global_ui_context.layout.offset_y+WIDGET_PADDING; - ui_scroll_begin(&lang_scroll); - { - for (s32 i = 0; i < current_project->languages.length; i++) - { - button_state btn_remove = ui_create_button(); - - bool pressed = false; - if (ui_push_button_image_with_confirmation(&btn_remove, "", delete_img)) - { - pressed = true; - } - - language *l = array_at(¤t_project->languages, i); - ui_push_text_width(l->name, global_ui_context.layout.width-200, false); - - color c = global_ui_context.style.foreground; - global_ui_context.style.foreground = rgb(110,110,110); - - char stats[50]; - sprintf(stats, localize("translated_stats"), get_translated_count_for_language(l->id), current_project->terms.length); - ui_push_text(stats); - - global_ui_context.style.foreground = c; - - if (pressed) - { - remove_language_from_project(l->id); - i--; - } - - ui_block_end(); - } - } - ui_scroll_end(); - } - else - { - render_text(font_medium, 330, 50, localize("create_a_new_project"), global_ui_context.style.foreground); - render_text_cutoff(font_small, 330, 70, - localize("no_project_loaded_info"), global_ui_context.style.foreground, 400); - - render_rectangle(330, 200, 10, 25, UNSAVED_CHANGES_COLOR); - render_text(font_small, 350, 208, localize("unsaved_changes"), global_ui_context.style.foreground); - - render_rectangle(330, 240, 10, 25, MISSING_TRANSLATION_COLOR); - render_text(font_small, 350, 248, localize("missing_translation"), global_ui_context.style.foreground); - } - - if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_O)) - { - load_project(); - } - if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_S)) - { - if (current_project) - { - if (string_equals(project_path, "")) - save_project(); - else - save_project_to_folder(project_path); - } - else - { - platform_show_message(main_window, localize("no_project_to_save"), localize("error_saving_project")); - } - } - if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_A)) - { - if (current_project) - { - save_project(); - } - else - { - platform_show_message(main_window, localize("no_project_to_save"), localize("error_saving_project")); - } - } - if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_Q)) - { - window.is_open = false; - } - } - ui_end(); - // end ui - - assets_do_post_process(); - platform_window_swap_buffers(&window); - - u64 current_stamp = platform_get_time(TIME_FULL, TIME_US); - u64 diff = current_stamp - last_stamp; - float diff_ms = diff / 1000.0f; - last_stamp = current_stamp; - - if (diff_ms < TARGET_FRAMERATE) - { - double time_to_wait = (TARGET_FRAMERATE) - diff_ms; - thread_sleep(time_to_wait*1000); - } - } - - settings_page_hide_without_save(); - - // write config file - if (!string_equals(project_path, "")) - settings_config_set_string(&config, "ACTIVE_PROJECT", project_path); - - vec2 win_size = platform_get_window_size(&window); - settings_config_set_number(&config, "WINDOW_WIDTH", win_size.x); - settings_config_set_number(&config, "WINDOW_HEIGHT", win_size.y); - - if (global_localization.active_localization != 0) - { - char *current_locale_id = locale_get_id(); - if (current_locale_id) - { - settings_config_set_string(&config, "LOCALE", current_locale_id); - } - } - - settings_config_write_to_file(&config, config_path_buffer); - settings_config_destroy(&config); - - //settings_page_destroy(); - - destroy_available_localizations(); - -#if 0 - // cleanup ui - ui_destroy_textbox(&textbox_path); - ui_destroy_textbox(&textbox_search_text); - ui_destroy_textbox(&textbox_file_filter); -#endif - ui_destroy(); - - // delete assets - assets_destroy_image(list_img); - assets_destroy_image(logo_small_img); - assets_destroy_image(delete_img); - assets_destroy_image(add_img); - - assets_destroy_font(font_small); - assets_destroy_font(font_mini); - - keyboard_input_destroy(&keyboard); - platform_destroy_window(&window); - - platform_destroy(); - - return 0; -} +/* +* BSD 2-Clause “Simplified” License +* Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com +* All rights reserved. +*/ + +#include "config.h" +#include "project_base.h" + +// TODO(Aldrik): delete file of language when deleting language + +s32 global_language_id = 1; +char project_path[MAX_INPUT_LENGTH]; + +typedef struct t_language +{ + char *name; + s32 id; +} language; + +typedef struct t_translation +{ + s32 language_id; + char *value; +} translation; + +typedef struct t_term +{ + char *name; + array translations; +} term; + +typedef struct t_translation_project +{ + array languages; + array terms; + int selected_term_index; +} translation_project; + +translation_project *current_project = 0; +array tb_translation_list; + +#include "save.h" +#include "save.c" + +#include "settings.h" +#include "settings.c" + +scroll_state term_scroll; +scroll_state lang_scroll; +scroll_state trans_scroll; +button_state btn_new_project; +button_state btn_new_language; +button_state btn_summary; +button_state btn_set_term_name; +dropdown_state dd_available_countries; +textbox_state tb_filter; +textbox_state tb_new_term; +textbox_state tb_new_language; + +image *set_img; +image *add_img; +image *list_img; +image *exclaim_img; +image *delete_img; +image *logo_small_img; + +font *font_medium; +font *font_small; +font *font_mini; + +static void load_assets() +{ + list_img = assets_load_image(_binary____data_imgs_list_png_start, + _binary____data_imgs_list_png_end, false); + exclaim_img = assets_load_image(_binary____data_imgs_exclaim_png_start, + _binary____data_imgs_exclaim_png_end, false); + logo_small_img = assets_load_image(_binary____data_imgs_logo_64_png_start, + _binary____data_imgs_logo_64_png_end, true); + delete_img = assets_load_image(_binary____data_imgs_delete_png_start, + _binary____data_imgs_delete_png_end, false); + add_img = assets_load_image(_binary____data_imgs_add_png_start, + _binary____data_imgs_add_png_end, false); + set_img = assets_load_image(_binary____data_imgs_set_png_start, + _binary____data_imgs_set_png_end, false); + + font_medium = assets_load_font(_binary____data_fonts_mono_ttf_start, + _binary____data_fonts_mono_ttf_end, 18); + font_small = assets_load_font(_binary____data_fonts_mono_ttf_start, + _binary____data_fonts_mono_ttf_end, 15); + font_mini = assets_load_font(_binary____data_fonts_mono_ttf_start, + _binary____data_fonts_mono_ttf_end, 12); +} + +bool term_has_missing_translations(term *t) +{ + for (s32 i = 0; i < t->translations.length; i++) + { + translation *tr = array_at(&t->translations, i); + if (string_equals(tr->value, "")) return true; + } + + return false; +} + +s32 get_translated_count_for_language(s32 language_id) +{ + s32 count = 0; + for (s32 i = 0; i < current_project->terms.length; i++) + { + term *t = array_at(¤t_project->terms, i); + + for (s32 x = 0; x < t->translations.length; x++) + { + translation *tr = array_at(&t->translations, x); + + if (tr->language_id == language_id && !string_equals(tr->value, "")) + { + count++; + break; + } + } + } + + return count; +} + +bool term_name_is_available(char *name) +{ + for (s32 i = 0; i < current_project->terms.length; i++) + { + term *tr = array_at(¤t_project->terms, i); + + if (string_equals(tr->name, name)) + { + return false; + } + } + + return true; +} + +language* get_language_by_id(s32 language_id) +{ + for (s32 i = 0; i < current_project->languages.length; i++) + { + language *l = array_at(¤t_project->languages, i); + if (l->id == language_id) + { + return l; + } + } + return 0; +} + +s32 add_language_to_project(char *buffer) +{ + if (string_equals(buffer, "")) + { + // TODO(Aldrik): localize + platform_show_message(main_window, "Language name cannot be empty", "Invalid info"); + return -1; + } + + for (s32 i = 0; i < current_project->languages.length; i++) + { + language *lang = array_at(¤t_project->languages, i); + if (string_equals(lang->name, buffer)) + { + // TODO(Aldrik): localize + platform_show_message(main_window, "Language already added", "Invalid info"); + return -1; + } + } + + char *val = mem_alloc(MAX_INPUT_LENGTH); + string_copyn(val, buffer, MAX_INPUT_LENGTH); + + language l; + l.name = val; + l.id = global_language_id++; + + s32 index = array_push(¤t_project->languages, &l); + + textbox_state new_tb; + new_tb = ui_create_textbox(MAX_INPUT_LENGTH); + new_tb.accept_newline = true; + new_tb.deselect_on_enter = false; + array_push(&tb_translation_list, &new_tb); + + for (s32 x = 0; x < current_project->terms.length; x++) + { + term *t = array_at(¤t_project->terms, x); + + translation new_t; + new_t.value = mem_alloc(MAX_INPUT_LENGTH); + string_copyn(new_t.value, "", MAX_INPUT_LENGTH); + new_t.language_id = l.id; + + array_push(&t->translations, &new_t); + } + + return l.id; +} + +void set_term_name(s32 index, char *name) +{ + if (strlen(name) > 0) + { + term *t = array_at(¤t_project->terms, index); + string_copyn(t->name, name, MAX_TERM_NAME_LENGTH); + } + else + { + platform_show_message(main_window, localize("term_name_cannot_be_empty"), localize("invalid_input")); + } +} + +void remove_term_from_project(s32 index) +{ + term *t = array_at(¤t_project->terms, index); + mem_free(t->name); + for (s32 i = 0; i < t->translations.length; i++) + { + translation *tr = array_at(&t->translations, i); + mem_free(tr->value); + } + array_destroy(&t->translations); + array_remove_at(¤t_project->terms, index); +} + +void remove_language_from_project(s32 language_id) +{ + for (s32 i = 0; i < current_project->languages.length; i++) + { + language *l = array_at(¤t_project->languages, i); + if (l->id == language_id) + { + char fullpath[MAX_INPUT_LENGTH]; + fullpath[0] = 0; + string_appendn(fullpath, project_path, MAX_INPUT_LENGTH); +#ifdef OS_WIN + string_appendn(fullpath, "\\", MAX_INPUT_LENGTH); +#endif +#ifdef OS_LINUX + string_appendn(fullpath, "/", MAX_INPUT_LENGTH); +#endif + string_appendn(fullpath, l->name, MAX_INPUT_LENGTH); + string_appendn(fullpath, ".mo", MAX_INPUT_LENGTH); + if (platform_file_exists(fullpath)) + { + platform_delete_file(fullpath); + } + + array_remove_at(¤t_project->languages, i); + textbox_state *st = array_at(&tb_translation_list, i); + mem_free(st->buffer); + array_remove_at(&tb_translation_list, i); + break; + } + } + + for (s32 x = 0; x < current_project->terms.length; x++) + { + term *tr = array_at(¤t_project->terms, x); + + for (s32 i = 0; i < tr->translations.length; i++) + { + translation *t = array_at(&tr->translations, i); + + if (t->language_id == language_id) + { + mem_free(t->value); + array_remove_at(&tr->translations, i); + break; + } + } + } +} + +void select_term(s32 index) +{ + current_project->selected_term_index = index; + term *t = array_at(¤t_project->terms, index); + ui_set_textbox_text(&tb_new_term, t->name); + + for (s32 i = 0; i < current_project->languages.length; i++) + { + translation *tr = array_at(&t->translations, i); + textbox_state *tb = array_at(&tb_translation_list, i); + tb->state = false; + + if (tr->value) + { + ui_set_textbox_text(tb, tr->value); + } + else + { + ui_set_textbox_text(tb, ""); + } + } +} + +s32 add_term_to_project() +{ + tb_filter.state = 0; + ui_set_textbox_text(&tb_filter, ""); + + term t; + t.name = mem_alloc(MAX_TERM_NAME_LENGTH); + + s32 count = 0; + do + { + char buffer[MAX_TERM_NAME_LENGTH]; + sprintf(buffer, "term_%d", count); + string_copyn(t.name, buffer, MAX_TERM_NAME_LENGTH); + count++; + } + while(!term_name_is_available(t.name)); + + t.translations = array_create(sizeof(translation)); + array_reserve(&t.translations, current_project->languages.length); + + for (s32 i = 0; i < current_project->languages.length; i++) + { + language *l = array_at(¤t_project->languages, i); + + translation tr; + tr.value = mem_alloc(MAX_INPUT_LENGTH); + string_copyn(tr.value, "", MAX_INPUT_LENGTH); + tr.language_id = l->id; + array_push(&t.translations, &tr); + } + + ui_set_textbox_active(&tb_new_term); + + return array_push(¤t_project->terms, &t); +} + +void save_term_changes() +{ + set_term_name(current_project->selected_term_index, tb_new_term.buffer); + + term *t = array_at(¤t_project->terms, current_project->selected_term_index); + + for (s32 i = 0; i < current_project->languages.length; i++) + { + translation *tr = array_at(&t->translations, i); + textbox_state *tb = array_at(&tb_translation_list, i); + + string_copyn(tr->value, tb->buffer, MAX_INPUT_LENGTH); + } +} + +void start_new_project() +{ + global_language_id = 1; + current_project = mem_alloc(sizeof(translation_project)); + + current_project->terms = array_create(sizeof(term)); + array_reserve(¤t_project->terms, 100); + current_project->terms.reserve_jump = 100; + + current_project->languages = array_create(sizeof(language)); + array_reserve(¤t_project->languages, 100); + current_project->languages.reserve_jump = 100; + + current_project->selected_term_index = -1; +} + +void load_config(settings_config *config) +{ + char *path = settings_config_get_string(config, "ACTIVE_PROJECT"); + char *locale_id = settings_config_get_string(config, "LOCALE"); + + if (path) + { + string_copyn(project_path, path, MAX_INPUT_LENGTH); + + if (platform_directory_exists(project_path)) + { + load_project_from_folder(project_path); + } + else + { + string_copyn(project_path, "", MAX_INPUT_LENGTH); + } + } + + if (locale_id) + set_locale(locale_id); + else + set_locale("en"); +} + +#if defined(OS_LINUX) || defined(OS_WIN) +int main(int argc, char **argv) +{ + platform_init(argc, argv); + + char config_path_buffer[PATH_MAX]; + get_config_save_location(config_path_buffer); + + // load config + settings_config config = settings_config_load_from_file(config_path_buffer); + + s32 window_w = settings_config_get_number(&config, "WINDOW_WIDTH"); + s32 window_h = settings_config_get_number(&config, "WINDOW_HEIGHT"); + if (window_w < 800 || window_h < 600) + { + window_w = 800; + window_h = 600; + } + + platform_window window = platform_open_window("mo-edit", window_w, window_h, 0, 0, 800, 600); + main_window = &window; + + validate_license(); + + settings_page_create(); + + load_available_localizations(); + set_locale("en"); + + load_assets(); + + keyboard_input keyboard = keyboard_input_create(); + mouse_input mouse = mouse_input_create(); + + camera camera; + camera.x = 0; + camera.y = 0; + camera.rotation = 0; + + ui_create(&window, &keyboard, &mouse, &camera, font_small); + term_scroll = ui_create_scroll(1); + lang_scroll = ui_create_scroll(1); + trans_scroll = ui_create_scroll(1); + btn_summary = ui_create_button(); + btn_set_term_name = ui_create_button(); + btn_new_project = ui_create_button(); + btn_new_language = ui_create_button(); + tb_filter = ui_create_textbox(MAX_INPUT_LENGTH); + tb_new_term = ui_create_textbox(MAX_TERM_NAME_LENGTH); + tb_new_language = ui_create_textbox(MAX_INPUT_LENGTH); + + // asset worker + thread asset_queue_worker1 = thread_start(assets_queue_worker, NULL); + thread asset_queue_worker2 = thread_start(assets_queue_worker, NULL); + thread_detach(&asset_queue_worker1); + thread_detach(&asset_queue_worker2); + + tb_translation_list = array_create(sizeof(textbox_state)); + load_config(&config); + + while(window.is_open) { + u64 last_stamp = platform_get_time(TIME_FULL, TIME_US); + platform_handle_events(&window, &mouse, &keyboard); + platform_set_cursor(&window, CURSOR_DEFAULT); + + settings_page_update_render(); + + platform_window_make_current(&window); + + if (!license_check_status()) break; + + static bool icon_loaded = false; + if (!icon_loaded && logo_small_img->loaded) + { + icon_loaded = true; + platform_set_icon(&window, logo_small_img); + } + + if (global_asset_collection.queue.queue.length == 0 && !global_asset_collection.done_loading_assets) + { + global_asset_collection.done_loading_assets = true; + } + + global_ui_context.layout.active_window = &window; + global_ui_context.keyboard = &keyboard; + global_ui_context.mouse = &mouse; + + render_clear(); + camera_apply_transformations(&window, &camera); + + global_ui_context.layout.width = global_ui_context.layout.active_window->width; + // begin ui + + ui_begin(1); + { + render_rectangle(0, 0, main_window->width, main_window->height, global_ui_context.style.background); + + ui_begin_menu_bar(); + { + if (ui_push_menu(localize("file"))) + { + if (ui_push_menu_item(localize("load_project"), "Ctrl + O")) + { + load_project(); + } + if (ui_push_menu_item(localize("save_project"), "Ctrl + S")) + { + if (current_project) + { + if (string_equals(project_path, "")) + save_project(); + else + save_project_to_folder(project_path); + } + else + { + platform_show_message(main_window, localize("no_project_to_save"), localize("error_saving_project")); + } + } + if (ui_push_menu_item(localize("save_project_as"), "Ctrl + A")) + { + if (current_project) + { + save_project(); + } + else + { + platform_show_message(main_window, localize("no_project_to_save"), localize("error_saving_project")); + } + } + if (ui_push_menu_item(localize("close_project"), "")) + { + current_project = 0; + project_path[0] = 0; + } + ui_push_menu_item_separator(); + if (ui_push_menu_item(localize("quit"), "Ctrl + Q")) + { + window.is_open = false; + } + } + if (ui_push_menu(localize("options"))) + { + if (ui_push_menu_item(localize("settings"), "")) + { + settings_page_show(); + } + } + } + ui_end_menu_bar(); + ui_push_separator(); + + global_ui_context.layout.width = 300; + ui_push_vertical_dragbar(); + + if (current_project) + { + ui_block_begin(LAYOUT_HORIZONTAL); + { + if (ui_push_button_image(&btn_summary, "", list_img)) + { + current_project->selected_term_index = -1; + } + + ui_push_textf_width(font_medium, localize("terms"), global_ui_context.layout.width-106); + + if (ui_push_button_image(&btn_summary, "", add_img)) + { + select_term(add_term_to_project()); + } + + //ui_push_button_image(&btn_summary, "", delete_img); + + } + ui_block_end(); + + ui_block_begin(LAYOUT_HORIZONTAL); + { + TEXTBOX_WIDTH = 280; + ui_push_textbox(&tb_filter, localize("filter_terms")); + } + ui_block_end(); + + ui_push_separator(); + + // reset scroll if filter text changed + if (tb_filter.state && keyboard.text_changed) + { + term_scroll.scroll = 0; + } + + term_scroll.height = main_window->height-global_ui_context.layout.offset_y+8; + ui_scroll_begin(&term_scroll); + { + for (s32 i = 0; i < current_project->terms.length; i++) + { + term *t = array_at(¤t_project->terms, i); + + if (!strlen(tb_filter.buffer) || string_contains(t->name, tb_filter.buffer)) + { + bool removed = false; + if (ui_push_button_image_with_confirmation(&btn_summary, "", delete_img)) + { + removed = true; + } + + //ui_push_image(exclaim_img, 14, 14, 1, rgb(255,255,255)); + + if (i == current_project->selected_term_index) + { + ui_push_rect(10, global_ui_context.style.textbox_active_border); + } + else if (term_has_missing_translations(t)) + { + ui_push_rect(10, MISSING_TRANSLATION_COLOR); + } + else + { + ui_push_rect(10, global_ui_context.style.background); + } + + if (ui_push_text_width(t->name, global_ui_context.layout.width-100, true)) + { + select_term(i); + } + + ui_block_end(); + + if (removed) + { + remove_term_from_project(i); + --i; + if (i >= 0) select_term(i); + } + } + } + } + ui_scroll_end(); + } + else + { + if (ui_push_button(&btn_new_project, localize("create_new_project"))) + { + start_new_project(); + } + } + + global_ui_context.layout.width = main_window->width - 310; + + global_ui_context.layout.offset_x = 310; + global_ui_context.layout.offset_y = MENU_BAR_HEIGHT + WIDGET_PADDING; + + if (current_project && current_project->selected_term_index >= 0) + { + if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_S)) + { + save_term_changes(); + } + + term *t = array_at(¤t_project->terms, + current_project->selected_term_index); + + ui_block_begin(LAYOUT_HORIZONTAL); + { + // editor + + if (string_equals(tb_new_term.buffer, t->name)) + ui_push_rect(10, global_ui_context.style.background); + else + ui_push_rect(10, UNSAVED_CHANGES_COLOR); + + ui_push_textbox(&tb_new_term, localize("term_name")); + + if (ui_push_button_image(&btn_set_term_name, "", set_img)) + { + save_term_changes(); + } + } + ui_block_end(); + + global_ui_context.layout.offset_x = 310; + ui_push_separator(); + + trans_scroll.height = main_window->height-global_ui_context.layout.offset_y+WIDGET_PADDING; + + ui_scroll_begin(&trans_scroll); + { + if (!current_project->languages.length) + { + ui_push_text(localize("no_languages_added")); + } + else + { + for (s32 i = 0; i < t->translations.length; i++) + { + translation *tr = array_at(&t->translations, i); + + TEXTBOX_WIDTH = global_ui_context.layout.width - 130; + + textbox_state *tbs = array_at(&tb_translation_list, i); + if (!strlen(tbs->buffer)) + { + ui_push_rect(10, MISSING_TRANSLATION_COLOR); + } + else if (string_equals(tbs->buffer, + tr->value)) + { + ui_push_rect(10, global_ui_context.style.background); + } + else + { + ui_push_rect(10, UNSAVED_CHANGES_COLOR); + } + + ui_push_textbox(tbs, ""); + + language *l = get_language_by_id(tr->language_id); + ui_push_text(l->name); + + global_ui_context.layout.offset_y += TEXTBOX_HEIGHT + WIDGET_PADDING; + global_ui_context.layout.offset_x = 310; + + if (keyboard_is_key_pressed(&keyboard, KEY_TAB) && tbs->state) + { + keyboard.input_keys[KEY_TAB] = false; + tbs->state = false; + + if (i+1 < t->translations.length) + { + ui_set_textbox_active(array_at(&tb_translation_list, i+1)); + } + else + { + ui_set_textbox_active(array_at(&tb_translation_list, 0)); + } + } + } + } + } + ui_scroll_end(); + } + else if (current_project) + { + // overview + ui_block_begin(LAYOUT_HORIZONTAL); + { + ui_push_textf_width(font_medium, localize("overview"), 100); + + char info_text[60]; + sprintf(info_text, localize("info_text"), current_project->terms.length, current_project->languages.length); + + color c = global_ui_context.style.foreground; + global_ui_context.style.foreground = rgb(110,110,110); + ui_push_textf(font_small, info_text); + global_ui_context.style.foreground = c; + } + ui_block_end(); + + ui_push_separator(); + + ui_block_begin(LAYOUT_HORIZONTAL); + { + bool selected = tb_new_language.state; + ui_push_textbox(&tb_new_language, localize("add_language")); + + if (keyboard_is_key_pressed(&keyboard, KEY_ENTER) && selected) + { + add_language_to_project(tb_new_language.buffer); + ui_set_textbox_text(&tb_new_language, ""); + keyboard_set_input_text(&keyboard, ""); + tb_new_language.state = true; + } + + if (ui_push_button(&btn_new_language, localize("add"))) + { + add_language_to_project(tb_new_language.buffer); + ui_set_textbox_text(&tb_new_language, ""); + keyboard_set_input_text(&keyboard, ""); + tb_new_language.state = true; + } + + if (!string_equals(tb_new_language.buffer, "")) + { + ui_block_end(); + char filename_buffer[MAX_INPUT_LENGTH]; + filename_buffer[0] = 0; + string_appendn(filename_buffer, localize("filename"), MAX_INPUT_LENGTH); + string_appendn(filename_buffer, ": ", MAX_INPUT_LENGTH); + string_appendn(filename_buffer, tb_new_language.buffer, MAX_INPUT_LENGTH); + string_appendn(filename_buffer, ".mo", MAX_INPUT_LENGTH); + color c = global_ui_context.style.foreground; + global_ui_context.style.foreground = rgb(110,110,110); + ui_push_textf(font_mini, filename_buffer); + global_ui_context.style.foreground = c; + } + } + ui_block_end(); + + if (dd_available_countries.selected_index >= 0) + ui_push_separator(); + + // languages + lang_scroll.height = main_window->height-global_ui_context.layout.offset_y+WIDGET_PADDING; + ui_scroll_begin(&lang_scroll); + { + for (s32 i = 0; i < current_project->languages.length; i++) + { + button_state btn_remove = ui_create_button(); + + bool pressed = false; + if (ui_push_button_image_with_confirmation(&btn_remove, "", delete_img)) + { + pressed = true; + } + + language *l = array_at(¤t_project->languages, i); + ui_push_text_width(l->name, global_ui_context.layout.width-200, false); + + color c = global_ui_context.style.foreground; + global_ui_context.style.foreground = rgb(110,110,110); + + char stats[50]; + sprintf(stats, localize("translated_stats"), get_translated_count_for_language(l->id), current_project->terms.length); + ui_push_text(stats); + + global_ui_context.style.foreground = c; + + if (pressed) + { + remove_language_from_project(l->id); + i--; + } + + ui_block_end(); + } + } + ui_scroll_end(); + } + else + { + render_text(font_medium, 330, 50, localize("create_a_new_project"), global_ui_context.style.foreground); + render_text_cutoff(font_small, 330, 70, + localize("no_project_loaded_info"), global_ui_context.style.foreground, 400); + + render_rectangle(330, 200, 10, 25, UNSAVED_CHANGES_COLOR); + render_text(font_small, 350, 208, localize("unsaved_changes"), global_ui_context.style.foreground); + + render_rectangle(330, 240, 10, 25, MISSING_TRANSLATION_COLOR); + render_text(font_small, 350, 248, localize("missing_translation"), global_ui_context.style.foreground); + } + + if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_O)) + { + load_project(); + } + if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_S)) + { + if (current_project) + { + if (string_equals(project_path, "")) + save_project(); + else + save_project_to_folder(project_path); + } + else + { + platform_show_message(main_window, localize("no_project_to_save"), localize("error_saving_project")); + } + } + if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_A)) + { + if (current_project) + { + save_project(); + } + else + { + platform_show_message(main_window, localize("no_project_to_save"), localize("error_saving_project")); + } + } + if (keyboard_is_key_down(&keyboard, KEY_LEFT_CONTROL) && keyboard_is_key_pressed(&keyboard, KEY_Q)) + { + window.is_open = false; + } + } + ui_end(); + // end ui + + assets_do_post_process(); + platform_window_swap_buffers(&window); + + u64 current_stamp = platform_get_time(TIME_FULL, TIME_US); + u64 diff = current_stamp - last_stamp; + float diff_ms = diff / 1000.0f; + last_stamp = current_stamp; + + if (diff_ms < TARGET_FRAMERATE) + { + double time_to_wait = (TARGET_FRAMERATE) - diff_ms; + thread_sleep(time_to_wait*1000); + } + } + + settings_page_hide_without_save(); + + // write config file + if (!string_equals(project_path, "")) + settings_config_set_string(&config, "ACTIVE_PROJECT", project_path); + + vec2 win_size = platform_get_window_size(&window); + settings_config_set_number(&config, "WINDOW_WIDTH", win_size.x); + settings_config_set_number(&config, "WINDOW_HEIGHT", win_size.y); + + if (global_localization.active_localization != 0) + { + char *current_locale_id = locale_get_id(); + if (current_locale_id) + { + settings_config_set_string(&config, "LOCALE", current_locale_id); + } + } + + settings_config_write_to_file(&config, config_path_buffer); + settings_config_destroy(&config); + + //settings_page_destroy(); + + destroy_available_localizations(); + +#if 0 + // cleanup ui + ui_destroy_textbox(&textbox_path); + ui_destroy_textbox(&textbox_search_text); + ui_destroy_textbox(&textbox_file_filter); +#endif + ui_destroy(); + + // delete assets + assets_destroy_image(list_img); + assets_destroy_image(logo_small_img); + assets_destroy_image(delete_img); + assets_destroy_image(add_img); + + assets_destroy_font(font_small); + assets_destroy_font(font_mini); + + keyboard_input_destroy(&keyboard); + platform_destroy_window(&window); + + platform_destroy(); + + return 0; +} #endif \ No newline at end of file -- cgit v1.2.3-70-g09d2