Page MenuHomePhabricator

efl.gfx.arrangement
Open, TODOPublic

Description

|interface Efl.Gfx.Arrangement @beta
|├ (P) content_align
|├ (P) content_padding
bu5hm4n created this task.May 3 2019, 11:18 AM
bu5hm4n triaged this task as TODO priority.

I do not understand how content_align is supposed to work. When playing with Efl.Ui.Box I see no difference between setting it or the align hint on the box. Any help?

zmike added a comment.Jul 9 2019, 11:15 AM

I think that's supposed to be like elm_box_align_set

From what I read, that should align the box itself inside its allocated space. Isn't that what Efl.Gfx.Hint.hint_align does?

Right now I don't see the point in having content_align inside Efl.Gfx.Arrangement :/

zmike added a comment.Jul 10 2019, 5:53 AM

No, it's a little different. For example, suppose there isn't enough space allocated to the box on the canvas. Using this API, you can specify which part of the box is visible. The alt+tab/winlist component in enlightenment uses the API for this purpose.

Wow, that's an unexpected turn. So alignment works both when there's room to spare and when there's not enough room to fit a widget. Got it.

But still, can't this alignment (when there's not enough room) be controlled through Efl.Gfx.Hint.hint_align instead of Efl.Gfx.Arrangement.content_align?

woohyun added a subscriber: YOhoho.Jul 10 2019, 6:30 PM

@YOhoho

I think you also have some idea on this discussion :)

Try as I might, I see no effect when I change Efl.Gfx.Arrangement.content_align on an Efl.Ui.Box. Looking at the code, content_align is unused by box.

I am updating the docs for the Box widget and I'd like to know the purpose of content_align.

EDIT: OK, I had to set the weight hint to -1, but still it only worked for the Y axis. And the relationship between Efl.Gfx.Arrangement.content_align and Efl.Gfx.Hint.align is not clear at all...

content_align is used in efl_ui_container_layout.c:126 // pack align is used if "no item has a weight" and _efl_ui_container_layout_init is called by _efl_ui_box_custom_layout in efl_ui_box_layout.c.
Efl.Gfx.Hint.align is box widget align that used by parent container(box).
When box is vertical mode, x-axis content_align is ignored. x-axis content_align is controlled by children's x-axis hint_align.

Example code is here.

/*
 * gcc -o efl_ui_box_example efl_ui_box_example.c `pkg-config --cflags --libs elementary`
 */
#define EFL_BETA_API_SUPPORT 1

#define EFL_UI_WIDGET_PROTECTED
#include <Efl_Ui.h>
#include <Elementary.h>

EAPI_MAIN void
efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
   Eo *win, *box[4], *bg[4];
   int i;

   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.Ui.Box example"),
                 efl_ui_win_autodel_set(efl_added, EINA_TRUE)
                );

   for (i = 0; i < 4; i++)
     {
        box[i] = efl_add(EFL_UI_BOX_CLASS, win);

        efl_gfx_hint_fill_set(box[i], EINA_FALSE, EINA_FALSE);
        efl_gfx_hint_weight_set(box[i], 0.0, 0.0);
     }
   efl_content_set(win, box[0]);

   // set size_min
   efl_gfx_hint_size_min_set(box[0], EINA_SIZE2D(400 , 400));
   efl_gfx_hint_size_min_set(box[1], EINA_SIZE2D(150 , 150));
   efl_gfx_hint_size_min_set(box[2], EINA_SIZE2D(150 , 150));
   efl_gfx_hint_size_min_set(box[3], EINA_SIZE2D(50 , 50));

   // set color
   efl_gfx_color_set(efl_part(box[0], "background"), 255, 255, 255, 255);
   efl_gfx_color_set(efl_part(box[1], "background"), 0, 255, 0, 255);
   efl_gfx_color_set(efl_part(box[2], "background"), 0, 0, 255, 255);
   efl_gfx_color_set(efl_part(box[3], "background"), 0, 255, 255, 255);

   // pack box
   efl_pack(box[0], box[1]);
   efl_pack(box[0], box[2]);
   efl_pack(box[1], box[3]);

   // set direction and align
   /* box[0] have box[1] and box[2]. only y-axis content_align will work. x-axis align is responsible for children's hint_align. */
   efl_ui_layout_orientation_set(box[0], EFL_UI_LAYOUT_ORIENTATION_VERTICAL); // it is default value.
   efl_gfx_arrangement_content_align_set(box[0], 0.2/*it is ignored because orientation is VERTICAL*/, 0.7);
   efl_gfx_hint_align_set(box[1], 0.7, 0.0/*it is ignored because there is no space(0-weight)*/);
   efl_gfx_hint_align_set(box[2], 0.2, 0.2/*it is ignored because there is no space(0-weight)*/);
   // efl_gfx_hint_weight_set(box[2], 1.0, 1.0); y-axis hint_align of box[2] will work with this code.
   /* box[1] have box[3]. only x-axis content_align will work. y-axis align is responsible for children's hint_align. */
   efl_ui_layout_orientation_set(box[1], EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
   efl_gfx_arrangement_content_align_set(box[1], 0.2, 0.7/*ignored*/);
   efl_gfx_hint_align_set(box[3], 0.7/*ignored*/, 0.9);

   efl_gfx_entity_size_set(win, EINA_SIZE2D(400, 400));
}
EFL_MAIN()

