Example C Calculator app

For simplicity, only integer operations and no direct editing of the numbers.
This is meant as a simple UI example, not as a CS exercise.
This commit is contained in:
Xavi Artigas 2019-10-23 13:39:47 +02:00
parent 95c373e8e3
commit 8caeaaf071
3 changed files with 211 additions and 0 deletions

View File

@ -0,0 +1,13 @@
project(
'efl-example-calculator', 'c',
version : '0.0.1',
default_options: [ 'c_std=gnu99', 'warning_level=2' ],
meson_version : '>= 0.38.0')
eina = dependency('eina', version : '>=1.20.99')
efl = dependency('efl-ui', version : '>=1.20.99')
elm = dependency('elementary', version : '>=1.20.99')
inc = include_directories('.')
subdir('src')

View File

@ -0,0 +1,186 @@
#define EFL_BETA_API_SUPPORT 1
#include <Elementary.h>
#include <Efl_Ui.h>
// Temporary workaround until Unified Text stops using Legacy classes internally
#include <efl_ui_text.eo.h>
#include <efl_text_interactive.eo.h>
static Efl_Ui_Text *_screen = NULL;
static int _prev_value = 0, _curr_value = 0;
static char _operation = '=';
static Eina_Bool _must_overwrite = EINA_FALSE;
static void
_gui_quit_cb(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
{
efl_exit(0);
}
static void
_operate()
{
switch (_operation)
{
case '+':
_curr_value += _prev_value;
break;
case '-':
_curr_value = _prev_value - _curr_value;
break;
case '*':
_curr_value *= _prev_value;
break;
case '/':
_curr_value = _prev_value / _curr_value;
break;
default:
break;
}
}
static void
_button_pressed_cb(void *data, const Efl_Event *event EINA_UNUSED)
{
char button = ((const char *)data)[0];
if (button >= '0' && button <= '9')
{
char str[2] = { button, '\0' };
if (_must_overwrite)
{
efl_text_set(_screen, "");
_must_overwrite = EINA_FALSE;
}
Efl_Text_Cursor_Cursor *cursor = efl_text_cursor_get(_screen, EFL_TEXT_CURSOR_GET_TYPE_MAIN);
efl_text_cursor_text_insert(_screen, cursor, str);
}
else
{
char str[32] = "";
switch (button)
{
case 'C':
efl_text_set(_screen, "0");
break;
case '+':
case '-':
case '*':
case '/':
case '=':
if (_operation != '=')
{
_operate();
snprintf(str, sizeof(str), "%d", _curr_value);
efl_text_set(_screen, str);
}
_operation = button;
_must_overwrite = EINA_TRUE;
_prev_value = _curr_value;
break;
default:
break;
}
}
}
static void
_screen_changed_cb(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
{
char _text[32] = "";
const char *str = efl_text_get(_screen);
int d;
if ((strcmp(str, "") == 0) || (strcmp(str, "-") == 0))
{
snprintf(_text, sizeof(_text), "0");
}
else if (sscanf(str, "%d", &d) == 1)
{
snprintf(_text, sizeof(_text), "%d", d);
_curr_value = d;
}
if (strncmp(_text, str, sizeof(_text)))
{
efl_text_set(_screen, _text);
}
}
// text is what is drawn on the button, which might be a multi-byte unicode string.
// command is a single-char id for the button.
static void
_button_add(Efl_Ui_Table *table, const char *text, const char *command, int posx, int posy, int r, int g, int b)
{
Efl_Ui_Button *button =
efl_add(EFL_UI_BUTTON_CLASS, table,
efl_pack_table(table, efl_added, posx, posy, 1, 1),
efl_event_callback_add(efl_added, EFL_INPUT_EVENT_CLICKED, _button_pressed_cb, command));
// Buttons can only have simple text (no font, styles or markup) but can swallow
// any other object we want.
// Therefore we create a more complex Efl_Ui_Text object and use it as content for the button.
Efl_Ui_Text *label =
efl_add(EFL_UI_TEXT_CLASS, button,
efl_text_interactive_editable_set(efl_added, EINA_FALSE),
efl_text_halign_set(efl_added, 0.5),
efl_text_valign_set(efl_added, 0.5),
efl_gfx_color_set(efl_added, r, g, b, 255),
efl_text_set(efl_added, text));
efl_text_font_set(label, "Sans", 36);
efl_content_set(button, label);
}
static void
_gui_setup()
{
Eo *win, *table;
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
efl_ui_win_type_set(efl_added, EFL_UI_WIN_TYPE_BASIC),
efl_text_set(efl_added, "EFL Calculator"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE));
// when the user clicks "close" on a window there is a request to delete
efl_event_callback_add(win, EFL_UI_WIN_EVENT_DELETE_REQUEST, _gui_quit_cb, NULL);
table = efl_add(EFL_UI_TABLE_CLASS, win,
efl_content_set(win, efl_added),
efl_pack_table_size_set(efl_added, 4, 5),
efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(300, 400)));
_button_add(table, "1", "1", 0, 3, 255, 255, 255);
_button_add(table, "2", "2", 1, 3, 255, 255, 255);
_button_add(table, "3", "3", 2, 3, 255, 255, 255);
_button_add(table, "4", "4", 0, 2, 255, 255, 255);
_button_add(table, "5", "5", 1, 2, 255, 255, 255);
_button_add(table, "6", "6", 2, 2, 255, 255, 255);
_button_add(table, "7", "7", 0, 1, 255, 255, 255);
_button_add(table, "8", "8", 1, 1, 255, 255, 255);
_button_add(table, "9", "9", 2, 1, 255, 255, 255);
_button_add(table, "0", "0", 1, 4, 255, 255, 255);
_button_add(table, "+", "+", 3, 1, 128, 128, 128);
_button_add(table, "", "-", 3, 2, 128, 128, 128);
_button_add(table, "×", "*", 3, 3, 128, 128, 128);
_button_add(table, "÷", "/", 3, 4, 128, 128, 128);
_button_add(table, "=", "=", 2, 4, 128, 128, 128);
_button_add(table, "C", "C", 0, 4, 0, 0, 0);
_screen = efl_add(EFL_UI_TEXT_CLASS, table,
efl_text_set(efl_added, "0"),
efl_text_multiline_set(efl_added, EINA_FALSE),
efl_text_interactive_editable_set(efl_added, EINA_FALSE),
efl_text_interactive_selection_allowed_set(efl_added, EINA_FALSE),
efl_pack_table(table, efl_added, 0, 0, 4, 1),
efl_text_halign_set(efl_added, 0.9),
efl_text_valign_set(efl_added, 0.5),
efl_text_effect_type_set(efl_added, EFL_TEXT_STYLE_EFFECT_TYPE_GLOW),
efl_text_glow_color_set(efl_added, 128, 128, 128, 128),
efl_event_callback_add(efl_added, EFL_UI_TEXT_EVENT_CHANGED,
_screen_changed_cb, NULL));
efl_text_font_set(_screen, "Sans", 48);
}
EAPI_MAIN void
efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
_gui_setup();
}
EFL_MAIN()

View File

@ -0,0 +1,12 @@
src = files([
'calculator.c',
])
deps = [eina, efl, elm]
executable('efl_example_calculator', src,
dependencies : deps,
include_directories : inc,
install : true
)