edc에서 group은 비교적 군더더기 없이 만들어져 있습니다.

group을 사용할 때, '충돌'이나 '이해할 수 없는 동작'을 고민할 필요가 없습니다.


group과 얽힌 재미난 에러를 하나쯤 언급하기 위해 기억을 더듬고 있지만,

도통 떠오르지 않네요.

비교적 간단한 역할을 담당하고 있으니 실구현에도 어려움은 없는 녀석이었나봅니다.

여러분도 그럴 것이라 믿어의심치 않습니다. :)



안녕하세요, Tizen 개발자 윤진입니다.


edc를 작성할 때 group은 하나의 완결된 구성이 됩니다.

c파일에서 elm_layout_add(), elm_layout_file_set() 콤보로 가져다 쓰는 단위가 group입니다.

하나의 collections에 수많은 group이 있다면,

c에서 필요한 group만큼 elm_layout_add()를 불러서 사용하면 됩니다.


그렇다면 완결된 구성을 위해서는 그 안에 어떤 요소를 담고 있어야 할까요?

그룹이 가진 많은 요소 중에 가장 중요한 요소는 parts와 programs 두가지입니다.

parts는 화면을 구성하는 part의 상위 블록이고,

programs는 part에 움직임을 부여할 수 있는 program의 상위 블록이지요.


