diff --git a/config/default/base.src.in b/config/default/base.src.in index 10d7d0e6a5..7e9444c10c 100644 --- a/config/default/base.src.in +++ b/config/default/base.src.in @@ -2796,5 +2796,274 @@ group "Elm_Config" struct { } } } + group "Elm_Config_Bindings_Widget" struct { + value "name" string: "Efl.Ui.List"; + group "key_bindings" list { + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Left"; + value "action" string: "move"; + value "params" string: "left"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Left"; + value "action" string: "move"; + value "params" string: "left_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Left"; + value "action" string: "move"; + value "params" string: "left"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Left"; + value "action" string: "move"; + value "params" string: "left_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Right"; + value "action" string: "move"; + value "params" string: "right"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Right"; + value "action" string: "move"; + value "params" string: "right_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Right"; + value "action" string: "move"; + value "params" string: "right"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Right"; + value "action" string: "move"; + value "params" string: "right_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Prior"; + value "action" string: "move"; + value "params" string: "prior"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Prior"; + value "action" string: "move"; + value "params" string: "prior"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Next"; + value "action" string: "move"; + value "params" string: "next"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Next"; + value "action" string: "move"; + value "params" string: "next"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Home"; + value "action" string: "move"; + value "params" string: "first"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Home"; + value "action" string: "move"; + value "params" string: "first"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "End"; + value "action" string: "move"; + value "params" string: "last"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_End"; + value "action" string: "move"; + value "params" string: "last"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Return"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Enter"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "space"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Escape"; + value "action" string: "escape"; + value "params" string: ""; + } + } + } } } diff --git a/config/mobile/base.src.in b/config/mobile/base.src.in index 5f5b5dd63b..18d3612548 100644 --- a/config/mobile/base.src.in +++ b/config/mobile/base.src.in @@ -2789,5 +2789,274 @@ group "Elm_Config" struct { } } } + group "Elm_Config_Bindings_Widget" struct { + value "name" string: "Efl.Ui.List"; + group "key_bindings" list { + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Left"; + value "action" string: "move"; + value "params" string: "left"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Left"; + value "action" string: "move"; + value "params" string: "left_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Left"; + value "action" string: "move"; + value "params" string: "left"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Left"; + value "action" string: "move"; + value "params" string: "left_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Right"; + value "action" string: "move"; + value "params" string: "right"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Right"; + value "action" string: "move"; + value "params" string: "right_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Right"; + value "action" string: "move"; + value "params" string: "right"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Right"; + value "action" string: "move"; + value "params" string: "right_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Prior"; + value "action" string: "move"; + value "params" string: "prior"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Prior"; + value "action" string: "move"; + value "params" string: "prior"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Next"; + value "action" string: "move"; + value "params" string: "next"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Next"; + value "action" string: "move"; + value "params" string: "next"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Home"; + value "action" string: "move"; + value "params" string: "first"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Home"; + value "action" string: "move"; + value "params" string: "first"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "End"; + value "action" string: "move"; + value "params" string: "last"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_End"; + value "action" string: "move"; + value "params" string: "last"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Return"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Enter"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "space"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Escape"; + value "action" string: "escape"; + value "params" string: ""; + } + } + } } } diff --git a/config/standard/base.src.in b/config/standard/base.src.in index 13497910ae..9781512539 100644 --- a/config/standard/base.src.in +++ b/config/standard/base.src.in @@ -2786,5 +2786,274 @@ group "Elm_Config" struct { } } } + group "Elm_Config_Bindings_Widget" struct { + value "name" string: "Efl.Ui.List"; + group "key_bindings" list { + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Left"; + value "action" string: "move"; + value "params" string: "left"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Left"; + value "action" string: "move"; + value "params" string: "left_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Left"; + value "action" string: "move"; + value "params" string: "left"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Left"; + value "action" string: "move"; + value "params" string: "left_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Right"; + value "action" string: "move"; + value "params" string: "right"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Right"; + value "action" string: "move"; + value "params" string: "right_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Right"; + value "action" string: "move"; + value "params" string: "right"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Right"; + value "action" string: "move"; + value "params" string: "right_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 0; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down_multi"; + group "modifiers" list { + group "Elm_Config_Binding_Modifier" struct { + value "mod" string: "Shift"; + value "flag" uchar: 1; + } + } + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Prior"; + value "action" string: "move"; + value "params" string: "prior"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Prior"; + value "action" string: "move"; + value "params" string: "prior"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Next"; + value "action" string: "move"; + value "params" string: "next"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Next"; + value "action" string: "move"; + value "params" string: "next"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Home"; + value "action" string: "move"; + value "params" string: "first"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Home"; + value "action" string: "move"; + value "params" string: "first"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "End"; + value "action" string: "move"; + value "params" string: "last"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_End"; + value "action" string: "move"; + value "params" string: "last"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Return"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Enter"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "space"; + value "action" string: "select"; + value "params" string: ""; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Escape"; + value "action" string: "escape"; + value "params" string: ""; + } + } + } } } diff --git a/data/elementary/themes/Makefile.am b/data/elementary/themes/Makefile.am index 40ff6973c8..74ba32fa63 100644 --- a/data/elementary/themes/Makefile.am +++ b/data/elementary/themes/Makefile.am @@ -1037,6 +1037,7 @@ elementary/themes/edc/efl/text.edc \ elementary/themes/edc/efl/textpath.edc \ elementary/themes/edc/efl/tooltip.edc \ elementary/themes/edc/efl/video.edc \ +elementary/themes/edc/efl/list.edc \ elementary/themes/edc/efl/win.edc elementary_fdo_actions_128_files = \ diff --git a/data/elementary/themes/default.edc b/data/elementary/themes/default.edc index 119f42eeba..0b43454863 100644 --- a/data/elementary/themes/default.edc +++ b/data/elementary/themes/default.edc @@ -168,6 +168,7 @@ collections { #include "edc/efl/button.edc" #include "edc/efl/calendar.edc" #include "edc/efl/nstate.edc" +#include "edc/efl/list.edc" // XXX: mobile mode needs invisible scrollers... make signals that do this #include "edc/efl/scroller.edc" // XXX: mobile mode needs different entry setup diff --git a/data/elementary/themes/edc/efl/list.edc b/data/elementary/themes/edc/efl/list.edc new file mode 100644 index 0000000000..2707924020 --- /dev/null +++ b/data/elementary/themes/edc/efl/list.edc @@ -0,0 +1,8 @@ +group { "efl/list"; + inherit: "elm/list/base/default"; +} + +group { "efl/list/item"; + inherit: "elm/list/item/default"; +} + diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index 4c78215646..17b689f07c 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -210,11 +210,18 @@ elm_legacy_eolian_files = \ lib/elementary/elm_slideshow_item.eo \ lib/elementary/elm_table.eo \ lib/elementary/elm_thumb.eo \ + lib/elementary/efl_ui_list.eo \ + lib/elementary/efl_ui_list_pan.eo \ + lib/elementary/efl_ui_list_model.eo \ + lib/elementary/efl_ui_list_relayout.eo \ + lib/elementary/efl_ui_list_precise_layouter.eo \ + lib/elementary/efl_ui_layout_factory.eo \ $(NULL) elm_eolian_type_files = \ lib/elementary/elm_general.eot \ - lib/elementary/efl_ui.eot + lib/elementary/efl_ui.eot \ + lib/elementary/efl_ui_list_types.eot elm_public_eolian_c = $(elm_public_eolian_files:%.eo=%.eo.c) elm_public_eolian_h = $(elm_public_eolian_files:%.eo=%.eo.h) \ @@ -333,6 +340,8 @@ includesunstable_HEADERS = \ lib/elementary/elm_widget_thumb.h \ lib/elementary/elm_widget_toolbar.h \ lib/elementary/efl_ui_video_private.h \ + lib/elementary/efl_ui_list_private.h \ + lib/elementary/efl_ui_list_segarray.h \ lib/elementary/elm_widget_web.h \ lib/elementary/efl_ui_clock.h \ lib/elementary/elm_code.h \ @@ -733,6 +742,10 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_focus_parent_provider_gen.c \ lib/elementary/efl_ui_focus_util.c \ lib/elementary/elm_widget_item_static_focus.c \ + lib/elementary/efl_ui_list.c \ + lib/elementary/efl_ui_list_precise_layouter.c \ + lib/elementary/efl_ui_list_segarray.c \ + lib/elementary/efl_ui_layout_factory.c \ $(NULL) diff --git a/src/examples/elementary/Makefile.am b/src/examples/elementary/Makefile.am index d1a3767d85..879a38f824 100644 --- a/src/examples/elementary/Makefile.am +++ b/src/examples/elementary/Makefile.am @@ -176,7 +176,14 @@ efl_thread_2.c \ efl_thread_3.c \ efl_thread_4.c \ efl_thread_5.c \ -efl_thread_6.c +efl_thread_6.c \ +efl_thread_win32_1.c \ +efl_thread_win32_2.c \ +efl_thread_win32_3.c \ +efl_thread_win32_4.c \ +efl_ui_list_example_1.c \ +efl_ui_list_example_2.c \ +efl_ui_list_example_3.c if HAVE_CXX11 SRCS += \ @@ -208,7 +215,8 @@ twitter_example_01.edc \ evas3d_map_example.edc \ theme_example.edc \ layout_example.edc \ -codegen_example.edc +codegen_example.edc \ +efl_ui_list_example.edc EDJS = $(EDCS:%.edc=%.edj) @@ -230,13 +238,15 @@ files_DATA += \ layout_example.edj\ codegen_example.edj \ evas3d_map_example.edj \ - twitter_example_01.edj + twitter_example_01.edj \ + efl_ui_list_example.edj CLEANFILES = \ theme_example.edj \ layout_example.edj\ evas3d_map_example.edj \ - twitter_example_01.edj + twitter_example_01.edj \ + efl_ui_list_example.edj clean-local: rm -f *.epb *.cfg *.cfg.bkp @@ -382,7 +392,10 @@ efl_thread_2 \ efl_thread_3 \ efl_thread_4 \ efl_thread_5 \ -efl_thread_6 +efl_thread_6 \ +efl_ui_list_example_1 \ +efl_ui_list_example_2 \ +efl_ui_list_example_3 #benchmark3d #sphere-hunter @@ -594,7 +607,7 @@ screenshots: examples convert $(HTML_SS_DIR)/$${SS_FILE} $(LATEX_SS_DIR)/$${SS_FILE/.png/.eps} ; \ done -EXTRA_DIST = dict.txt layout_example.edc theme_example.edc codegen_example.edc evas3d_map_example.edc twitter_example_01.edc performance/layout.edc performance/background.png performance/target_texture.png sphere_hunter/sphere_hunter.edc sphere_hunter/score.jpg sphere_hunter/EFL_victory.png sphere_hunter/EFL_defeat.png codegen_example_generated.c codegen_example_generated.h codegen_example.edj prefs_example_01.epc prefs_example_02.epc prefs_example_03.epc prefs_example_03.edc +EXTRA_DIST = dict.txt layout_example.edc theme_example.edc codegen_example.edc evas3d_map_example.edc twitter_example_01.edc efl_ui_list_example.edc performance/layout.edc performance/background.png performance/target_texture.png sphere_hunter/sphere_hunter.edc sphere_hunter/score.jpg sphere_hunter/EFL_victory.png sphere_hunter/EFL_defeat.png codegen_example_generated.c codegen_example_generated.h codegen_example.edj prefs_example_01.epc prefs_example_02.epc prefs_example_03.epc prefs_example_03.edc examples: $(examples_PROGRAMS) $(EDJS) diff --git a/src/examples/elementary/efl_ui_list_example.edc b/src/examples/elementary/efl_ui_list_example.edc new file mode 100644 index 0000000000..3b46863b71 --- /dev/null +++ b/src/examples/elementary/efl_ui_list_example.edc @@ -0,0 +1,280 @@ + +#define FN_COL_DEFAULT 255 255 255 255; color3: 0 0 0 128 +#define FN_COL_DISABLE 21 21 21 255; color3: 255 255 255 25; +#define FN_COL_HIGHLIGHT 51 153 255 255; color2: 51 153 255 24; color3: 51 153 255 18 +#define FIXED_SIZE(_WIDTH, _HEIGHT) \ + min: _WIDTH _HEIGHT; max: _WIDTH _HEIGHT; fixed: 1 1; + + +collections { + +group { + name: "elm/list/item/custom"; + alias: "elm/list/item/default"; + data.item: "selectraise" "on"; + data.item: "focusraise" "on"; + parts { + part { name: "event"; type: RECT; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "disabled" 0.0; + inherit: "default" 0.0; + visible: 0; + } + } + part { name: "base"; type: RECT; mouse_events: 0; + description { state: "default" 0.0; + color: 46 46 56 255; + color_class: "list_item_base_odd"; + } + description { state: "odd" 0.0; + color: 56 56 56 255; + color_class: "list_item_base_odd"; + } + } + program { + signal: "elm,state,odd"; source: "elm"; + action: STATE_SET "odd" 1.0; + target: "base"; + } + program { + signal: "elm,state,even"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "base"; + } + part { name: "sel_shadow"; mouse_events: 0; + description { state: "default" 0.0; + visible: 0; + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "sel_base"; mouse_events: 0; + description { state: "default" 0.0; + fill.smooth: 0; + visible: 0; + fill { size { relative: 0.0 1.0; offset: 120 0; } } + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "sel_bevel"; mouse_events: 0; + description { state: "default" 0.0; + fill.smooth: 0; + visible: 0; + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + program { + signal: "elm,state,selected"; source: "elm"; + action: STATE_SET "selected" 0.0; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + } + program { + signal: "elm,state,unselected"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + } + program { + signal: "elm,state,disabled"; source: "elm"; + action: STATE_SET "disabled" 0.0; + target: "event"; + } + program { + signal: "elm,state,enabled"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "event"; + } + + //##// + part { name: "elm.text"; type: TEXT; mouse_events: 0; + effect: SHADOW BOTTOM; + scale: 1; + description { state: "default" 0.0; + rel1.offset: 2 3; + rel1.relative: 1.0 0.0; + rel1.to_x: "elm.swallow.icon"; + rel2.offset: -3 -3; + rel2.relative: 0.0 1.0; + rel2.to_x: "elm.swallow.end"; + color: FN_COL_DEFAULT; + color_class: "list_item"; + text { font: FN; size: 10; + min: 1 1; + ellipsis: -1; + align: 0.0 0.5; + text_class: "list_item"; + } + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 0; + } + description { state: "disabled" 0.0; + inherit: "default" 0.0; + visible: 0; + } + } + part { name: "label2"; type: TEXT; mouse_events: 0; + effect: SHADOW BOTTOM; + scale: 1; + description { state: "default" 0.0; + rel1.to: "elm.text"; + rel2.to: "elm.text"; + color: FN_COL_DISABLE; + color_class: "list_item_disabled"; + text { font: FN; size: 10; + text_source: "elm.text"; + align: 0.0 0.5; + text_class: "list_item"; + } + visible: 0; + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 0; + } + description { state: "disabled" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "label3"; type: TEXT; mouse_events: 0; + effect: GLOW; + scale: 1; + description { state: "default" 0.0; + rel1.offset: -2 -3; + rel1.to: "elm.text"; + rel2.offset: 1 1; + rel2.to: "elm.text"; + color: FN_COL_HIGHLIGHT; + color_class: "list_item_selected"; + text { font: FN; size: 10; + text_source: "elm.text"; + align: 0.0 0.5; + text_class: "list_item"; + } + visible: 0; + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + } + description { state: "disabled" 0.0; + inherit: "default" 0.0; + visible: 0; + } + } + program { + signal: "elm,state,selected"; source: "elm"; + action: STATE_SET "selected" 0.0; + target: "elm.text"; + target: "label2"; + target: "label3"; + } + program { + signal: "elm,state,unselected"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "elm.text"; + target: "label2"; + target: "label3"; + } + program { + signal: "elm,state,disabled"; source: "elm"; + action: STATE_SET "disabled" 0.0; + target: "elm.text"; + target: "label2"; + target: "label3"; + } + program { + signal: "elm,state,enabled"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "elm.text"; + target: "label2"; + target: "label3"; + } + //##// + part { name: "elm.swallow.icon"; type: SWALLOW; + description { state: "default" 0.0; + fixed: 1 0; + align: 0.0 0.5; + aspect: 1.0 1.0; + rel1.offset: 2 2; + rel2.relative: 0.0 1.0; + rel2.offset: 2 -3; + } + } + part { name: "elm.swallow.end"; type: SWALLOW; + description { state: "default" 0.0; + fixed: 1 0; + align: 1.0 0.5; + aspect: 1.0 1.0; + rel1.offset: -3 2; + rel1.relative: 1.0 0.0; + rel2.offset: -3 -3; + } + } + //##// + + part { name: "sel_shine"; mouse_events: 0; + description { state: "default" 0.0; + rel1.offset: 0 -2; + rel1.to: "sel_base"; + rel2.relative: 1.0 0.0; + rel2.offset: -1 2; + rel2.to: "sel_base"; + visible: 0; + FIXED_SIZE(69, 5) + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + part { name: "event_block"; type: RECT; + description { state: "default" 0.0; + color: 0 0 0 0; + visible: 0; + } + description { state: "disabled" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + program { + signal: "elm,state,selected"; source: "elm"; + action: STATE_SET "selected" 0.0; + target: "sel_shine"; + } + program { + signal: "elm,state,unselected"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "sel_shine"; + } + program { + signal: "elm,state,disabled"; source: "elm"; + action: STATE_SET "disabled" 0.0; + target: "event_block"; + } + program { + signal: "elm,state,enabled"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "event_block"; + } + } +} + +} + diff --git a/src/examples/elementary/efl_ui_list_example_1.c b/src/examples/elementary/efl_ui_list_example_1.c new file mode 100644 index 0000000000..488dca0dfb --- /dev/null +++ b/src/examples/elementary/efl_ui_list_example_1.c @@ -0,0 +1,111 @@ +// gcc -o efl_ui_list_example_1 efl_ui_list_example_1.c `pkg-config --cflags --libs elementary` + +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#else +# define EFL_BETA_API_SUPPORT 1 +# define EFL_EO_API_SUPPORT 1 +#endif + +#include +#include +#include +#include + +#define NUM_ITEMS 400 + +const char *styles[] = { + "odd", + "even" + }; + +char edj_path[PATH_MAX]; + +static void +_realized_cb(void *data, const Efl_Event *event) +{ + Efl_Ui_List_Item_Event *ie = event->info; + if (!ie->layout) return; + + Efl_Ui_Layout *layout = ie->layout; + elm_object_focus_allow_set(layout, EINA_TRUE); +} + +/* +static void +_unrealized_cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + Efl_Ui_List_Item_Event *ie = event->info; + + efl_ui_view_model_set(ie->layout, NULL); + efl_del(ie->layout); +} +*/ +static Efl_Model* +_make_model() +{ + Eina_Value vtext, vstyle; + Efl_Model_Item *model, *child; + unsigned int i, s; + char buf[256]; + + model = efl_add(EFL_MODEL_ITEM_CLASS, NULL); + eina_value_setup(&vtext, EINA_VALUE_TYPE_STRING); + + for (i = 0; i < (NUM_ITEMS); i++) + { + s = i%2; + child = efl_model_child_add(model); + eina_value_set(&vtext, styles[s]); + efl_model_property_set(child, "odd_style", &vtext); + + snprintf(buf, sizeof(buf), "Item # %i", i); + eina_value_set(&vtext, buf); + efl_model_property_set(child, "name", &vtext); + } + + eina_value_flush(&vtext); + return model; +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Efl_Ui_Layout_Factory *factory; + Evas_Object *win, *li, *bx, *vbx; + Eo *model; + + win = elm_win_util_standard_add("viewlist", "Viewlist"); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + + elm_win_autodel_set(win, EINA_TRUE); + + model = _make_model(); + + factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win); + efl_ui_model_connect(factory, "signal/elm,state,%v", "odd_style"); + efl_ui_model_connect(factory, "elm.text", "name"); + efl_ui_layout_factory_theme_config(factory, "list", "item", "default"); + + li = efl_add(EFL_UI_LIST_CLASS, win); + efl_ui_list_layout_factory_set(li, factory); + efl_ui_view_model_set(li, model); + elm_box_pack_end(bx, li); + + efl_event_callback_add(li, EFL_UI_LIST_EVENT_ITEM_REALIZED, _realized_cb, NULL); +// efl_event_callback_add(li, EFL_UI_LIST_EVENT_ITEM_UNREALIZED, _unrealized_cb, NULL); + + elm_win_resize_object_add(win, li); + evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL); + + //showall + evas_object_show(li); + evas_object_resize(win, 320, 320); + evas_object_show(win); + + elm_run(); + + return 0; +} +ELM_MAIN() diff --git a/src/examples/elementary/efl_ui_list_example_2.c b/src/examples/elementary/efl_ui_list_example_2.c new file mode 100644 index 0000000000..9f37e322e5 --- /dev/null +++ b/src/examples/elementary/efl_ui_list_example_2.c @@ -0,0 +1,74 @@ +// gcc -o efl_ui_list_example_2 efl_ui_list_example_2.c `pkg-config --cflags --libs elementary` + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define EFL_BETA_API_SUPPORT 1 +# define EFL_EO_API_SUPPORT 1 +#endif + +#include +#include +#include +#include + +#define EFL_MODEL_TEST_FILENAME_PATH "/tmp" + +static void +_realized_cb(void *data, const Efl_Event *event) +{ + Efl_Ui_List_Item_Event *ie = event->info; + Eo *imf = data; + printf("realize %d\n", ie->index); + + evas_object_size_hint_weight_set(ie->layout, EVAS_HINT_EXPAND, 0); + evas_object_size_hint_align_set(ie->layout, EVAS_HINT_FILL, EVAS_HINT_FILL); + + efl_ui_model_factory_connect(ie->layout, "elm.swallow.icon", imf); +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Efl_Ui_Layout_Factory *factory; + Evas_Object *win; + Eo *imf, *model, *li; + char *dirname; + + win = elm_win_util_standard_add("viewlist", "Viewlist"); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + + elm_win_autodel_set(win, EINA_TRUE); + + if (argv[1] != NULL) dirname = argv[1]; + else dirname = EFL_MODEL_TEST_FILENAME_PATH; + + model = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, dirname)); + factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win); + efl_ui_model_connect(factory, "elm.text", "filename"); + efl_ui_layout_factory_theme_config(factory, "list", "item", "default"); + + li = efl_add(EFL_UI_LIST_CLASS, win); + efl_ui_list_layout_factory_set(li, factory); + efl_ui_view_model_set(li, model); + + evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL); + + + imf = efl_add(EFL_UI_IMAGE_FACTORY_CLASS, win); + efl_ui_model_connect(imf, "", "path"); //connect to "path" property + efl_event_callback_add(li, EFL_UI_LIST_EVENT_ITEM_REALIZED, _realized_cb, imf); + + elm_win_resize_object_add(win, li); + + //showall + evas_object_show(li); + evas_object_resize(win, 320, 320); + evas_object_show(win); + + elm_run(); + + return 0; +} +ELM_MAIN() diff --git a/src/examples/elementary/efl_ui_list_example_3.c b/src/examples/elementary/efl_ui_list_example_3.c new file mode 100644 index 0000000000..3b35ec3528 --- /dev/null +++ b/src/examples/elementary/efl_ui_list_example_3.c @@ -0,0 +1,329 @@ +// gcc -o efl_ui_list_example_3 efl_ui_list_example_3.c `pkg-config --cflags --libs elementary` + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define EFL_BETA_API_SUPPORT 1 +# define EFL_EO_API_SUPPORT 1 +#endif + +#define ELM_INTERFACE_ATSPI_SELECTION_PROTECTED + +#include +#include +#include +#include +#include + +const char *subtexts[] = { + "Captain", + "Princess ", + "Actor", + "Translator", + "Jedi", + "Singer", + "Fighter" + }; + +const char *texts[] = { + "Morpheus", + "Leia", + "Chuck Norris", + "Nyota Uhura", + "Darth Vader", + "Elvis Presley", + "Chun-Li" + }; + +char edj_path[PATH_MAX]; + +struct _Priv_Data +{ + Eo *model; + Evas_Object *list1; + Evas_Object *list2; + Evas_Object *e_name; + Evas_Object *e_occ; + Evas_Object *selected; +}; +typedef struct _Priv_Data Priv_Data; + +static void +_cleanup_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Priv_Data *priv = (Priv_Data*)data; + efl_unref(priv->model); +} + +static void +_focused(void *data, const Efl_Event *event) +{ + Priv_Data *priv = (Priv_Data*)data; + priv->selected = efl_ui_focus_manager_focus_get(event->object); +} + +static void +_bt_add_clicked(void *data, Evas_Object *obj, void *event_info) +{ + Priv_Data *priv = (Priv_Data*)data; + Eina_Value vtext, value; + Efl_Model_Item *child; + + eina_value_setup(&vtext, EINA_VALUE_TYPE_STRING); + eina_value_setup(&value, EINA_VALUE_TYPE_UCHAR); + child = efl_model_child_add(priv->model); + + eina_value_set(&vtext, elm_object_text_get(priv->e_name)); + efl_model_property_set(child, "name", &vtext); + + eina_value_set(&vtext, elm_object_text_get(priv->e_occ)); + efl_model_property_set(child, "occupation", &vtext); + + eina_value_set(&value, EINA_FALSE); + efl_model_property_set(child, "selected", &vtext); + + eina_value_flush(&vtext); + eina_value_flush(&value); +} + +static void +_bt_del_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Priv_Data *priv = (Priv_Data*)data; + Eo *child = NULL; + + //l = efl_ui_focus_manager_focus_get(priv->list1); + if(priv->selected) + { + printf("focused %p\n", priv->selected); + child = efl_ui_view_model_get(priv->selected); + efl_model_child_del(priv->model, child); + priv->selected = NULL; + } + else + { + printf("no focused\n"); + } +} + +static void +_bt_none_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Evas_Object *li = data; + efl_ui_list_select_mode_set(li, ELM_OBJECT_SELECT_MODE_NONE); +} + +static void +_bt_donly_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Evas_Object *li = data; + efl_ui_list_select_mode_set(li, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY); +} + +static void +_bt_default_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Evas_Object *li = data; + efl_ui_list_select_mode_set(li, ELM_OBJECT_SELECT_MODE_DEFAULT); +} + +static void +_bt_set_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Priv_Data *priv = data; + efl_ui_view_model_set(priv->list2, priv->model); +} + +static void +_bt_unset_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Evas_Object *li = data; + efl_ui_view_model_set(li, NULL); +} +static void +_realized_1_cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + Efl_Ui_List_Item_Event *ie = event->info; + + evas_object_size_hint_weight_set(ie->layout, EVAS_HINT_EXPAND, 0); + evas_object_size_hint_align_set(ie->layout, EVAS_HINT_FILL, EVAS_HINT_FILL); + efl_ui_model_connect(ie->layout, "elm.text", "name"); + efl_ui_model_connect(ie->layout, "signal/elm,state,%v", "odd_style"); +} + +static void +_realized_2_cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + Efl_Ui_List_Item_Event *ie = event->info; + printf("relized 2\n"); + + elm_object_focus_allow_set(ie->layout, EINA_TRUE); + evas_object_size_hint_weight_set(ie->layout, EVAS_HINT_EXPAND, 0); + evas_object_size_hint_align_set(ie->layout, EVAS_HINT_FILL, EVAS_HINT_FILL); + efl_ui_model_connect(ie->layout, "elm.text", "occupation"); +} + +static Efl_Model* +_make_model() +{ + Eina_Value vtext, value; + Efl_Model_Item *model, *child; + unsigned int i, len; + + model = efl_add(EFL_MODEL_ITEM_CLASS, NULL); + eina_value_setup(&vtext, EINA_VALUE_TYPE_STRING); + eina_value_setup(&value, EINA_VALUE_TYPE_UCHAR); + + len = sizeof(texts)/sizeof(const char*); + for (i = 0; i < (len); i++) + { + child = efl_model_child_add(model); + + i%2 ? eina_value_set(&vtext, "even") : eina_value_set(&vtext, "odd"); + efl_model_property_set(child, "odd_style", &vtext); + + eina_value_set(&vtext, texts[(i % len)]); + efl_model_property_set(child, "name", &vtext); + + eina_value_set(&vtext, subtexts[(i % len)]); + efl_model_property_set(child, "occupation", &vtext); + + eina_value_set(&value, EINA_FALSE); + efl_model_property_set(child, "selected", &value); + } + + eina_value_flush(&vtext); + eina_value_flush(&value); + return model; +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Priv_Data *priv; + Evas_Object *win, *bx, *vbx, *bt; + Efl_Ui_Layout_Factory *factory; + + priv = alloca(sizeof(Priv_Data)); + memset(priv, 0, sizeof(Priv_Data)); + + win = elm_win_util_standard_add("viewlist", "Viewlist"); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + elm_win_autodel_set(win, EINA_TRUE); + + bx = elm_box_add(win); + elm_box_horizontal_set(bx, EINA_TRUE); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bx); + evas_object_show(bx); + + priv->model = _make_model(); + factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win); + efl_ui_model_connect(factory, "elm.text", "filename"); + efl_ui_layout_factory_theme_config(factory, "list", "item", "default"); + + priv->list1 = efl_add(EFL_UI_LIST_CLASS, win, efl_ui_view_model_set(efl_added, priv->model)); + efl_event_callback_add(priv->list1, EFL_UI_LIST_EVENT_ITEM_REALIZED, _realized_1_cb, priv); + evas_object_size_hint_weight_set(priv->list1, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(priv->list1, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bx, priv->list1); + efl_ui_list_layout_factory_set(priv->list1, factory); + + factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win); + efl_ui_model_connect(factory, "elm.text", "filename"); + efl_ui_model_connect(factory, "signal/elm,state,%v", "selected"); + efl_ui_layout_factory_theme_config(factory, "list", "item", "default"); + priv->list2 = efl_add(EFL_UI_LIST_CLASS, win, efl_ui_view_model_set(efl_added, priv->model)); + efl_event_callback_add(priv->list2, EFL_UI_LIST_EVENT_ITEM_REALIZED, _realized_2_cb, priv->list2); + evas_object_size_hint_weight_set(priv->list2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(priv->list2, EVAS_HINT_FILL, EVAS_HINT_FILL); + efl_ui_list_layout_factory_set(priv->list2, factory); + + vbx = elm_box_add(win); + elm_box_pack_end(bx, vbx); + + bt = elm_label_add(win); + elm_object_text_set(bt, "Name:"); + elm_box_pack_end(vbx, bt); + evas_object_show(bt); + + priv->e_name = elm_entry_add(win); + elm_box_pack_end(vbx, priv->e_name); + elm_object_text_set(priv->e_name, "Neo"); + evas_object_size_hint_weight_set(priv->e_name, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(priv->e_name, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(priv->e_name); + + bt = elm_label_add(win); + elm_object_text_set(bt, "Occupation:"); + elm_box_pack_end(vbx, bt); + evas_object_show(bt); + + priv->e_occ = elm_entry_add(win); + elm_box_pack_end(vbx, priv->e_occ); + elm_object_text_set(priv->e_occ, "Chosen"); + evas_object_size_hint_weight_set(priv->e_occ, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(priv->e_occ, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(priv->e_occ); + + bt = elm_button_add(win); + elm_object_text_set(bt, "Add Item"); + evas_object_smart_callback_add(bt, "clicked", _bt_add_clicked, priv); + evas_object_show(bt); + elm_box_pack_end(vbx, bt); + + bt = elm_button_add(win); + elm_object_text_set(bt, "Delete Item"); + evas_object_smart_callback_add(bt, "clicked", _bt_del_clicked, priv); + evas_object_show(bt); + elm_box_pack_end(vbx, bt); + + bt = elm_button_add(win); + elm_object_text_set(bt, "Select None"); + evas_object_smart_callback_add(bt, "clicked", _bt_none_clicked, priv->list2); + evas_object_show(bt); + elm_box_pack_end(vbx, bt); + + bt = elm_button_add(win); + elm_object_text_set(bt, "Select DisplayOnly"); + evas_object_smart_callback_add(bt, "clicked", _bt_donly_clicked, priv->list2); + evas_object_show(bt); + elm_box_pack_end(vbx, bt); + + bt = elm_button_add(win); + elm_object_text_set(bt, "Select Default"); + evas_object_smart_callback_add(bt, "clicked", _bt_default_clicked, priv->list2); + evas_object_show(bt); + elm_box_pack_end(vbx, bt); + + bt = elm_button_add(win); + elm_object_text_set(bt, "Model Set"); + evas_object_smart_callback_add(bt, "clicked", _bt_set_clicked, priv); + evas_object_show(bt); + elm_box_pack_end(vbx, bt); + + + bt = elm_button_add(win); + elm_object_text_set(bt, "Model Unset"); + evas_object_smart_callback_add(bt, "clicked", _bt_unset_clicked, priv->list2); + evas_object_show(bt); + elm_box_pack_end(vbx, bt); + + elm_box_pack_end(bx, priv->list2); + efl_event_callback_add(priv->list2, EFL_UI_FOCUS_MANAGER_EVENT_FOCUSED, _focused ,priv); + + evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _cleanup_cb, priv); + + //showall + evas_object_show(priv->list1); + evas_object_show(priv->list2); + evas_object_show(bx); + evas_object_show(vbx); + evas_object_resize(win, 400, 320); + evas_object_show(win); + + elm_run(); + + return 0; +} +ELM_MAIN() diff --git a/src/examples/elementary/layout_model_connect.c b/src/examples/elementary/layout_model_connect.c index b856692246..aa34478f08 100644 --- a/src/examples/elementary/layout_model_connect.c +++ b/src/examples/elementary/layout_model_connect.c @@ -127,7 +127,6 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) elm_object_part_content_set(panes, "right", bxr); /*Label widget */ - _label_init(win, bxr, "FILENAME:"); priv->label = _label_init(win, bxr, ""); efl_ui_model_connect(priv->label, "default", "path"); //connect "default" to "filename" property diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index 66b3c8fd14..c1422ae838 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -280,6 +280,7 @@ EAPI extern Elm_Version *elm_version; #include #ifdef EFL_EO_API_SUPPORT +#include "efl_ui_list_segarray.h" # include # include # include @@ -312,6 +313,13 @@ EAPI extern Elm_Version *elm_version; # include # include # include +# include +# include +# include +# include +# include +# include +# include #endif /* include deprecated calls last of all */ diff --git a/src/lib/elementary/efl_ui_layout.c b/src/lib/elementary/efl_ui_layout.c index 24fb83fd6c..5981fc1a54 100644 --- a/src/lib/elementary/efl_ui_layout.c +++ b/src/lib/elementary/efl_ui_layout.c @@ -1849,6 +1849,7 @@ _prop_future_then_cb(void* data, Efl_Event const*event) Efl_Ui_Layout_Sub_Connect *sc = data; const Eina_Value_Type *vtype; Eina_Value *value = (Eina_Value *)((Efl_Future_Event_Success*)event->info)->value; + Eina_Stringshare *selected; char *text; sc->future = NULL; @@ -1858,6 +1859,18 @@ _prop_future_then_cb(void* data, Efl_Event const*event) { eina_value_get(value, &text); _view_update(sc, text); + return; + } + + selected = eina_stringshare_add("selected"); + if (vtype == EINA_VALUE_TYPE_UCHAR && sc->property == selected) + { + Eina_Bool sb = EINA_FALSE; + eina_value_get(value, &sb); + if (sb) + _view_update(sc, "selected"); + else + _view_update(sc, "unselected"); } else { @@ -1865,6 +1878,8 @@ _prop_future_then_cb(void* data, Efl_Event const*event) _view_update(sc, text); free(text); } + + eina_stringshare_del(selected); } static void @@ -1904,6 +1919,7 @@ _efl_model_properties_changed_cb(void *data, const Efl_Event *event) { if (sc->property == ss_prop) { + if (sc->future) efl_future_cancel(sc->future); sc->future = efl_model_property_get(pd->model, sc->property); efl_future_then(sc->future, &_prop_future_then_cb, &_prop_future_error_cb, NULL, sc); } @@ -1915,9 +1931,15 @@ _efl_model_properties_changed_cb(void *data, const Efl_Event *event) EOLIAN static void _efl_ui_layout_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *pd, Efl_Model *model) { + Efl_Ui_Layout_Sub_Connect *sc; + Eina_List *l; + if (pd->model) { efl_event_callback_del(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, pd); + EINA_LIST_FOREACH(pd->prop_connect, l, sc) + if (sc->future) efl_future_cancel(sc->future); + efl_unref(pd->model); pd->model = NULL; } @@ -1929,7 +1951,15 @@ _efl_ui_layout_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Data *pd efl_event_callback_add(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, pd); } else - return; + { + EINA_LIST_FOREACH(pd->prop_connect, l, sc) + { + if (!sc->is_signal) + elm_layout_text_set(obj, sc->name, NULL); + } + + return; + } if (pd->prop_connect) _efl_ui_layout_view_model_update(pd); diff --git a/src/lib/elementary/efl_ui_layout_factory.c b/src/lib/elementary/efl_ui_layout_factory.c new file mode 100644 index 0000000000..6fe150dc3d --- /dev/null +++ b/src/lib/elementary/efl_ui_layout_factory.c @@ -0,0 +1,127 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include +#include "elm_priv.h" + +#define MY_CLASS EFL_UI_LAYOUT_FACTORY_CLASS +#define MY_CLASS_NAME "Efl.Ui.Layout_Factory" + +typedef struct _Efl_Ui_Layout_Factory_Data +{ + Eina_Array *layouts; + Eina_Hash *connects; + Eina_Stringshare *klass; + Eina_Stringshare *group; + Eina_Stringshare *style; +} Efl_Ui_Layout_Factory_Data; + +Eina_Bool +_model_connect(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata) +{ + Eo *layout = fdata; + Eina_Stringshare *name = key; + Eina_Stringshare *property = data; + + efl_ui_model_connect(layout, name, property); + + return EINA_TRUE; +} + +EOLIAN static Eo * +_efl_ui_layout_factory_efl_object_constructor(Eo *obj, Efl_Ui_Layout_Factory_Data *pd) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + + pd->klass = NULL; + pd->group = NULL; + pd->style = NULL; + pd->layouts = eina_array_new(8); + pd->connects = eina_hash_stringshared_new(EINA_FREE_CB(eina_stringshare_del)); + + return obj; +} + +EOLIAN static void +_efl_ui_layout_factory_efl_object_destructor(Eo *obj, Efl_Ui_Layout_Factory_Data *pd) +{ + Eina_Array_Iterator iterator; + Eo *layout; + unsigned int i; + + eina_stringshare_del(pd->klass); + eina_stringshare_del(pd->group); + eina_stringshare_del(pd->style); + + EINA_ARRAY_ITER_NEXT(pd->layouts, i, layout, iterator) + efl_parent_set(layout, NULL); + + eina_array_free(pd->layouts); + eina_hash_free(pd->connects); + + efl_destructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static Efl_Gfx * +_efl_ui_layout_factory_efl_ui_factory_create(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Factory_Data *pd + , Efl_Model *model, Efl_Gfx *parent) +{ + Efl_Gfx *layout; + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); +/* + if (eina_array_count(pd->layouts)) + { + layout = eina_array_pop(pd->layouts); + efl_parent_set(layout, parent); + efl_ui_view_model_set(layout, model); + } + else */ + { + layout = efl_add(EFL_UI_LAYOUT_CLASS, parent, + efl_ui_view_model_set(efl_added, model), + elm_layout_theme_set(efl_added, pd->klass, pd->group, pd->style)); + + eina_hash_foreach(pd->connects, _model_connect, layout); + + evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, 0); + evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL); + } + + return layout; +} + +EOLIAN static void +_efl_ui_layout_factory_efl_ui_factory_release(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Factory_Data *pd EINA_UNUSED, Efl_Gfx *layout) +{ + efl_ui_view_model_set(layout, NULL); + efl_del(layout); +} + +EOLIAN static void +_efl_ui_layout_factory_efl_ui_model_connect_connect(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Factory_Data *pd + , const char *name, const char *property) +{ + Eina_Stringshare *ss_name, *ss_prop; + ss_name = eina_stringshare_add(name); + + if (property == NULL) + { + eina_hash_del(pd->connects, ss_name, NULL); + return; + } + + ss_prop = eina_stringshare_add(property); + eina_stringshare_del(eina_hash_set(pd->connects, ss_name, ss_prop)); +} + +EOLIAN static void +_efl_ui_layout_factory_theme_config(Eo *obj EINA_UNUSED, Efl_Ui_Layout_Factory_Data *pd + , const char *klass, const char *group, const char *style) +{ + eina_stringshare_replace(&pd->klass, klass); + eina_stringshare_replace(&pd->group, group); + eina_stringshare_replace(&pd->style, style); +} + +#include "efl_ui_layout_factory.eo.c" diff --git a/src/lib/elementary/efl_ui_layout_factory.eo b/src/lib/elementary/efl_ui_layout_factory.eo new file mode 100644 index 0000000000..e712900d1c --- /dev/null +++ b/src/lib/elementary/efl_ui_layout_factory.eo @@ -0,0 +1,22 @@ +class Efl.Ui.Layout_Factory (Efl.Object, Efl.Ui.Factory) +{ + [[Efl Ui Layout Factory class]] + methods { + theme_config { + [[]] + params { + klass: string; [[The class of the group.]] + group: string; [[The group.]] + style: string; [[The style to used.]] + } + } + } + + implements { + Efl.Object.constructor; + Efl.Object.destructor; + Efl.Ui.Factory.create; + Efl.Ui.Factory.release; + Efl.Ui.Model.Connect.connect; + } +} diff --git a/src/lib/elementary/efl_ui_list.c b/src/lib/elementary/efl_ui_list.c new file mode 100644 index 0000000000..4a70ab5bf4 --- /dev/null +++ b/src/lib/elementary/efl_ui_list.c @@ -0,0 +1,668 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif +#define ELM_ACCESS_PROTECTED +#define ELM_ACCESS_WIDGET_ACTION_PROTECTED +#define EFL_ACCESS_SELECTION_PROTECTED + +#include +#include "efl_ui_list_private.h" +#include "efl_ui_list_precise_layouter.eo.h" + +#include + +#define MY_CLASS EFL_UI_LIST_CLASS +#define MY_CLASS_NAME "Efl.Ui.List" + +#define MY_PAN_CLASS EFL_UI_LIST_PAN_CLASS + +#define SIG_CHILD_ADDED "child,added" +#define SIG_CHILD_REMOVED "child,removed" +#define SELECTED_PROP "selected" + +static const Evas_Smart_Cb_Description _smart_callbacks[] = { + {SIG_CHILD_ADDED, ""}, + {SIG_CHILD_REMOVED, ""}, + {NULL, NULL} +}; + +void _efl_ui_list_custom_layout(Efl_Ui_List *); +void _efl_ui_list_item_select_set(Efl_Ui_List_LayoutItem*, Eina_Bool); +static void _layout(Efl_Ui_List_Data* pd); + +static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); +static Eina_Bool _key_action_select(Evas_Object *obj, const char *params); +static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params); + +static const Elm_Action key_actions[] = { + {"move", _key_action_move}, + {"select", _key_action_select}, + {"escape", _key_action_escape}, + {NULL, NULL} +}; + +EOLIAN static void +_efl_ui_list_pan_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Efl_Ui_List_Pan_Data *psd) +{ + evas_object_smart_changed(psd->wobj); +} + + +EOLIAN static void +_efl_ui_list_pan_elm_pan_pos_set(Eo *obj EINA_UNUSED, Efl_Ui_List_Pan_Data *psd, Evas_Coord x, Evas_Coord y) +{ + if ((x == psd->x) && (y == psd->y)) return; + + psd->x = x; + psd->y = y; + + evas_object_smart_changed(psd->wobj); +} + +EOLIAN static void +_efl_ui_list_pan_elm_pan_pos_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y) +{ + if (x) *x = psd->x; + if (y) *y = psd->y; +} + +EOLIAN static void +_efl_ui_list_pan_elm_pan_pos_max_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y) +{ + Evas_Coord ow, oh; + Eina_Size2D min; + + elm_interface_scrollable_content_viewport_geometry_get + (psd->wobj, NULL, NULL, &ow, &oh); + + min = efl_ui_list_model_min_size_get(psd->wobj); + ow = min.w - ow; + if (ow < 0) ow = 0; + oh = min.h - oh; + if (oh < 0) oh = 0; + + if (x) *x = ow; + if (y) *y = oh; +} + +EOLIAN static void +_efl_ui_list_pan_elm_pan_pos_min_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Pan_Data *psd EINA_UNUSED, Evas_Coord *x, Evas_Coord *y) +{ + if (x) *x = 0; + if (y) *y = 0; +} + +EOLIAN static void +_efl_ui_list_pan_elm_pan_content_size_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Pan_Data *psd, Evas_Coord *w, Evas_Coord *h) +{ + Eina_Size2D min; + min = efl_ui_list_model_min_size_get(psd->wobj); + + if (w) *w = min.w; + if (h) *h = min.h; +} + +EOLIAN static void +_efl_ui_list_pan_efl_object_destructor(Eo *obj, Efl_Ui_List_Pan_Data *psd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_PAN_CLASS)); +} + +#include "efl_ui_list_pan.eo.c" + +static Eina_Bool +_efl_model_properties_has(Efl_Model *model, Eina_Stringshare *propfind) +{ + const Eina_Array *properties; + Eina_Array_Iterator iter_prop; + Eina_Stringshare *property; + Eina_Bool ret = EINA_FALSE; + unsigned i = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(model, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(propfind, EINA_FALSE); + + properties = efl_model_properties_get(model); + + EINA_ARRAY_ITER_NEXT(properties, i, property, iter_prop) + { + if (property == propfind) + { + ret = EINA_TRUE; + break; + } + } + return ret; +} + +static void +_on_item_mouse_up(void *data, Evas *evas EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info) +{ + Evas_Event_Mouse_Down *ev = event_info; + Efl_Ui_List_LayoutItem *item = data; + + if (ev->button != 1) return; + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; + + _efl_ui_list_item_select_set(item, EINA_TRUE); +} + +static void +_count_then(void * data, Efl_Event const* event EINA_UNUSED) +{ + Efl_Ui_List_Data *pd = data; + EINA_SAFETY_ON_NULL_RETURN(pd); + + pd->count_future = NULL; + _layout(pd); +} + +static void +_count_error(void * data, Efl_Event const* event EINA_UNUSED) +{ + Efl_Ui_List_Data *pd = data; + EINA_SAFETY_ON_NULL_RETURN(pd); + pd->count_future = NULL; +} + +static void +_children_slice_error(void * data EINA_UNUSED, Efl_Event const* event EINA_UNUSED) +{ + Efl_Ui_List_Data *pd = data; + EINA_SAFETY_ON_NULL_RETURN(pd); + pd->slice_future = NULL; +} + +static void +_show_region_hook(void *data EINA_UNUSED, Evas_Object *obj, Eina_Rect r) +{ + elm_interface_scrollable_content_region_show(obj, r.x, r.y, r.w, r.h); +} + +EOLIAN static void +_efl_ui_list_select_mode_set(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, Elm_Object_Select_Mode mode) +{ + if (pd->select_mode == mode) + return; + + pd->select_mode = mode; +} + +EOLIAN static Elm_Object_Select_Mode +_efl_ui_list_select_mode_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->select_mode; +} + +EOLIAN static void +_efl_ui_list_default_style_set(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, Eina_Stringshare *style) +{ + eina_stringshare_replace(&pd->style, style); +} + +EOLIAN static Eina_Stringshare * +_efl_ui_list_default_style_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->style; +} + +EOLIAN static void +_efl_ui_list_homogeneous_set(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, Eina_Bool homogeneous) +{ + pd->homogeneous = homogeneous; +} + +EOLIAN static Eina_Bool +_efl_ui_list_homogeneous_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->homogeneous; +} + +EOLIAN static void +_efl_ui_list_efl_gfx_position_set(Eo *obj, Efl_Ui_List_Data *pd, Eina_Position2D p) +{ + int pan_x, pan_y; + if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, p.x, p.y)) + return; + + efl_gfx_position_set(efl_super(obj, MY_CLASS), p); + + elm_pan_pos_get(pd->pan_obj, &pan_x, &pan_y); + evas_object_move(pd->hit_rect, p.x, p.y); + evas_object_move(pd->pan_obj, p.x - pan_x, p.y - pan_y); + evas_object_smart_changed(pd->obj); +} + +EOLIAN static void +_efl_ui_list_elm_interface_scrollable_region_bring_in(Eo *obj, Efl_Ui_List_Data *pd, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) +{ + int pan_x, pan_y; + elm_pan_pos_get(pd->pan_obj, &pan_x, &pan_y); + elm_interface_scrollable_region_bring_in(efl_super(obj, MY_CLASS), x + pan_x, y + pan_y, w, h); +} + +EOLIAN static void +_efl_ui_list_efl_gfx_size_set(Eo *obj, Efl_Ui_List_Data *pd, Eina_Size2D size) +{ + if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, size.w, size.h)) + return; + + evas_object_resize(pd->hit_rect, size.w, size.h); + efl_gfx_size_set(efl_super(obj, MY_CLASS), size); + + evas_object_smart_changed(pd->obj); +} + +EOLIAN static void +_efl_ui_list_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + _layout(pd); +} + +EOLIAN static void +_efl_ui_list_efl_canvas_group_group_member_add(Eo *obj, Efl_Ui_List_Data *pd, Evas_Object *member) +{ + efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member); + + if (pd->hit_rect) + evas_object_raise(pd->hit_rect); +} + +EOLIAN static void +_efl_ui_list_efl_canvas_group_group_add(Eo *obj, Efl_Ui_List_Data *pd) +{ + Efl_Ui_List_Pan_Data *pan_data; + Evas_Coord minw, minh; + + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + efl_canvas_group_add(efl_super(obj, MY_CLASS)); + elm_widget_sub_object_parent_add(obj); + + elm_widget_can_focus_set(obj, EINA_TRUE); + + if (!elm_layout_theme_set(obj, "list", "base", elm_widget_style_get(obj))) + CRI("Failed to set layout!"); + + pd->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj)); + evas_object_data_set(pd->hit_rect, "_elm_leaveme", obj); + evas_object_smart_member_add(pd->hit_rect, obj); + elm_widget_sub_object_add(obj, pd->hit_rect); + + /* common scroller hit rectangle setup */ + evas_object_color_set(pd->hit_rect, 0, 0, 0, 0); + evas_object_show(pd->hit_rect); + evas_object_repeat_events_set(pd->hit_rect, EINA_TRUE); + + elm_widget_on_show_region_hook_set(obj, NULL, _show_region_hook, NULL); + + elm_interface_scrollable_objects_set(obj, wd->resize_obj, pd->hit_rect); + elm_interface_scrollable_bounce_allow_set + (obj, EINA_FALSE, _elm_config->thumbscroll_bounce_enable); + + pd->mode = ELM_LIST_COMPRESS; + + efl_access_type_set(obj, EFL_ACCESS_TYPE_DISABLED); + pd->pan_obj = efl_add(MY_PAN_CLASS, evas_object_evas_get(obj)); + pan_data = efl_data_scope_get(pd->pan_obj, MY_PAN_CLASS); + pan_data->wobj = obj; + + elm_interface_scrollable_extern_pan_set(obj, pd->pan_obj); + evas_object_show(pd->pan_obj); + + edje_object_size_min_calc(wd->resize_obj, &minw, &minh); + evas_object_size_hint_min_set(obj, minw, minh); + + elm_layout_sizing_eval(obj); +} + +EOLIAN static void +_efl_ui_list_efl_canvas_group_group_del(Eo *obj, Efl_Ui_List_Data *pd) +{ + ELM_SAFE_FREE(pd->pan_obj, evas_object_del); + efl_canvas_group_del(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_efl_ui_list_efl_ui_focus_manager_focus_set(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, Efl_Ui_Focus_Object *focus) +{ + efl_ui_focus_manager_focus_set(pd->manager, focus); +} + +EOLIAN static Efl_Ui_Focus_Manager* +_efl_ui_list_elm_widget_focus_manager_create(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root) +{ + if (!pd->manager) + pd->manager = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj, + efl_ui_focus_manager_root_set(efl_added, root)); + + return pd->manager; +} + +EOLIAN static Eo * +_efl_ui_list_efl_object_finalize(Eo *obj, Efl_Ui_List_Data *pd) +{ + + if (!pd->factory) + pd->factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, NULL); + + if(!pd->relayout) + { + pd->relayout = efl_add(EFL_UI_LIST_PRECISE_LAYOUTER_CLASS, obj); + if (pd->model) + efl_ui_list_relayout_model_set(pd->relayout, pd->model); + } + return obj; +} + +EOLIAN static Eo * +_efl_ui_list_efl_object_constructor(Eo *obj, Efl_Ui_List_Data *pd) +{ + Efl_Ui_Focus_Manager *manager; + + obj = efl_constructor(efl_super(obj, MY_CLASS)); + pd->obj = obj; + efl_canvas_object_type_set(obj, MY_CLASS_NAME); + evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); + efl_access_role_set(obj, EFL_ACCESS_ROLE_LIST); + + efl_ui_list_segarray_setup(&pd->segarray, 32); + + manager = efl_ui_widget_focus_manager_create(obj, obj); + efl_composite_attach(obj, manager); + _efl_ui_focus_manager_redirect_events_add(manager, obj); + + pd->style = eina_stringshare_add(elm_widget_style_get(obj)); + + pd->factory = NULL; + pd->orient = EFL_ORIENT_DOWN; + pd->align.h = 0; + pd->align.v = 0; + pd->min.w = 0; + pd->min.h = 0; + + return obj; +} + +EOLIAN static void +_efl_ui_list_efl_object_destructor(Eo *obj, Efl_Ui_List_Data *pd) +{ + efl_ui_list_relayout_model_set(pd->relayout, NULL); + + efl_unref(pd->model); + eina_stringshare_del(pd->style); + + efl_ui_list_segarray_flush(&pd->segarray); + + efl_destructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_efl_ui_list_layout_factory_set(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, Efl_Ui_Factory *factory) +{ + if (pd->factory) + efl_unref(pd->factory); + + pd->factory = factory; + efl_ref(pd->factory); +} + +EOLIAN static void +_efl_ui_list_efl_ui_view_model_set(Eo *obj, Efl_Ui_List_Data *pd, Efl_Model *model) +{ + if (pd->model == model) + return; + + if (pd->count_future) + { + efl_future_cancel(pd->count_future); + pd->count_future = NULL; + } + + if (pd->model) + { + if (pd->relayout) + efl_ui_list_relayout_model_set(pd->relayout, NULL); + efl_ui_list_segarray_flush(&pd->segarray); + efl_unref(pd->model); + pd->model = NULL; + } + + if (model) + { + pd->model = model; + efl_ref(pd->model); + if (pd->relayout) + efl_ui_list_relayout_model_set(pd->relayout, model); + pd->count_future = efl_model_children_count_get(pd->model); + efl_future_then(pd->count_future, &_count_then, &_count_error, NULL, pd); + } + + evas_object_smart_changed(pd->obj); +} + +EOLIAN static Efl_Model * +_efl_ui_list_efl_ui_view_model_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->model; +} + +EOLIAN int +_efl_ui_list_efl_access_selection_selected_children_count_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return eina_list_count(pd->selected_items); +} + +EOLIAN Eo* +_efl_ui_list_efl_access_selection_selected_child_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, int child_index) +{ + if(child_index < (int) eina_list_count(pd->selected_items)) + { + Efl_Ui_List_Item* items = eina_list_nth(pd->selected_items, child_index); + return items[child_index].item.layout; + } + else + return NULL; +} + +EOLIAN Eina_Bool +_efl_ui_list_efl_access_selection_child_select(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd EINA_UNUSED, int child_index EINA_UNUSED) +{ + return EINA_FALSE; +} + +EOLIAN Eina_Bool +_efl_ui_list_efl_access_selection_selected_child_deselect(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd EINA_UNUSED, int child_index EINA_UNUSED) +{ + return EINA_FALSE; +} + +EOLIAN Eina_Bool +_efl_ui_list_efl_access_selection_is_child_selected(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, int child_index) +{ + return EINA_FALSE; +} + +EOLIAN Eina_Bool +_efl_ui_list_efl_access_selection_all_children_select(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return EINA_TRUE; +} + +EOLIAN Eina_Bool +_efl_ui_list_efl_access_selection_clear(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return EINA_TRUE; +} + +EOLIAN Eina_Bool +_efl_ui_list_efl_access_selection_child_deselect(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd EINA_UNUSED, int child_index EINA_UNUSED) +{ + return EINA_FALSE; +} + +static Eina_Bool +_key_action_move(Evas_Object *obj, const char *params) +{ + return EINA_FALSE; +} + +static Eina_Bool +_key_action_select(Evas_Object *obj, const char *params EINA_UNUSED) +{ + return EINA_FALSE; +} + +static Eina_Bool +_key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED) +{ + efl_ui_focus_manager_reset_history(obj); + return EINA_TRUE; +} + +ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_list, Efl_Ui_List_Data) + +void +_efl_ui_list_item_select_set(Efl_Ui_List_LayoutItem *item, Eina_Bool selected) +{ + Eina_Stringshare *sprop; + assert(item != NULL); + assert(item->children != NULL); + + selected = !!selected; + + sprop = eina_stringshare_add(SELECTED_PROP); + + if (_efl_model_properties_has(item->children, sprop)) + { + Eina_Value v; + eina_value_setup(&v, EINA_VALUE_TYPE_UCHAR); + eina_value_set(&v, selected); + efl_model_property_set(item->children, sprop, &v); + eina_value_flush(&v); + } + eina_stringshare_del(sprop); +} + +static void +_efl_ui_list_relayout_set(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd EINA_UNUSED, Efl_Ui_List_Relayout *object) +{ + if(pd->relayout) + efl_unref(pd->relayout); + + pd->relayout = object; + efl_ref(pd->relayout); +} + +static Efl_Ui_List_Relayout * +_efl_ui_list_relayout_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd EINA_UNUSED) +{ + return pd->relayout; +} + +static void +_layout(Efl_Ui_List_Data *pd) +{ + if (!pd->model) + return; + + efl_ui_list_relayout_layout_do(pd->relayout, pd->obj, pd->segarray_first, &pd->segarray); +} + +static void +_children_slice_then(void * data, Efl_Event const* event) +{ + Efl_Ui_List_Data *pd = data; + Eina_Accessor *acc = (Eina_Accessor*)((Efl_Future_Event_Success*)event->info)->value; + + efl_ui_list_segarray_insert_accessor(&pd->segarray, pd->outstanding_slice.slice_start, acc); + + pd->segarray_first = pd->outstanding_slice.slice_start; + pd->outstanding_slice.slice_start = pd->outstanding_slice.slice_count = 0; + pd->slice_future = NULL; +} + +/* EFL UI LIST MODEL INTERFACE */ +EOLIAN static Eina_Size2D +_efl_ui_list_efl_ui_list_model_min_size_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->min; +} + +EOLIAN static void +_efl_ui_list_efl_ui_list_model_min_size_set(Eo *obj, Efl_Ui_List_Data *pd, Eina_Size2D min) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + pd->min.w = min.w; + pd->min.h = min.h; + + evas_object_size_hint_min_set(wd->resize_obj, pd->min.w, pd->min.h); + efl_event_callback_legacy_call(pd->pan_obj, ELM_PAN_EVENT_CHANGED, NULL); +} + +EOLIAN static Efl_Ui_List_LayoutItem * +_efl_ui_list_efl_ui_list_model_realize(Eo *obj, Efl_Ui_List_Data *pd, Efl_Ui_List_LayoutItem *item) +{ + Efl_Ui_List_Item_Event evt; + EINA_SAFETY_ON_NULL_RETURN_VAL(item->children, item); + + item->layout = efl_ui_factory_create(pd->factory, item->children, obj); + evas_object_smart_member_add(item->layout, pd->pan_obj); + evas_object_event_callback_add(item->layout, EVAS_CALLBACK_MOUSE_UP, _on_item_mouse_up, item); + + evt.child = item->children; + evt.layout = item->layout; + evt.index = efl_ui_list_item_index_get((Efl_Ui_List_Item *)item); + efl_event_callback_call(obj, EFL_UI_LIST_EVENT_ITEM_REALIZED, &evt); + + evas_object_show(item->layout); + return item; +} + +EOLIAN static void +_efl_ui_list_efl_ui_list_model_unrealize(Eo *obj, Efl_Ui_List_Data *pd, Efl_Ui_List_LayoutItem *item) +{ + Efl_Ui_List_Item_Event evt; + EINA_SAFETY_ON_NULL_RETURN(item->layout); + + evas_object_event_callback_del_full(item->layout, EVAS_CALLBACK_MOUSE_UP, _on_item_mouse_up, item); + evas_object_hide(item->layout); + evas_object_move(item->layout, -9999, -9999); + + evt.child = item->children; + evt.layout = item->layout; + evt.index = efl_ui_list_item_index_get((Efl_Ui_List_Item *)item); + efl_event_callback_call(obj, EFL_UI_LIST_EVENT_ITEM_UNREALIZED, &evt); + + evas_object_smart_member_del(item->layout); + efl_ui_factory_release(pd->factory, item->layout); + item->layout = NULL; +} + +EOLIAN static void +_efl_ui_list_efl_ui_list_model_load_range_set(Eo* obj EINA_UNUSED, Efl_Ui_List_Data* pd, int first, int count) +{ + if(!pd->slice_future) + { + pd->slice_future = efl_model_children_slice_get(pd->model, first, count); + pd->outstanding_slice.slice_start = first; + pd->outstanding_slice.slice_count = count; + efl_future_then(pd->slice_future, &_children_slice_then, &_children_slice_error, NULL, pd); + } +} + +EOLIAN static int +_efl_ui_list_efl_ui_list_model_size_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->item_count; +} + +/* Internal EO APIs and hidden overrides */ + +#define EFL_UI_LIST_EXTRA_OPS \ + EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_list) + +#include "efl_ui_list.eo.c" +#include "efl_ui_list_relayout.eo.c" +#include "efl_ui_list_model.eo.c" diff --git a/src/lib/elementary/efl_ui_list.eo b/src/lib/elementary/efl_ui_list.eo new file mode 100644 index 0000000000..e484b38504 --- /dev/null +++ b/src/lib/elementary/efl_ui_list.eo @@ -0,0 +1,108 @@ +import elm_general; + +struct Efl.Ui.List.Item_Event +{ + layout: Efl.Ui.Layout; + child: Efl.Model; + index: int; +} +class Efl.Ui.List (Efl.Ui.Layout, Efl.Ui.View, Elm.Interface_Scrollable, + Efl.Access.Widget.Action, Efl.Access.Selection, + Efl.Ui.Clickable, Efl.Ui.Selectable, Efl.Ui.List.Model) +{ + methods { + @property relayout { + values { + object: Efl.Ui.List.Relayout; + } + } + @property homogeneous { + get { + [[Get whether the homogeneous mode is enabled.]] + } + set { + [[Enable/disable homogeneous mode.]] + } + values { + homogeneous: bool; [[Assume the items within the genlist are of + the same height and width. Default is $false.]] + } + } + @property select_mode { + [[Listview select mode.]] + get {} + set {} + values { + mode: Elm.Object.Select_Mode(Elm.Object.Select_Mode.max); [[The select mode.]] + } + } + @property default_style { + values { + style: stringshare; + } + } + @property layout_factory { + [[Listview layout factory set.]] + set {} + values { + factory: Efl.Ui.Factory; [[The factory.]] + } + } + } + events { + item,realized : Efl.Ui.List.Item_Event; + item,unrealized : Efl.Ui.List.Item_Event; + item,focused : Efl.Ui.List.Item_Event; + item,unfocused : Efl.Ui.List.Item_Event; + item,highlighted : Efl.Ui.List.Item_Event; + item,unhighlighted : Efl.Ui.List.Item_Event; + item,selected : Efl.Ui.List.Item_Event; + item,unselected : Efl.Ui.List.Item_Event; + } + + implements { + Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.destructor; + Efl.Gfx.position { set; } + Efl.Gfx.size { set; } + // Smart obj + Efl.Canvas.Group.group_member_add; + Efl.Canvas.Group.group_calculate; + + Efl.Ui.List.Model.load_range { set;} + Efl.Ui.List.Model.realize; + Efl.Ui.List.Model.unrealize; + Efl.Ui.List.Model.size { get; } + Efl.Ui.List.Model.min_size { get; set; } + + // Widget +// Elm.Widget.focus_next_manager_is; +// Elm.Widget.focus_direction_manager_is; +// Elm.Widget.focus_register; +// Elm.Widget.focus_next; +// Elm.Widget.on_focus_update; +// Elm.Widget.activate; +// Elm.Widget.focused_item { get; } +// Elm.Widget.focused_object { get; } + Elm.Widget.focus_manager_create; + Elm.Widget.widget_event; + +// Efl.Ui.Focus.Manager.focus {set; } + //Efl.Ui.Layout.sizing_eval; + Efl.Ui.View.model { get; set; } + + Elm.Interface_Scrollable.region_bring_in; +// Elm.Interface.Atspi_Accessible.children { get; } +// Elm.Interface.Atspi_Widget_Action.elm_actions { get; } +// Efl.Access.Widget.Action.elm_actions { get; } + Efl.Access.Selection.selected_children_count { get; } + Efl.Access.Selection.selected_child { get; } + Efl.Access.Selection.selected_child_deselect; + Efl.Access.Selection.child_select; + Efl.Access.Selection.child_deselect; + Efl.Access.Selection.is_child_selected; + Efl.Access.Selection.all_children_select; + Efl.Access.Selection.clear; + } +} diff --git a/src/lib/elementary/efl_ui_list_model.eo b/src/lib/elementary/efl_ui_list_model.eo new file mode 100644 index 0000000000..ba2b2dc107 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_model.eo @@ -0,0 +1,48 @@ +import efl_ui_list_types; + +interface Efl.Ui.List.Model (Efl.Interface) +{ + methods { + @property load_range { + set {} + values { + first: int; + count: int; + } + } + realize { + params { + item: ptr(Efl.Ui.List.LayoutItem); + } + return: ptr(Efl.Ui.List.LayoutItem); + } + unrealize { + params { + item: ptr(Efl.Ui.List.LayoutItem); + } + } + // @property visible_range { + // set {} + // values { + // first: int; + // count: int; + // } + // } + @property size { + get {} + values { + s: int; + } + } + @property min_size { + [[Minimal content size.]] + set {} + get {} + values { + min: Eina.Size2D; + } + } + + + } +} diff --git a/src/lib/elementary/efl_ui_list_pan.eo b/src/lib/elementary/efl_ui_list_pan.eo new file mode 100644 index 0000000000..7bbb176666 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_pan.eo @@ -0,0 +1,16 @@ +class Efl.Ui.List.Pan (Elm.Pan) +{ + [[Elementary Efl_Ui_List pan class]] + implements { + Efl.Object.destructor; + Elm.Pan.content_size { get; } + Elm.Pan.pos { get; set; } + Elm.Pan.pos_min { get; } + Elm.Pan.pos_max { get; } + Efl.Canvas.Group.group_calculate; + } + events { + item,focused; [[Called when item got focus]] + item,unfocused; [[Called when item lost focus]] + } +} diff --git a/src/lib/elementary/efl_ui_list_precise_layouter.c b/src/lib/elementary/efl_ui_list_precise_layouter.c new file mode 100644 index 0000000000..7f37b7f4b6 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_precise_layouter.c @@ -0,0 +1,659 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include + +#include + +#include "elm_priv.h" +#include "efl_ui_list_segarray.h" + +#define MY_CLASS EFL_UI_LIST_PRECISE_LAYOUTER_CLASS + +typedef struct _Efl_Ui_List_Precise_Layouter_Data +{ + Eina_Bool initialized; + Eina_Bool recalc; + Eina_Bool resize; + Eina_Size2D min; + Efl_Model* model; + Efl_Ui_List_Model *modeler; + Efl_Future *count_future; + Ecore_Job *calc_job; + Efl_Ui_List_SegArray *segarray; + int first; + int count_total; + unsigned int calc_progress; +} Efl_Ui_List_Precise_Layouter_Data; + +typedef struct _Efl_Ui_List_Precise_Layouter_Node_Data +{ + Eina_Size2D min; + Eina_Size2D size; + Eina_Bool realized; +} Efl_Ui_List_Precise_Layouter_Node_Data; + +typedef struct _Efl_Ui_List_Precise_Layouter_Callback_Data +{ + Efl_Ui_List_Precise_Layouter_Data* pd; + Efl_Ui_List_LayoutItem* item; +} Efl_Ui_List_Precise_Layouter_Callback_Data; + + +#include "efl_ui_list_precise_layouter.eo.h" + + +static void _efl_ui_list_relayout_layout_do(Efl_Ui_List_Precise_Layouter_Data *); +static void _initilize(Eo *, Efl_Ui_List_Precise_Layouter_Data*, Efl_Ui_List_Model*, Efl_Ui_List_SegArray*); +static void _finalize(Eo *, Efl_Ui_List_Precise_Layouter_Data*); +static void _node_realize(Efl_Ui_List_Precise_Layouter_Data*, Efl_Ui_List_SegArray_Node*); +static void _node_unrealize(Efl_Ui_List_Precise_Layouter_Data*, Efl_Ui_List_SegArray_Node*); + +static void +_item_size_calc(Efl_Ui_List_Precise_Layouter_Data *pd, Efl_Ui_List_LayoutItem* item) +{ + int boxx, boxy, boxw, boxh, boxl, boxr, boxt, boxb, pad[4]; + double align[2]; + Eina_Size2D max; + + efl_gfx_size_hint_margin_get(item->layout, &pad[0], &pad[1], &pad[2], &pad[3]); + evas_object_geometry_get(pd->modeler, &boxx, &boxy, &boxw, &boxh); + efl_gfx_size_hint_margin_get(pd->modeler, &boxl, &boxr, &boxt, &boxb); + efl_gfx_size_hint_align_get(item->layout, &align[0], &align[1]); + max = efl_gfx_size_hint_max_get(item->layout); + + // box outer margin + boxw -= boxl + boxr; + boxh -= boxt + boxb; + boxx += boxl; + boxy += boxt; + + if (align[0] < 0) align[0] = -1; + if (align[1] < 0) align[1] = -1; + if (align[0] > 1) align[0] = 1; + if (align[1] > 1) align[1] = 1; + + if (max.w <= 0) max.w = INT_MAX; + if (max.h <= 0) max.h = INT_MAX; + if (max.w < item->min.w) max.w = item->min.w; + if (max.h < item->min.h) max.h = item->min.h; + + // horizontally + if (max.w < INT_MAX) + { + item->size.w = MIN(MAX(item->min.w - pad[0] - pad[1], max.w), boxw); + item->pos.x = boxx + pad[0]; + } + else if (align[0] < 0) + { + // fill x + item->size.w = boxw - pad[0] - pad[1]; + item->pos.x = boxx + pad[0]; + } + else + { + item->size.w = item->min.w - pad[0] - pad[1]; + item->pos.x = boxx + ((boxw - item->size.w) * align[0]) + pad[0]; + } + + // vertically + if (max.h < INT_MAX) + { + item->size.h = MIN(MAX(item->min.h - pad[2] - pad[3], max.h), boxh); + item->pos.y = boxy + pad[2]; + } + else if (align[1] < 0) + { + // fill y + item->size.h = item->min.h - pad[2] - pad[3]; + item->pos.y = boxy + pad[2]; + } + else + { + item->size.h = item->min.h - pad[2] - pad[3]; + item->pos.y = boxy + ((item->min.h - item->size.h) * align[1]) + pad[2]; + } +} + +static void +_item_min_calc(Efl_Ui_List_Precise_Layouter_Data *pd, Efl_Ui_List_LayoutItem* item + , Eina_Size2D min, Efl_Ui_List_SegArray_Node *itemnode) +{ + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata = itemnode->layout_data; + Efl_Ui_List_LayoutItem *layout_item; + int i, pad[4]; + + efl_gfx_size_hint_margin_get(item->layout, &pad[0], &pad[1], &pad[2], &pad[3]); + + min.w += pad[0] + pad[1]; + min.h += pad[2] + pad[3]; + + if (item->min.h == min.h && item->min.w == min.h) + return; + + pd->min.h += min.h - item->min.h; + nodedata->min.h += min.h - item->min.h; + + if (nodedata->min.w <= min.w) + nodedata->min.w = min.w; + else if (nodedata->min.w == item->min.w) + { + nodedata->min.w = 0; + for (i = 0; i != itemnode->length; ++i) + { + layout_item = (Efl_Ui_List_LayoutItem *)itemnode->pointers[i]; + if (nodedata->min.w < layout_item->min.w) + nodedata->min.w = layout_item->min.w; + + if (item->min.w == layout_item->min.w) + break; + } + } + + if (pd->min.w <= min.w) + pd->min.w = min.w; + else if (pd->min.w == item->min.w) + { + Efl_Ui_List_SegArray_Node *node; + Eina_Accessor *nodes = efl_ui_list_segarray_node_accessor_get(pd->segarray); + pd->min.w = min.w; + + EINA_ACCESSOR_FOREACH(nodes, i, node) + { + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata = node->layout_data; + if (pd->min.w < nodedata->min.w) + pd->min.w = nodedata->min.w; + + if (item->min.w == nodedata->min.w) + break; + } + eina_accessor_free(nodes); + } + + item->min.w = min.w; + item->min.h = min.h; + + _item_size_calc(pd, item); +} + +static void +_count_then(void * data, Efl_Event const* event) +{ + Efl_Ui_List_Precise_Layouter_Data *pd = data; + EINA_SAFETY_ON_NULL_RETURN(pd); + pd->count_future = NULL; + + pd->count_total = *(int*)((Efl_Future_Event_Success*)event->info)->value; + + if (pd->modeler && (pd->count_total != efl_ui_list_segarray_count(pd->segarray))) + { + pd->recalc = EINA_TRUE; + efl_ui_list_model_load_range_set(pd->modeler, 0, 0); // load all + } +} + +static void +_count_error(void * data, Efl_Event const* event EINA_UNUSED) +{ + Efl_Ui_List_Precise_Layouter_Data *pd = data; + EINA_SAFETY_ON_NULL_RETURN(pd); + pd->count_future = NULL; +} + +static void +_on_item_size_hint_change(void *data, Evas *e EINA_UNUSED, + Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Efl_Ui_List_Precise_Layouter_Callback_Data *cb_data = data; + Efl_Ui_List_Precise_Layouter_Data *pd = cb_data->pd; + Efl_Ui_List_LayoutItem *item = cb_data->item;; + Efl_Ui_List_SegArray_Node *node = item->tree_node; + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata = node->layout_data; + + Eina_Size2D min = efl_gfx_size_hint_combined_min_get(obj); + _item_min_calc(pd, item, min, node); + if (!nodedata->realized) + { + free(evas_object_event_callback_del(item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change)); + efl_ui_list_model_unrealize(pd->modeler, item); + } +} + +static void +_on_modeler_resize(void *data, Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Efl_Ui_List_Precise_Layouter_Data *pd = data; + pd->resize = EINA_TRUE; +} + +static void +_child_added_cb(void *data, const Efl_Event *event) +{ + Efl_Model_Children_Event* evt = event->info; + Efl_Ui_List_Precise_Layouter_Data *pd = data; + + efl_ui_list_segarray_insert(pd->segarray, evt->index, evt->child); + pd->recalc = EINA_TRUE; + evas_object_smart_changed(pd->modeler); +} + +static void +_child_removed_cb(void *data, const Efl_Event *event) +{ + Efl_Model_Children_Event* evt = event->info; + Efl_Ui_List_Precise_Layouter_Data *pd = data; + Efl_Ui_List_LayoutItem *layout_item, *litem; + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata; + Efl_Ui_List_SegArray_Node *itemnode; + Efl_Ui_List_Item* item; + int i; + + item = efl_ui_list_segarray_remove(pd->segarray, evt->index); + if (!item) return; + + litem = (Efl_Ui_List_LayoutItem *)item; + itemnode = litem->tree_node; + nodedata = itemnode->layout_data; + + free(evas_object_event_callback_del(litem->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change)); + + pd->min.h -= litem->min.h; + nodedata->min.h -= litem->min.h; + + if (nodedata->min.w == litem->min.w) + nodedata->min.w = 0; + for (i = 0; i != itemnode->length; ++i) + { + layout_item = (Efl_Ui_List_LayoutItem *)itemnode->pointers[i]; + if (nodedata->min.w < layout_item->min.w) + nodedata->min.w = layout_item->min.w; + + if (litem->min.w == layout_item->min.w) + { + nodedata->min.w = layout_item->min.w; + break; + } + } + + if (pd->min.w == litem->min.w) + { + Efl_Ui_List_SegArray_Node *node; + Eina_Accessor *nodes = efl_ui_list_segarray_node_accessor_get(pd->segarray); + pd->min.w = 0; + + EINA_ACCESSOR_FOREACH(nodes, i, node) + { + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata = node->layout_data; + if (pd->min.w < nodedata->min.w) + pd->min.w = nodedata->min.w; + + if (litem->min.w == nodedata->min.w) + break; + } + eina_accessor_free(nodes); + } + + efl_ui_list_model_unrealize(pd->modeler, litem); + + free(item); + pd->recalc = EINA_TRUE; + evas_object_smart_changed(pd->modeler); +} + +static void +_initilize(Eo *obj EINA_UNUSED, Efl_Ui_List_Precise_Layouter_Data *pd, Efl_Ui_List_Model *modeler, Efl_Ui_List_SegArray *segarray) +{ + if(pd->initialized) + return; + + pd->recalc = EINA_TRUE; + pd->initialized = EINA_TRUE; + + pd->modeler = modeler; + pd->segarray = segarray; + + evas_object_event_callback_add(modeler, EVAS_CALLBACK_RESIZE, _on_modeler_resize, pd); +// efl_event_callback_add(pd->model, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, _count_changed, pd); + efl_event_callback_add(pd->model, EFL_MODEL_EVENT_CHILD_ADDED, _child_added_cb, pd); + efl_event_callback_add(pd->model, EFL_MODEL_EVENT_CHILD_REMOVED, _child_removed_cb, pd); + efl_ui_list_model_load_range_set(modeler, 0, 0); // load all + + pd->min.w = 0; + pd->min.h = 0; +} + +static void +_finalize(Eo *obj EINA_UNUSED, Efl_Ui_List_Precise_Layouter_Data *pd) +{ + Efl_Ui_List_SegArray_Node* node; + int i = 0; + + evas_object_event_callback_del_full(pd->modeler, EVAS_CALLBACK_RESIZE, _on_modeler_resize, pd); + efl_event_callback_del(pd->model, EFL_MODEL_EVENT_CHILD_ADDED, _child_added_cb, pd); + efl_event_callback_del(pd->model, EFL_MODEL_EVENT_CHILD_REMOVED, _child_removed_cb, pd); +// efl_event_callback_del(pd->model, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, _count_changed, pd); + + Eina_Accessor *nodes = efl_ui_list_segarray_node_accessor_get(pd->segarray); + EINA_ACCESSOR_FOREACH(nodes, i, node) + { + _node_unrealize(pd, node); + free(node->layout_data); + } + + eina_accessor_free(nodes); + + pd->min.w = 0; + pd->min.h = 0; + + efl_ui_list_model_min_size_set(pd->modeler, pd->min); + + pd->segarray = NULL; + pd->modeler = NULL; + + pd->initialized = EINA_FALSE; +} + +static void +_node_realize(Efl_Ui_List_Precise_Layouter_Data *pd, Efl_Ui_List_SegArray_Node *node) +{ + Efl_Ui_List_LayoutItem* layout_item; + Efl_Ui_List_Precise_Layouter_Callback_Data *cb_data; + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata = node->layout_data; + int i; + + if (nodedata->realized) + return; + + nodedata->realized = EINA_TRUE; + + for (i = 0; i != node->length; ++i) + { + layout_item = (Efl_Ui_List_LayoutItem *)node->pointers[i]; + efl_ui_list_model_realize(pd->modeler, layout_item); + + if (layout_item->layout) + { + cb_data = calloc(1, sizeof(Efl_Ui_List_Precise_Layouter_Callback_Data)); + cb_data->pd = pd; + cb_data->item = layout_item; + evas_object_event_callback_add(layout_item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change, cb_data); + _item_size_calc(pd, layout_item); + } + } +} + +static void +_node_unrealize(Efl_Ui_List_Precise_Layouter_Data *pd, Efl_Ui_List_SegArray_Node *node) +{ + Efl_Ui_List_LayoutItem* layout_item; + Efl_Ui_List_Precise_Layouter_Callback_Data *cb_data; + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata = node->layout_data; + int i; + + if (!nodedata->realized) + return; + + nodedata->realized = EINA_FALSE; + + for (i = 0; i != node->length; ++i) + { + layout_item = (Efl_Ui_List_LayoutItem *)node->pointers[i]; + if (layout_item->layout) + { + cb_data = evas_object_event_callback_del(layout_item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change); + free(cb_data); + } + efl_ui_list_model_unrealize(pd->modeler, layout_item); + } +} + +static void +_calc_range(Efl_Ui_List_Precise_Layouter_Data *pd) +{ + Efl_Ui_List_SegArray_Node *node; + Evas_Coord ow, oh, scr_x, scr_y, ch; + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata; + int i; + + elm_interface_scrollable_content_viewport_geometry_get + (pd->modeler, NULL, NULL, &ow, &oh); + elm_interface_scrollable_content_pos_get(pd->modeler, &scr_x, &scr_y); + + ch = 0; + Eina_Accessor *nodes = efl_ui_list_segarray_node_accessor_get(pd->segarray); + EINA_ACCESSOR_FOREACH(nodes, i, node) + { + nodedata = node->layout_data; + if (!nodedata || !nodedata->min.h) + continue; + + if ((scr_y < ch || scr_y < nodedata->min.h + ch) && + (scr_y + oh > ch || scr_y + oh > nodedata->min.h + ch)) + _node_realize(pd, node); + else + _node_unrealize(pd, node); + + ch += nodedata->min.h; + } + eina_accessor_free(nodes); +} + +static void +_calc_size_job(void *data) +{ + Efl_Ui_List_Precise_Layouter_Data *pd; + Efl_Ui_List_SegArray_Node *node; + Efl_Ui_List_LayoutItem *layout_item; + Eo *obj = data; + Eina_Size2D min; + int i; + double start_time = ecore_time_get(); + + EINA_SAFETY_ON_NULL_RETURN(data); + pd = efl_data_scope_get(obj, MY_CLASS); + if (EINA_UNLIKELY(!pd)) return; + + pd->recalc = EINA_FALSE; + + Eina_Accessor *nodes = efl_ui_list_segarray_node_accessor_get(pd->segarray); + while (eina_accessor_data_get(nodes, pd->calc_progress, (void **)&node)) + { + pd->calc_progress++; + if (!node->layout_data) + node->layout_data = calloc(1, sizeof(Efl_Ui_List_Precise_Layouter_Node_Data)); + + for (i = 0; i != node->length; ++i) + { + layout_item = (Efl_Ui_List_LayoutItem *)node->pointers[i]; + EINA_SAFETY_ON_NULL_RETURN(layout_item); + + // cache size of new items + if ((layout_item->min.w == 0) && (layout_item->min.h == 0)) + { + if (!layout_item->layout) + { + efl_ui_list_model_realize(pd->modeler, layout_item); + } + + min = efl_gfx_size_hint_combined_min_get(layout_item->layout); + if (min.w && min.h) + { + _item_min_calc(pd, layout_item, min, node); + efl_ui_list_model_unrealize(pd->modeler, layout_item); + } + else + { + Efl_Ui_List_Precise_Layouter_Callback_Data *cb_data = calloc(1, sizeof(Efl_Ui_List_Precise_Layouter_Callback_Data)); + cb_data->pd = pd; + cb_data->item = layout_item; + evas_object_event_callback_add(layout_item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change, cb_data); + } + } + } + if ( (ecore_time_get() - start_time ) > 0.01 ) + { + ecore_job_del(pd->calc_job); + pd->calc_job = ecore_job_add(_calc_size_job, obj); + eina_accessor_free(nodes); + return; + } + } + eina_accessor_free(nodes); + pd->calc_progress = 0; + pd->calc_job = NULL; + + evas_object_smart_changed(pd->modeler); +} + +EOLIAN static Efl_Object * +_efl_ui_list_precise_layouter_efl_object_constructor(Eo *obj EINA_UNUSED, Efl_Ui_List_Precise_Layouter_Data *pd) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + pd->initialized = EINA_FALSE; + pd->count_future = NULL; + + return obj; +} + +EOLIAN static void +_efl_ui_list_precise_layouter_efl_ui_list_relayout_model_set(Eo *obj EINA_UNUSED, Efl_Ui_List_Precise_Layouter_Data *pd, Efl_Model *model) +{ + if (pd->model == model) + return; + + pd->count_total = 0; + if (pd->count_future) + { + efl_future_cancel(pd->count_future); + pd->count_future = NULL; + } + + if (pd->model) + { + _finalize(obj, pd); + efl_unref(pd->model); + pd->model = NULL; + } + + if (model) + { + pd->model = model; + efl_ref(pd->model); + pd->count_future = efl_model_children_count_get(pd->model); + efl_future_then(pd->count_future, &_count_then, &_count_error, NULL, pd); + } +} + +static void +_efl_ui_list_relayout_layout_do(Efl_Ui_List_Precise_Layouter_Data *pd) +{ + Evas_Coord ow, oh, scr_x, scr_y; + double cur_pos = 0; + Efl_Ui_List_LayoutItem* layout_item; + Efl_Ui_List_SegArray_Node *items_node; + int i, j = 0; + + _calc_range(pd); + + int boxx, boxy, boxw, boxh, extra = 0, rounding = 0; + int boxl = 0, boxr = 0, boxt = 0, boxb = 0; + evas_object_geometry_get(pd->modeler, &boxx, &boxy, &boxw, &boxh); + efl_gfx_size_hint_margin_get(pd->modeler, &boxl, &boxr, &boxt, &boxb); + + // box outer margin + boxw -= boxl + boxr; + boxh -= boxt + boxb; + boxx += boxl; + boxy += boxt; + + //padding can not be squeezed (note: could make it an option) +// int pad; +// double scale; +// scale = evas_object_scale_get(pd->modeler); +// pad = 0;//pd->pad.scalable ? (pd->pad.v * scale) : pd->pad.v; +// length -= pad * (pd->count_total - 1); + + // available space. if <0 we overflow + extra = boxh - pd->min.h; + if (extra < 0) extra = 0; + + efl_ui_list_model_min_size_set(pd->modeler, pd->min); + + elm_interface_scrollable_content_viewport_geometry_get(pd->modeler, NULL, NULL, &ow, &oh); + elm_interface_scrollable_content_pos_get(pd->modeler, &scr_x, &scr_y); + + Eina_Accessor *nodes = efl_ui_list_segarray_node_accessor_get(pd->segarray); + EINA_ACCESSOR_FOREACH(nodes, i, items_node) + { + Efl_Ui_List_Precise_Layouter_Node_Data *nodedata = items_node->layout_data; + if (!nodedata) + { + continue; + } + + if (nodedata->realized) + { + for(j = 0; j != items_node->length;++j) + { + layout_item = (Efl_Ui_List_LayoutItem *)items_node->pointers[j]; + double x, y, w, h; + double weight_x, weight_y; + + if (layout_item->min.w && layout_item->min.h) + { + assert(layout_item->layout != NULL); + if (pd->resize) + _item_size_calc(pd, layout_item); + + efl_gfx_size_hint_weight_get(layout_item->layout, &weight_x, &weight_y); + // extra rounding up (compensate cumulative error) + if ((i == (pd->count_total - 1)) && (cur_pos - floor(cur_pos) >= 0.5)) + rounding = 1; + + x = layout_item->pos.x; + y = layout_item->pos.y + cur_pos; + w = layout_item->size.w; + h = layout_item->size.h + rounding + weight_y * extra; + cur_pos += h; + + if (w < pd->min.w) w = pd->min.w; + if (w > ow) w = ow; + + evas_object_geometry_set(layout_item->layout, (x + 0 - scr_x), (y + 0 - scr_y), w, h); + } + } + } + else + { + cur_pos += nodedata->min.h; + } + } + eina_accessor_free(nodes); + + pd->resize = EINA_FALSE; +} + +EOLIAN static void +_efl_ui_list_precise_layouter_efl_ui_list_relayout_layout_do + (Eo *obj EINA_UNUSED, Efl_Ui_List_Precise_Layouter_Data *pd + , Efl_Ui_List_Model *modeler, int first, Efl_Ui_List_SegArray *segarray) +{ + _initilize(obj, pd, modeler, segarray); + + pd->first = first; + + if (pd->recalc) + { + // cache size of new items + pd->calc_progress = 0; + ecore_job_del(pd->calc_job); + pd->calc_job = ecore_job_add(_calc_size_job, obj); + return; + } + + _efl_ui_list_relayout_layout_do(pd); +} + +#include "efl_ui_list_precise_layouter.eo.c" diff --git a/src/lib/elementary/efl_ui_list_precise_layouter.eo b/src/lib/elementary/efl_ui_list_precise_layouter.eo new file mode 100644 index 0000000000..d6d276e4a4 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_precise_layouter.eo @@ -0,0 +1,8 @@ +class Efl.Ui.List.Precise_Layouter (Efl.Object, Efl.Ui.List.Relayout) +{ + implements { + Efl.Object.constructor; + Efl.Ui.List.Relayout.layout_do; + Efl.Ui.List.Relayout.model { set; } + } +} diff --git a/src/lib/elementary/efl_ui_list_private.h b/src/lib/elementary/efl_ui_list_private.h new file mode 100644 index 0000000000..607d1fe2b2 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_private.h @@ -0,0 +1,132 @@ +#ifndef EFL_UI_LIST_PRIVATE_H +#define EFL_UI_LIST_PRIVATE_H + +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED +#define ELM_INTERFACE_ATSPI_SELECTION_PROTECTED +#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED + +#include +#include "elm_priv.h" + +typedef struct _Efl_Ui_List_Item Efl_Ui_List_Item; +typedef struct _Efl_Ui_List_Data Efl_Ui_List_Data; + +struct _Efl_Ui_List_Item +{ + Efl_Ui_List_LayoutItem item; + Efl_Future *future; + Efl_Ui_List *list; + // Evas_Coord x, y, minw, minh, w, h; + // // double h, v, wx, wy; + // double wx, wy; +}; + +int efl_ui_list_item_index_get(Efl_Ui_List_Item const* item); + +typedef struct _Efl_Ui_List_Data Efl_Ui_List_Data; + +#include "efl_ui_list_segarray.h" + +struct _Efl_Ui_List_Data +{ + Eo *obj; + Evas_Object *hit_rect; + Efl_Model *model; + + Efl_Orient orient; + + struct { + double h, v; + Eina_Bool scalable: 1; + } pad; + + struct { + double h, v; + } align; + + struct { + double x, y; + } weight; + + // struct { + // Evas_Coord w, h; + // int start; + // int slice; + // } realized; + + int segarray_first; + Efl_Ui_List_SegArray segarray; + + Evas_Object *pan_obj; + + Efl_Ui_Layout_Factory *factory; + Eina_List *selected_items; + // struct { + // Eina_Inarray array; + // } items; + Eina_Stringshare *style; + Elm_Object_Select_Mode select_mode; + Elm_List_Mode mode; + + Efl_Ui_Focus_Manager *manager; + Eina_Size2D min; + int /*average_item_size, avsom, */item_count; + Efl_Future *slice_future; + Efl_Future *count_future; + Efl_Ui_List_Relayout *relayout; + struct { + int slice_start; + int slice_count; + } outstanding_slice; + + Eina_Bool homogeneous : 1; + Eina_Bool recalc : 1; + Eina_Bool on_hold : 1; +}; + +typedef struct _Efl_Ui_List_Pan_Data Efl_Ui_List_Pan_Data; + +struct _Efl_Ui_List_Pan_Data +{ + Eo *wobj; + Evas_Coord x, y, move_diff; + + Ecore_Job *resize_job; +}; + +typedef struct _Efl_Ui_List_Slice Efl_Ui_List_Slice; + +struct _Efl_Ui_List_Slice +{ + Efl_Ui_List_Data *pd; + int newstart, slicestart, newslice; +}; + + + +#define EFL_UI_LIST_DATA_GET(o, ptr) \ + Efl_Ui_List_Data * ptr = efl_data_scope_get(o, EFL_UI_LIST_CLASS) + +#define EFL_UI_LIST_DATA_GET_OR_RETURN(o, ptr) \ + EFL_UI_LIST_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + CRI("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return; \ + } + +#define EFL_UI_LIST_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ + EFL_UI_LIST_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + CRI("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return val; \ + } + +#endif diff --git a/src/lib/elementary/efl_ui_list_relayout.eo b/src/lib/elementary/efl_ui_list_relayout.eo new file mode 100644 index 0000000000..94daa479d5 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_relayout.eo @@ -0,0 +1,23 @@ +import efl_ui_list_types; + +struct @extern Efl_Ui_List_SegArray; + +interface Efl.Ui.List.Relayout (Efl.Interface) +{ + methods { + layout_do { + params { + modeler: Efl.Ui.List.Model; + first: int; + children: ptr(Efl_Ui_List_SegArray); + } + } + @property model { + [[Model that is/will be ]] + set {} + values { + model: Efl.Model; [[Efl model]] + } + } + } +} diff --git a/src/lib/elementary/efl_ui_list_segarray.c b/src/lib/elementary/efl_ui_list_segarray.c new file mode 100644 index 0000000000..79c55fbbe4 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_segarray.c @@ -0,0 +1,427 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include "efl_ui_list_private.h" +#include "efl_ui_list_segarray.h" + +#include + +#include + +static int _search_lookup_cb(Eina_Rbtree const* rbtree, const void* key, int length EINA_UNUSED, void* data EINA_UNUSED) +{ + Efl_Ui_List_SegArray_Node const* node = (void const*)rbtree; + int index = *(int*)key; + if(index < node->first) + { + return 1; + } + else if(index < node->first + node->length) + { + return 0; + } + else + { + return -1; + } +} + +static int _insert_lookup_cb(Eina_Rbtree const* rbtree, const void* key, int length EINA_UNUSED, void* data EINA_UNUSED) +{ + Efl_Ui_List_SegArray_Node const* node = (void const*)rbtree; + int index = *(int*)key; + if(index < node->first) + { + return 1; + } + else if(index < node->first + node->max) + { + return 0; + } + else + { + return -1; + } +} + +static Eina_Rbtree_Direction _rbtree_compare(Efl_Ui_List_SegArray_Node const* left, + Efl_Ui_List_SegArray_Node const* right, void* data EINA_UNUSED) +{ + if(left->first < right->first) + return EINA_RBTREE_LEFT; + else + return EINA_RBTREE_RIGHT; +} + + +static void +_free_node(Efl_Ui_List_SegArray_Node* node, void* data EINA_UNUSED) +{ + int i = 0; + + while (i < node->length) + { + free(node->pointers[i]); + ++i; + } + + free(node); +} + +static Efl_Ui_List_SegArray_Node* +_alloc_node(Efl_Ui_List_SegArray* segarray, int first, int max) +{ + Efl_Ui_List_SegArray_Node* node; + node = calloc(1, sizeof(Efl_Ui_List_SegArray_Node) + max*sizeof(Efl_Ui_List_Item*)); + node->first = first; + node->max = max; + void* tmp = segarray->root; + segarray->root = (void*)eina_rbtree_inline_insert(EINA_RBTREE_GET(segarray->root), EINA_RBTREE_GET(node), + EINA_RBTREE_CMP_NODE_CB(&_rbtree_compare), NULL); + segarray->node_count++; + return node; +} + +void efl_ui_list_segarray_setup(Efl_Ui_List_SegArray* segarray, //int member_size, + int initial_step_size) +{ + segarray->root = NULL; + segarray->array_initial_size = initial_step_size; +} + +void efl_ui_list_segarray_flush(Efl_Ui_List_SegArray* segarray) +{ + eina_rbtree_delete(EINA_RBTREE_GET(segarray->root), EINA_RBTREE_FREE_CB(_free_node), NULL); + segarray->root = NULL; +} + +static Efl_Ui_List_Item* _create_item_partial(Efl_Model* model) +{ + Efl_Ui_List_Item* item = calloc(1, sizeof(Efl_Ui_List_Item)); + item->item.children = model; + return item; +} + +static Efl_Ui_List_Item* _create_item(Efl_Model* model, Efl_Ui_List_SegArray_Node* node, unsigned int index) +{ + Efl_Ui_List_Item* item = _create_item_partial(model); + item->item.index_offset = index - node->first; + item->item.tree_node = node; + return item; +} + +Efl_Ui_List_Item* +efl_ui_list_segarray_remove(Efl_Ui_List_SegArray* segarray, int index) +{ + Efl_Ui_List_SegArray_Node *node; + Efl_Ui_List_Item *item, *rt; + Eina_Iterator* iterator; + int offset; + + node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(segarray->root), + &index, sizeof(index), &_insert_lookup_cb, NULL); + if (!node) return NULL; + + offset = index - node->first; + if (offset >= node->length) return NULL; + + rt = node->pointers[offset]; + segarray->count--; + node->length--; + + if (offset >= node->length) return NULL; + + while (offset < node->length) + { + node->pointers[offset] = node->pointers[offset+1]; + item = node->pointers[offset]; + --item->item.index_offset; + ++offset; + } + + node = (void*)EINA_RBTREE_GET(node)->son[EINA_RBTREE_LEFT]; + iterator = eina_rbtree_iterator_infix((void*)node); + while(eina_iterator_next(iterator, (void**)&node)) + node->first--; + + return rt; +} + +static void +_efl_ui_list_segarray_insert_at_node(Efl_Ui_List_SegArray* segarray, int index, Efl_Ui_List_Item* item, Efl_Ui_List_SegArray_Node* node) +{ + Eina_Iterator* iterator; + int pos; + + if(node && node->length != node->max && (index - node->first) <= node->length) + { + pos = index - node->first; + item->item.tree_node = node; + item->item.index_offset = pos; + if(pos < node->length) + { + assert(node->length != node->max); + + memmove(&node->pointers[pos], &node->pointers[pos+1], sizeof(node->pointers[pos])*(node->length - pos)); + node->pointers[pos] = item; + node->length++; + } + else + { + assert(pos == node->length); + + assert(node->length != node->max); + node->pointers[pos] = item; + node->length++; + } + } + else + { + node = _alloc_node(segarray, index, segarray->array_initial_size); + node->pointers[0] = item; + node->length++; + item->item.index_offset = 0; + item->item.tree_node = node; + } + + node = (void*)EINA_RBTREE_GET(node)->son[EINA_RBTREE_LEFT]; + iterator = eina_rbtree_iterator_infix((void*)node); + while(eina_iterator_next(iterator, (void**)&node)) + { + node->first++; + } + + eina_iterator_free(iterator); +} + + +void efl_ui_list_segarray_insert(Efl_Ui_List_SegArray* segarray, int index, Efl_Model* model) +{ + Efl_Ui_List_SegArray_Node* node, *next; + Efl_Ui_List_Item* item; + + item = _create_item_partial(model); + + node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(segarray->root), + &index, sizeof(index), &_insert_lookup_cb, NULL); + if(node) + { + next = (void*)EINA_RBTREE_GET(node)->son[EINA_RBTREE_LEFT]; + if(next && next->first <= index) + _efl_ui_list_segarray_insert_at_node(segarray, index, item, next); + else + _efl_ui_list_segarray_insert_at_node(segarray, index, item, node); + } + else + _efl_ui_list_segarray_insert_at_node(segarray, index, item, NULL); +} + +void efl_ui_list_segarray_insert_accessor(Efl_Ui_List_SegArray* segarray, int first, Eina_Accessor* accessor) +{ + int i; + Efl_Model* children; + + EINA_ACCESSOR_FOREACH(accessor, i, children) + { + Efl_Ui_List_SegArray_Node *node; + int idx = first + i; + + node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(segarray->root), + &idx, sizeof(idx), &_insert_lookup_cb, NULL); + if (!node) + { + node = _alloc_node(segarray, idx, segarray->array_initial_size); + } + + assert(node->length < node->max); + node->pointers[node->length] = _create_item(children, node, idx); + node->length++; + segarray->count++; + } +} + +int efl_ui_list_segarray_count(Efl_Ui_List_SegArray const* segarray) +{ + return segarray->count; +} + +typedef struct _Efl_Ui_List_Segarray_Eina_Accessor +{ + Eina_Accessor vtable; + Efl_Ui_List_SegArray* segarray; +} Efl_Ui_List_Segarray_Eina_Accessor; + +static Eina_Bool +_efl_ui_list_segarray_accessor_get_at(Efl_Ui_List_Segarray_Eina_Accessor* acc, + int idx, void** data) +{ + Efl_Ui_List_SegArray_Node* node; + node = (void*)eina_rbtree_inline_lookup(EINA_RBTREE_GET(acc->segarray->root), + &idx, sizeof(idx), &_search_lookup_cb, NULL); + if(node) + { + if(node->first <= idx && node->first + node->length > idx) + { + int i = idx - node->first; + Efl_Ui_List_Item* item = node->pointers[i]; + *data = item; + return EINA_TRUE; + } + } + return EINA_FALSE; +} + +static void* +_efl_ui_list_segarray_accessor_get_container(Efl_Ui_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ + return NULL; +} + +static void +_efl_ui_list_segarray_accessor_free(Efl_Ui_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ + free(acc); +} + +static void +_efl_ui_list_segarray_accessor_lock(Efl_Ui_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ +} + +static void +_efl_ui_list_segarray_accessor_unlock(Efl_Ui_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ +} + +static Eina_Accessor* +_efl_ui_list_segarray_accessor_clone(Efl_Ui_List_Segarray_Eina_Accessor* acc EINA_UNUSED) +{ + return &acc->vtable; +} + +static void +_efl_ui_list_segarray_accessor_setup(Efl_Ui_List_Segarray_Eina_Accessor* acc, Efl_Ui_List_SegArray* segarray) +{ + EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR); + acc->vtable.version = EINA_ACCESSOR_VERSION; + acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(_efl_ui_list_segarray_accessor_get_at); + acc->vtable.get_container = FUNC_ACCESSOR_GET_CONTAINER(_efl_ui_list_segarray_accessor_get_container); + acc->vtable.free = FUNC_ACCESSOR_FREE(_efl_ui_list_segarray_accessor_free); + acc->vtable.lock = FUNC_ACCESSOR_LOCK(_efl_ui_list_segarray_accessor_lock); + acc->vtable.unlock = FUNC_ACCESSOR_LOCK(_efl_ui_list_segarray_accessor_unlock); + acc->vtable.clone = FUNC_ACCESSOR_CLONE(_efl_ui_list_segarray_accessor_clone); + acc->segarray = segarray; +} + +Eina_Accessor* efl_ui_list_segarray_accessor_get(Efl_Ui_List_SegArray* segarray) +{ + Efl_Ui_List_Segarray_Eina_Accessor* acc = calloc(1, sizeof(Efl_Ui_List_Segarray_Eina_Accessor)); + _efl_ui_list_segarray_accessor_setup(acc, segarray); + return &acc->vtable; +} + +typedef struct _Efl_Ui_List_Segarray_Node_Accessor +{ + Eina_Accessor vtable; + Efl_Ui_List_SegArray* segarray; + Eina_Iterator* pre_iterator; + Efl_Ui_List_SegArray_Node* current_node; + int current_index; +} Efl_Ui_List_Segarray_Node_Accessor; + +static Eina_Bool +_efl_ui_list_segarray_node_accessor_get_at(Efl_Ui_List_Segarray_Node_Accessor* acc, + int idx, void** data) +{ + if(idx == acc->current_index && acc->current_node) + { + (*data) = acc->current_node; + } + else + { + if(acc->current_index >= idx || !acc->current_node) + { + eina_iterator_free(acc->pre_iterator); + acc->pre_iterator = NULL; + acc->current_node = NULL; + acc->current_index = -1; + } + + if(!acc->pre_iterator) + acc->pre_iterator = eina_rbtree_iterator_infix((void*)acc->segarray->root); + + for(;acc->current_index != idx;++acc->current_index) + { + if(!eina_iterator_next(acc->pre_iterator, (void**)&acc->current_node)) + { + --acc->current_index; + return EINA_FALSE; + } + } + (*data) = acc->current_node; + return EINA_TRUE; + } + return EINA_FALSE; +} + +static void* +_efl_ui_list_segarray_node_accessor_get_container(Efl_Ui_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ + return NULL; +} + +static void +_efl_ui_list_segarray_node_accessor_free(Efl_Ui_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ + if (acc->pre_iterator) + eina_iterator_free(acc->pre_iterator); + free(acc); +} + +static void +_efl_ui_list_segarray_node_accessor_lock(Efl_Ui_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ +} + +static void +_efl_ui_list_segarray_node_accessor_unlock(Efl_Ui_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ +} + +static Eina_Accessor* +_efl_ui_list_segarray_node_accessor_clone(Efl_Ui_List_Segarray_Node_Accessor* acc EINA_UNUSED) +{ + return &acc->vtable; +} + +static void +_efl_ui_list_segarray_node_accessor_setup(Efl_Ui_List_Segarray_Node_Accessor* acc, Efl_Ui_List_SegArray* segarray) +{ + EINA_MAGIC_SET(&acc->vtable, EINA_MAGIC_ACCESSOR); + acc->vtable.version = EINA_ACCESSOR_VERSION; + acc->vtable.get_at = FUNC_ACCESSOR_GET_AT(_efl_ui_list_segarray_node_accessor_get_at); + acc->vtable.get_container = FUNC_ACCESSOR_GET_CONTAINER(_efl_ui_list_segarray_node_accessor_get_container); + acc->vtable.free = FUNC_ACCESSOR_FREE(_efl_ui_list_segarray_node_accessor_free); + acc->vtable.lock = FUNC_ACCESSOR_LOCK(_efl_ui_list_segarray_node_accessor_lock); + acc->vtable.unlock = FUNC_ACCESSOR_LOCK(_efl_ui_list_segarray_node_accessor_unlock); + acc->vtable.clone = FUNC_ACCESSOR_CLONE(_efl_ui_list_segarray_node_accessor_clone); + acc->segarray = segarray; + acc->pre_iterator = NULL; + acc->current_index = -1; + acc->current_node = NULL; +} + +Eina_Accessor* efl_ui_list_segarray_node_accessor_get(Efl_Ui_List_SegArray* segarray) +{ + Efl_Ui_List_Segarray_Node_Accessor* acc = calloc(1, sizeof(Efl_Ui_List_Segarray_Node_Accessor)); + _efl_ui_list_segarray_node_accessor_setup(acc, segarray); + return &acc->vtable; +} + +int efl_ui_list_item_index_get(Efl_Ui_List_Item const* item) +{ + Efl_Ui_List_SegArray_Node* node = item->item.tree_node; + return item->item.index_offset + node->first; +} + diff --git a/src/lib/elementary/efl_ui_list_segarray.h b/src/lib/elementary/efl_ui_list_segarray.h new file mode 100644 index 0000000000..eb8529a0c2 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_segarray.h @@ -0,0 +1,42 @@ +#ifndef EFL_UI_LIST_SEGARRAY_H +#define EFL_UI_LIST_SEGARRAY_H + +#include "efl_ui_list_segarray.h" + +typedef struct _Efl_Ui_List_Item Efl_Ui_List_Item; + +typedef struct _Efl_Ui_List_SegArray_Node +{ + EINA_RBTREE; + + int length; + int max; + int first; + + void* layout_data; + + Efl_Ui_List_Item* pointers[0]; +} Efl_Ui_List_SegArray_Node; + +typedef struct _Efl_Ui_List_SegArray +{ + Efl_Ui_List_SegArray_Node *root; // of Efl_Ui_List_SegArray_Nodea + + int array_initial_size; + int node_count; + int count; +} Efl_Ui_List_SegArray; + +Eina_Accessor* efl_ui_list_segarray_accessor_get(Efl_Ui_List_SegArray* segarray); +Eina_Accessor* efl_ui_list_segarray_node_accessor_get(Efl_Ui_List_SegArray* segarray); +Efl_Ui_List_SegArray_Node* efl_ui_list_segarray_item_node_get(Efl_Ui_List_SegArray* segarray, + Efl_Ui_List_Item* item); +void efl_ui_list_segarray_insert_accessor(Efl_Ui_List_SegArray* segarray, int first, Eina_Accessor* accessor); +int efl_ui_list_segarray_count(Efl_Ui_List_SegArray const* segarray); +void efl_ui_list_segarray_setup(Efl_Ui_List_SegArray* segarray, int initial_step_size); +void efl_ui_list_segarray_flush(Efl_Ui_List_SegArray* segarray); + +void efl_ui_list_segarray_insert(Efl_Ui_List_SegArray* segarray, int index, Efl_Model* model); +Efl_Ui_List_Item *efl_ui_list_segarray_remove(Efl_Ui_List_SegArray* segarray, int index); + +#endif diff --git a/src/lib/elementary/efl_ui_list_types.eot b/src/lib/elementary/efl_ui_list_types.eot new file mode 100644 index 0000000000..a0997c8db4 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_types.eot @@ -0,0 +1,9 @@ +struct Efl.Ui.List.LayoutItem { + layout: Efl.Ui.Layout; + children: Efl.Model; + index_offset: int; + tree_node: void_ptr; + min: Eina.Size2D; + size: Eina.Size2D; + pos: Eina.Position2D; +} diff --git a/src/lib/elementary/elm_widget_layout.h b/src/lib/elementary/elm_widget_layout.h index 1a3cf2a394..0e0c088b73 100644 --- a/src/lib/elementary/elm_widget_layout.h +++ b/src/lib/elementary/elm_widget_layout.h @@ -53,7 +53,7 @@ typedef struct _Elm_Layout_Smart_Data Eina_List *subs; /**< List of Elm_Layout_Sub_Object_Data structs, to hold the actual sub objects such as text, content and the children of box and table. */ Eina_List *edje_signals; /**< The list of edje signal callbacks. */ Eina_List *parts_cursors; /**< The list of cursor names of layout parts. This is a list of Elm_Layout_Sub_Object_Cursor struct. */ - Eina_List *prop_connect; /**< The hash of properties connected to layout parts. */ + Eina_List *prop_connect; /**< The list of properties connected to layout parts. */ Eina_Hash *factories; /**< The hash with parts connected to factories. */ Efl_Model *model; /**< The model */ int frozen; /**< Layout freeze counter */