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