collections {
   group {
      parts {
         part{}
         part{}
         part{}
         part{}
      }
      programs {
         program{}
         program{}
         program{}
         program{}
      }
   }


지난
collections 포스팅에서도 언급한 블록도에서 programs를 추가해봤습니다.

위의 블록도처럼 group에 parts와 programs만 있으면 화면에 무언가 그려낼 수 있습니다.

parts와 programs 블록은 각각 며칠씩 공을 들여 설명해보도록 하겠습니다.


group에는 parts와 programs 외에 다른 요소들도 있습니다.

name, inherit, min, max.

위의 요소들은 parts와 programs에 비하면 아주 간단하게 설명할 수 있습니다.


- name: [group name];

   그룹의 이름을 지정합니다.

   위에서 잠깐 언급한 elm_layout_file_set()에서 세번째 인자가 그룹 name입니다.

   c파일에서는 group이 있는 파일명과 여기서 지정한 그룹명으로 그룹에 접근할 수 있습니다.

   만약 group 이름이 동일하다면 새로운 group이 이전 group을 완전히 override해버립니다.

   edc에서 group override를 의미있게 사용하는 것을 보질 못해서,

   이 부분은 컴파일을 위한 편의가 아닐까 추정하고 있습니다.

   어쨌든, override되지 않게 그리고 문맥에 맞게 사용하려면 group명을 잘 지어주세요.

   언제나 모든 것은 적절한 네이밍에서 시작하지요.


- min: [width] [height];

   min의 의미는 "최소한 이 사이즈를 확보해주세요"입니다.

   group이 어디에 포함되어 들어가든 min 사이즈만큼은 확보가 됩니다.

   min에서 지정한 사이즈보다 group이 작아질 수는 없습니다.

   원칙적으로 그렇습니다.

   min에서는 그룹의 높이와 너비를 지정하겠지요.

   그룹의 높이/너비가 확정되어 있고 '절대로 변할 일이 없다'면,

   group 차원에서 정의해도 무방합니다.

   하지만, group이 상태에 따라 사이즈가 바뀐다면,

   여기서 min을 사용하면 안됩니다.

   min은 mandatory가 아니기에 상황에 따라 사용하면 됩니다.

   참고로 전 group에서 min을 사용하지 않습니다.

   min은 다른 곳에서 더 재미있는 형태로 사용할 수 있습니다.


- max: [width] [height];

   max는 min과는 반대의 개념입니다.

   "최대한 이 사이즈를 넘지 않도록 해주세요" 입니다.

   max의 중요성은 min에 비해 상당히 떨어지는데요,

   각각의 요소들이 사이즈를 잡을때 min을 기준으로 잡기 때문입니다.

   max는 느슨한 가이드라인이지요.

   그렇다고 사용하지 않는다는 것은 절대 아닙니다.

   차후에 min/max에 대해서는 계속 설명할 기회가 있을 겁니다.

   어쨌든 그룹이 max 값을 넘지 않게 합니다.

   min처럼 mandatory가 아니기 때문에 필요에 의해 사용하면 됩니다.


- alias: [additional group name];

   alias에서 그룹에 별칭을 지정할 수 있습니다.

   하나의 그룹이 다수의 이름을 가질 필요가 있을때 사용합니다.

   그룹을 하나 만들었는데 여러 군데에서 사용할 수 있고,

   각각에 고유한 네이밍을 하길 원할 때가 있습니다.

   그 때 alias는 의미있는 선택이 될 수 있습니다.


group의 모든 요소를 골고루 사용하는 define문을 icon.edc에서 찾았습니다.

Repository : git://review.tizen.org/framework/uifw/elementary

Branch : tizen_2.3

File : data/themes/widgets/icon.edc


#define GROUP_ALIAS_ICON(Name, Alias, File, Min, Max)                   \
   group { name: "elm/icon/"##Name##"/default"; min: Min Min; max: Max Max; \
      images.image: File COMP; parts { part { name: "base";             \
            description { aspect: 1.0 1.0; aspect_preference: BOTH;     \
               image.normal: File; } } } }
/*** 생략 ***/
GROUP_ALIAS_ICON("home", "toolbar/home", "icon_home.png", 32, 0);
GROUP_ALIAS_ICON("close", "toolbar/close", "icon_close.png", 32, 0);
GROUP_ALIAS_ICON("apps", "toolbar/apps", "icon_apps.png", 32, 0);
GROUP_ALIAS_ICON("arrow_up", "toolbar/arrow_up", "icon_arrow_up.png", 32, 0);
GROUP_ALIAS_ICON("arrow_left", "toolbar/arrow_left", "icon_arrow_left.png", 32, 0);
GROUP_ALIAS_ICON("arrow_right", "toolbar/arrow_right", "icon_arrow_right.png", 32, 0);
GROUP_ALIAS_ICON("chat", "toolbar/chat", "icon_chat.png", 32, 0);
GROUP_ALIAS_ICON("clock", "toolbar/clock", "icon_clock.png", 32, 0);
GROUP_ALIAS_ICON("delete", "toolbar/delete", "icon_delete.png", 32, 0);
GROUP_ALIAS_ICON("edit", "toolbar/edit", "icon_edit.png", 32, 0);
GROUP_ALIAS_ICON("refresh", "toolbar/refresh", "icon_refresh.png", 32, 0);
GROUP_ALIAS_ICON("folder", "toolbar/folder", "icon_folder.png", 32, 0);
GROUP_ALIAS_ICON("file", "toolbar/file", "icon_file.png", 32, 0);
GROUP_ALIAS_ICON("no_photo", "photo/no_photo", "head.png", 32, 0);


위에서 난데없는 #define이 나와서 당황하셨을 지도 모르겠군요.

C언어에서처럼 #define을 유사하게 사용할 수 있습니다.

우리가 살펴봐야할 부분은 GROUP_ALIAS_ICON의 Name, Alias, Min, Max입니다.

실제로 #define이 사용되는 부분을 보면,

Name, Alias, Min값을 주로 사용하고 있군요.

Max는 마지막 인자로 '0'을 넣어주고 있네요.

최대 크기가 0이라는 의미는 아니고 Max를 사용하지 않겠다는 의미입니다.

이 예시에서는 그룹의 Name과 Alias를 지정하고,

최소/최대 사이즈를 지정하였습니다.


group에 대한 설명은 이것으로 간단하게 마치겠습니다.

다음 시간에는 part에 대해서 살펴보도록 하겠습니다.


그럼 좋은 하루 보내세요~

끝_



EFL에 대해 블로깅을 하는 날이 오고야 말았습니다.

오늘부터 n일 동안 edc에 대해서 하나씩 살펴보도록 하겠습니다.


진도를 빨리 뺀다는 마음보다는,

다소 느리더라도 천천히 하나하나 맛을 음미하며 진행하고 싶네요.


하지만, 충분히 설명해낼 수 있을지는 확신이 안 서네요.



안녕하세요, Tizen 개발자 윤진입니다.


edc는 EFL의 백미라 할 수 있습니다.

(써 놓고 보니 '백미' 타이틀은 ecore나 evas에게 주어야하지 않나라는 생각도 듭니다;)

edc 스크립트를 사용하여 레이아웃을 잡고 이미지를 배치하고 텍스트를 심습니다.

이러한 정적인 배치는 edc의 part를 이용하여 구성할 수 있습니다.


위에 나열한 정적인 요소에 program을 통해 생명력을 불어넣을 수 있습니다.

part 하나 하나가 program의 손길로 동적인 효과를 가집니다.

네다섯줄의 스크립팅으로 부드러운 애니메이션을 탑재할 수 있습니다.


edc 스크립트에서 가장 처음 마주하게 되는 블록이 collections입니다.

collections에는 하나의 유의미한 단위로 동작하는 group이 들어갑니다.

group 화면을 구성하는 완결된 하나의 집합이고,

collections는 그러한 group을 1개 이상 가집니다.


예를 들어 버튼+텍스트의 집합을 하나의 완결된 'button' group이 있다고 하죠.

경우에 따라서 버튼의 모양은 천양지차로 다를 수 있습니다.

네모난 버튼이 일반적이긴 하지만, 사각이 라운딩 처리된 라운딩 버튼이 있을 수도 있습니다.

이럴 경우 네모난 버튼용 group과 라운딩 버튼용 group이 따로 둘 수 있습니다.

세모난 버튼용 group이나 투명 버튼용 group도 있을 수 있겠네요.

생김새는 조금씩 다르지만 버튼이라는 기능적인 유사성이 있기 때문에,

하나의 collections로 모아서 관리할 수 있겠죠.

이처럼 collections는 다양한 theme을 묶어주는 역할을 할 수 있습니다.


그렇다면 group이 하나만 있어도 collections로 묶어줘야 할까요?

네, 맞습니다.

collections는 group이 1개 이상 있는 경우에 반드시 써주어야 합니다.

collections로 감싸지지 않은 group은 제대로 컴파일되지 않습니다.

collections - group - parts - part

혹은

Collections - group - programs - program

위에 이르는 블록 구조에서 최상단에는 언제나 collections가 있습니다.


edc 파일은 collections를 반드시 갖지만,

두 개 이상 가질 수는 없습니다.

edc 파일에는 오직 하나의 collections만 사용할 수 있습니다.


collections {
   group {
      parts {
         part{}
         part{}
         part{}
         part{}
      }
   }


EFL elementary repository에서 사용하고 있는 edc 파일을 예제로 살펴보겠습니다.

Repository : git://review.tizen.org/framework/uifw/elementary

Branch : tizen_2.3

File : data/themes/default.edc

collections {
///////////////////////////////////////////////////////////////////////////////
   group { name: "elm/focus_highlight/top/default";
   /* ... 생략 ... */
      parts {
         part { name: "base";
            type: RECT;
            repeat_events: 1;
            description { state: "default" 0.0;
               rel1.relative: 0.0 0.0;
               rel2.relative: 1.0 1.0;
               visible: 0;
            }
         }
         part { name: "shine";
            type: IMAGE;
            mouse_events: 1;
            repeat_events: 1;
            ignore_flags: ON_HOLD;
            description { state: "default" 0.0;
               image {
                  normal: "emo-unhappy.png";
               }
               rel1.to: "base";
               rel1.relative: 1.0 0.0;
               rel1.offset: -15 -15;
               rel2.to: "base";
               rel2.relative: 1.0 0.0;
               rel2.offset: 14 14;
            }
            description { state: "disabled" 0.0;
               inherit:  "default" 0.0;
               color: 0 0 0 0;
            }
         }
   /* ... 생략 ... */
///////////////////////////////////////////////////////////////////////////////
   group { name: "elm/focus_highlight/bottom/default";
      parts {
         part { name: "shine";
            type: RECT;
            mouse_events: 1;
            repeat_events: 1;
            ignore_flags: ON_HOLD;
            description { state: "default" 0.0;
               color: 0 255 0 50;
               rel1.offset: 0 0;
               rel2.offset: 0 0;
            }
            description { state: "disabled" 0.0;
               inherit:  "default" 0.0;
               color: 0 0 0 0;
            }
         } 
   /* ... 생략 ... */
///////////////////////////////////////////////////////////////////////////////
   group { name: "elm/access/base/default";
      images {
         image: "access_glow.png" LOSSY 85;
      }
      parts {
         part { name: "block1"; type: RECT;
            mouse_events:  0;
            description { state: "default" 0.0;
               color: 0 0 0 200;
               rel1 { to: "base";
                  relative: 0.0 0.0;
                  offset: -100000 -100000;
               }
               rel2 { to: "base";
                  relative: 1.0 0.0;
                  offset: 100000 96;
               }
            }
         }
         part { name: "block2"; type: RECT;
            mouse_events:  0;
            description { state: "default" 0.0;
               color: 0 0 0 200;
               rel1 { to: "base";
                  relative: 0.0 1.0;
                  offset: -100000 -97;
               }
               rel2 { to: "base";
                  relative: 1.0 1.0;
                  offset: 100000 100000;
               }
            }
         }
         part { name: "block3"; type: RECT;
            mouse_events:  0;
            description { state: "default" 0.0;
               color: 0 0 0 200;
               rel1 { to: "block1";
                  relative: 0.0 1.0;
                  offset: 0 0;
               }
               rel2 { to_x: "base"; to_y: "block2";
                  relative: 0.0 0.0;
                  offset: 96 -1;
               }
            }
         }
         part { name: "block4"; type: RECT;
            mouse_events:  0;
            description { state: "default" 0.0;
               color: 0 0 0 200;
               rel1 { to_x: "base"; to_y: "block1";
                  relative: 1.0 1.0;
                  offset: -97 0;
               }
               rel2 { to: "block2";
                  relative: 1.0 0.0;
                  offset: -1 -1;
               }
            }
         }
         part { name: "base";
            mouse_events:  0;
            description { state: "default" 0.0;
               image.normal: "access_glow.png";
               image.border: 112 112 112 112;
               rel1.offset: -102 -102;
               rel2.offset:  101  101;
               fill.smooth: 0;
            }
         }
      }
   }


위에서 보시다시피 하나의 collections 아래에 다수의 group이 놓여져 있습니다.

focus와 highlight와 관련된 기능이 group으로 구현되어 있네요.


group이 더욱 많이지면 collections에다가 제대로 붙이기 힘들 정도로 길어질 수도 있습니다.

이럴 때는 collections 문 안에서 #include 문을 사용하여 group을 include할 수 있습니다.

같은 파일의 아랫 부분을 보면, #include 문을 사용했습니다.


collections {
   /* ... 생략 ... */
#include "widgets/bg.edc"
#include "widgets/border.edc"
#include "widgets/scroller.edc"
#include "widgets/label.edc"
#include "widgets/button.edc"
#include "widgets/clock.edc"
#include "widgets/datetime.edc"
#include "widgets/dayselector.edc"
#include "widgets/menu.edc"
#include "widgets/frame.edc"
#include "widgets/tooltip.edc"
#include "widgets/hover.edc"
#include "widgets/ctxpopup.edc"
#include "widgets/entry.edc"
#include "widgets/bubble.edc"
#include "widgets/photo.edc"
#include "widgets/thumb.edc"
#include "widgets/icon.edc"
#include "widgets/toolbar.edc"
#include "widgets/notify.edc"
#include "widgets/slideshow.edc"
#include "widgets/win.edc"
#include "widgets/list.edc"
#include "widgets/slider.edc"
#include "widgets/actionslider.edc"
#include "widgets/genlist.edc"
#include "widgets/check.edc"
#include "widgets/radio.edc"
#include "widgets/progressbar.edc"
#include "widgets/separator.edc"
#include "widgets/spinner.edc"
#include "widgets/index.edc"
#include "widgets/gengrid.edc"
#include "widgets/photocam.edc"
#include "widgets/map.edc"
#include "widgets/panes.edc"
#include "widgets/panel.edc"
#include "widgets/conformant.edc"
#include "widgets/calendar.edc"
#include "widgets/colorselector.edc"
#include "widgets/flipselector.edc"
#include "widgets/diskselector.edc"
#include "widgets/fileselector.edc"
#include "widgets/layout.edc"
#include "widgets/segment_control.edc"
#include "widgets/player.edc"
#include "widgets/video.edc"
#include "widgets/naviframe.edc"
#include "widgets/multibuttonentry.edc"
#include "widgets/popup.edc"
#include "ews.edc"
#include "widgets/pointer.edc"
}


위에서 사용한 #include 문은 현재 파일이 있는 위치를 기준으로 상대경로를 사용했습니다.

widgets 디렉토리 아래에 있는 수많은 edc 파일을 include하였지요.

edc 파일들을 하나씩 열어보면 모두 group인 것을 알 수 있습니다.

collections를 품고 있는 edc는 단 하나도 없습니다.

왜냐하면 이미 collections로 감싸졌기 때문입니다.


위의 예에서는 모든 위젯을 하나의 collections에서 관리하고 있습니다.

- 이처럼, 하나의 프로젝트 단위에서는 하나의 collections를 사용할 수 있습니다.

- 혹은, 각각의 위젯을 하나의 collections 단위로 쪼갤 수도 있겠지요.

관리상 용이한 것을 따르시면 됩니다.

꼭 정해진 것은 없습니다.


오늘은 collections에 대해서 간단하게 살펴보았습니다.

다음 시간에는 group에 대해서 훑어보도록 하겠습니다.


그럼 좋은 하루 보내세요~

끝_

+ Recent posts