달력

5

« 2024/5 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31


출처 : http://blog.daum.net/nyx21/7577691

 출처  - 자바 개발자를 위한 이클립스 바이블 제 2판 (피어슨에듀케이션코리아) p.287~288



목적확장점
오브젝트 레이블에 텍스트나 아이콘 장식 추가org.eclipse.ui.decorators
Window > Show View 메뉴 선택에 새로운 뷰 기여org.eclipse.ui.views
새로 만들기 마법사org.eclipse.ui.newWizards
표준 Export… 과 Import 메뉴 선택에 새로운 마법사 기여org.eclipse.ui.exportWizards
org.eclipse.ui.importWizards
표준 File > New 메뉴 선택에 새로운 마법사 기여org.eclipse.ui.newWizards
Window > Preferences 대화상자에 설정 페이지 기여org.eclipse.ui.preferencePages
오브젝트의 프로퍼티 대화상자에 페이지 기여org.eclipse.ui.propertyPages
리소스에 대한 새로운 편집기 정의
Open With 메뉴 분기에 선택으로 보인다.
org.eclipse.ui.editors
Window > Open Perspective 메뉴 선택에 대한 새로운 퍼스
펙티브 정의. 새로운 퍼스펙티브의 숏컷, 뷰 숏컷 그리고 기
존의 퍼스펙티브에 액션 집합 추가
org.eclipse.ui.perspectives
org.eclipse.ui.perspectiveExtentions
워크벤치 윈도우 메뉴 바 또는 툴바에 액션 기여org.eclipse.ui.actionSets
퍼스펙티브에서 지정된 뷰/편집기가 열려 있다면 웨크벤치
윈도우 메뉴 바 또는 툴바에 액션을 기여
org.eclipse.ui.actionSetPartAssociations
편집기의 툴바나 메뉴 선택에 액션 기여org.eclipse.ui.editorActions
편집기, 뷰 또는 객체의 콘텍스트 메뉴에 액션 기여org.eclipse.ui.popupMenus
뷰의 툴바나 풀다운 메뉴에 기여org.eclipse.ui.viewActions
Help > Help Contents 선택으로 활용 가능한 온라인 도움말
정의
org.eclipse.ui.help
org.eclipse.help.contentProducer
네비게이터 뷰의 Filter… 메뉴 선택에 대한 추가적인 필터
정의
org.eclipse.ui.ide.resourceFilters
기존의 리소스 또는 새로운 리소스 타입에 대해 자신만의
점진적인 빌드 과정 정의(Project > Rebuild Project).
프로젝트 기능을 향상
org.eclipse.core.resources.builders
org.eclipse.core.resources.natures
사용자 정보로 리소스에 태그를 붙임. 마커는 태스크 뷰나,
텍스트 편집기의 수직 표시자와 같은 뷰나 편집기와 아웃
라인 뷰에서 레이블 장식으로 표시될 수 있다.
org.eclipse.core.resources.markers
만들어져 있는 텍스트 편집기, JFace Text 는 사용자의 일관
된 편집 경험을 보장하기 위해 화장 가능하고 재사용 가능
한 텍스트 편집기를 제공한다. 그것을 알맞게 조정하여 표
시자에서 유일한 텍스트 주석에 대한 추가적인 요구, 라인
숫자, 구문 강조, 내용 돕기와 같은 추가적인 정보를 알려줄
수 있다.
org.eclipse.core.filebuffers.documentSetup
org.eclipse.ui.editors.templates
사용자의 행동에 기반하여 활용 가능한 옵션의 수 줄이기org.eclipse.ui.activities


:
Posted by 라면스프
2013. 1. 29. 15:43

SVN 권한 설정 Enjoy/etc2013. 1. 29. 15:43


출처 : http://ummae.tistory.com/197



SVN 권한 설정


svnserve.conf

[general]
anon-access=none
auth-access = write
password-db = passwd
authz-db = authz
realm = Kanji_Proj

요로코롬 짧아진다. 그럼 각각의 의미를 알아 보자.

[general]
anon-access=none           #인증되지않은(즉 계정이 없는) 사용자에 대해 접근을 거부한다.
auth-access = write          #인증된 사용자에 대해 쓰기 권한을 준다.
password-db = passwd     # 인증된 사용자에 대한 계정 정보(아이디/패스) 정보가 기록된 파일명을 의미한다.(기본값 passwd) 
authz-db = authz              # 인증된 사용자에 대해 저장소에 대한 권한 설정이 기록된 파일명(기본값)
#realm = Kanji_Proj             #현재 파일에 해당되는 저장소의 영역에 대해 설정하는 것인데 여기서는 주석처리로 하고 넘어가자.(ㅌㅌ)

즉, 인증된 사용자에게 저장소의 접근권한을 일체 주지 않고, 인증된 사용자에게만 접근을 허용하는 그런 의미를 갖는 svnserve.conf파일이 되겠다. 

다음으로 passwd 파일을 살펴보자.

passwd 

[users]
# harry = harryssecret
# sally = sallyssecret

aaa = a
bbb = b
ccc = c

= 를 기준으로 왼쪽이 아이디 오른족이 비밀번호가 된다. 
id: aaa, pw: a
id: bbb, pw: b 이런식이다.

마지막으로 authz

authz

[groups]
# harry_and_sally = harry,sally
gABC = aaa, bbb, ccc

# [/foo/bar]
# harry = rw
# * =

# [repository:/baz/fuz]
# @harry_and_sally = rw
# * = r

[/]
@gABC = r

[ABC:/]
* = r
@gABC  = rw

authz 파일의 의미를 살펴보자

[groups]
# harry_and_sally = harry,sally   # 사용자를 그룹단위로 묶을 수 있다.
gABC = aaa, bbb, ccc               # 즉, 사용자 aaa, bbb, ccc를 묶어서 gABC라는 그룹으로 관리.

# [/foo/bar]
# harry = rw
# * =

# [repository:/baz/fuz]             #repository저장소의 /baz/fuz위치에 대한 권한
# @harry_and_sally = rw            #@<-의 의미는 그룹을 뜻한다. harry_and_sally 그룹에 읽기/쓰기권한을 준다.
# * = r                                     # * 는 모든 사용자를 의미한다. 모든 사용자에게 읽기 권한을 준다.            

[ABC:/]                                 #ABC:/저장소
* = r                                       #모든 사용자에게 읽기 권한을 준다.
@gABC  = rw                          #gABC그룹에게 읽기/쓰기 권한을 준다.


주의 1. authz 파일에 보면 *(와일드카드)가 모든 사용자를 의미한다고 했는데, 만약 svnserve.conf 파일에 anon-access=none (인증된 사용자에 대한 권한접근을 거부) 설정이 안되 있으면 말 그대로 아이디가 있건 없고 모든 접속한 사용자에 대한 권한이 되 버린다. 하지만 anon-access=none 이 설정되 되어 있다면 아이디/비번을(계정) 을 갖고 있는 사용자들에 대한 권한 설정이 될 것이다.

:
Posted by 라면스프
2013. 1. 21. 11:06

SVN(Subversion) 명령어 사용 방법 Enjoy/etc2013. 1. 21. 11:06

