2007. 11. 20. 15:56
다음의 포스팅은 Peter Ent 블로그Coloring the Background of Cells 포스트의 검쉰 맘대로 해석판입니다.
말이 안되게 타이프 해놓은 것도 있으니(ㅡㅡ;) 그러려니... 하여 주세요 ;)

아래의 결과물은 해당 포스트의 소스를 빌드하여 올려보았습니다.



위의 예제는 총 5개로 되어 있습니다만, 4개만 설명 합니다.
1. 아이템렌더러(itemRenderer)를 이용하여 특정컬럼의 배경색을 바꾸기 (itemRenderer Tab)
2. 컬럼에 직접 배경색을 지정하기 (backgroundColor Tab)
3. drawColumnBackground function을 재정의하여 배경색에 alpha 값을 주기 (backgroundAlpha Tab)
4. drawRowBackground function을 재정의하여 row에 배경색을 주기 (Custom Row Background Tab)



1. 아이템 렌더러(itemRenderer)를 이용하여 특정 컬럼의 배경색을 바꾸기 
   (itemRenderer Tab 참고)

특정 Cell의 배경색을 바꾸려면 아이템렌더러(itemRenderer)가 필요합니다.
아이템렌더러(itemRenderer)는 데이터그리드(Datagrid)의 전체에 적용하거나 특정 컬럼에 적용이 가능합니다만,
아래의 아이템렌더러(itemRenderer) 예제에는 Year 컬럼에만 적용하도록 하겠습니다.

간단하게 Label을 상속받아 updateDisplayList function을 재정의 하여서
Year의 값을 판단(Year의 값이 2000년 이전이면 파란색, 2000년 이후이면 녹색) 하여
Label에 파란색 또는 녹색의 사각형을 그려 배경색을 나타내고 있습니다.

<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
    <![CDATA[

      import flash.geom.Matrix;
      import flash.display.GradientType;
      import flash.display.Graphics;

      override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
      {
        super.updateDisplayList(unscaledWidth,unscaledHeight);

        var m:Matrix = new Matrix();
        m.createGradientBox(unscaledWidth,unscaledHeight);

        var g:Graphics = graphics;
        var colors:Array = (data.col3 < 2000 ? [0x0000CC,0x0000FF] : [0x00CC00,0x00FF00]);

        g.clear();
        g.beginGradientFill(GradientType.LINEAR, colors, [0.2,0.6], [0,255], m);
        g.drawRect(0, -2, unscaledWidth, unscaledHeight+4 );
        g.endFill();
      }
    ]]>
  </mx:Script>
</mx:Label>

아래는 AS Class 로 동일하게 만들어본 아이템 렌더러입니다.
package
{
  import flash.geom.Matrix;
  import flash.display.GradientType;
  import flash.display.Graphics;
  import mx.controls.Label;

  public class ColoredBackgroundItemRenderer extends Label
  {
    public function ColoredBackgroundItemRenderer()
    {
      super();
    }

    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
      super.updateDisplayList(unscaledWidth,unscaledHeight);

      var m:Matrix = new Matrix();
      m.createGradientBox(unscaledWidth,unscaledHeight);

      var g:Graphics = graphics;
      var colors:Array = (data.col3 < 2000 ? [0x0000CC,0x0000FF] : [0x00CC00,0x00FF00]);

      g.clear();
      g.beginGradientFill(GradientType.LINEAR, colors, [0.2,0.6], [0,255], m);
      g.drawRect(0, -2, unscaledWidth, unscaledHeight+4 );
      g.endFill();
    }
  }
}



2. 컬럼에 직접 배경색을 지정하기
   (backgroundColor Tab 참고)




단지 컬럼의 모든 Cell에 배경색을 지정하고 싶은 것이라면 아이템 렌더러를 만들 필요는 없습니다.
아래와 같이 데이터그리드(Datagrid) 컬럼에 있는 backgroundColor 속성을 이용하면 쉽게 가능합니다.

<mx:DataGridColumn headerText="Make" backgroundColor="0xCC0000" dataField="col1"/>

0xCC0000은  빨강색() 입니다. backgroundColor Tab에서 Make 컬럼에 적용되어 있습니다.
backgroundColor="red" 같은 경우도 가능합니다.



