pfritz

August 9, 2009

The new state system for the themers

Filed under: edje,ewl — pfritz @ 21:47

I’ve already written an article about the new state system of ewl for
programmers. This article will concentrate on the stuff that is interesting for
the themers. In fact the new event system gives the themers more possibilities
to design their theme. This was one of the motivations to do this changes.
To keep this article simple and general I will not comment the actual changes,
but I’ll talk about how the event system works now.

Some words about the lifetime of an edje object

Unlike to other widgets lib based on edje, ewl has not a permanent edje object
per widget. If a widget gets off-screen or is hidden it will not have an edje
object. This state is called obscured in ewl. This means that any change to a
obscured widget cannot be repeated to the edje object, because there is no
edje object. So we will differ in ewl and in this article two different types
of state changes. The first type is an active change, i.e. there already exists
a edje object and a state changes. The second type is for a widget that is
revealed (= the widget is not longer obscured), it already has some states set,
maybe long before.

A little example

This all may sound complicated for you. Let’s take a look on a real-life
example to illustrate the difference. We have a list of check buttons in a
scroll pane. Now we click on an un-checked and visible check box. The check box
will toggle to the checked state. As a themer you maybe want to have an
animation here, like the check is bouncing or fades-in. Now we scroll this
check button off-screen, hence it is no longer visible. Ewl will now destroy the
edje object, in fact it will not destroy it but reuse it for other widgets. The
important point is that the widget doesn’t have this theme object any longer
associated to itself and thus we lost all state informations for the theme
object. If we now move the check button back to the screen, ewl will create a
new theme object for it, so we need to inform it that the widget is already
checked, but this time we do not want the animation, because the state of the
widget has not been changed. It is only the state of the edje object that
changes. So we need another signal name for it.

And here comes the new state system, formerly it was not possible in ewl
to distinguish between such different edje theme state changes. Now it is!

The new signal names

Puh, that was much text, sorry I’m bad in summarizing stuff. Besides that we
differ between getting a state and having a state. We uniformed the signal
names. Here is a table of them:

adding state        removing state       has state

"mouse,in"          "mouse,out"          "hovered"
"mouse,down"        "mouse,up"           "pressed"
"focus,in"          "focus,out"          "focused"
"disable"           "enable"             "disabled"
"highlight,on"      "highlight,off"      "highlighted"
"selection,on"      "selection,off"      "selected"
"state,on"          "state,off"          "on"
"odd,on"            "odd,off"            "odd"
"dnd,in"            "dnd,out"            "dnd"

One special case is “mouse,down” and “mouse,up” you also get a “mouse,down,x”
and “mouse,up,x” where x is the button number pressed. But this states are
custom states and aren’t inherit to the internal child widgets. You’ll learn
more about internal child widgets in the next section.

Even more things are now possible

Many ewl widgets are a composition of different widgets, for instance let’s
talk about a button. A button is a container that holds a label and maybe
an icon, if present. This label is an internal widget, because it is not added
by the app writer, but an inherent part of the widget. Those internal widgets
now inherit the states of the parent widget. To differentiate between state
changes of the parent and of the widget itself the source is a different.

It used to be “EWL”, now it is “ewl/this” if the change is done to the widget
itself, if the state of the parent is changed the source is “ewl/parent”. There
is even a third source I’ll explain later.

Let’s go back to our button example, if the mouse enters the button you maybe
want to change the background (the outer shape) of the button, that isn’t nor
was it a problem. But what happen if you turn the light background into a dark
one? Now the font of the label is most probably not visible. In contrast it
needs to be changed from dark to light.

Now the label theme object will also receive a signal if the background state
changes, so that you can adjust the font color. Very often you don’t care if the
state changes happens to the widget or it close parent. It should always behave
the same. Therefor there is a third source “ewl/both”, it is send if one of the
widgets (the actual widget for theme and the (maybe indirect) parent) is getting
the state, or if none of them is having it no longer.

Custom states

Because the list of states given above is not always sufficient for every
widget, there are also custom states. Custom states are more like pure edje
signals, they are not repeated to the child widgets of a container, and they
do not necessarily differ between getting and having a state. But the usage of
custom states in ewl is rare. Custom states will always have “ewl/this” as
source.

I hoped this explained the new features of the new state system. If you still
have questions about it, do not hesitate to ask them.

Advertisements

August 5, 2009

Kissed by a nymph

Filed under: ewl — pfritz @ 20:31

Most apps and libs in the e-land are migrating or are already migrated to eina.
And you probably know that Nathan and me are not big fans of eina. Here a
some points we dislike:

  • the API
  • the licence (unlike almost all efl libs it is not BSD-like)
  • the scope (eina handles many things that do not belong into a data type lib)

I’m not going to go into details here. The decisions are already done. We
will not use eina for EWL. As you see it’s not only one point, but a bunch of
several issues that we dislike. At the moment EWL is using the ecore data types,
but I guess they will be removed from ecore soon. So we have basically two
choices:

  1. We can revive EWD, i.e. make a stand-alone lib out of the ecore data types
  2. We can switch to another data type library

