Page MenuHomePhabricator

RFC Efl.Ui.Item_Position_Manager
Open, HighPublic

Description

interface Efl.Ui.Item_Position_Manager extends Efl.Gfx.Arrangement, Efl.Ui.Layout_Orientable
{
   methods {
      @property data_access {
         [[set at construction time, general interface for accessing data fast]]
         set {

         }
         values {
           access : accessor<Efl.Gfx.Entity>;
           size : int;
         }
      }
      @property viewport_size {
         [[called when the viewport is resized]]
         set {

         }
         values {
           size : Eina.Size2D;
         }
      }
      item_added {
        params {
          added_index : int;
          subobj : Efl.Gfx.Entity;
        }
      }
      item_removed {
        params {
          removed_index : int;
          subobj : Efl.Gfx.Entity;
        }
      }
      @property scroll_positon {
         [[called when the position of the items has changed]]
         set {

         }
         values {
           x : double; [[X position of the scroller]]
           y : double; [[Y position of the scroller]]
         }
      }
   }
   events {
     content_size,changed : Eina.Size2D; [[called when the absolut size of all contents has changed, this can be used to resize the pan object]]
   }
}

First idea of what the positon_manager could do.

bu5hm4n created this task.Fri, Jun 28, 2:28 AM
bu5hm4n triaged this task as High priority.

@cedric do you think this could work ?

bu5hm4n updated the task description. (Show Details)Fri, Jun 28, 7:50 AM
bu5hm4n updated the task description. (Show Details)
bu5hm4n updated the task description. (Show Details)Fri, Jun 28, 7:55 AM

Hum, I was going for a very different approach actually. I was thinking of having a function to call on a object with something like :

interface @beta Efl.Ui.Items_Position_Manager
{
   methods {
      layout_items {
         [[Function in charge of placing widget after they have been realized.
           This function will be called again with more items or if any of the realized
           item get there size changed.
         ]]
         params {
            @in viewport: Eina.Rect; [[Define the current space that need to be filled by the items]]
            @in items: iterator<Efl.Ui.Widget>; [[All the items that need to fit inside the viewport]]
         }
         return: bool; [[Return $true if the viewport was filled, $false if it needs more items to fill it.]]
      }
   }
}

The part that I don't know how to expose is the total space which is calculated by the Model in the MVVM case, but would have to be calculated somehow by the List/Grid in the non MVVM case.

So we will be going with @bu5hm4n solution. He has already build more code around it and I don't see anything wrong with it.

Their is a missing bit: a cache interface for the current information about the total size of all the object and a function to update that size when an item or a set of item get their size changed. The MVVM part will bind that cache to the Model information and that is how homogeneous and friends will be implemented.

We haven't talked about how special item like group header would be handled by the layout function, but I think they can just carry a specific interface that the layout function would recognize and properly place.

On the bit I would change in the current proposal, I would remove the item_add/item_del and just have a way to reset the accessor with a different offset. Additionally I do think we need an additional event for asking more items or dropping some.

@cedric you can find my current implementation in https://git.enlightenment.org/core/efl.git/log/?h=devs/bu5hm4n/work_container

the cache

After working more on the implementations, it turned out that a good cache heavily depends on the way of displaying, so the cache implemented in the list_item_position_manager is not helpfull for the grid. In order to work around that, i have dragged the cache from the item_container back into the position_manager. However, the whole thing has an access to the sizes through a accessor.

Group headers

I am not sure how we are going to identify them. But from a code POV:

  • It does not matter to the item_container if this is a header item or not
  • The position will just position it different, and change the viewport accordingly, should be easy i think

item_add / item_del / item_changed

I have done that because this turned out in the view_manager of active_view to be super helpfull. If you need to perform operations on each and every object element that gets added, you can simply do it there, without loops or so. It also takes away the burdon of searching for the changed item

Future work

Right now the implementation of the list is rather poor, we can do way more smart things with the caches, we are currently invalidating them *way* too often. Additionally, there are a lot of bugs arround, the version up there is just a early draft. However, the basic feature set is more or less done and implemented.