달력

3

« 2024/3 »

  • 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
2015. 3. 2. 23:32

그리드 헤더 체크박스 Enjoy/FLEX2015. 3. 2. 23:32

3 state checkbox for headerrenderer in datagrid




출처 : https://srinichekuri.wordpress.com/2011/05/20/3-state-checkbox-for-headerrenderer-in-datagrid/


Today I made by first contribution to Adobe Cook by posting about this topic. The idea on this topic started by showing my earlier post on gmail header to my colleague who also happens to be the owner of post in adobe cookbook that talks about 3State checkbox for TreeRenderer. He pointed out that the checkbox in the header can be threeState. Well thats a common problem but suprisingly this was not addressed in the online opensource community for Datagrid. I saw an opportunity and coded it.

Note:
There is a bug in my colleague’s post that it doesn’t take care of the initial state, I have taken care of that bug in my code.My code itself is inspired by my colleagues post.

The checkbox in headerRenderer will have three states:

  • All the rows in the datagrid are selected (‘select’ State).
  • None of the rows in the datagrid are selected(‘unselected’ State)
  • One or more rows (but not all) are selected(‘undecided’ State).

ScreenShots:
Change of state from ‘unselect’ state to ‘select’ state:

Change of state from ‘select’ state to ‘undecided’ state:

Code:

Here is the code for Main.mxml:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                xmlns:s="library://ns.adobe.com/flex/spark"
                xmlns:mx="library://ns.adobe.com/flex/mx"
                creationComplete="creationCompleteHandler(event)">
 
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;
            import mx.events.FlexEvent;
 
            private var _dataProvider:ArrayCollection;
            [Bindable]
            public function set dataProvider(value:Object):void{
                _dataProvider=value as ArrayCollection
            }
            public function get dataProvider():Object{
                return _dataProvider;
            }
 
            protected function creationCompleteHandler(event:FlexEvent):void
            {
                dataProvider = new ArrayCollection([
                    {checked:true, name:'Jim Smith'},
                    {checked:false, name:'Yancy Williams'}]);
            }
 
        ]]>
    </fx:Script>
 
    <mx:DataGrid id="myDataGrid" left="10" top="10" dataProvider="@{dataProvider}">
        <mx:columns>
            <mx:DataGridColumn textAlign="center" dataField="checked"
                                       width="90"
                                       rendererIsEditor="true"
                                       sortable="false"
                                       itemRenderer="renderer.CheckboxItemRenderer"
                                       headerRenderer="renderer.ThreeStateCheckBoxHeaderRenderer"
                                       />
            <mx:DataGridColumn headerText="Name" dataField="name" width="110"/>
        </mx:columns>
    </mx:DataGrid>
 
</s:Application>