Since there are some problems with the ecore data types, in particular the
missing iterator implementations and we also missed some other sugar, we took
the second way. After checking several adt libs, we chose to write our own one, because none has all the feature we want.

For sure this step was not ill-considered, we already discussed years ago about
the future about the ecore data types, but now we are taking the chance to
switch to a similar but not API compatible design. The lib is called
cmaid.

Cmaid

The basic design ideas of cmaid is a mixture of ecore, libast and some new bits.

From libast it has the interface design. I.e. you program against an interface
and only on creation of the data type, you choose what implementation you
actually take. This makes it easy to switch from one implementation to another.
It also brings an inheritance stair, so ecore_hash_count() and
ecore_list_count() becomes cmaid_container_count().

From ecore it has the API and also the hash implementation, most of the
function names are very similar to the one of ecore, except those for
iterating. Not directly from ecore but from an idea of Nathan for improving
ecore_hash is Cmaid_Value. It’s describing the data to be stored in the
container. This can reduce the allocation time because it can in-line the data
into the data node, of course, only if you desire it.

Really new is the iterator concept. Unlike to many other adt libs there is
no rule like: Do not touch the container while you are iterating. If you
remove some item the container will correct your (other) iterators to point to
the right and valid position. This works because the container has a list of
all attached iterators. It might sound heavy, but those few checks that are
done, are not a really slow down, compared to the luxury they bring. Of course
if you artificially add thousands of iterators it becomes heavy, but that’s not
the life as it is.

If you are now curious about cmaid you can find it
here and
here the documentation. BTW cmaid is still
not finished, and the port of ewl to it will take some time.

July 1, 2009

The new state system of EWL

Filed under: ewl — pfritz @ 23:04

Maybe you have already seen it, I started some weeks ago a branch for ewl in svn. Since the changes aren’t self explaining, I want to describe here how the new system works and also why it works that way.


The old system

Let’s start with some history about the old, but still current main trunk system. There are two different kinds of states:

  • One are for internal usage only. They are part of the Ewl_Flag enumeration and are set with macros like ewl_widget_state_add(). They are to keep track if a widget is pressed, has focus, etc.
  • The second kind is to keep the widget decoration informed about some evens. It is a tight wrapper around edje_object_signal_emit(). With “tight” I mean that it doesn’t provide any extra functionality besides that it can save one (and only one!) set state, so that the state will be applied if the widget is obscured and revealed again (this happens if the widget gets offscreen, or hidden for some time).

Losing states

This design has some flaws, because it ignores the fact that most ewl widgets are a composition of several widgets. For instance the label in a button need to know when the parent button container changes its appearance, in other words when it changes its state. On the first sight the solution seems to be obvious. Simply pass the state changes to the internal children.

But what happens if the label goes offscreen, but not the button? Or what happens if we create the label later than the button changed it theme? The label will not know about the state changes of the button. That means we need to keep track of all state changes so we can apply it to the children, when they are created or recreated. This list approach has also problems, for example if you apply “mouse,in”, you need to remove it from the list before you apply later “mouse,out”.


Having a state is different to getting a state

Another problem that exists with the current system is that we do not differ between retrieving a state and having a state. For example a themer might want to add a fancy animation when a checkbutton is checked, but on the other hand he maybe do not want an animation when the check is already applied, when the widget is new created or it is on-screen again. This issue is not inherent in the current system, and could probably also be solved in it. But it is something I had also in mind when I was going to switch to the new system.


The solution

I hope you understand now some of the issues that led me to change the current system. The first step is to remove the tight wrapping of edje_object_signal_emit(). I doubt it is possible to find a way that is not memory wasting and slow, but managed all the states in plain strings.

Like we already did it for the internal state management, states are now labeled by an enumeration. Every state in this enum reserves its own bit, so you can easily combine them with ORing. This atomatically solves the list problem. If the mouse enters the widget you simply add the EWL_STATE_MOUSE_IN bit and if the mouse later leaves you remove the state again.

Since old internal state keeping and the new state system works very similar, I simply merged them to one system, with the main difference that ewl_widget_state_add() will now inform the theme (actually the engine), that the state changed. If the widget isn’t already realized, the theme gets another information on realization, namely that the widget has this state. This solves the second problem.

The widget does not only save the directly applied states, but also the states that it inherits from the parent widget. Those are easily queried on realization and are kept up-to-date, if the state changes on the parent widget.

But the state enumeration is not enough. In some rare, but important cases, we still need custom states, that only makes sense for the given widget and are not general enough to be put into the enum. For those cases there is still a function that works as a tight wrapper around edje_object_signal_emit(). It is called ewl_widget_custom_state_set() and works like the old ewl_widget_state_set(), i.e. it does not inform the internal children about the change.

I hope I’ll write a second part of this blog discussing the changes from the view of a themer.

Blog at WordPress.com.