Result

@YOhoho Thank you very much for this very detailed explanation. Now I understand how it works.

This looks very complicated, but I guess finding a simpler mechanism would require some time.

This definitely needs a tutorial, and it is not going to be pretty.

zmike moved this task from Backlog to Evaluating on the efl: api board.Thu, Aug 29, 7:49 AM

This is a bit hard to describe, but I think the existing API is fine. The issue, however, is the name. The properties are named content_* but the namespace is Arrangement; this seems strange?

Maybe we want something like Efl.Gfx.Content_Layout? Needs brainstorming.

We already spent some time looking for a name to describe "a collection of things uniformly spaced inside another thing"... and this was the best we came up with.
Maybe a second round (and fresh eyes) help.

My issue is solely with the reuse of content here since we have a whole Efl.Content namespace which this does not appear to directly be related to in its own namespace, yet does seem to have some relation to in function.

hmmm, yeah.

arrangement_padding and arrangement_alignment seem a bit overkill, no?

Big problem (imo):

this interface has content_padding:

values {
   pad_horiz: double; [[Horizontal padding]]
   pad_vert:  double; [[Vertical padding]]
   scalable:  bool; [[$true if scalable, $false otherwise]]
}

efl.gfx.hint has hint_margin, which is identical in terms of functionality, but it has:

values {
   l: int; [[Integer to specify left padding.]]
   r: int; [[Integer to specify right padding.]]
   t: int; [[Integer to specify top padding.]]
   b: int; [[Integer to specify bottom padding.]]
}

These property names should be the same and they should have the same values.

Hmmm... yeah, that's pretty inconsistent.
So we should rename content_padding to content_margin and move it from two doubles to 4 ints?
It wasn't clear anyway what those two doubles meant.. fractional pixels?

zmike added a comment.Mon, Sep 16, 7:11 AM

Alright, after sleeping on this again, I think we can actually ignore that: these mechanisms function fundamentally differently. margin is applied to an object always. content_padding appears to be the same on the surface, but really this is a uniform size that's applied to all sub-objects of a container; it wouldn't make much sense to have an inset-style property for this, you're only trying to set the space between the content objects.

This needs some clarifying in docs to explain it a little more clearly at the conceptual level I think.

What would you add to the docs for content_padding?

[[This property determines the space between a container's content items.

  It is different than the @Efl.Gfx.Hint.hint_margin property in that it is applied to each
  content item within the container instead of a single item. The calculation for these two properties
  is cumulative.

  See also @Efl.Gfx.Hint.hint_margin.
]]
zmike added a comment.Mon, Sep 16, 8:14 AM

I'm not sure? I just feel like if I put myself in the mind of a clueless new developer then there's some nuance missing in that explanation.

Hahaha, OK, I found what is missing. The fricking units. Is it pixels? Why is it a double, then?

This would also need diagrams, for sure.
And there's an Elementary positioning tutorial pending.

It does seem like it should be a uint...

Agreed, if you confirm that they are pixels.

I can neither confirm nor deny this, but I can say that all existing implementations and usages of this property are currently using pixels.

Let the games begin then

zmike added a comment.EditedWed, Sep 18, 8:48 AM

@woohyun @YOhoho Is there a reason to have the scalable value for content_padding? Is there really a case where apps would want to set this and not have it scale?

Also can't the pad_horiz and pad_vert values become uint since the other similar properties are also integer types?

YOhoho added a comment.EditedThu, Sep 19, 12:34 AM

I have no idea of scalable value and double type history. The first commit is 57e64ee65b6ae35107f40ca155e2fb318a0082f6.
I think it is better to use int type (or Eina.Size2D) without scalable for consistency.

zmike added a subscriber: jpeg.Thu, Sep 19, 12:10 PM

I spoke with @jpeg and he seemed to think that there were cases where users would want to enable/disable scaling of padding between items? This is just his opinion from when he wrote it, however.

We should clarify what behavior we need/want here. I think at minimum we can change double, though I am not sure if we want Eina.Size2D since this is not technically a size, it is a border...

We also need to determine whether we want the values to scale or not, or if there is a need to have this configurable on a per-object basis.