In this tutorial you will learn how to build an EFL application with several widgets, including a text box with editable text and two buttons arranged vertically, each with distinct functions.
The end result should look something like this:
You will be basing your text editor on the application you built in the previous guide. The final program (including an expanded text box) looked like this:
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include <Efl.h>
#include <Elementary.h>
static void
_gui_setup()
{
Eo *win, *box, *text; //*
win = efl_add(EFL_UI_WIN_CLASS, NULL,
efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
efl_text_set(efl_added, "Hello World"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE));
box = efl_add(EFL_UI_BOX_CLASS, win,
efl_content_set(win, efl_added),
efl_gfx_size_hint_min_set(efl_added, EINA_SIZE2D(360, 240)));
text = efl_add(EFL_UI_TEXT_CLASS, box,
efl_text_set(efl_added, "Hello World!"),
efl_pack(box, efl_added));
}
EAPI_MAIN void
efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
_gui_setup();
}
EFL_MAIN()
This program creates a window with a text box 360 pixels wide by 240 pixels high and displays the message "Hello World!" inside it.
The first order of business is to make the text box editable. To do this change the name of the text
object on line to editor
. Don't forget to change on line 23 too.
Next, change the definition of editor
from:
[...]
editor = efl_add(EFL_UI_TEXT_CLASS, box,
efl_text_set(efl_added, "Hello World!"),
efl_pack(box, efl_added));
[...]
To:
[...]
editor = efl_add(EFL_UI_TEXT_CLASS, box,
efl_text_set(efl_added, "Edit me"),
efl_ui_text_interactive_editable_set(efl_added, EINA_TRUE),
efl_ui_text_scrollable_set(efl_added, EINA_TRUE),
efl_pack(box, efl_added));
[...]
By adding the efl_ui_text_interactive_editable_set()
you make the text box editable. With efl_ui_text_scrollable_set()
users can type more text than is available in the visible area, as they can scroll with the cursor or the Home and End keys.
NOTE:
[...]
in a Code Block indicates existing code which has been excluded for the sake of brevity. There is no need to type[...]
into your program.
Next you're going to add two buttons. One will be an About button which displays text on the command line when pressed. The other will exit the program.
To add buttons, first add a new object to the variable declarations on line 12:
[...]
Eo *win, *box, *editor, *button;
[...]
You can then use the EFL_UI_BUTTON_CLASS
macro to define your buttons:
[...]
button = efl_add(EFL_UI_BUTTON_CLASS, box,
efl_text_set(efl_added, "About"),
efl_pack(box, efl_added),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED,
_gui_about_clicked_cb, efl_added));
button = efl_add(EFL_UI_BUTTON_CLASS, box,
efl_text_set(efl_added, "Quit"),
efl_pack(box, efl_added),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED,
_gui_quit_clicked_cb, efl_added));
[...]
Use efl_text_set()
to set the buttons' labels and efl_pack()
to fit the buttons to the box. The efl_event_callback_add()
is used to describe the event that will trigger an action. In this case, the action will be triggered when the button is clicked, as specified by EFL_UI_EVENT_CLICKED
. The actions the buttons trigger are defined by functions which you will have to add to your program.
In the code above line 6 tells your application to run the function _gui_about_clicked_cb()
when users click the About button and the _gui_quit_clicked_cb()
function when they click the Quit button. Add those two functions to your program (you can leave them empty for the moment) so you can compile it.
Your program should now look like this:
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include <Efl.h>
#include <Elementary.h>
static void
_gui_about_clicked_cb()
{
/* code */
}
static void
_gui_quit_clicked_cb()
{
/* code */
}
static void
_gui_setup()
{
Eo *win, *box, *editor, *button;
win = efl_add(EFL_UI_WIN_CLASS, NULL,
efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
efl_text_set(efl_added, "Basic Editor"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE));
box = efl_add(EFL_UI_BOX_CLASS, win,
efl_content_set(win, efl_added),
efl_gfx_size_hint_min_set(efl_added, EINA_SIZE2D(360, 240)));
editor = efl_add(EFL_UI_TEXT_CLASS, box,
efl_text_set(efl_added, "Edit me"),
efl_ui_text_interactive_editable_set(efl_added, EINA_TRUE),
efl_ui_text_scrollable_set(efl_added, EINA_TRUE),
efl_pack(box, efl_added));
button = efl_add(EFL_UI_BUTTON_CLASS, box,
efl_text_set(efl_added, "About"),
efl_pack(box, efl_added),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED,
_gui_about_clicked_cb, efl_added));
button = efl_add(EFL_UI_BUTTON_CLASS, box,
efl_text_set(efl_added, "Quit"),
efl_pack(box, efl_added),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED,
_gui_quit_clicked_cb, efl_added));
}
EAPI_MAIN void
efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
_gui_setup();
}
EFL_MAIN()
If you now compile and run this program, you will see something like this:
Note how Enlightenment splits the space in the box equally between the text box and the two buttons, assigning about a third to each. You'll learn how to organise and assign space yourself in the next section.
So far you've bundled all your elements into single box. Next you're going to create a new box exclusively for the buttons and place them side by side instead of one on top of the other. This looks much more tidy.
Add a new object called hbox
to the the object declaration line in _gui_setup()
:
[...]
Eo *win, *box, *hbox, *editor, *button;
[...]
Now write its definition between the definition of editor
and the definition of your first button
:
[...]
hbox = efl_add(EFL_UI_BOX_CLASS, box,
efl_ui_direction_set(efl_added, EFL_UI_DIR_HORIZONTAL),
efl_gfx_size_hint_weight_set(efl_added, 1.0, 0.1),
efl_pack(box, efl_added));
[...]
This creates a new box, with the difference that the widgets you put in it will be laid out horizontally (efl_ui_direction_set(efl_added, EFL_UI_DIR_HORIZONTAL)
) instead of vertically, which is the default.
Note that hbox
is placed within box
. The editor
text box is also in box
. This means they're both sharing a container. You use the the two parameters in efl_gfx_size_hint_weight_set()
to establish how much space each gets. The first value (1.0
) sets how much space the object takes up horizontally. As box
is using the default layout, it is stacking widgets one on top of the other. As a result, no matter what value you enter here (values can range from 0.0
to 1.0
) both editor
and hbox
will stretch to the full width of the box
container.
The second value, 0.1
, establishes how much space the hbox
widget takes up vertically. As widgets in box
are stacked vertically, changing this value will change its size and by extension that available to the buttons it contains. For example if you set it to 1.0
, it will take up the full space it would be assigned by default which is half the height of the containing box
: Remember box
now contains two widgets and will assign by default half the space available to each. Setting it to 0.1
makes the box and any buttons it contains slightly taller than the bare minimum. Anything value in between will assign varying heights.
Next, change the buttons so their parent is hbox
instead of box
:
[...]
button = efl_add(EFL_UI_BUTTON_CLASS, hbox,
efl_text_set(efl_added, "About"),
efl_pack(hbox, efl_added),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED,
_gui_about_clicked_cb, efl_added));
button = efl_add(EFL_UI_BUTTON_CLASS, hbox,
efl_text_set(efl_added, "Quit"),
efl_pack(hbox, efl_added),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED,
_gui_quit_clicked_cb, efl_added));
[...]
When you compile and run this program, you will see something like this:
All that's missing now is adding actions that get executed when the buttons are pressed. This means filling out the _gui_about_clicked_cb()
and _gui_quit_clicked_cb()
you created earlier:
[...]
static void
_gui_about_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED)
{
printf("Clicked About\n");
}
static void
_gui_quit_clicked_cb(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
{
efl_exit(0);
}
[...]
There is nothing complex about this code: _gui_about_clicked_cb()
just prints a string to the command line and _gui_quit_clicked_cb()
calls EFL's inbuilt efl_exit()
function, which closes EFL applications.
The complete program is listed below::
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include <Efl.h>
#include <Elementary.h>
static void
_gui_about_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED)
{
Eo *button = data;
printf("Clicked About\n");
}
static void
_gui_quit_clicked_cb(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
{
efl_exit(0);
}
static void
_gui_setup()
{
Eo *win, *box, *hbox, *editor, *button;
win = efl_add(EFL_UI_WIN_CLASS, NULL,
efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
efl_text_set(efl_added, "Hello World"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE));
box = efl_add(EFL_UI_BOX_CLASS, win,
efl_content_set(win, efl_added),
efl_gfx_size_hint_min_set(efl_added, EINA_SIZE2D(360, 240)));
editor = efl_add(EFL_UI_TEXT_CLASS, box,
efl_text_set(efl_added, "Edit me"),
efl_ui_text_interactive_editable_set(efl_added, EINA_TRUE),
efl_ui_text_scrollable_set(efl_added, EINA_TRUE),
efl_pack(box, efl_added));
hbox = efl_add(EFL_UI_BOX_CLASS, box,
efl_ui_direction_set(efl_added, EFL_UI_DIR_HORIZONTAL),
efl_gfx_size_hint_weight_set(efl_added, 1.0, 0.1),
efl_pack(box, efl_added));
button = efl_add(EFL_UI_BUTTON_CLASS, hbox,
efl_text_set(efl_added, "About"),
efl_pack(hbox, efl_added),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED,
_gui_about_clicked_cb, efl_added));
button = efl_add(EFL_UI_BUTTON_CLASS, hbox,
efl_text_set(efl_added, "Quit"),
efl_pack(hbox, efl_added),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED,
_gui_quit_clicked_cb, efl_added));
}
EAPI_MAIN void
efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
_gui_setup();
}
EFL_MAIN()
The instructions of the [Compile and Run section in the EFL Installation Guide](TODO: efl-installation-guide.md#Compiling) will create an executable file called "basic-editor". Run your program with:
./basic-editor
You will see something like what is shown below.
Clicking on the About button will print the message "Clicked About" on the command line. Clicking Quit will close the program.
If anything goes wrong check out the Troubleshooting section at the end of this page.
As it stands, the editor is not terribly useful. Users cannot save their work for instance. This would certainly be something worth developing further, by implementing Open File and Save buttons.
Another issue is that when you reach the right-most edge of the window and keep typing any text you've already typed scrolls left and disappears. The cursor does not jump to a new line. Also, there is no scrollbar, which means that the only way to move back and forth along the text is by moving the cursor with the arrow keys or the Home and End keys.
You will learn how to solve all of the above issues in [the next tutorial](TODO: LINK TO FULL EDITOR TUTORIAL).
The most important lessons you can take away from this tutorial are:
efl_ui_text_interactive_editable_set(efl_added, EINA_TRUE)
, for example, suddenly makes the text in a text box editable.efl_event_callback_add()
functions.When you try compile the program above, you may see the following error:
basic-editor.c: In function ‘_gui_quit_clicked_cb’:
basic-editor.c:18:14: error: macro "efl_exit" passed 1 arguments, but takes just 0
efl_exit(0);
^
basic-editor.c:18:4: error: ‘efl_exit’ undeclared (first use in this function)
efl_exit(0);
^
basic-editor.c:18:4: note: each undeclared identifier is reported only once for each function it appears in
This happens if you're using a slightly older version of EFL libraries. Resolve the issue by downloading and using the latest version of EFL.
It this isn't possible you can avoid this problem by changing the line:
[...]
efl_exit(0);
[...]
in _gui_quit_clicked_cb()
to:
[...]
efl_exit();
[...]
basic-editor.c
from hereIn the [next guide](TODO: Insert correct link to next guide) you will learn how to make a a much more advanced text editor. The editor will wrap overlapping text and allow users to open and save text files.