summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build-win.bat2
-rw-r--r--release-windows.bat4
-rw-r--r--src/mo_edit.c1904
3 files changed, 951 insertions, 959 deletions
diff --git a/build-win.bat b/build-win.bat
index c7a65c6..bad1738 100644
--- a/build-win.bat
+++ b/build-win.bat
@@ -9,7 +9,7 @@ ld -r -b binary -o ../bin/data.o ../data/imgs/en.png ../data/imgs/nl.png ../dat
if "%1"=="-w" (SET defs=-DMODE_DEVELOPER -DMODE_GDBDEBUG) else (SET defs=-DMODE_DEVELOPER)
-x86_64-w64-mingw32-gcc -m64 -Wall -g %defs% -Wno-unused-label -Wno-unused-variable mo_edit.c ../bin/data.o -o ../bin/mo-edit.exe ../misc/icon.res -lopengl32 -lkernel32 -lglu32 -lgdi32 -lcomdlg32 -lgdiplus -lole32 -lshlwapi -lwininet
+x86_64-w64-mingw32-gcc -m64 -Wall -g %defs% -Wno-unused-label -Wno-unused-variable mo_edit.c ../bin/data.o -o ../bin/mo-edit.exe ../misc/icon.res -lopengl32 -lkernel32 -lglu32 -lgdi32 -lcomdlg32 -lgdiplus -lole32 -lshlwapi -lwininet -liphlpapi
DEL /Q "../bin/data.o"
diff --git a/release-windows.bat b/release-windows.bat
index e3ca659..446bb9e 100644
--- a/release-windows.bat
+++ b/release-windows.bat
@@ -1,5 +1,3 @@
-#!/bin/bash
-
DEL /S /Q "bin"
if not exist "release" mkdir "release"
if not exist "release" mkdir "release/windows"
@@ -9,7 +7,7 @@ cd src
ld -r -b binary -o ../bin/data.o ../data/imgs/en.png ../data/imgs/nl.png ../data/imgs/logo_64.png ../data/fonts/mono.ttf ../data/translations/en-English.mo ../data/translations/nl-Dutch.mo ../data/imgs/list.png ../data/imgs/delete.png ../data/imgs/exclaim.png ../data/imgs/add.png ../data/imgs/set.png
-x86_64-w64-mingw32-gcc -Wall -m64 -O3 -Wno-unused-label -Wno-unused-variable mo_edit.c ../bin/data.o -o ../bin/mo-edit.exe ../misc/icon.res -lopengl32 -lkernel32 -lglu32 -lgdi32 -lcomdlg32 -lgdiplus -lole32 -lshlwapi -lwininet
+x86_64-w64-mingw32-gcc -Wall -m64 -O3 -Wno-unused-label -Wno-unused-variable mo_edit.c ../bin/data.o -o ../bin/mo-edit.exe ../misc/icon.res -lopengl32 -lkernel32 -lglu32 -lgdi32 -lcomdlg32 -lgdiplus -lole32 -lshlwapi -lwininet -liphlpapi
DEL /Q "../bin/data.o"
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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_project->terms, &t);
-}
-
-void save_term_changes()
-{
- set_term_name(current_project->selected_term_index, tb_new_term.buffer);
-
- term *t = array_at(&current_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(&current_project->terms, 100);
- current_project->terms.reserve_jump = 100;
-
- current_project->languages = array_create(sizeof(language));
- array_reserve(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_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(&current_project->terms, &t);
+}
+
+void save_term_changes()
+{
+ set_term_name(current_project->selected_term_index, tb_new_term.buffer);
+
+ term *t = array_at(&current_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(&current_project->terms, 100);
+ current_project->terms.reserve_jump = 100;
+
+ current_project->languages = array_create(sizeof(language));
+ array_reserve(&current_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(&current_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(&current_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(&current_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