본문 바로가기

Blog/Flex

Flex 4 Component (2) - What’s new in Flex 4?

What's new in Flex 4?

이전 글에서 컴포넌트의 Lifecycle에 대해서 알아보았습니다. 이번글에서 Flex4 컴포넌트에 대해서 알아보기로 했지만, 컴포넌트 사용과 관련해서 Flex4에서 바뀐 점을 먼저 살펴보겠습니다.

Namespace

  • xmlns:fx="http://ns.adobe.com/mxml/2009"
    Script, Style등의 태그와 Array, String, Number 등의 타입이 fx 네임스페이스로 바뀌었습니다.
  • xmlns:s="library://ns.adobe.com/flex/spark"
    Flex4에서 새롭게 소개된 모든 클래스와 RPC, Graphics 관련 클래스는 이 네임스페이스를 사용합니다.
  • xmlns:mx="library://ns.adobe.com/flex/mx"
    Flex3에서 사용했던 범주와 같습니다.

<fx:Declarations/> tag

nonVisual 컴포넌트(services, Data Models, singletons…)나 UI 상에서 보여지지 않는 것들, child로 추가될 컴포넌트중 아직 추가되지 않은 컴포넌트 등을 이 태그에 정의할 수 있습니다.

Styles

  • Qualified CSS selectors :
  • <Style>
        @namespace s "library://ns.adobe.com/flex/spark";
        s|Button {
        }
    </Style>
  • 네임스페이스는 컴파일타임에 해석되어 런타임에는 qualified className이 사용됩니다.
  •  s|Button à spark.components.Button

Style 사용

  • Multiple Class Selectors:
  •  <Button id="upButton" styleName="default tiny" />
  • ID Selectors:
  •  #upButton { fontSize: 14 }
  • Descendant Selectors:
  •  s|Scrollbar #upButton { baseColor: #FF8888 }
  • Pseudo Selectors:
  •  s|Scrollbar #upButton:over { baseColor: #8888FF } 

State

AddChild, RemoveChild 등이 State에서 사용 되므로써 상태(state)에 대한 코드 결합도가 높아 문서를 점점 더 복잡하게 만들게 되고, 최적화 시키는 문제들로 인해 실제 사용하기가 복잡하고 어려운 점이 있었습니다. Flex4에서는 다음과 같이 간단하게 사용합니다.

<states>
  <State name="login"/>
    <State name="register"/>
    <State name="someOtherState" stateGroups="group1"/>
</states>
<Group>
    <TextBox text="username:" /><TextInput />
    <TextBox text="password:" /><TextInput />
    <Button label="new user?" />
    <Checkbox includeIn="register" label="agree to terms" />
    <Button label="log in" label.register="sign up" />
</Group> 
 

각 state는 <State>tag에 선언하는데 StateGroups 속성으로 그룹화도 가능합니다. state간 child 이동을 위해 <fx:Reparent> tag 를 사용합니다.

MXML Graphics

지원되는 스펙은 다음과 같습니다.

  • Simple Shape primitives (Rectangles, rounded rects, ellipses, circles)
  • Complex Paths (Linear, Quadratic, and Bezier curve segments)
  • Full range of fills and strokes (solid, transparent, bitmap, linear and radial gradients)
  • Masking, filters, blend modes, and more. (blur, glow, dropshadow, screen, multiply…)
  • Color and 2D transformations (rotate, scale, tint, brighten…)
  • Integrated text, bitmaps  
<Graphic>
    <Path data=" ….. ">
        <fill>
            <LinearGradient angle="90">…. </LinearGradient>
        </fill>
    </Path>
    <Path blendMode="screen" data="…" >
        <fill>
            <LinearGradient angle="45">… </LinearGradient>
        </fill>
    </Path>
    <GraphicText text="MXML Graphics">
        <filters>
            <Glow color="#00FF00" strength="3" … />
        </filters>
    </GraphicText>
</Graphic>