Code for headerRenderer

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package renderer
{
    import flash.events.MouseEvent;
 
    import mx.collections.ArrayCollection;
    import mx.controls.DataGrid;
    import mx.controls.Image;
    import mx.controls.dataGridClasses.DataGridListData;
    import mx.controls.dataGridClasses.MXDataGridItemRenderer;
 
    import spark.components.CheckBox;
 
    /**
     * HeaderRender with a Three State Checkbox.
     * <p>Functionality:<br>
     *    <li>Selecting the checkbox will select all the rows in the datagrid</li>
     *    <li>Unselecting the checkbox will unselect all the rows in the datagrid</li>
     *
     * <p>The checkbox can be three states at any point:<br>
     *    <li>select: This would mean that all the rows are selected</li>
     *    <li>unselect: This would mean that none of the rows are selected</li>
     *    <li>undecided: This would mean that one or more (but not all) of the rows are selected</li>
     *
     * @author Srinivas Chekuri
     *
     */
    public class ThreeStateCheckBoxHeaderRenderer extends MXDataGridItemRenderer
    {
        protected var myCheckBox:CheckBox;
        protected var myImage:Image;
        private var imageWidth:Number   = 9.5;
        private var imageHeight:Number  = 9.5;
        private var inner:String    = "assets/inner.png";
 
        private const SELECT_STATE:String="select";
        private const UNSELECT_STATE:String="unselect";
        private const UNDECIDED_STATE:String="undecided";
 
        private var STATE:String = UNSELECT_STATE;
 
        /**
         * Constuctor
         *
         */
        public function ThreeStateCheckBoxHeaderRenderer()
        {
            super();
        }
 
        /**
         * overides the function <code>createChildren</code> in the component lifecyle. This instantiates
         * <code>myCheckBox</code> and <code>myImage</code>.
         *
         */
        override protected function createChildren():void{
            super.createChildren();
            myCheckBox = new CheckBox();
            myCheckBox.setStyle("horizontalCenter", "0");
            myCheckBox.setStyle("verticalCenter", "0");
            myCheckBox.addEventListener( MouseEvent.CLICK, checkBoxClickHandler );
            addElement(myCheckBox);
            myImage = new Image();
            myImage.source = inner;
            myImage.addEventListener( MouseEvent.CLICK, imageClickHandler );
            myImage.visible=false;
            addElement(myImage);
        }
 
        /**
         * overides the function <code>updateDisplayList</code> in the component lifecyle. This sets the
         * display settings of <code>myCheckBox</code> and <code>myImage</code>. This also updates the state
         * according to the selections made in the datagrid.
         *
         * @param unscaledWidth
         * @param unscaledHeight
         *
         */
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
            super.updateDisplayList(unscaledWidth,unscaledHeight);
 
            myImage.x=myCheckBox.x+1.5;
            myImage.y=myCheckBox.y+5.5;
 
            myImage.width=imageWidth;
            myImage.height=imageHeight;
 
            if(areAllSelected()){
                STATE=SELECT_STATE;
            }else if(isAnyColumnSelected()){
                STATE=UNDECIDED_STATE;
            }else if(!isAnyColumnSelected()){
                STATE=UNSELECT_STATE;
            }
            checkState();
        }
 
        /**
         * Makes adjustments to the <code>visible</code> property of <code>myImage</code> and
         * <code>selected</code> of <code>myCheckBox</code> according to the state.
         *
         * @private
         *
         */
        private function checkState():void{
            if(STATE==SELECT_STATE){
                myImage.visible=false;
                myCheckBox.selected=true;
            }else if(STATE==UNSELECT_STATE){
                myImage.visible=false;
                myCheckBox.selected=false;
            }else{
                myImage.visible=true;
                myCheckBox.selected=false;
            }
        }
 
        /**
         * Handler method for <code>MouseEvent.CLICK</code> event on <code>myImage</code>.
         *
         * @param event
         *
         */
        protected function imageClickHandler(event:MouseEvent):void{
            STATE=SELECT_STATE;
            checkState();
            selectAll();
        }
 
        /**
         * Handler method for <code>MouseEvent.CLICK</code> event on <code>myCheckBox</code>.
         *
         * @param event
         *
         */
        protected function checkBoxClickHandler(event:MouseEvent):void{
            selectAll();
        }
 
        /**
         * Selects all the rows in the datagrid.
         *
         */
        private function selectAll():void{
            var ac:ArrayCollection = DataGrid(DataGridListData(listData).owner).dataProvider as ArrayCollection;
            for each (var o:Object in ac){
                o.checked=myCheckBox.selected;
            }
            DataGrid(DataGridListData(listData).owner).dataProvider = ac;
        }
 
        /**
         * Checks if all the rows are selected in the datagrid.
         *
         * @return Boolean: returns <code>true</code> if all rows are selected else returns
         * <code>false</code>.
         *
         */
        private function areAllSelected():Boolean{
            var ac:ArrayCollection = DataGrid(DataGridListData(listData).owner).dataProvider as ArrayCollection;
            var b:Boolean=true;
            for each (var o:Object in ac){
                if(!o.checked){
                    b=false;
                    break;
                }
            }
            return b;
        }
 
        /**
         * Checks to see if any one of the rows are selected.
         *
         * @return Boolean: return <code>true</code> if any one the rows are selected.
         *
         */
        private function isAnyColumnSelected():Boolean{
            var ac:ArrayCollection = DataGrid(DataGridListData(listData).owner).dataProvider as ArrayCollection;
            var b:Boolean=false;
            for each (var o:Object in ac){
                if(o.checked){
                    b=true;
                    break;
                }
            }
            return b;
        }
    }
}

Code for itemRenderer:

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
32
33
<!--?xml version="1.0" encoding="utf-8"?-->
 
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.controls.DataGrid;
            import mx.controls.dataGridClasses.DataGridListData;
            import mx.events.FlexEvent;
 
            /**
             * Handler function for <code>MouseEvent.CLICK</code> on checkbox.
             *
             * @param event MouseEvent
             *
             */
            public function clickHandler(event:MouseEvent):void{
                var o:Object = DataGrid(DataGridListData(listData).owner).selectedItem;
                o.checked=cb.selected;
                ArrayCollection(DataGrid(DataGridListData(listData).owner).dataProvider).setItemAt(o,DataGrid(DataGridListData(listData).owner).selectedIndex);
            }
 
            /**
             * Overides <code>data</code> parameter to set the <code>selected</code> parameter of the
             * checkbox.
             *
             * @param value Object
             */
            override public function set data(value:Object):void{
                if(value!=null){
                    super.data=value;
                    cb.selected=value.checked;
                }
            }
        ]]>

You can download the code from my post in Adobe cook book.

:
Posted by 라면스프
2013. 11. 22. 15:26

