My name is Dan, and I'm a casual e17 user with some interest in code and theme development. I'm putting things in here mostly as a scratch pad, and if any entries seem useful I may migrate them to pages of their own. Please feel free to make contributions or suggestions to the code samples here, as I am just learning, and don't yet know the "right" way to do many of the things I'm trying to do.
RbdPngn from #EWL@freenode, after answering a few of my questions, suggested that I make a wiki page instead of complaining about a lack of documentation, so this is the beginning of that effort. If I get some good feedback, or learn enough on my own to figure things out I'll consolidate such learnings into a real page.
I've been trying to figure out how to get applications written using the EFL, and have found the documentation to be a bit lacking in some basic areas. There is a great deal of documentation out there, but some of the fundamental things --Dank 13:23, 15 February 2008 (PST)that more experienced folks (who usually do the documenting!) take for granted are either not covered, or are covered in places I've not yet found. The projects below are bits I had trouble with, hopefully soon to include advice or suggestions from more advanced developers.
This little guy explores the "visibility" of an object. The main program defines two boxes, one to be shown and one to be hidden.
Each box contains one button. All widgets are have a ewl_widget_show() call, so I'm expecting that the second box/button are the widgets which should be displayed (as I assume that the first box/button are covered and hidden by the second box).
Both buttons trigger the same _CLICKED callback method, which determines who was the issuing button by evaluating the label of the passed button widget.
In the callback method the box containing the issuing button is hidden with ewl_widget_hide(), and the other box is shown (possibly redundantly, but I would guess that this doesn't matter) with ewl_widget_show().
All this program is supposed to do is switch between two visible boxes. There is probably a better way to get this task accomplished (like maybe setting layer priority, which did work when both buttons were just sitting in the same box and overlapping each other, but didn't work when being applied to the containing boxes) but this was the most intuitive in my mind. Suggestions welcome :)
#include <Ewl.h>
#include <stdio.h>
#include <string.h>
Ewl_Widget *win, *intro_box, *file_box, *o;
char *label1 = "first";
char *label2 = "second";
void CB_exit(Ewl_Widget *w, void *event_data, void *user_data);
void CB_btn_click(Ewl_Widget *w, void *event_data, void *user_data);
int main(int argc, char **argv)
{
if(!ewl_init(&argc, argv)){
fprintf(stderr, "Unable to initialize EWL.\n");
return 1;
}
win = ewl_window_new();
ewl_window_title_set(EWL_WINDOW(win), "EWL gtkrc-2.0 File Editor");
ewl_callback_append(win, EWL_CALLBACK_DELETE_WINDOW, CB_exit, NULL);
ewl_widget_show(win);
CURRENT_W(win)=200;
CURRENT_H(win)=100;
/*
* Fix A goes here (see below)
*/
intro_box = ewl_vbox_new();
/*
* Fix B replaces next line down (see below)
*/
ewl_container_child_append(EWL_CONTAINER(win), intro_box);
CURRENT_W(intro_box)=150;
CURRENT_H(intro_box)=80;
ewl_widget_show(intro_box);
Ewl_Widget *btn1 = ewl_button_new();
ewl_callback_append(btn1, EWL_CALLBACK_CLICKED, CB_btn_click, NULL);
ewl_object_alignment_set(EWL_OBJECT(btn1), EWL_FLAG_ALIGN_LEFT);
ewl_object_fill_policy_set(EWL_OBJECT(btn1), EWL_FLAG_FILL_VFILL);
ewl_container_child_append(EWL_CONTAINER(intro_box), btn1);
ewl_button_label_set(EWL_BUTTON(btn1), label1);
ewl_widget_show(btn1);
file_box = ewl_vbox_new();
/*
* Fix C replaces next line down (see below)
*/
ewl_container_child_append(EWL_CONTAINER(win), file_box);
CURRENT_W(file_box)=150;
CURRENT_H(file_box)=80;
// if line below is left in then I see the second button/box instead.
ewl_widget_show(file_box);
Ewl_Widget *btn2 = ewl_button_new();
ewl_callback_append(btn2, EWL_CALLBACK_CLICKED, CB_btn_click, NULL);
ewl_object_alignment_set(EWL_OBJECT(btn2), EWL_FLAG_ALIGN_RIGHT);
ewl_object_fill_policy_set(EWL_OBJECT(btn2), EWL_FLAG_FILL_VFILL);
ewl_container_child_append(EWL_CONTAINER(file_box), btn2);
ewl_button_label_set(EWL_BUTTON(btn2), label2);
ewl_widget_show(btn2);
// intro_box is "visible, unrealized", file_box is "visible, unrealized"
ewl_widget_print_verbose(intro_box);
ewl_widget_print_verbose(file_box);
ewl_main();
return 0;
}
/**
* Called when either button is clicked.
* Should evaluate the label of the button causing the event, and hide/show
* parent boxes as needed.
* Show() is done before Hide() because because otherwise I get a messy error
* about "visible children = -1" or something.
* This doesn't actually -work- because, while the hide() seems to "take"
* (the button, and presumably the parent box, become hidden), the show()
* does not (nothing appears to replace the hiding box/button set).
*/
void CB_btn_click(Ewl_Widget *w, void *event_data, void *user_data)
{
fprintf(stderr, "\nClicky! (from [%s], matches [%s] ? [%d])\n\n",
ewl_button_label_get(EWL_BUTTON(w)),
label1,
strcmp(ewl_button_label_get(EWL_BUTTON(w)),label1));
if(strcmp(ewl_button_label_get(EWL_BUTTON(w)),label1)==0){
ewl_widget_show(file_box);
ewl_widget_hide(intro_box);
}else{
ewl_widget_show(intro_box);
ewl_widget_hide(file_box);
}
// intro_box is "visible, not realized", file_box is "not visible, realized"
ewl_widget_print_verbose(intro_box);
ewl_widget_print_verbose(file_box);
return;
}
void CB_exit(Ewl_Widget *w, void *event_data, void *user_data)
{
ewl_widget_destroy(win);
ewl_main_quit();
return;
}
dank@dank:~/myCode$ ./box_switcher
0x6747c0:vbox geometry (0, 0) 150 x 80
visible, not realized, not destroyed, enabled
Preferred size: 1x1 Minimum size: 1x1 Maximum size: 2147483647x2147483647
Insets: 0, 0, 0, 0
Padding: 0, 0, 0, 0
Fill policy: HFILL VFILL
Alignment: CENTER
0x675ca0:vbox geometry (0, 0) 150 x 80
visible, not realized, not destroyed, enabled
Preferred size: 1x1 Minimum size: 1x1 Maximum size: 2147483647x2147483647
Insets: 0, 0, 0, 0
Padding: 0, 0, 0, 0
Fill policy: HFILL VFILL
Alignment: CENTER
Clicky! (from [second], matches [first] ? [1])
***** Ewl Developer Warning ***** :
To find where this is occurring set a breakpoint
for the function ewl_print_warning.
In function:
ewl_container_child_hide_call();
visible_children is -1
0x6747c0:vbox geometry (0, 0) 150 x 80
visible, not realized, not destroyed, enabled
Preferred size: 61x38 Minimum size: 61x38 Maximum size: 2147483647x2147483647
Insets: 0, 0, 0, 0
Padding: 0, 0, 0, 0
Fill policy: HFILL VFILL
Alignment: CENTER
0x675ca0:vbox geometry (2, 2) 200 x 100
not visible, realized, not destroyed, enabled
Preferred size: 74x38 Minimum size: 74x38 Maximum size: 2147483647x2147483647
Insets: 0, 0, 0, 0
Padding: 0, 0, 0, 0
Fill policy: HFILL VFILL
Alignment: CENTER
dank@dank:~/myCode$
The program opens and appears to be on the right track. Both box widgets issue debug output like "visible, not realized", which doesn't bother me so much, because I see what I want to see, initially. I've got a button labeled "second" on the right-hand side, and I can click on it and it'll disappear. The problem is that intro_box and btn1 do not appear as expected.
The error output message "visible_children is -1" indicates (if originating from the window widget) that the intro_box widget is "not visible", but debug output contradicts this.
Debug output "visible, not realized" for the intro_box widget leads me to believe that there is some action, further to calling the ewl_widget_show() method, required before widgets will actually be shown. Or that I'm doing things out of order somehow.
Can someone define the difference between widgets which are "realized" vs. "not realized", and what it means for their programmatic interaction?
do not use the CURRENT_* macros to set a value, they are meant for read only. You can use ewl_object_size_request() or similar function, but most container will ignore these value, or better said they will override the values. The main idea is that the container places the widgets, and you only choose which layout you want for the given job. You can fine tune this layout with some of the ewl_object function. For example you can set the fill policy, the alignment, the padding etc. And most container have some extra functions where you set even more things, Like ewl_box_homogeneous_set() for example.
you cannot append two children to the window. The window inherits from the cell, that is supposed to have only one child. What actually happen is, that when you append the second box the first box will be removed. So if you want to have to children or more in the window, you have to put them into a container and the put the container into the window.
Here is an example how it could look like, don't know if it really does what you want, but i think it matches your description.
http://phpfi.com/296606 --pfritz 09:34, 15 February 2008 (PST)
I think the most important thing I learned here is the relationship between the box and window objects in EWL. In my reading I did not notice any indication that the window could contain only one child. This is critical. Most of my coding experience is for web applications, and I had assumed that the window object would be like the <body> tag, with as many sub-components as you like. Instead I see that EWL treats the window as a special container, more like the <html> tag, and you must (may?) instantiate one standard container object as your <body> to hold the rest of your interface elements. Applying this idea with the corrections below as pfritz instructs corrects the functionality of this program:
/**
* fix A: instantiate a box which will contain the two "active" boxes:
*/
Ewl_Widget *box = ewl_box_new();
ewl_container_child_append(EWL_CONTAINER(win), box);
ewl_widget_show(box);
/**
* fix B: correct _append() method call to append to new box:
*/
ewl_container_child_append(EWL_CONTAINER(box), intro_box);
/**
* fix C: correct _append() method call to append to new box:
*/
ewl_container_child_append(EWL_CONTAINER(box), file_box);
Functionality now is as expected: Program opens a window and I am able to select, via button click, which box (only containing one button each for this example, but which may eventually each hold many widgets) is available to the user for interaction.
Correcting code-cleanliness is a little simpler, as replacing my CURRENT_*() calls with a single ewl_object_size_request(win) call performs the same sizing task.
I had no idea what your reference to ewl_box_homogeneous_set() meant, so had to look it up. It is a method name which essentially has no meaning without definition. It is defined in the docs as "Change the homogeneous layout of the box." and "Boxes use homogeneous layout by default, this can be used to change that.", which is not useful, but a better definition exists in section 7.5 of the EWL Book: "...the ewl_box_homogeneous_set() will set the box to give all items in it the same size if this is set to true, otherwise they will have their required size.". Ahhhh, lightbulbs go off :) (the method name does make sense, but is not immediately obvious)