출처 : http://blog.naver.com/sjh77ch/62179981



SVN(Subversion)은 형상관리를 위한 도구이다. 다시 말하면 소프트웨어 개발의 버전 관리 시스템이다.

 

SVN에서 많이 사용되는 명령어는 다음과 같다.

 

checkout 또는 co - 저장소(repository)에서 로컬 작업공간으로 소스를 받아오는 것.

$ svn checkout 저장소URL [PATH...]

: 지정된 로컬경로에 저장소의 소스가 복사된다. 경로가 지정안되면 저장소URL의 맨마지막 디렉토리명이 저장될 디렉토리로 사용되어진다. -r 옵션으로 리비전을 지정한 경우엔 해당 리비전의 소스를 가져온다.

예제) svn checkout -r 99 http://repository/src src

설명) 저장소에서 리비전 번호 99의 src경로내의 소스를 가져온다.

 

update 또는 up - 저장소(repository)의 최신 내용으로 로컬 소스를 갱신 한다.

$ svn update [PATH...]

: 기본적으로 최신 리비전을 반영한다. 그러나 -r 옵션으로 리비전을 지정한 경우엔 그 리비전으로 맞춘다.

 

commit 또는 ci - 로컬에서 수정된 내용을 저장소에 적용시킨다.

$ svn commit [PATH...]

: 기본적으로 이 명령을 내리면 수정 사항을 코멘트할 수 있게 로그 편집기가 실행된다. lock된 파일이나 디렉토리는 commit성공후 자동적으로 unlock된다.

 

lock - 저장소의 파일이나 디렉토리를 잠근다.

$ svn lock TARGET

: lock이 걸린 파일이나 디렉토리는 다른 사용자가 변경하여 commit할 수 없다. 해당 경로의 작업이 너무 방대하여 그 동안 다른 사용자가 수정하지 못하도록 할때 유용.

 

unlock - 저장소의 잠근 파일이나 디렉토리를 풀어준다.

$ svn unlock TARGET

: lock의 반대. 기본적으로 lock을 건 사용자가 풀어줘야 한다.

 

add - 새 파일이나 디렉토리를 추가한다.

$ svn add PATH...

: add 명령은 지정된 PATH의 새로운 파일이나 디렉토리를 버전관리 대상에 등록할 뿐이므로, add후 commit 명령을 수행해야만 실제로 저장소에 해당 파일이 추가된다.

 

delete 또는 del, remove, rm - 파일이나 디렉토리를 제거한다.

$ svn delete PATH...(URL)

: delete 명령은 add와 반대로 해당 PATH의 파일이나 디렉토리을 버전관리 대상에서 삭제한다. 역시 commit 명령을 수행해야만 실제로 저장소에서 해당 목록이 제거된다. URL로 지정했을 경우 해당 목록은 즉시 저장소에서 제거된다.

 

 

copy 또는 cp - 로컬 사본이나 저장소 내용을 복사한다. 브랜치(branch)를 만들기 위해 사용.

$ svn copy SRC  DST

: SRC가 로컬경로이고 DST도 로컬경로일 경우, 로컬복사되고 commit시 저장소에 복사 목록이 추가 저장된다. SRC가 로컬경로이고 DST가 저장소URL일 경우, URL에 복사되고 즉시 commit됨. SRC가 저장소URL이고 DST가 로컬경로일 경우, 로컬로 checkout하고 commit시 저장소에 해당 사본이 추가.

SRC가 저장소URL이고 DST도 저장소URL일 경우, 저장소 내에 브랜치(branch)를 만듬.

 

move 또는 mv, rename, ren - 파일이나 디렉토리의 이름을 바꾸거나 이동시킨다. 이 명령은 copy후 delete와 같다.

$ svn move SRC  DST

: SRC가 로컬경로이고 DST도 로컬경로일 경우, 로컬로 rename 또는 move되고 commit시 저장소에 반영된다. SRC가 저장소URL이고 DST도 저장소URL일 경우, 저장소에서 rename,move가 바로 commit됨.

 

info - 해당 파일에 대한 정보를 출력한다.

$ svn info TARGET

: TARGET의 저장소 URL경로나 마지막 수정 일자등에 대한 정보를 보여준다.

 

log - 해당 경로나 파일의 로그( 리비전에 따라 변경된 내역)를 볼수 있다.

$ svn log [PATH]

: 지정된 로컬 PATH에 대한 로그를 출력한다. -r 옵션을 지정하면 출력할 리비젼 범위등을 정할 수 있다.

예제) svn log -r 30:100 test.c

설명) 리비전 번호 30~100 내에서 test.c에 대한 로그를 출력한다.

 

status 또는 stat, st - 로컬 경로의 파일이나 디렉토리의 상태를 보여준다.

$ svn status [PATH]

: 해당 파일이 수정, 추가되었는지 등의 정보를 보여준다. -u 옵션을 주면 저장소의 최신 리비젼이 얼마인지 알려준다.

 

diff 또는 di - 서로 다른 리비젼 간에 차이점을 출력해준다.

$ svn diff [-r N:MTARGET

: 지정된 파일이나 경로에 대해 이전 리비젼하고 차이점을 보여준다. -r 을 지정하면 리비젼 N과 M사이의 차이점을 출력해준다.

예제) svn -r 30:45 test

설명) test 경로내에서 리비젼 번호 30과 45의 차이점을 출력해준다.

 

merge - 두 source 사이에 변경 내용을 작업 경로에 적용해준다.