[펌][BlazeDS] 메세징을 위한 폴링과 설정 Enjoy/FLEX2013. 11. 22. 15:26

원문출처 : http://jjaeko.tistory.com/115



[BlazeDS] 메세징을 위한 폴링과 설정



BlazeDS 에서는 rtmp 채널을 지원하지 않기 때문에, 디폴트로 폴링 방식으로 메세징을 지원 합니다.
이런 사실 때문에, real-time messaging을 지원하지 않을거라는 착각을 할 수 있는데 다양한 테크닉으로 real-time messaging을 구현할 수 있습니다. 하지만 앞으로 소개될 테크닉들은 http-based 이기 때문에 독자적인 socket을 사용하는 lcds에 비해 속도와 동시접속에 있어서 뒤쳐질 수 밖에 없습니다.


Simple Polling




이 방식은 real-time의 효과를 볼 수 없는 기본적인 polling 입니다. 일정한 간격으로 요청(poll)하고 응답(ack) 받습니다. 만약 요청 했을 때, 다른 client로 부터 메세지가 들어와 있지 않다면 비어 있는 응답을 받습니다.

설정 방법은 다음과 같습니다.

<channel-definition id="polling-amf" class="mx.messaging.channels.AMFChannel">
    <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
    <properties>
        <polling-enabled>true</polling-enabled>
        <polling-interval-seconds>4</polling-interval-seconds>
    </properties>
</channel-definition>




Piggybacking Polling
이 방식은 Simple Polling에서 일정한 간격에 의한 poll 이전에 다른 client의 메세지가 들어와 있을 경우, 다른 어떤 요청(Producer 또는 RemoteObject)을 보낸다면 그에 대한 결과와 더불어 메세지도 함께 응답 합니다.

설정 방법은 다음과 같습니다.

<channel-definition id="polling-amf" class="mx.messaging.channels.AMFChannel">
    <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
    <properties>
        <polling-enabled>true</polling-enabled>
        <polling-interval-seconds>4</polling-interval-seconds>
        <piggybacking-enabled >true</piggybacking-enabled >
    </properties>
</channel-definition>




Long Polling




이 방식은 polling 이지만 다른 client로 부터 메세지가 올 때까지(또는 설정한 기간 만큼) poll을 잡아 놓음으로써 real-time의 효과를 볼 수 있습니다.

설정 방법은 다음과 같습니다.
wait-interval-millis : (default 0) poll 의 대기시간 입니다. -1의 경우 다른 client의 메세지가 올 때까지 무한대로 기다립니다.
max-waiting-poll-requests : 대기하는 poll의 갯수입니다.

<channel-definition id="long-polling-amf" class="mx.messaging.channels.AMFChannel">
    <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
    <properties>
        <polling-enabled>true</polling-enabled>
        <wait-interval-millis>-1</wait-interval-millis>
        <polling-interval-millis>100</polling-interval-millis>
        <max-waiting-poll-requests>50</max-waiting-poll-requests>
    </properties>
</channel-definition>




Streaming




HTTP1.1 스펙의 open connection 기능을 이용함으로써, 서버 push를 구현하는 방법 입니다.
서버 push이기 때문에 real-time 그 자체라고 할 수 있습니다.

설정 방법은 다음과 같습니다.
max-streaming-clients : open connection의 갯수입니다.

<channel-definition id="streaming-amf" class="mx.messaging.channels.StreamingAMFChannel">
    <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/>
    <properties>
        <max-streaming-clients>10</max-streaming-clients>
    </properties>
</channel-definition>




퍼포먼스는 Stream -> long polling -> piggybacking polling -> simple polling 순으로 좋습니다.
설정 가능한 프로퍼티는 참고 문서를 참조 하세요.





참고 사이트. http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=lcconfig_3.html


Configuring channels with servlet-based endpoints


The servlet-based endpoints are part of both BlazeDS and LiveCycle Data Services ES.

Simple channels and endpoints

The AMFEndpoint and HTTPEndpoint are simple servlet-based endpoints. You generally use channels with these endpoints without client polling for RPC service components, which require simple call and response communication with a destination. When working with the Messaging Service, you can use these channels with client polling to constantly poll the destination on the server for new messages, or with long polling to provide near real-time messaging when using a streaming channel is not an option in your network environment.

Property

Description

polling-enabled

Optional channel property. Default value is false.

polling-interval-millis

Optional channel property. Default value is 3000. This parameter specifies the number of milliseconds the client waits before polling the server again. When polling-interval-millis is 0, the client polls as soon as it receives a response from the server with no delay.

wait-interval-millis

Optional endpoint property. Default value is 0. This parameter specifies the number of milliseconds the server poll response thread waits for new messages to arrive when the server has no messages for the client at the time of poll request handling. For this setting to take effect, you must use a nonzero value for the max-waiting-poll-requests property.

