이 글은 Flex3 기준 입니다.

Container 클래스도 다른 컨트롤과 마찬가지로 UIComponent를 상속 받습니다.
Container 클래스를 상속받은 다양한 컨테이너들은 각각 나름대로의 방식으로 자식 컨트롤들을 배치 합니다.
만약 자식 컨트롤의 크기(width, hetight)가 변경된다면, 기본적으로 부모 컨테이너는 자식 컨트롤들을 자동으로 다시 배치 합니다. 이 때 만약 자식 컨트롤의 크기가 변경 되더라도, 부모 컨테이너가 자식 컨트롤들을 다시 배치하는 것을 막으려면 autoLayout 속성을 false로 설정 하면 됩니다. autoLayout 속성의 역할은 다음과 같습니다.

autoLayout
true일 경우, 자식의 크기가 변경되면 부모 컨테이너는 자식들을 다시 배치한다.
false일 경우, 자식이 추가되거나 제거될 때 단 한번만 자식들을 다시 배치한다.
디폴트로 true.

이 내용을 Flex SDK의 소스코드에서 확인해보면...
컴포넌트의 크기가 변경되었을 경우, 부모의 invalidate~() 메소드 2개를 호출하는 코드를 확인할 수 있습니다.
override public function set width(value:Number):void
{
    if (explicitWidth != value)
    {
        explicitWidth = value;

        // We invalidate size because locking in width
        // may change the measured height in flow-based components.
        invalidateSize();
    }

    if (_width != value)
    {
        invalidateProperties();
        invalidateDisplayList();

        var p:IInvalidating = parent as IInvalidating;
        if (p && includeInLayout)
        {
            p.invalidateSize();
            p.invalidateDisplayList();
        }

        _width = value;

        dispatchEvent(new Event("widthChanged"));
    }
}

그리고 자식의 크기가 변경되어 부모는 다시 배치를 시도하지만, autoLayout 속성에 따라 다시 배치할지 안할지를 경정하는 코드를 확인할 수 있습니다.
override public function validateDisplayList():void
{
    // trace(">>Container validateLayoutPhase " + this);
   
    var vm:EdgeMetrics;

    // If autoLayout is turned off and we haven't recently created or
    // destroyed any children, then don't do any layout
    if (_autoLayout || forceLayout)
    {
        doingLayout = true;
        super.validateDisplayList();
        doingLayout = false;
    }
    else
    {
         Layout borders, Panel headers, and other border chrome.
         layoutChrome(unscaledWidth, unscaledHeight);
     }
}
(forceLayout 속성은 autoLayout 속성이 false일 경우, 자식이 추가 되거나 제거될 때 사용되는 플래그 입니다.)

위 코드에서 autoLayout 속성이 true라면, validateDisplay() 메소드가 호출될 것이고, 그것에 의해서 결국updateDisplayList() 메소드가 호출됨으로써 자식 컨트롤을 다시 배치하게 됩니다. Container 클래스의 updateDisplayList() 메소드에서는 layoutChrome() 이라는 메소드를 호출하게 됩니다. 이것의 흐름을 정리해보면 다음과 같습니다.

(autoLayout == true) -> updateDisplayList() -> layoutChrome()

그리고 다시 위 코드를 보면 autoLayout 속성이 false일 경우 layoutChrome() 메소드만 별도로 호출하는 코드를 확인할 수 있습니다. 이것까지 합쳐 흐름을 다시 정리해보면 다음과 같습니다.

(autoLayout == true) -> updateDisplayList() -> layoutChrome()
(autoLayout != true) -> layoutChrome()

감 잡으셨나요? autoLayout 속성이 true이든 false이든 자식 컨트롤의 크기가 변경되면, 부모 컨테이너의layoutChrome() 메소드는 반드시 호출 됩니다. 이쯤에서 layoutChrome() 메소드의 역할을 알아보겠습니다.

layoutChrome()
컨테이너의 경계선을 정의한다.
Panel의 경우 layoutChrome() 메소드에서 경계선 및 타이틀바를 정의한다.

그렇다면 layoutChrome() 메소드는 왜 updateDisplayList() 메소드로부터 따로 독립 했을까요?
그 이유는 layoutChrome() 메소드의 역할 자체에 있습니다. 자식 컨트롤의 크기가 변경되었을 경우, autoLayout 속성에 상관없이 컨테이너의 경계선을 다시 그리기 위함 입니다.


※ 보너스 정보
absolute 형식의 레이아웃을 지원하는 컨테이너의 경우, 자식 컨트롤의 크기가 변경되었을 때 뿐만 아니라 좌표가 변경되었을 경우에도 자식 컨트롤을 다시 배치 합니다. 하지만 UIComponent의 좌표 속성(x, y)에는 자신만 변경을 하고, 부모 컨테이너의 invalidate~() 메소드를 호출하지 않습니다. 그럼에도 불구하고 자식의 좌표가 변경 되었는지 감지하는 이유는, 자식이 추가될때 Move 이벤트 리스너를 장착하기 때문 입니다. 이것은 absolute 형식의 레이아웃을 지원하는 컨테이너에만 해당하는 내용이며, 그 외의 모든 컨테이너는 크기가 변경되었을 경우만 자식들을 다시 배치 합니다.

신고
Posted by 째코


티스토리 툴바