1. $ svn merge URL1[@NURL2[@M] [PATH]

2. $ svn merge [-r N:MSOURCE [PATH]

: 1. URL1[리비젼 N]과 URL2[리비젼 M]을 비교하여, 변경 내용을 작업경로에 적용한다.

  2. SOURCE의 리비젼 N과 M을 비교하여, 해당 작업경로에 적용한다.

merge는 branch로 분리된 source에 대해 각각의 변경 내용을 현재의 작업에 병합하고자 할때 유용하다.

 

blame 또는 praise, annotate, ann - 지정한 파일이나 URL의 내용 수정내역을 각 라인별로 보여준다.

$ svn blame TARGET

: 해당 파일의 각 라인에 대해 리비젼과 작성자를 나타내 준다. 누가 언제 어떤행을 수정했는지 알수 있음.

 

import - 파일과 디렉토리를 저장소에 추가한다.

$ svn import [PATHURL

 

: URL에 지정된 PATH의 하위 디렉토리는 재귀적으로 추가되며, 필요시 상위 디렉토리가 자동으로 생성된다.

 

export - 저장소에서 순수하게 프로그램 소스만 가져온다.

$ svn export URL [PATH]

: export는 버전관리를 위한 부속 파일들은 제외하고 순수한 소스만 받아오기 때문에, 주로 source release 용도로 사용되게된다. -r 옵션을 지정해서 해당 리비젼의 소스를 받아올 수 있다.

:
Posted by 라면스프
2013. 1. 14. 16:44

[C] HTTP POST로 파일 업로드하는 코드 Enjoy/etc2013. 1. 14. 16:44

출처 : http://visu4l.tistory.com/396



[C] HTTP POST로 파일 업로드하는 코드


Java나 C++ objective-c는 http 용 기본 라이브러리가 있어서 편하지만


C용은 직접 만들어 써야한다. 이미 제작해서 라이브러리는 배포하는곳도 있지만 간단한 파일을 보내는데


어마어마한 라이브러리는 포함시킬필요는 없다.


그래서 C 언어로 간한히 POST 업로드하는 코드를 만들어 놨다.


body를 만드는 부분이 중요하다. 그렇기 때문에 상세히 분석후 수정하여 사용하자.



예문

:
Posted by 라면스프
2013. 1. 10. 10:10

Flex DataGrid ItemRenderer #3 Enjoy/FLEX2013. 1. 10. 10:10

출처 : http://igna84.blogspot.kr/2010/03/flex-datagrid-itemrenderer-3-%EB%98%90%EB%8B%A4%EB%A5%B8-%EC%A0%84%EC%9F%81%EC%9D%98-%EC%84%9C%EB%A7%89.html



Flex DataGrid ItemRenderer #3- 또다른 전쟁의 서막

지난 시간 제기한 문제점은 아래와 같았습니다.

 

1. "Y", "N" 값으로만 작동하게 되어있다.

2. CheckBox를 클릭하면 뭔가 다른 행동을 하고 싶을땐 어떻게 하나.

 

외부에서 들어오는 데이터가 "0"이나 "1"이면 어떻한다?(혹은 true 나 false일지도..)

CheckBox를 클릭하면 Alert 창이 떠야한다면?

 

이럴때마다 ItemRenderer를 열어서 수정해야한다면 말이 안되겠지요.

일단 2번 같은 경우는 제가 알기로는 두가지 방법이 있습니다만 그중 하나는 Bubbles라는 이벤트 속성을 이용하는 방법입니다만 ItemRenderer에서 이벤트를 발생시키면서 bubbles 속성을 true로 지정해주면 DataGrid 밖에서 이벤트를 받아올 수 있지요.

다만.. bubbles라는 녀석의 특성상 데이터가 많이 꼬일 염려가 있다는게 문제입니다.

(꼬인다는건 "디버깅"이 어려워질 수 있다는 말을 쉽게 풀어 쓴 말입니다.)

 

그래서 저는 가장 확실한 방법으로 CallBack 함수를 지정해 놓는 방법을 선택했습니다.

아래의 코드를 봐주세요.

 

Main.mxml
[code xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:renderers="classes.controls.renderers.*">
<mx:Script>
    <![CDATA[
    import mx.collections.ArrayCollection;
    import mx.controls.Alert;

    [Bindable]
    private var ac:ArrayCollection = new ArrayCollection([
                                        {index:1, description:"test1", toggle:"Y"},
                                        {index:2, description:"test2", toggle:"N"},
                                        {index:3, description:"test3", toggle:"N"},
                                        {index:4, description:"test4", toggle:"Y"},
                                        {index:5, description:"test5", toggle:"N"},
                                        {index:6, description:"test6", toggle:"N"},
                                        {index:7, description:"test7", toggle:"Y"},
                                        {index:8, description:"test8", toggle:"N"},
                                        {index:9, description:"test9", toggle:"N"},
                                        {index:10, description:"test10", toggle:"N"},
                                        {index:11, description:"test11", toggle:"N"},
                                        {index:12, description:"test12", toggle:"N"}
                                        ]);

    public function checkBoxRendererClickHandler(data:Object):void
    {
        Alert.show("click by " + data.description);
    }
    ]]>
</mx:Script>
<mx:DataGrid dataProvider="{ac}">
    <mx:columns>
        <mx:DataGridColumn headerText="index" dataField="index" />
        <mx:DataGridColumn headerText="description" dataField="description" />
        <mx:DataGridColumn headerText="radio" dataField="toggle">
            <mx:itemRenderer>
                <mx:Component>
                    <renderers:CheckBoxRenderer onClickFunction="{outerDocument.checkBoxRendererClickHandler}" />
                </mx:Component>
            </mx:itemRenderer>
        </mx:DataGridColumn>
    </mx:columns>
</mx:DataGrid>
</mx:Application>
[/code]

CheckBoxRenderer.as
[code as3]
package classes.controls.renderers
{
//-----------------------------------------------------------------------------
//
//  Import
//
//-----------------------------------------------------------------------------
import flash.events.MouseEvent;

import mx.core.IDataRenderer;
import mx.controls.CheckBox;
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.mx_internal;
import mx.events.FlexEvent;

use namespace mx_internal;

public class CheckBoxRenderer extends CheckBox
{
    //-----------------------------------------------------------------------------
    //
    //  Constructor
    //
    //-----------------------------------------------------------------------------
    /**
     *  Constructor.
     */
    public function CheckBoxRenderer()
    {
        super();
    }

    //-----------------------------------------------------------------------------
    //
    //  Variables
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  데이터 변경 확인 플래그
     */
    private var dataChanged:Boolean = false;

    //-----------------------------------------------------------------------------
    //
    //  Properties
    //
    //-----------------------------------------------------------------------------
    //-------------------------------------
    //  onClickFunction
    //-------------------------------------
    /**
     *  @private
     */    
    private var _onClickFunction:Function;
    /**
     *  클릭시 실행할 콜백함수 속성
     */
    public function set onClickFunction(value:Function):void
    {
        _onClickFunction = value;
    }
    /**
     *  @private
     */    
    public function get onClickFunction():Function
    {
        return onClickFunction;
    }
    //-----------------------------------------------------------------------------
    //
    //  Override Properties
    //
    //-----------------------------------------------------------------------------
    override public function set data(value:Object):void
    {
        super.data = value;

        dataChanged = true;
        invalidateProperties();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();

        if(dataChanged)
        {
            dataChanged = false;
            updateProperties();
        }
    }

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

        currentIcon.x = (unscaledWidth - currentIcon.width) / 2;
    }

    //-----------------------------------------------------------------------------
    //
    //  Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  CheckBox의 속성을 변경
     */
    private function updateProperties():void
    {
        if(listData.label == "Y")
        {
            selected = true;
        }
        else
        {
            selected = false;
        }

        invalidateDisplayList();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override EventHandler
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function clickHandler(event:MouseEvent):void
    {
        super.clickHandler(event);

        //data[DataGridListData(listData).dataField] = selected ? "Y" : "N";

        if(selected)
        {
            data[DataGridListData(listData).dataField] = "Y";
        }
        else
        {
            data[DataGridListData(listData).dataField] = "N";
        }

        if(_onClickFunction != null)
        {
            _onClickFunction(data);
        }
    }
}
}
[/code]

 

위와같이 코딩하게 되면 아래와 같은 산출물이 나오게 됩니다.

 

 

CheckBoxRenderer를 클릭해보세요. Alert창이 뜨는걸 볼 수 있지요.

그럼 2번 문제는 해결된것 같습니다. 그럼 1번 문제인 "Y", "N" 이외의 다른 문자열이 들어올땐 어떻게 할까요? 라는 문제는 방금 2번 문제를 해결한것과 같이 해결하면 될것 같습니다.

아래 처럼요.

 

[code as3]
package classes.controls.renderers
{
//-----------------------------------------------------------------------------
//
//  Import
//
//-----------------------------------------------------------------------------
import flash.events.MouseEvent;

import mx.core.IDataRenderer;
import mx.controls.CheckBox;
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.mx_internal;
import mx.events.FlexEvent;

use namespace mx_internal;

public class CheckBoxRenderer extends CheckBox
{
    //-----------------------------------------------------------------------------
    //
    //  Constructor
    //
    //-----------------------------------------------------------------------------
    /**
     *  Constructor.
     */
    public function CheckBoxRenderer()
    {
        super();
    }

    //-----------------------------------------------------------------------------
    //
    //  Variables
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  데이터 변경 확인 플래그
     */
    private var dataChanged:Boolean = false;
    //-----------------------------------------------------------------------------
    //
    //  Properties
    //
    //-----------------------------------------------------------------------------
    //-------------------------------------
    //  onClickFunction
    //-------------------------------------
    /**
     *  @private
     */    
    private var _onClickFunction:Function;

    /**
     *  클릭시 실행할 콜백함수 속성
     */
    public function set onClickFunction(value:Function):void
    {
        _onClickFunction = value;
    }

    /**
     *  @private
     */    
    public function get onClickFunction():Function
    {
        return onClickFunction;
    }

    //-------------------------------------
    //  selectedFlag
    //-------------------------------------
    /**
     *  @private
     */    
    private var _selectedFlag:Array = ["Y", "N"];

    /**
     *  <p>true, false를 처리할 flag를 Array형태로 받아 처리.</p>
     *  <p>이때 selectedFlag의 length는 2를 초과할 수 없음.</p>
     *  @default    ["Y", "N"]
     */    
    public function set selectedFlag(value:Array):void
    {
        if(value.length > 2)
        {
            throw(new Error("selectedFlag:Array의 값은 두개를 초과할 수 없습니다."));
        }
        _selectedFlag = value;
    }

    /**
     *  @private
     */    
    public function get selectedFlag():Array
    {
        return _selectedFlag;
    }
    //-----------------------------------------------------------------------------
    //
    //  Override Properties
    //
    //-----------------------------------------------------------------------------
    override public function set data(value:Object):void
    {
        super.data = value;
        dataChanged = true;
        invalidateProperties();
    }
    //-----------------------------------------------------------------------------
    //
    //  Override Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();

        if(dataChanged)
        {
            dataChanged = false;

            updateProperties();
        }
    }

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

        currentIcon.x = (unscaledWidth - currentIcon.width) / 2;
    }

    //-----------------------------------------------------------------------------
    //
    //  Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  CheckBox의 속성을 변경
     */
    private function updateProperties():void
    {
        if(data[DataGridListData(listData).dataField] == _selectedFlag[0])
        {
            selected = true;
        }
        else
        {
            selected = false;
        }

        invalidateDisplayList();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override EventHandler
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function clickHandler(event:MouseEvent):void
    {
        super.clickHandler(event);

        //data[DataGridListData(listData).dataField] = selected ? _selectedFlag[0] : _selectedFlag[1];

        if(selected)
        {
            data[DataGridListData(listData).dataField] = _selectedFlag[0];
        }
        else
        {
            data[DataGridListData(listData).dataField] = _selectedFlag[1];
        }

        if(_onClickFunction != null)
        {
            _onClickFunction(data);
        }
    }
}
}
[/code]

이렇게 수정하고 나면 눈으로 보기엔 아무 바뀐게 없어 보일지 모르겠지만 데이터가 "Y", "N"이 아니라 true나 false로 들어온다 하더라도 selectedFlag를 변경해주면 바로 적용할 수 있게 된다.

(163번째 줄 확인 꼭 하셔야합니다. label로 되어있던걸 data에서 바로 값을 뽑아서 비교하게끔 했어요. 이유는 true나 false같은 경우는 String이 아니기때문에 비교식 성립이 안되거든요.)

 

아래와 같이 Main.mxml 파일을 수정해보면 알 수 있다.

[code xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:renderers="classes.controls.renderers.*">
<mx:Script>
    <![CDATA[
    import mx.collections.ArrayCollection;
    import mx.controls.Alert;

    [Bindable]
    private var ac:ArrayCollection = new ArrayCollection([
                               {index:1, description:"test1", toggle:true},
                               {index:2, description:"test2", toggle:false},
                               {index:3, description:"test3", toggle:false},
                               {index:4, description:"test4", toggle:true},
                               {index:5, description:"test5", toggle:false},
                               {index:6, description:"test6", toggle:false},
                               {index:7, description:"test7", toggle:true},
                               {index:8, description:"test8", toggle:false},
                               {index:9, description:"test9", toggle:false},
                               {index:10, description:"test10", toggle:false},
                               {index:11, description:"test11", toggle:false},
                               {index:12, description:"test12", toggle:false}
                               ]);

    public function checkBoxRendererClickHandler(data:Object):void
    {
        Alert.show("click by " + data.description);
    }
    ]]>
</mx:Script>
<mx:DataGrid dataProvider="{ac}">
    <mx:columns>
        <mx:DataGridColumn headerText="index" dataField="index" />
        <mx:DataGridColumn headerText="description" dataField="description" />
        <mx:DataGridColumn headerText="radio" dataField="toggle">
            <mx:itemRenderer>
                <mx:Component>
                    <renderers:CheckBoxRenderer
                        selectedFlag="{[true, false]}"
                        onClickFunction="{outerDocument.checkBoxRendererClickHandler}" />
                </mx:Component>
            </mx:itemRenderer>
        </mx:DataGridColumn>
    </mx:columns>
</mx:DataGrid>

</mx:Application>
[/code]

이제 대충 감이 오시나요?

Renderer에 대해서 감이 오셨다면 다행입니다.

하지만 "CheckBox"는 대충 알겠는데 "ComboBox"는? "ComboBoxRenderer"는 어떻게 만드나요? 라고 하신다면 1, 2, 3회에 걸쳐 Renderer에 대해 설명한 이유가 없어요. 다시 한번 훑어보시고 연구하시면 될거 같아요.

답은 스스로 만들어가는 것.

 

다음 시간엔... HeaderRenderer를 해볼까 하다가 좀 다른게 만져보고 싶어져서.. 기대하세요.

:
Posted by 라면스프
2013. 1. 10. 10:04

Flex DataGrid ItemRenderer #2 Enjoy/FLEX2013. 1. 10. 10:04

출처 : http://igna84.blogspot.kr/2010/03/flex-datagrid-itemrenderer-2-%EC%A0%84%EB%A9%B4%EC%A0%84.html


Flex DataGrid ItemRenderer #2 - 전면전

경력사원임에도 불구하고 나이가 어려서 그런지 신입사원 연수를 다녀오라는 지시에 지난 목요일 금요일 다녀오는 바람에 ItemRenderer 이야기가 늦어졌습니다. 기다리신 분 계신가요?? 죄송합니다. 본의아니게;;

아무튼 DataGrid ItemRenderer 라는 뜨거운 감자를 삼키기위해 어떤 모양의 ItemRenderer를 만들지 한번 생각해보도록 할까요.

 

처음이니 간단하게 CheckBox 아이템 렌더러를 만들도록 해봅시다.

 

일단 메인 어플리케이션을 만들어 놓습니다.

 

[code xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
    <![CDATA[
    import mx.collections.ArrayCollection;

    [Bindable]
    private var ac:ArrayCollection = new ArrayCollection([
                                     {index:1, description:"test1", toggle:"Y"},
                                     {index:2, description:"test2", toggle:"N"},
                                     {index:3, description:"test3", toggle:"N"},
                                     {index:4, description:"test4", toggle:"Y"},
                                     {index:5, description:"test5", toggle:"N"},
                                     {index:6, description:"test6", toggle:"N"},
                                     {index:7, description:"test7", toggle:"Y"},
                                     {index:8, description:"test8", toggle:"N"},
                                     {index:9, description:"test9", toggle:"N"},
                                     {index:10, description:"test10", toggle:"N"},
                                     {index:11, description:"test11", toggle:"N"},
                                     {index:12, description:"test12", toggle:"N"}
                                     ]);
    ]]>
</mx:Script>
<mx:DataGrid dataProvider="{ac}">
    <mx:columns>
        <mx:DataGridColumn headerText="index" dataField="index" />
        <mx:DataGridColumn headerText="description" dataField="description" />
        <mx:DataGridColumn headerText="check" dataField="toggle" />
    </mx:columns>
</mx:DataGrid>
</mx:Application>
[/code]

 

위와같이 코딩하고 컴파일하게되면 아래와 같이 산출물이 나오게 됩니다.

 

 

그럼 우리는 ratio라고 적혀있는 곳에 ItemRenderer를 적용할겁니다.

 

CheckBox를 상속받아 작업할겁니다. 왜 "UIComponent 안쓰고!"라고 말씀하신다면

그 이유는 UIComponent를 상속받은 클래스이기도 하고 지난시간 말했던 IDataRenderer, IDropInListitemRenderer, IListItemRenderer 이렇게 세 인터페이스가 이미 구현되어있으며 우리가 원하는 아이템 렌더러는 CheckBox아이템 렌더러이기 때문이지요.

 

[code as3]
package classes.controls.renderers
{
//-----------------------------------------------------------------------------
//
//  Import
//
//-----------------------------------------------------------------------------
import mx.core.IDataRenderer;
import mx.controls.CheckBox;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.events.FlexEvent;
public class CheckBoxRenderer extends CheckBox
{
    //-----------------------------------------------------------------------------
    //
    //  Constructor
    //
    //-----------------------------------------------------------------------------
    /**
     *  Constructor.
     */
    public function CheckBoxRenderer()
    {
        super();
    }

    //-----------------------------------------------------------------------------
    //
    //  Variables
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  데이터 변경 확인 플래그
     */
    private var dataChanged:Boolean = false;

    //-----------------------------------------------------------------------------
    //
    //  Override Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();
    }

    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
    }
}
}
[/code]

초벌로 createChildren, commitProperties, updateDisplayList도 확장해 두고 아이템 랜더러로 사용하기 위한 준비를 마쳤습니다.

그리고 메인 어플리케이션은 아래와 같이 수정하고 컴파일 합니다.

[code xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
    <![CDATA[
    import mx.collections.ArrayCollection;

    [Bindable]
    private var ac:ArrayCollection = new ArrayCollection([
                                        {index:1, description:"test1", toggle:"Y"},
                                        {index:2, description:"test2", toggle:"N"},
                                        {index:3, description:"test3", toggle:"N"},
                                        {index:4, description:"test4", toggle:"Y"},
                                        {index:5, description:"test5", toggle:"N"},
                                        {index:6, description:"test6", toggle:"N"},
                                        {index:7, description:"test7", toggle:"Y"},
                                        {index:8, description:"test8", toggle:"N"},
                                        {index:9, description:"test9", toggle:"N"},
                                        {index:10, description:"test10", toggle:"N"},
                                        {index:11, description:"test11", toggle:"N"},
                                        {index:12, description:"test12", toggle:"N"}
                                        ]);
    ]]>
</mx:Script>
<mx:DataGrid dataProvider="{ac}">
    <mx:columns>
        <mx:DataGridColumn headerText="index" dataField="index" />
        <mx:DataGridColumn headerText="description" dataField="description" />
        <mx:DataGridColumn headerText="radio" dataField="toggle" itemRenderer="classes.controls.renderers.CheckBoxRenderer" />
    </mx:columns>
</mx:DataGrid>
</mx:Application>
[/code]

일단 아래와 같은 결과가 나오면 성공입니다.

 

CheckBox 가 "Y"냐 "N"이냐에 따라 selected가 처리되는 로직이 필요합니다. 그러기 위해서는 그 코드를 어디에 넣는것이 좋을지 고민해봐야하는데 아까도 말했듯 모든 속성처리는 commitProperties에서 하게 됩니다. commitProperties를 호출하기 위해서는 저번에 이야기 했었던 대로 invalidateProperties() 메서드를 호출하면 됩니다. 그렇다면 코드를 아래와 같이 수정합니다.

 

[code as3]
package classes.controls.renderers
{
//-----------------------------------------------------------------------------
//
//  Import
//
//-----------------------------------------------------------------------------
import mx.core.IDataRenderer;
import mx.controls.CheckBox;
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.events.FlexEvent;
public class CheckBoxRenderer extends CheckBox
{
    //-----------------------------------------------------------------------------
    //
    //  Constructor
    //
    //-----------------------------------------------------------------------------
    /**
     *  Constructor.
     */
    public function CheckBoxRenderer()
    {
        super();
    }

    //-----------------------------------------------------------------------------
    //
    //  Variables
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  데이터 변경 확인 플래그
     */
    private var dataChanged:Boolean = false;
    //-----------------------------------------------------------------------------
    //
    //  Override Properties
    //
    //-----------------------------------------------------------------------------
    override public function set data(value:Object):void
    {
        super.data = value;

        dataChanged = true;

        invalidateProperties();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();
        if(dataChanged)
        {
            dataChanged = false;
            updateProperties();
        }
    }

    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
    }

    //-----------------------------------------------------------------------------
    //
    //  Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  CheckBox의 속성을 변경
     */
    private function updateProperties():void
    {
        if(listData.label == "Y")
        {
            selected = true;
        }
        else
        {
            selected = false;
        }

        invalidateDisplayList();
    }
}
}
[/code]

위와 같이 코딩하게 되면 아래와 같은 산출물이 나오게 됩니다.

 

 

썩 잘나오는거 같습니다. 몇가지 마음에 안 드는 것이 있는데 일단 CheckBox가 셀의 중앙에 갔으면 좋겠고 CheckBox를 클릭하고 휠을 돌려보면 Check가 풀려버리는 버그가 있다는 것이지요.

 

CheckBox를 중앙에 놓으려면 CheckBox의 너비를 알아야하는데 그것은 CheckBox는 기본적으로 14픽셀의 넓이를 갖습니다. 그것을 어떻게 아냐구요?

measuredWidth를 trace 해보면 간단하게 알 수 있습니다. 아, measuredWidth는 컨포넌트 객체의 기본 너비를 이야기 합니다.

 

위의 두가지 문제점을 해결하기 위해 아래와 같이 코드를 수정합니다.

 

[code as3]
package classes.controls.renderers
{
//-----------------------------------------------------------------------------
//
//  Import
//
//-----------------------------------------------------------------------------
import flash.events.MouseEvent;

import mx.core.IDataRenderer;
import mx.controls.CheckBox;
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.mx_internal;
import mx.events.FlexEvent;

use namespace mx_internal;

public class CheckBoxRenderer extends CheckBox
{
    //-----------------------------------------------------------------------------
    //
    //  Constructor
    //
    //-----------------------------------------------------------------------------
    /**
     *  Constructor.
     */
    public function CheckBoxRenderer()
    {
        super();
    }

    //-----------------------------------------------------------------------------
    //
    //  Variables
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  데이터 변경 확인 플래그
     */
    private var dataChanged:Boolean = false;

    //-----------------------------------------------------------------------------
    //
    //  Override Properties
    //
    //-----------------------------------------------------------------------------
    override public function set data(value:Object):void
    {
        super.data = value;

        dataChanged = true;

        invalidateProperties();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();
        if(dataChanged)
        {
            dataChanged = false;

            updateProperties();
        }
    }

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

        currentIcon.x = (unscaledWidth - currentIcon.width) / 2;
    }

    //-----------------------------------------------------------------------------
    //
    //  Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  CheckBox의 속성을 변경
     */
    private function updateProperties():void
    {
        if(listData.label == "Y")
        {
            selected = true;
        }
        else
        {
            selected = false;
        }

        invalidateDisplayList();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override EventHandler
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function clickHandler(event:MouseEvent):void
    {
        super.clickHandler(event);

        //data[DataGridListData(listData).dataField] = selected ? "Y" : "N";

        if(selected)
        {
            data[DataGridListData(listData).dataField] = "Y";
        }
        else
        {
            data[DataGridListData(listData).dataField] = "N";
        }
    }
}
}
[/code]

 

currentIcon이라는 생소한 속성을 위에서 보실 수 있습니다. 그것은 체크박스에서 체크되는 아이콘을 지칭합니다. 그 currentIcon이란 녀석은 mx_internal이라는 접근자를 이용하고 있고 LanguageReference에는 표시되지 않고 있어서 그 존재를 모르는 사람이 많습니다.

예전에 저도 그것을 몰라서 HBox에다가 넣고 horizontalAlign="center"를 주는 바보같은 짓을 일삼았는데 이 사실을 알고 난뒤에 Container를 사용하지 않고 좀더 가볍게 itemRenderer를 만들어 낼 수 있었지요.


그래서 updateDisplayList() 메서드에서 좌표를 잡아서 셀의 중앙에 놓고 clickHandler라는 메서드를 확장하여 변경된 값을 data에 반영하게 합니다. 그렇게 되면 아래와 같은 결과물이 나오게 되지요.

 

 

오. 그럴싸하게 작동하는 것 같습니다만 몇가지 아쉬운점이 있습니다.

 

1. "Y", "N" 값으로만 작동하게 되어있다.

2. CheckBox를 클릭하면 뭔가 다른 행동을 하고 싶을땐 어떻게 하나.

 

이렇게 두가지 사항인데요.

이 부분에 대해서는 다음시간에 알아보도록 해요~

:
Posted by 라면스프
2013. 1. 10. 10:03

Flex DataGrid ItemRenderer #1 Enjoy/FLEX2013. 1. 10. 10:03

출처 : http://igna84.blogspot.kr/2010/03/flex-datagrid-itemrenderer-1-%EC%A0%84%EC%B4%88%EC%A0%84.html



Flex DataGrid ItemRenderer #1 - 전초전

사실 Flex를 개발하다보면 DataGrid를 밥먹듯이 사용하는 경우가 많지요.

하지만 모두가 알다시피 DataGrid를 이용하는데 있어서 가장 큰일이 바로 아이템렌더러를 만드는 것일지도 모르겠습니다.(모르는게 아니에요. 당연할거라고 생각하고 있습니다.)

 

하지만 아이템렌더러.. 만들기 쉽지 않습니다.

저는 심지어 이런 코드도 봤지요.

 

[code xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
    <![CDATA[
    import mx.collection.ArrayCollection;

    [Bindable]
    private var ac:ArrayCollection = new ArrayCollection([
                        {check: true, description: "test1"},
                        {check: true, description: "test1"},
                        {check: true, description: "test1"},
                        {check: true, description: "test1"},
                        {check: true, description: "test1"}]);
    ]]>
</mx:Script>
<mx:DataGrid dataProvider="{ac}">
    <mx:columns>
        <mx:DataGridColumn dataField="check">
             <mx:itemRenderer>
                 <mx:Component>
                     <mx:CheckBox />
                 </mx:Component>
             </mx:itemRenderer>
        </mx:DataGridColumn>
        <mx:DataGridColumn dataField="description" />
    </mx:columns>
</mx:DataGrid>
</mx:Application>
[/code]

이렇게 하면 아래처럼 나오긴 하겠지요.

하지만 문제는 아다시피 저기서 아무리 체크박스를 눌러대도 실데이터는 바뀌지 않는다는 사실입니다.

그 다음에 밀려오는 문제는 "데이터가 변하지 않아요? 어쩌죠?" 하는 질문을 올려서 답변을 받아보거나 책을 찾아보거나 뭐.. 여러가지 행동들을 할 수 있을테지만 문제는 늘 그렇듯 근본적인 해결이 되지 않는 다는 사실입니다.

 

Flex 프로젝트를 1년간 11개나 해치워보니 알 수 있는건 당연하게도 매번 아이템 렌더러를 그때 그때마다 새로 만든다는게 엄청나게 귀찮은 일이었고 화면설계서를 받아보면 경악하여 기획자와 디자이너를 닥달하며 "구현이 불가능한 기능"이라는 사실을 강조하고 화면설계를 수정하자 요구 했었습니다.

사실 뭐.. 프로젝트에 투입되고 본격적인 개발이 시작되고 난뒤 약 40%정도의 시간을 그렇게 설득하고 우회하는 방법을 찾느라 소비했지요.

 

그렇다면 근본적인 해결점을 찾아보는 것이 어떻지 고민해보는 것이 좋겠다 싶었습니다.

괜찮은 아이템 렌더러를 만들어 놓고 앞으로 계속해서 이용하는 것이지요. 일단 그런 아이템 렌더러를 만들기 위해서는 데이터 그리드가 어떻게 만들어졌는지 알아야 합니다.

 

데이터 그리드의 구조 입니다.

전체적으로 각 객체의 컨트롤을 맡고 있는 DataGrid 상위 객체 안에 DataGridColumn들이 Array형태로 들어가 있고 DataGridColumn 안에 Header와 ItemRenderer가 같이 들어있습니다.

(단순하게 표현하면 그렇다는 거지요.. 실제로는 더 까다롭고 복잡한 구조입니다..)

 

일단 저정도만 알고 있으면 우리가 만들려는 DataGridItemRenderer가 어떤 놈인지 mx 패키지에서 확인해볼 필요가 있습니다.

 

 

TextField군요.. DataGridRenderer를 확장해서는 버튼이나 콤보박스같은건 넣을 수가 없겠다고 판단됩니다. 그럼 결국 DataGridItemRenderer에서 몇가지 인터페이스 클래스를 구현하여 아이템 렌더러를 만들어 내지요. 뭐. 저것도 사람이 만든건데 우리라고 만들지 말란법은 없으니까요.

 

일단 구현해야할 인터페이스 클래스는 IDataRenderer, IDropInListItemRenderer, IListItemRenderer 이렇게 3가지면 괜찮습니다. ILayoutManagerClient나 IStyleClient는 왜 구현하지 않냐고 물어보시면  우리는 UIComponent를 상속받아 아이템 렌더러를 만들것이기 때문이라고 말씀드리고 싶습니다.

왜냐하면 UIComponent는 ILayoutManagerClient나 IStyleClient를 구현하고 있기 때문이지요.

 

 

이러한 연유로 IDataRenderer, IDropInListItemRenderer, IListItemRenderer 이렇게 3가지 인터페이스만 구현해 볼까 합니다.

 

중요한 첫번째 내용이 끝이 났어요.

두번째 내용은 Flex의 UIComponent의 라이프 사이클(Life Cycle)에 대해 알아야할 순서입니다.

UIComponent의 Protect 접근자 클래스를 잘 이해해야하는데요.

그 중에서도 특히 updateDisplayList() 메서드와 createChildren()메서드. 그리고 commitProperties() 메서드를 잘 이해해야합니다.

 

 

이 updateDisplayList라는 메서드는 자식객체를 그리거나 혹은 자식객체의 사이즈나 위치를 변경할 때 사용됩니다. 그리고 Flex에서 이 메서드를 호출하기 위해서는 invalidateDisplayList()라는 메서드를 호출하거나 자식객체를 addChild할때 실행되게 되어있는 메서드입니다.

 

한마디로 자식객체에 변경이 생겨서 새로 화면을 그려내야할때 사용되는 녀석인데요.

자칫 잘못하면 본의아니게 계속해서 호출해 시스템을 다운시키는 원인이 될 수 있으니 조심히 사용해야합니다.

 

자식객체를 생성할때 호출하는 녀석으로 컨포넌트를 최초에 생성시킬때 한번 호출되고 다음부터는 고의로 호출하지 않는이상 호출되지 않는 메서드입니다.

 

 

commitProperties 메서드는 자식객체를 addChild()하거나 invalidateProperties() 에서드를 호출하면 실행되는 메서드로 이때 자식객체의 프로퍼티를 지정하고 변경값을 적용하는 역할을 합니다.

 

이정도만 알고 있으면 어느정도 아이템렌더러를 만들 수 있는 구색은 갖춰졌습니다.

다음시간에 본격적으로 시작해 보도록 할까요?

:
Posted by 라면스프
2013. 1. 10. 09:39

MecGridWizard Enjoy/FLEX2013. 1. 10. 09:39


출처 : http://www.mechansp.com/demo/mecgrid/MecGridWizard/MecGridWizard.html



:
Posted by 라면스프


출처 : http://knight76.tistory.com/entry/%EA%B5%AC%EA%B8%80-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-%EB%B2%84%ED%8D%BC-Google-Protocl-Buffer


구글 프로토콜 버퍼 (Google Protocl Buffer)


PPT 작성 자료








* 배경
RPC와 쉽게 연동, Not RPC
하나의 개념으로 다양한 언어에서 쓸 수 있게 구글에서 다양한 언어별로 개발 하다 보니. 통신을 위한 단일 표준이 필요

  proto 파일 -> proto 컴파일러 -> 여러 언어로 변환 (java, python, c++)

Not socket
구글 에서 2008년 7월 발표
이슈 제시
- XML 문제
- Parsing, serialization  (debugging)
- Portable : IDL처럼 사용
- Heavy Optimization
- Language 지원 
짧은 데이터의 송수신 용도/긴 데이터 송수신이 목표가 아님

* XML 보다 좋은 점
Simple
3~10배 작음
20~100배 속도 빠름
모호하지 않음
바로 프로그램에 사용하기 쉬움

* 레퍼런스
Protocol Buffers: A new open source release
    http://www.youtube.com/watch?v=K-e8DDRwVUg

Home Page
   http://code.google.com/p/protobuf/

개발자 가이드
   http://code.google.com/intl/ko-KR/apis/protocolbuffers/docs/overview.html

Protocol Buffer Language Guide
    http://code.google.com/intl/ko-KR/apis/protocolbuffers/docs/proto.html

API
    http://code.google.com/intl/ko-KR/apis/protocolbuffers/docs/reference/java/index.html

PB 포맷
    http://wiki.openstreetmap.org/wiki/PBF_Format

비슷한 솔루션과 비교
    https://github.com/eishay/jvm-serializers/wiki


* 활용 
구글
- 원래 index server request/response protocol로 사용했었음
- 48,162 different message types
- 12,183 .proto files
다양한 회사
국내/외 게임 회사의 통신


* 장점
쓰기 편함
Stub 코드 자동 생성
- 통신에서 가져야 할 보편적 특성을 다 추가
- Serializing, Parsing 지원
코드 일치
- 클라이언트/서버 코드 동일
IDL 형태로 정의가 단순
- Portable
- 클래스 또는 struct 디자인
언어 지원
java, c++, python
3rd party lib (많은 언어 지원.http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns#RPC_Implementations)
배우기 쉬움
이클립스 플러그인 존재
Lite 버전 개발 가능
Good Document
BSD license
언어마다 특화되고 쓰기 편한 특징을 제공

* 단점
Output이 binary만 존재
- PB의 Reflection을 이용해서 json으로 전달 가능 
Map, set 지원 없음


* 개발환경 구성
Download proto compiler in google code
http://code.google.com/p/protobuf/downloads/list

(Option) eclipse plugin
http://protoclipse.googlecode.com/svn/trunk/site/


* proto 파일


// text.txt
package test;

message Request {
  required string command = 1;
  optional string param = 2;
}


 



/cygdrive/c/protocolbuffer
$ ./protoc.exe test.txt --java_out=.



Test폴더 생기고 TestTxt.java 생성됨
(17KB, Protocol buffer 내부 클래스 사용)

// c++ 로 하면
test.txt.pb.cc (12K)
test.txt.pb.h (8K)

// python으로 하면,
test/txt_pb2.py (2K)

* 생성된 자바 코드
Descriptor 지원
- internal_static_test_Request_descriptor
Reflection 지원
- Message / Message.Builder interfaces.
- Json 처럼 프로토콜로 변경 가능 (ajax 가능)
메시지 수정시 하위 호환 보장, 새로운 메시지로 변경되면 기존 코드에 대한 필드만 처리
파일이름을 디폴트로 해서 소스를 생성하지만, 내가 원하는 클래지 이름과 클래스 이름의 개별 지정이 가능
- option java_package = "com.example.foo.bar";
- option java_outer_classname = “ProtocolData";
PB의 Enum은 java의 enum으로 변경


* 크기 제한 
디폴트로 크기 제한 : 64 MB
속도를 최적화 또는 악의를 가진 사용자로부터 보호하기 위해서 크기를 제한할 수 있음
- CodedInputStream/CodedOutputStream (ZeroCopyInputStream/ZeroCopyOutputStream ) 
   SetTotalBytesLimit 메소드

* proto 파일 생성시 유의할 점
package 선언
클래스 파일 이름
운영을 위한 파일명 .proto
message 등록
- Protocol buffer language guide
Protoc.exe(컴파일러)에 의해 만들어진 java, python, c++ 코드는 고치지 말아야 한다.(immutable)
protoc에서 컴파일 되면, 자동으로 accessor가 붙는다.
- get/set/has…

* message 설명
package
Type
- Bool, int32, uint32, float, double, string, bytes,  ….
- Enum
Nested type
Default value
importing
Modifier
- required : 반드시 사용해야 할 필드. 미초기화된 상태 미초기화된 메시지를 빌드하면 RuntimeException, 초기화되지 않은 메시지를 파싱하면서 에러나면 IOException발생
- optional : option의 개념
     hasXXX() 로 확인
- repeated : 0을 포함하는 개수를 계속 넣을 수 있음
     자바에서는 List객체로 구현됨


* 필드에 번호를 반드시 주는 이유 
번호를 주지 않으면 protoc 에러 발생
Write/Read 할 때, serialization 순서를 주기 위함
필드 정보가 set되었는지 쉽게 알기 위함(내부적으로 bit 연산함)

* Versioning 정보가 없는 이유
새로운 필드를 언제든지 추가 될 수 있음
모든 정보를 볼 필요 없이 필요한 정보만 파싱할 수 있도록 함
But, java는 기본으로 존재하지 않지만, c++ 은 존재한다. 링킹 이슈. (GOOGLE_PROTOBUF_VERIFY_VERSION 매크로)
Incompatible한 버전 때문에 문제가 없도록 해야 함


* 데모 1

// text.txt
package test;

message Request {
  required string command = 1;
  optional string param = 2;
}


 



generated 자바 코드 로 컴파일


<Writer.java>

package com.example.test;

import java.io.FileOutputStream;
import test.Test.Request;

public class Writer {
    public static void main(String[] args) throws Exception {
        Request request = Request.newBuilder()
                                       .setCommand("commit")
                                       .setParam("every files")
                                       .build();
        FileOutputStream output = new FileOutputStream("r.os");
        request.writeTo(output);
        output.close();
    }
}




<Reader.java>
package com.example.test;

import java.io.FileInputStream;
import test.Test.Request;

public class Reader {
    public static void main(String[] args) throws Exception {
        Request request = Request.parseFrom(new FileInputStream("r.os"));
        System.out.println("command : " + request.getCommand());
        if (request.hasParam()) {
            System.out.println("params : " + request.getParam());
        } 
    }
}



 

<실행결과>
command : commit
params : every files


* 데모 2


<writer.cpp>

#include <iostream>
#include <fstream>
#include <string>
#include "test.pb.h"

using namespace std;

int main(int argc, char* argv[]) { 
 Request request;
   request.set_command("init");
 request.set_param("0");

           fstream out("streams", ios::out | ios::binary | ios::trunc); 
 request.SerializeToOstream(&out); 
 out.close();

 return 1;
}



 



<reader.cpp>
#include <iostream>
#include <fstream>
#include <string>
#include "test.pb.h"

using namespace std;

int main(int argc, char* argv[]) { 
    Request request;
    fstream in(“streams", ios::in | ios::binary); 
    if (!request.ParseFromIstream(&in)) { 
          cerr << "Failed to parse streams." << endl; 
          exit(1); 
    } 
    cout << “command: " << request.command() << endl; 
    if (request.has_param()) { 
         cout << “param: " << request.param() << endl; 
    }
}

 

* 데모 3


package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}

message AddressBook {
  repeated Person person = 1;
}



Posted by My Story '김용환'




:
Posted by 라면스프
2012. 12. 11. 10:40

tomcat 메모리 CATALINA_OPTS 설정 Enjoy/JSP2012. 12. 11. 10:40

tomcat 에 힙사이즈 설정


catalina.sh 파일에 아래 내용 추가


export CATALINA_OPTS="-Djava.awt.headless=true -server -Xms2048m -Xmx2048m -Xmn1024m

                      -XX:NewSize=512m -XX:MaxNewSize=512m -XX:PermSize=512m -XX:MaxPermSize=512m 

                      -XX:+UseParNewGC -XX:+UseConcMarkSweepGC

                      -XX:SurvivorRatio=4 -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError"


  • CATALINA_OPTS="-server -Xss256k -Xms256m -Xmx512m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m -XX:SurvivorRatio=5 -XX:ReservedCodeCacheSize=128m -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.awt.headless=true "

-Xmx1024m -Xms1024m -XX:MaxNewSize=384m -XX:MaxPermSize=128m

힙덤프

-XX:-HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./java_pid<pid>.hprof

GC 옵션

-XX:ParallelGCThreads=2 -XX:-UseConcMarkSweepGC

GC 로그 옵션

-XX:-PrintGC -XX:-PrintGCDetails -XX:-PrintGCTimeStamps -XX:-TraceClassUnloading -XX:-TraceClassLoading

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_BASE/logs




http://helloworld.naver.com/helloworld/184615

표 3 모니터링 후 옵션변경 예시

종류

옵션

동작 모드

-sever

전체 힙 크기

-Xms와 –Xmx의 값을 같게

New 영역 크기

-XX:NewRatio

2~4 정도의 값

-XX:NewSize=? –XX:MaxNewSize=?

NewRatio 대신 NewSize를 지정하는 것도 좋다.

Perm 크기

-XX:PermSize=256m

-XX:MaxPermSize=256m

성능에 영향을 미치지 않으므로 동작에 문제가 없을 정도만 지정한다.

GC 로그

-Xloggc:$CATALINA_BASE/logs/gc.log

-XX:+PrintGCDetails

-XX:+PrintGCDateStamps

GC로그를 남기는 것은 특별히 Java 애플리케이션 수행 성능에 영향을 미치지 않는다. 가급적이면 GC 로그를 남기는 것이 좋다.

GC 알고리즘

-XX:+UseParNewGC

-XX:+CMSParallelRemarkEnabled

-XX:+UseConcMarkSweepGC

-XX:CMSInitiatingOccupancyFraction=75

일반적으로 권할만한 설정일 뿐이다. 애플리케이션 특성에 따라 다른 선택이 더 좋을 수 있다.

OOM 에러 발생 시 힙 덤프 생성

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_BASE/logs

OOM 발생 이후 조치

-XX:OnOutOfMemoryError=$CATALINA_HOME/bin/stop.sh

또는

-XX:OnOutOfMemoryError=$CATALINA_HOME/bin/restart.sh

힙 덤프를 남긴 뒤, 관리 정책에 맞게 적합한 동작을 취할 수 있도록 한다.





:
Posted by 라면스프