A value of 0 means that server does not wait for new messages for the client and returns an empty acknowledgment as usual. A value of-1 means that server waits indefinitely until new messages arrive for the client before responding to the client poll request.

The recommended value is 60000 milliseconds (one minute).

client-wait-interval-millis

Optional channel property. Default value is 0. Specifies the number of milliseconds the client will wait after it receives a poll response from the server that involved a server wait. A value of 0 means the client uses its configured polling-interval-millis value to determine the wait until its next poll. Otherwise, this value overrides the default polling interval of the client. Setting this value to 1 allows clients that poll the server with wait to poll immediately upon receiving a poll response, providing a real-time message stream from the server to the client. Any clients that poll the server and are not serviced with a server wait use the polling-interval-millis value.

max-waiting-poll-requests

Optional endpoint property. Default value is 0. Specifies the maximum number of server poll response threads that can be in wait state. When this limit is reached, the subsequent poll requests are treated as having zero wait-interval-millis.

piggybacking-enabled

Optional endpoint property. Default value is false. Enable to support piggybacking of queued messaging and data management subscription data along with responses to any messages the client sends to the server over this channel.

login-after-disconnect

Optional channel property. Default value is false. Setting to true causes clients to automatically attempt to reauthenticate themselves with the server when they send a message that fails because credentials have been reset due to server session timeout. The failed messages are resent after reauthentication, making the session timeout transparent to the client with respect to authentication.

flex-client-outbound-queue-processor

Optional channel property. Use to manage messaging quality of service for subscribers. Every client that subscribes to the server over this channel is assigned a unique instance of the specified outbound queue processor implementation that manages the flow of messages to the client. This can include message conflation, filtering, scheduled delivery and load shedding. You can define configuration properties, and if so, they are used to configure each new queue processor instance that is created. The following example shows how to provide a configuration property:

<flex-client-outbound-queue-processor class="my.company.QoSQueueProcessor"> <properties> <custom-property>5000</custom-property> </properties> </flex-client-outbound-queue-processor>
serialization

Optional serialization properties on endpoint. For more information, see Configuring AMF serialization on a channel.

connect-timeout-seconds

Optional channel property. Use to limit the client channel's connect attempt to the specified time interval.

invalidate-session-on-disconnect

Optional endpoint property. Disabled by default. If enabled, when a disconnect message is received from a client channel, the corresponding server session is invalidated. If the client is closed without first disconnecting its channel, no disconnect message is sent, and the server session is invalidated when its idle timeout elapses.

add-no-cache-headers

Optional endpoint property. Default value is true. HTTPS requests on some browsers do not work when pragma no-cache headers are set. By default, the server adds headers, including pragma no-cache headers to HTTP responses to stop caching by the browsers.

Non-polling AMF and HTTP channels

The simplest types of channels are AMF and HTTP channels in non-polling mode, which operate in a single request-reply pattern. The following example shows AMF and HTTP channel definitions configured for no polling:

<!-- Simple AMF -->
<channel-definition id="samples-amf"
    type="mx.messaging.channels.AMFChannel">
    <endpoint url="http://{server.name}:8400/myapp/messagebroker/amf"
        type="flex.messaging.endpoints.AmfEndpoint"/>
</channel-definition>
<!-- Simple secure AMF -->
<channel-definition id="my-secure-amf"
    class="mx.messaging.channels.SecureAMFChannel">
    <endpoint url="https://{server.name}:9100/dev/messagebroker/
        amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
</channel-definition>
<!-- Simple HTTP -->
<channel-definition id="my-http"
    class="mx.messaging.channels.HTTPChannel">
    <endpoint url="http://{server.name}:8400/dev/messagebroker/http"
        class="flex.messaging.endpoints.HTTPEndpoint"/>
</channel-definition>
<!-- Simple secure HTTP -->
<channel-definition id="my-secure-http" class="mx.messaging.channels.SecureHTTPChannel">
    <endpoint url=
        "https://{server.name}:9100/dev/messagebroker/
            httpsecure"
        class="flex.messaging.endpoints.SecureHTTPEndpoint"/>
</channel-definition>

Polling AMF and HTTP channels

You can use an AMF or HTTP channel in polling mode to repeatedly poll the endpoint to create client-pull message consumers. The interval at which the polling occurs is configurable on the channel. You can also manually poll by calling the poll() method of a channel for which polling is enabled; for example, you want set the polling interval to a high number so that the channel does not automatically poll, and call the poll() method to poll manually based on an event, such as a button click.

When you use a polling AMF or HTTP channel, you set the polling property to true in the channel definition. You can also configure the polling interval in the channel definition.

Note: You can also use AMF and HTTP channels in long polling mode to get pushed messages to the client when the other more efficient and real-time mechanisms are not suitable. For information about long polling, see Long polling AMF and HTTP channels.