이렇게 그래픽 객체를 mxml로 표현함으로써 effect, state, transition등과 같은 효과를 적용하기가 쉬워졌고, Spark 컴포넌트에 쉽게 적용할 수 있게 됬습니다. 이런 GraphicElement는 적은 ovethead와 빠른 렌더링에 최적화 되어있어 퍼포먼스 향상에 도움을 줍니다. 하나의 DisplayObject에 여러 GraphicElement (Ellipse, Line, Path, Bitmap Image..)들이 그려질 수 있습니다. 컴포넌트 역시 DisplayObject이므로 GraphicElement를 내부에 그릴 수 있습니다. DisplayObject는 메모리, 퍼포먼스, 렌더링 최적화를 위해 공유됩니다. 따라서 공유된 요소는 Rotation, Scale, 3D, BlendMode, Alpha, Filter 등의 효과가 공통으로 적용됩니다.

Text

Flash player 10에는 새로운 Low level text engine (FTE)와 이에 대한 text layout library (TLF) 가 제공됩니다. 이전 버전에 비해 향상된 점은 다음과 같습니다.

  • Soft hyphens (we know you've all been missing those!)
  • Baseline control (e.g., superscripts and subscripts)
  • Right, center, and decimal tabs
  • Vertical justification
  • Multiple columns
  • Ligatures, capitalization styles, digit styles
  • Integrated Rendering of device fonts (a.k.a. I can fade and rotate my text FINALLY)
  • Bi-Directional text. etc.

이런 향상된 기능을 바탕으로 새로운 Text 객체를 (SimpleText, RichText, RichEditableText) 제공합니다. 이 Text 객체는 UIComponent를 확장한 컴포넌트가 아님을 주의해야 합니다. 대신 제공되는 Spart 컴포넌트가 이 Text 객체를 기반으로 만들어진 TextInput과 TextArea 컴포넌트(sinnable component)입니다.

TextField VS Text Engine

Flex3 / Halo

Flex4 / Spark 

Based on TextField
Simple layout support
Uses DefineFont3 embedded fonts

Based on Flash Text Engine
Complex layout and editing support
Uses DefineFont4 embedded fonts

embedded fonts can't be shared. (Adobe is working on resolving this issue)

Effects, Animation

GraphicElement도 지원 가능하고, Catalyst 와 같은 툴에서도 사용 가능하도록 좀더 유연하고 새롭게 디자인 되었습니다. floats, integers, colors, vectors, paths 등의 새로운 타입을 지원하고, Auto-reversing 동작이나 복잡한 transition에 대한 정확한 타이밍을 핸들링 할 수 있습니다.

<Animate target="{pane}">
    <MotionPath property="x">
        <KeyFrame time="0" value="200" />
        <KeyFrame time="150" value="250" />
        <KeyFrame time="300" value="400" />
    </MotionPath>
    <MotionPath property="baseColor">
        <interpolator><HSBInterpolator /></interpolator>
        <KeyFrame time="0" value="200" />
        <KeyFrame time="150" value="250" >
            <easer><Sine easeInFraction=".3" /></easer>
        </KeyFrame>
        <KeyFrame time="300" value="400" />
    </MotionPath>
</Animate>

AnimateTransform으로 서로 다른 종류의 transform을 Animate시킬 수 있습니다. 또한 AnimateTransform 의 서브 클래스(AnimateTransformMove, AnimateTransformRotate, AnimateTransformScale)로 3D animation을 지원 합니다.

Container, Layout

Container
Layout 기능과 Container를 분리시켰습니다. Flex3에서 Container는 Container 클래스(UIComponent 파생 클래스)를 상속 받았습니다. 그래서 사실은 필요하지 않은 너무 많은 기능들을 가지고 있었고, – container의 scrollbar는 사용하지 않을 때도 있다 – 기존의 LayoutManager를 이용한 layout 규칙은 container의 비즈니스 로직을 유연성 없는 코드간 강한 결합도를 가지게 하였습니다. 또한 flex4의 새로운 기능인 GraphicElement, 3D effect와 transform을 지원해주지 못하기 때문에 새로운 Container 구조가 필요하게 되었습니다.

  • Group
    UIComponent와 GraphicElement를 모두 지원하고, layout과 contain기능만을 가진 Spark framework에서 가장 낮은 단계의 container 입니다.
  • DataGroup
    List 계열의 기본 container 입니다. (ItemRenderer 사용)

결국 Spark에서 표현되는 모든 것은 Group내에 속해 있게 됩니다.

Children VS Elements

Flex3 / Halo

Flex4 / Spark 

Use the Container Child List
addChild(), removeChild(), etc.
All children are UIComponents

Use the Group Elements list
addElement(), removeElement(), etc.
All elements are UIComponents or GraphicElements

Layout
이전의 layout 모델은 container의 코드와 layout의 코드가 너무 강하게 결합되어 있었습니다. 때문에 하나의 container에서 여러 가지 정렬 방법을 가지는 list를 만들기가 어려웠습니다. 또한 DataProvider로 인해 data와 view를 분리시키긴 하였지만 Flex4에서는 Layout class를 도입하여 view 계층을 더욱 추상화 시켰습니다.

모든 layout 클래스는 - VerticalLayout, HorizontalLayout, TileLayout, BasicLayout (Canvas) -LayoutBase 클래스를 확장합니다. 이 layout 클래스를 이용하여 모든 container, list, skin등을 정렬합니다. 이런 방식은 layout하는 방식을 보다 단순화 하면서도 일관된 방법으로 확장에 용이하도록 하기 위함입니다. 특이한 점은 layout 또한 transform을 지원한다는 것입니다. (Example: Ryan Campbell's layout demo)

Component

이전 버전의 component 역시 view부분의 작은 변경사항에도 component 자체를 패치 시켜야 하는 확장에 어려운 점이 있었습니다. 따라서 Flex4에서는 visual, state, animation, layout 으로부터 data, logic, behavior를 분리시키는 작업을 하였습니다. 그리하여 표시 형태에 구애받지 않는 component-logic을 생성하고, 역시 logic에 구애받지 않는 component-view를 생성할 수 있게 되었습니다.

Button 컴포넌트를 예로 들면 Halo 컴포넌트는 컴포넌트 내부에 view를 포함하면서 view의 일부 속성만을 style등을 이용하여 변경 가능한 구조로 되어 있는 반면 Spark 컴포넌트에서는 view 전체를 Skin으로 떼어내어 data나 logic과 분리된 구조를 갖도록 하였습니다.

Button에 icon을 추가한다고 가정할 때 컴포넌트 수정작업 비교 :

  • Halo Component
    New 생성자를 이용해 인스턴스를 만드는 작업부터 위치, 크기를 변경하는 작업을 모두 Button 컴포넌트와 UIComponent의 logic에 대한 이해와 ActionScript에 대한 지식이 필요로 하는 경우가 있습니다.(거의 대부분의 경우에…)
  • Spark Component
    기본 Button Skin으로부터 MXML을 복사해 아이콘을 생성하기 위해 태그를 추가하고 아이콘의 위치, 크기를 적용하는 모든 작업을 MXML로 마칠 수 있습니다.

Skin - Component

Skin Parts
컴포넌트는 Metadata로 필수 skin part인지 아닌지를 명확히 합니다. 만약 Skin에서 필수 part가 발견되지 않으면 에러를 발생합니다.

[SkinPart(required="true")]
public var labelElement:SimpleText;
Skin implements skin parts

Skin States
역시 Metadata를 통해 컴포넌트에서 정의합니다. 현재 어떤 state인지 상태 변화는 component로부터 skin으로 전달됩니다. 모든 state에 대한 표현이 skin에 구현되어 있어야 하고, 그렇지 않을 경우엔 에러가 발생됩니다.

[SkinState("up")]
[SkinState("down")]

Data
Data는 컴포넌트로부터 skin으로 전달하거나, skin에서 사용된 data-binding에 의해 skin이 컴포넌트로부터 얻을 수도 있습니다만, 에러발생 가능성이나 캡슐화를 고려한다면 전자의 방식을 권합니다.

Style
Skin을 통해 스타일링하는 작업이 쉽기 때문에 주로 색상에 관련된 style이 주가 됩니다. Skin은 어떤 Element가 어떤 Style에 영향을 받는지 명확히 구분할 필요가 있습니다.

이상으로 Flex4에서 새롭게 바뀌거나 추가된 점들을 대충 알아보았습니다. 터무니 없이 부족한 내용이지만 아마 Flex4 기술에 대해서 전체적으로 바라보는 시각을 가지는데 조금이나마 도움이 되었으면 합니다. 다음 글에서는 Skin - Component 관계 및 구조를 좀더 자세히 알아보도록 하겠습니다.

참고

이 글은 Flex4 Overview 내용을 참고로 작성되었습니다.