3. drawColumnBackground function을 재정의하여 배경색에 alpha 값을 주기
   (backgroundAlpha Tab 참고)



데이터그리드(Datagrid) 컬럼은 투명도(Alpha)를 주는 속성이 없습니다.
하지만  데이터그리드(Datagrid)에 있는 drawColumnBackground function을 재정의하여 투명도를 줄 수 가 있습니다.
데이터그리드(Datagrid)를 상속받아서 만든 Class에서 아래와 같이 drawColumnBackground function을 재정의 합니다.

override protected function drawColumnBackground(s:Sprite, columnIndex:int, color:uint, column:DataGridColumn):void
{
  super.drawColumnBackground(s,columnIndex,color,column);

  var background:Shape = Shape(s.getChildByName(columnIndex.toString()));
 
  if( background )
  {
    background.alpha = 0.5;
  }
}

하지만 위의 코드에서는 투명도가 0.5로 하드코딩 되어 있으므로 권장할 만한 코드가 안됩니다.
그래서 다음과 같이 Class 내에 투명도를 저장할 변수 columnBackgroundAlpha를 정의합니다.

public var columnBackgroundAlpha:Number = 1;

그리고 재정의한 drawColumnBackground function의 코드를 변수 columnBackgroundAlpha에 의해
투명도를 변경할 수 있도록 다음과 같이 수정합니다.

backgroundAlpha = columnBackgroundAlpha;

외부에서 투명도는 아래와 같이 변경 할 수 있습니다.

<local:ColoredBackgroundDataGrid columnBackgroundAlpha="0.3" ... >



4. drawRowBackground function을 재정의하여 row에 배경색을 주기
   (Custom Row Background Tab 참고)


특정 컬럼이 아닌 한 줄(row)의 배경색을 바꾸려면 데이터그리드(Datagrid)를 상속받은 Class에서
아래와 같이 drawRowBackground function을 재정의 하여 배경색을 바꿀 수 있습니다.

year의 값이 2000년 이전이면 오렌지색, 2000년 이후면 흰색, 값이 없으면 녹색으로 출력하도록 하였습니다.

override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number, color:uint, dataIndex:int):void
{
  var dp:ArrayCollection = dataProvider as ArrayCollection;
  var item:Object;

  if( dataIndex < dp.length ) item = dp.getItemAt(dataIndex);

  if( item != null && item.year < 20000 ) color = 0xFF8800;
  else if( item != null && item.year>= 2000 ) color = 0xFFFFFF;
  else color = 0x00CC00;

  super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}

하지만, 위의 코드는 색깔과 기준값들이 하드코딩되어 있어 권장할만한 코드가 못됩니다.
이 때, 배경색으로 쓰일 색을 외부에서 따로 구현할 수 있도록 하여 해결하도록 하겠습니다.

외부의 function을 쓰기 위해 Class에 아래와 같이 속성을 하나 추가하겠습니다.

public var rowColorFunction:Function;

그리고 아래와 같이 color값을 위에서 만든 Function에서 받아올 수 있도록 하여 줍니다.

override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number, color:uint,dataIndex:int):void
{
  if( rowColorFunction != null )
  {
    var dp:ArrayCollection = dataProvider as ArrayCollection;
    var item:Object;
   
    if( dataIndex < dp.length ) item = dp.getItemAt(dataIndex);

    color = rowColorFunction( item, rowIndex, dataIndex, color );
  }
 
  super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}

그리고 아래와 같이 rowColorFunction에 외부의 function을 지정하여 주고,

<local:ColoredBackgroundDataGrid rowColorFunction="determineColor" ... >

지정된 determineColor function은 아래와 같이 정의합니다.

private function determineColor( item:Object, rowIndex:int, dataIndex:int, oldColor:uint ) : uint
{
  if( item == null ) return 0x00CC00; // green are empty rows
  if( item.year< 2000 ) return 0xFFCC00;
  else if( item.year >= 2000 ) return 0xFFFFFF;
}

이제 정의 하였던 Class 외부에서 rowColorFunction에 알맞는 function을 정의하여 배경색을 변경 할 수 있게 되었습니다.