The following example shows AMF and HTTP channel definitions configured for polling:

<!-- AMF with polling -->
<channel-definition id="samples-polling-amf"
    type="mx.messaging.channels.AMFChannel">
    <endpoint url="http://{server.name}:8700/dev/messagebroker/amfpolling"
        type="flex.messaging.endpoints.AMFEndpoint"/>
    <properties>
            <polling-enabled>true</polling-enabled>
            <polling-interval-seconds>8</polling-interval-seconds>
    </properties>
</channel-definition>
<!-- HTTP with polling -->
<channel-definition id="samples-polling-http"
    type="mx.messaging.channels.HTTPChannel">
    <endpoint url="http://{server.name}:8700/dev/messagebroker/httppolling"
        type="flex.messaging.endpoints.HTTPEndpoint"/>
    <properties>
            <polling-enabled>true</polling-enabled>
            <polling-interval-seconds>8</polling-interval-seconds>
    </properties>
</channel-definition>

Note: You can also use secure AMF or HTTP channels in polling mode.

Long polling AMF and HTTP channels

In the default configuration for a polling AMF or HTTP channel, the endpoint does not wait for messages on the server. When the poll request is received, it checks whether any messages are queued for the polling client and if so, those messages are delivered in the response to the HTTP request. You configure long polling in the same way as polling, but you also must set the wait-interval-millismax-waiting-poll-requests, and client-wait-interval-millis properties.

To achieve long polling, you set the following properties in the properties section of a channel definition in the services-config.xml file:

  • polling-enabled
  • polling-interval-millis
  • wait-interval-millis
  • max-waiting-poll-requests.
  • client-wait-interval-millis

Using different settings for these properties results in different behavior. For example, setting the wait-interval-millis property to 0 (zero) and setting thepolling-interval-millis property to a nonzero positive value results in normal polling. Setting the wait-interval-millis property to a high value reduces the number of poll messages that the server must process, but the number of request handling threads on the server limits the total number of parked poll requests.

The following example shows AMF and HTTP channel definitions configured for long polling:

<!-- Long polling AMF -->
<channel-definition id="my-amf-longpoll" class="mx.messaging.channels.AMFChannel">
    <endpoint
        url="http://servername:8700/contextroot/messagebroker/myamflongpoll" 
        class="flex.messaging.endpoints.AMFEndpoint"/>
    <properties>
        <polling-enabled>true</polling-enabled>
        <polling-interval-seconds>0</polling-interval-seconds>
        <wait-interval-millis>60000</wait-interval-millis>
        <client-wait-interval-millis>3000</client-wait-interval-millis>
        <max-waiting-poll-requests>100</max-waiting-poll-requests>
    </properties>
</channel-definition>

<!-- Long polling HTTP -->
<channel-definition id="my-http-longpoll" class="mx.messaging.channels.HTTPChannel">
    <endpoint
        url="http://servername:8700/contextroot/messagebroker/myhttplongpoll" 
        class="flex.messaging.endpoints.HTTPEndpoint"/>
    <properties>
        <polling-enabled>true</polling-enabled>
        <polling-interval-seconds>0</polling-interval-seconds>
        <wait-interval-millis>60000</wait-interval-millis>
        <client-wait-interval-millis>3000</client-wait-interval-millis>
        <max-waiting-poll-requests>100</max-waiting-poll-requests>
    </properties>
</channel-definition>

Note: You can also use secure AMF or HTTP channels in polling mode.

The caveat for using the wait-interval-millis BlazeDS is the utilization of available application server threads. Because this channel ties up one application server request handling thread for each parked poll request, this mechanism can have an impact on server resources and performance. Modern JVMs can typically support about 200 threads comfortably if given enough heap space. Check the maximum thread stack size (often 1 or 2 megabytes per thread) and make sure that you have enough memory and heap space for the number of application server threads you configure.

To ensure that Flex clients using channels with wait-interval-millis do not lock up your application server, BlazeDS requires that you set the max-waiting-poll-requests property, which specifies the maximum number of waiting connections that BlazeDS should manage. This number must be set to a number smaller than the number of HTTP request threads your application server is configured to use. For example, you configure the application server to have at most 200 threads and allow at most 170 waiting poll requests. This setting would ensure that you have at least 30 application server threads to use for handling other HTTP requests. Your free application server threads should be large enough to maximize parallel opportunities for computation. Applications that are I/O heavy can require a large number of threads to ensure all I/O channels are utilized completely. Multiple threads are useful for the following operations:

  • Simultaneously writing responses to clients behind slow network connections
  • Executing database queries or updates
  • Performing computation on behalf of user requests

