|
|
|
NavigationPersonal tools |
EWL Introduction (pt)Este artigo é uma simples introdução por exemplos para a EWL. Quando terminarmos teremos um simples visualizador de imagens que vai terminar quando o usuário pressiona a barra de espaço ou 'q' when. Um exemplo relativamente simples mas que vai mostrar algumas das características fundamentais da EWL. [edit] Explicação do CódigoVamos passar direto para a explicação do código. No final do artigo há todo o código na íntegra, para ser mais fácil de copiar e compilar. #include <Ewl.h> #include <stdio.h> Toda aplicação EWL precisa incluir Ewl.h. Ewl.h incluirá todos os arquivos de cabeçalho requeridos pela EWL. Você nunca deve ter de incluir qualquer outro cabeçalho relacionado com a EWL enquanto escreve uma aplicação. static void
cb_window_destroy(Ewl_Widget *w, void *ev, void *data)
{
ewl_main_quit();
}
EWL usa callbacks para sinalizar a aplicação que está rodando enquanto um evento acontece. Quando você registra um callback, da qual iremos ver mais tarde, você ajustará uma função callback para ser executada enquanto o evento acontece. Essas funções callback *sempre* tem a mesma assinatura. void func(Ewl_Widget *w, void *ev, void *data), é clato que você pode mudar o nome da função e o nome dos parâmetros. O primeiro parâmetro para a função callback é o widget que o callback anexou também. O segundo parâmetro é tanto NULL quanto uma estrutura de evento que contém informações adicionais. O parâmetro final são dados que podemos anexar ao callback se precisarmos também. Nesse caso não precisamos nos preocupar com qualquer um dos parâmetros. Depois no código nós configuramos esse callback para ser disparado enquanto a janela principal é destruída. Já que a EWL vai gerenciar a destruição e a limpeza das janelas precisamos apenas de um sinal EWL para quebrar sesu próprios comandos principais por chamar ewl_main_quit(). Isso causará a chamada de ewl_main(), da qual vamos ver mais tarde, para retornar.
static void
cb_window_close(Ewl_Widget *w, void *ev, void *data)
{
ewl_widget_destroy(w);
}
Aqui temos outra callback. It is triggered, when the user request the window to close. You could also pop-up a dialog window to ask if the user is sure to quit. We haven't got any data to save, thus we can simply destroy our window. Note: this doesn't stop the application. The whole application won't stop until we call ewl_main_quit().
static void
cb_key_down(Ewl_Widget *w, void *ev, void *data)
{
Ewl_Event_Key_Down *e;
e = ev;
if (!strcmp(e->base.keyname, "Escape")
|| !strcmp(e->base.keyname, "q"))
{
Ewl_Widget *win;
win = ewl_widget_name_find("main_win");
ewl_widget_destroy(win);
}
}
cb_key_down is the callback we'll assign to the window to handle keyboard input. The key event callbacks are passed an Ewl_Event_Key_Down event structure. In this example we take the event structure and look for either the Escape or q key name. (These names come from Ecore.) If either of those two keys have been pressed we'll lookup the widget named main_win using ewl_widget_name_find. It is possible to assign names to your widgets in EWL. Assigning names is optional, but can be handy in cases like this to remove the need for global variables. Once we've received our main window we call ewl_widget_destroy to tell EWL to destroy the widget. This will trigger the EWL_CALLBACK_DESTROY and hence, cause cb_window_destroy to be called. EWL makes extensive use of callbacks internally to signal changes between its widgets. This has the added benefit that you can override the internal EWL behavior by removing its callbacks and adding custom functions.
int
main(int argc, char ** argv)
{
Ewl_Widget *win, *scroll, *o;
if (!ewl_init(&argc, argv))
{
fprintf(stderr, "Unable to init EWL.\n");
return 1;
}
With the pre-amble out of the way we finally get to our main program. All of the widgets we create will be of type Ewl_Widget. EWL uses a simple single inheritance model in its widgets. Through this chain every widget has Ewl_Widget as a base widget. This means, with a simple cast, you can call Ewl_Widget methods in any widget in the hierarchy. This also holds true for other inheritance items. So, you can call Ewl_Container methods on Ewl_Box widgets. An example of this inheritance can be seen in the following image. Although this is a bit out of date it gives a good idea of how the system functions. To find out the actual inheritance trees it's probably best to refer to the header files. Before you can use EWL you have to initialize the system. This is done by calling ewl_init(). You can pass the programs argc and argv parameters to EWL if you wish to have EWL strip out any EWL specific options. (EWL takes flags like --ewl-print-theme-keys, --ewl-help). This will strip the EWL flags out of argv and decrement argc as needed. If you don't want to have EWL do this, just pass NULLs into ewl_init(). It'll do the right thing. ewl_init() will return TRUE if the system was successfully configured or FALSE otherwise. If something goes wrong there should be some helpful messages printed to the command line. if (argc < 2)
{
fprintf(stderr, "Need image to view.\n");
return 1;
}
Just making sure that we've still got an image file to display. This is done after the call to ewl_init() because, as I mentioned, ewl_init() may decrement the argc variable. win = ewl_window_new(); The first thing to do is create our main window. This is done by calling ewl_window_new(). All of the widget creation calls in EWL, either currently or in the future, accept no parameters and return an Ewl_Widget object. This keeps everything consistent. ewl_window_title_set(EWL_WINDOW(win), "EWL Image Viewer");
ewl_window_class_set(EWL_WINDOW(win), "ewl_image_viewer");
ewl_window_name_set(EWL_WINDOW(win), "ewl_image_viewer");
Once we've got our window we can setup some window manager properties. This includes setting the title of the window by calling ewl_window_title_set and setting its name and class. The ewl_window_* functions accept an Ewl_Window object as their first parameter. In this case we need to cast win from an Ewl_Widget to an Ewl_Window. Each widget in EWL has a way to cast that is the widget name in upper case. In this example we want to cast to an Ewl_Window widget so we use EWL_WINDOW() to cast. You'll see this typing of casting scattered around the code. ewl_object_fill_policy_set(EWL_OBJECT(win), EWL_FLAG_FILL_ALL);
ewl_object_size_request(EWL_OBJECT(win), 640, 480);
By default an Ewl_Window will become large enough to hold its children and won't allow you to resize below the preferred child size. For our application that isn't the behavior we want. We want to be able to shrink the window down and have scrollbars appears. In order to achieve this we need to change the fill policy of the window. This is done by calling ewl_object_fill_policy_set(). We need to pass an Ewl_Object widget into the ewl_object_* functions but since Ewl_Widget inherits from Ewl_Object, all EWL widgets inherit from Ewl_Object. An explanation of the EWL fill policies can be found at: Filler Up. Since we've now changed the fill policy to, basically, be all possible fill policies the window won't have any size to start. In this case we need to request a size for the window. This is done by calling ewl_object_size_request() and providing the width and height for the object. ewl_callback_append(win, EWL_CALLBACK_DELETE_WINDOW, cb_window_close, NULL);
ewl_callback_append(win, EWL_CALLBACK_KEY_DOWN, cb_key_down, NULL);
ewl_callback_append(win, EWL_CALLBACK_DESTROY, cb_window_destroy, NULL);
We attach three callbacks onto the window. The first, EWL_CALLBACK_DELETE_WINDOW will be triggered when the user attempts to close the application. The second, EWL_CALLBACK_KEY_DOWN will be triggered when a keyboard event arrives on the window. The third will be called when the widget (here the window) will be destroyed. In this example we are using ewl_callback_append() to attach the callbacks. There are several other ways to attach callbacks including; ewl_callback_prepend() and ewl_callback_insert(). The functions to add callbacks all have the same signature. The first parameter is the Ewl_Widget to attach the callback too. Second is the callback type. A listing of these types can be found in EWL Callback Information. Third is the function to be called as was explained above. Finally is the user data. This is data is what is passed as the third parameter to your callback function. This can be set to anything you want or need. ewl_widget_name_set(win, "main_win"); As I mentioned earlier you can set names on widgets. This is done by calling ewl_widget_name_set() and specifying the widget and the name so set. ewl_widget_show(win); Finally we show the widget. In order for a widget to be display it, and all of its parents, need to be displayed. This is done by calling ewl_widget_show() and passing in the widget. scroll = ewl_scrollpane_new();
ewl_container_child_append(EWL_CONTAINER(win), scroll);
ewl_widget_show(scroll);
With the main window out of the way we move onto the scroll pane. In EWL the Ewl_Window widget will place all children in the position they request, typically top left. This is usually not what you want. To get a better layout you'll need to pack a widget into Ewl_Window to handle the layout. This is typically something like Ewl_Scrollpane or Ewl_Box. In this case we're packing a scrollpane. As before we use the _new() call to create a new scrollpane which returns an Ewl_Widget object. We then add this object into its parent container. Beacuse the window inherits from Ewl_Container we are able to use the EWL_CONTAINER() cast to allow passing our window to ewl_container_child_append(). There are other ways to append a child to a containter, ewl_container_child_prepend(), ewl_container_child_insert() among others. See the ewl_container.h header file for a list of available functions. o = ewl_image_new();
ewl_image_file_path_set(EWL_IMAGE(o), argv[1]);
ewl_container_child_append(EWL_CONTAINER(scroll), o);
ewl_widget_show(o);
The last widget to be created is our image. The sequence of calls is very similar to the window and scrollpane cases. The only extra piece is setting the image into the Ewl_Image object. This is done by calling ewl_image_file_path_set() and passing in the full path to the image. There is also ewl_image_file_set() which takes an extra group parameter, used when displaying Edje files. ewl_main();
return 0;
}
With all of the widgets created and initialized we're ready to kick off our program by calling ewl_main(). This will startup the main run loop and start calling the callbacks to your program. ewl_main() will return when ewl_main_quit() is called. ewl_main_quit() will handle the call to ewl_shutdown() so you can safely just return once ewl_main() is finished. Compiling the program is as simple as executing: dj2@cerberus [~/t] -> gcc -o eiv tut.c `ewl-config --cflags --libs` EWL ships with the ewl-config shell script that provides all of the needed parameters to compile your program. You should now be able to run your application and display a provided image. As you've hopefully seen, EWL has been designed for simplicity and consistency. We've tried to get the maximal amount of flexibility out of the system while keeping the API consistent and minimizing code duplication. [edit] Complete Code Listing
#include <Ewl.h>
#include <stdio.h>
static void
cb_window_destroy(Ewl_Widget *w, void *ev, void *data)
{
ewl_main_quit();
}
static void
cb_window_close(Ewl_Widget *w, void *ev, void *data)
{
ewl_widget_destroy(w);
}
static void
cb_key_down(Ewl_Widget *w, void *ev, void *data)
{
Ewl_Event_Key_Down *e;
e = ev;
if (!strcmp(e->base.keyname, "Escape")
|| !strcmp(e->base.keyname, "q"))
{
Ewl_Widget *win;
win = ewl_widget_name_find("main_win");
ewl_widget_destroy(win);
}
}
int
main(int argc, char ** argv)
{
Ewl_Widget *win, *scroll, *o;
if (!ewl_init(&argc, argv))
{
fprintf(stderr, "Unable to init EWL.\n");
return 1;
}
if (argc < 2)
{
fprintf(stderr, "Need image to view.\n");
return 1;
}
win = ewl_window_new();
ewl_window_title_set(EWL_WINDOW(win), "EWL Image Viewer");
ewl_window_class_set(EWL_WINDOW(win), "ewl_image_viewer");
ewl_window_name_set(EWL_WINDOW(win), "ewl_image_viewer");
ewl_object_fill_policy_set(EWL_OBJECT(win), EWL_FLAG_FILL_ALL);
ewl_object_size_request(EWL_OBJECT(win), 640, 480);
ewl_callback_append(win, EWL_CALLBACK_DELETE_WINDOW, cb_window_close, NULL);
ewl_callback_append(win, EWL_CALLBACK_KEY_DOWN, cb_key_down, NULL);
ewl_callback_append(win, EWL_CALLBACK_DESTROY, cb_window_destroy, NULL);
ewl_widget_name_set(win, "main_win");
ewl_widget_show(win);
scroll = ewl_scrollpane_new();
ewl_container_child_append(EWL_CONTAINER(win), scroll);
ewl_widget_show(scroll);
o = ewl_image_new();
ewl_image_file_path_set(EWL_IMAGE(o), argv[1]);
ewl_container_child_append(EWL_CONTAINER(scroll), o);
ewl_widget_show(o);
ewl_main();
return 0;
}
|