Another consideration for using wait-interval-millis is that BlazeDS must avoid monopolizing the available connections that the browser allocates for communicating with a server. The HTTP 1.1 specification recommends that browsers allocate at most two connections to the same server when the server supports HTTP 1.1. To avoid using more that one connection from a single browser, BlazeDS allows only one waiting thread for a given application server session at a time. If more than one Flash Player instance within the same browser process attempts to interact with the server using long polling, the server forces them to poll on the default interval with no server wait to avoid busy polling.

Streaming AMF and HTTP channels

The streaming AMF and HTTP channels are HTTP-based streaming channels that the BlazeDS server can use to push updates to clients using a technique called HTTP streaming. These channels give you the option of using standard HTTP for real-time messaging. This capability is supported for HTTP 1.1, but is not available for HTTP 1.0. There are also a number of proxy servers still in use that are not compliant with HTTP 1.1. When using a streaming channel, make sure that the channel hasconnect-timeout-seconds defined and the channel set has a channel to fall back to, such as an AMF polling channel.

Using streaming AMF or HTTP channels/endpoints is like setting a long polling interval on a standard AMF or HTTP channel/endpoint, but the connection is never closed even after the server pushes the data to the client. By keeping a dedicated connection for server updates open, network latency is greatly reduced because the client and the server do not continuously open and close the connection. Unlike polling channels, because streaming channels keep a constant connection open, they can be adversely affected by HTTP connectors, proxies, reverse proxies or other network components that can buffer the response stream.

The following table describes the channel and endpoint configuration properties in the services-config.xml file that are specific to streaming AMF and HTTP channels/endpoints. The table includes the default property values as well as considerations for specific environments and applications.

Property

Description

connect-timeout-seconds

Using a streaming connection that passes through an HTTP 1.1 proxy server that incorrectly buffers the response sent back to the client hangs the connection. For this reason, you must set the connect-timeout-seconds property to a relatively short timeout period and specify a fallback channel such as an AMF polling channel.

idle-timeout-minutes

Optional channel property. Default value is 0. Specifies the number of minutes that a streaming channel is allowed to remain idle before it is closed. Setting the idle-timeout-minutes property to 0 disables the timeout completely, but it is a potential security concern.

max-streaming-clients

Optional endpoint property. Default value is 10. Limits the number of Flex clients that can open a streaming connection to the endpoint. To determine an appropriate value, consider the number of threads available on your application server because each streaming connection open between a FlexClient and the streaming endpoints uses a thread on the server. Use a value that is lower than the maximum number of threads available on the application server.

This value is for the number of Flex client application instances, which can each contain one or more MessageAgents (Producer or Consumer components).

server-to-client-heartbeat-millis

Optional endpoint property. Default value is 5000. Number of milliseconds that the server waits before writing a single byte to the streaming connection to make sure that the client is still available. This is important to determine when a client is no longer available so that its resources associated with the streaming connection can be cleaned up. Note that this functionality keeps the session alive. A non-positive value disables this functionality.

user-agent-settings

Optional endpoint property. Default values are as shown in the following example:

<user-agent-settings> <user-agent match-on="MSIE" kickstart-bytes= "2048" max-streaming-connections-per-session="1"/> <user-agent match-on="Firefox" kickstart-bytes="0" max-streaming-connections-per-session="1"/> </user-agent-settings>

User agents are used to customize the streaming endpoint for specific web browsers for the following reasons:

  • A certain number of bytes must be written before the endpoint can reliably use a streaming connection as specified by the kickstart-bytes attribute.
  • There is a browser-specific limit to the number of connections allowed per session. In Firefox, the limit is eight connections per session. In Internet Explorer, the limit is two connections allowed per session. Therefore, BlazeDS must limit the number of streaming connections per session on the server to stay below this limit.

By default, BlazeDS uses 1 as the value for max-streaming-connections-per-session. You can change the values for Internet Explorer and Firefox, and you can add other browser-specific limits by specifying a new user-agent element with a match-on value for a specific browser user agent.

The following example shows streaming AMF and HTTP channel definitions:

<!-- AMF with streaming -->
<channel-definition id="my-amf-stream"
    class="mx.messaging.channels.StreamingAMFChannel">
    <endpoint url="http://servername:2080/myapp/messagebroker/streamingamf" 
        class="flex.messaging.endpoints.StreamingAMFEndpoint"/>
</channel-definition>

<!-- Secure AMF with streaming -->
<channel-definition id="my-secure-amf-stream"
    class="mx.messaging.channels.SecureStreamingAMFChannel">
    <endpoint url="http://servername:2080/myapp/messagebroker/securestreamingamf" 
        class="flex.messaging.endpoints.SecureStreamingAMFEndpoint"/>
</channel-definition>

<!-- HTTP with streaming -->
<channel-definition id="my-http-stream"
    class="mx.messaging.channels.StreamingHTTPChannel">
    <endpoint url="http://servername:2080/myapp/messagebroker/streaminghttp" 
        class="flex.messaging.endpoints.StreamingHTTPEndpoint"/>
</channel-definition>

<!-- Secure HTTP with streaming -->
<channel-definition id="my-secure-http-stream"
    class="mx.messaging.channels.SecureStreamingHTTPChannel">
    <endpoint url="http://servername:2080/myapp/messagebroker/securestreaminghttp" 
        class="flex.messaging.endpoints.SecureStreamingHTTPEndpoint"/>
</channel-definition>


:
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 라면스프
2012. 11. 30. 13:57

Adobe BlazeDS download Enjoy/FLEX2012. 11. 30. 13:57


출처 : https://www.adobe.com/cfusion/entitlement/index.cfm?e=lc_blazeds


adobe 로그인이 필요함



Adobe BlazeDS download

BlazeDS, powered by Adobe LiveCycle Data Services ES2 a server‐based Java remoting and web messaging technology that enables developers to easily connect to back‐end distributed data and push data to Adobe® Flex® and Adobe AIR™ applications for more responsive rich Internet application (RIA) experiences. For more performance and capable rich Internet applications, organizations need to consider the complete product offering available with LiveCycle Data Services ES2. Review the BlazeDS and LiveCycle Data Services ES2 comparison table for details.

BLAZEDS RELEASE BUILDS

Turnkey

The turnkey download contains a ready-to-use version of Tomcat (version 6.0.14) in which the BlazeDS WAR file has already been deployed and configured along with a variety sample applications. The turnkey allows you to get up and running with BlazeDS in a matter of minutes. BlazeDS is licensed under GNU Lesser General Public License, Version 3. Please refer to the Legal Stuff page for specific licensing information.

Binary Distribution

The binary distribution of BlazeDS contains the BlazeDS WAR file. BlazeDS is licensed under GNU Lesser General Public License, Version 3.

Source

The source download is a zip file that includes the BlazeDS source code and build scripts, everything you need to build BlazeDS from source. For more information about the BlazeDS source code or to browse the source tree, go here. BlazeDS is licensed underGNU Lesser General Public License, Version 3.

Explore your options

FeaturesBlazeDSLiveCycle Data Services ES2
RPC services
Java remoting/Action Message Format (AMF)YesYes
Ajax client libraries to Java™ remotingYesYes
WS/JSON proxy serviceYesYes
Messaging
Servlet-based messaging services (hundreds of clients per CPU)YesYes
Java NIO high-performance messaging (thousands of clients per CPU)NoYes
Real Time Messaging Protocol (RTMP)NoYes
Data throttlingNoYes
Reliable communicationsNoYes
Data management
Transaction (batch processing)NoYes
Data pagingNoYes
Lazy loading (on demand)NoYes
Conflict resolution and synchronizationNoYes
SQL adapterNoYes
Hibernate adapterNoYes
"Fiber-aware" assemblerNoYes
Offline web applicationsNoYes
Development and deployment
Spring integration supportYesYes
Adobe Flash® Builder™ modeling plug-inNoYes
Enterprise supportNoYes
RIA PDF generationNoYes
WSRP portal integrationNoYes
Load/stress testing toolNoYes
Edge serverNoYes
Enterprise support plansNoYes

Downloads

DownloadMD5 checksum
BlazeDS turnkeyTurnkey (ZIP, 43.7M)01fef59b87fcf28b664d55adaeba5cde
BlazeDS binary distributionBinary distribution(ZIP, 4.1M)d5655a04196f0c107a48734b181bde42
BlazeDS sourceSource (ZIP, 358.8M)b971bd31fadaa0f6fded3aab7f522ba4

THESE RESOURCES ARE AVAILABLE TO SUPPORT YOU IN THE INSTALLATION AND EVALUATION PROCESS.

DIFFICULTIES DOWNLOADING?

Download help

Adobe BlazeDS download

:
Posted by 라면스프

출처 : http://www.adobe.com/cfusion/tdrc/index.cfm?product=flex_eclipse


adobe 로그인이 필요함


Download Adobe Flex Builder 3.0.2 Professional Eclipse Plug-in


Adobe® Flex® Builder 3 Professional Eclipse Plug-in (60 day trial)
A professional Eclipse™-based developer tool enabling intelligent coding, interactive step-through debugging, and visual design of user interface layout and behavior for Flex applications. Includes support for building desktop applications with Adobe AIR.

This download requires Eclipse 3.3 or higher to be installed.

Difficulties downloading?

Download help Download help



Notice: By downloading this product, I authorize Adobe and its agents ("Adobe") to contact me about Adobe and its products and services, including product releases and upgrades, events, surveys, and offers. I will have the opportunity to opt out of future communications, and Adobe may use data I have provided in accordance with the Adobe Online Privacy Policy. I understand I may access, modify, or request deletion of my data. This disclaimer is not applicable for residents of Hungary or Spain.

EU residents: You are consenting that your personal data may be transferred to countries outside the EU and be stored by Adobe at Adobe's offices or the offices of Adobe's trusted vendors in the following countries: United States, Canada, India, Argentina, and the Philippines. If you do not provide consent, you may not download the software.

Please review Adobe's Online Privacy Policy.

 

System requirements 

       

 



  
View sample email

By providing your information and continuing, you are agreeing to the Adobe Privacy Policy.
Note: This does not enable other communications from Adobe, and messages will not be sent after 60 days.

See all downloads


Download Adobe Flex Builder 3.0.2 Professional Eclipse Plug-in

Download Adobe Flex Builder 3.0.2 Professional Eclipse Plug-in

:
Posted by 라면스프
2012. 11. 28. 10:13

Flex 3.2: Loading sub-apps Enjoy/FLEX2012. 11. 28. 10:13


https://learn.adobe.com/wiki/display/Flex/Getting+Started


http://livedocs.adobe.com/flex/3/html/help.html

:
Posted by 라면스프
2012. 11. 28. 09:58

Flex 3 SDK Downloads Enjoy/FLEX2012. 11. 28. 09:58

sdk 3 다운링크 페이지

http://sourceforge.net/adobe/flexsdk/wiki/Download%20Flex%203/



** 20170816 내용 수정 됨.







# Flex 3 SDK Downloads Look [here](Downloads) for a description regarding the types of SDKs available. Look [here](Build%20Types) for an explanation of the different build types found on this page. Look [here](Using%20Flex%203%20Builds%20in%20Flex%20Builder) for an explanation of how to use a stable or nightly build in Flex Builder. **Please refer to [this document](Targeting%20Flash%20Player%2010%20Beta) if you wish to target the [Astro beta](http://labs.adobe.com/technologies/flashplayer10/).** ### Latest Milestone Release Builds Milestone|Build|Build Date|Adobe Flex SDK|Open Source Flex SDK|Adobe Add-ons| ---------|-----|----------|--------------|--------------------|-------------| 3.6A|3.6.0.16995A|Tue May 3, 2011|[Download (ZIP, 122MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.6.0.16995A&pkgtype=1) 3.5B|3.5.0.12683B|Fri Dec 18, 2009|[Download (ZIP, 122MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.5.0.12683B&pkgtype=1)|[Download (ZIP, 26MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.5.0.12683B&pkgtype=2)|[Download (ZIP, 65MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.5.0.12683B&pkgtype=3) 3.4A|3.4.0.9271A|Tue Aug 18, 2009|[Download (ZIP, 122MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.4.0.9271A%26amp%3Bpkgtype%3D1)|[Download (ZIP, 26MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.4.0.9271A&pkgtype=2)|[Download (ZIP, 65MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.4.0.9271A&pkgtype=3) 3.3A|3.3.0.4852A|Thu Feb 5, 2009|[Download (ZIP, 121MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.3.0.4852A&pkgtype=1)|[Download (ZIP, 24MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.3.0.4852A&pkgtype=2)|[Download (ZIP, 63MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.3.0.4852A&pkgtype=3) 3.2A|3.2.0.3958A|Wed Oct 29, 2008|[Download (ZIP, 118MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.2.0.3958A&pkgtype=1)|[Download (ZIP, 24MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.2.0.3958A&pkgtype=2)|[Download (ZIP, 63MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.2.0.3958A&pkgtype=3) 3.1A|3.1.0.2710A|Fri Aug 15, 2008|[Download (ZIP, 82MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.1.0.2710A&pkgtype=1)|[Download (ZIP, 23MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.1.0.2710A&pkgtype=2)|[Download (ZIP, 59MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.1.0.2710A&pkgtype=3) 3.0A|3.0.0.477A|Tue Feb 12, 2008|[Download (ZIP, 79MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.0.0.477A&pkgtype=1)|[Download (ZIP, 23MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.0.0.477A&pkgtype=2)|[Download (ZIP, 57MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.0.0.477A&pkgtype=3) ### Stable Builds Stable|Build|Build Date|Adobe Flex SDK|Open Source Flex SDK|Adobe Add-ons | ------|-----|----------|--------------|--------------------|--------------| 3.4.1A|3.4.1.10084A|Tue Nov, 2011|[Download (ZIP, 122MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.4.1.10084A&pkgtype=1) 3.0.1A|3.0.1.1732A|Tue Nov, 2011|[Download (ZIP, 122MB)](http://blogs.adobe.com/flex/files/2012/05/FlexLicense.swf?build=3.0.1.1732A&pkgtype=1)



3.0 빌더 링크가 있는 페이지 http://shon.yee.kr/39



:
Posted by 라면스프