Qooxdoo 로 클레스 만들기.


// 클레스 - 기본상속 (qx.core.Object)

qx.Class.define("projectName.path.fileName" {

statics:{},

construct:function() { /* 생성자 */ this.base(arguments); },

events:{},

properties:{},

members:{},

destruct:function() { /*파괴자*/ }

});


// qx.core.Object 상속

qx.Class.define("projectName.path.fileName" {

extend:qx.core.Object,

statics:{},

construct:function() { /* 생성자 */ this.base(arguments); },

events:{},

properties:{},

members:{},

destruct:function() { /*파괴자*/ }

});


// 싱글톤

qx.Class.define("projectName.path.fileName" {

type:"Singleton",

statics:{},

construct:function() { /* 생성자 */ this.base(arguments); },

events:{},

properties:{},

members:{},

destruct:function() { /*파괴자*/ }

});


// 싱글톤

qx.Class.define("projectName.path.fileName" {

type:"Singleton",

statics:{},

construct:function() { /* 생성자 */ this.base(arguments); },

events:{},

properties:{},

members:{},

destruct:function() { /*파괴자*/ }

});

랩핑한지 오래 되었지만 제가 직접 하나하나 랩핑하였습니다.


https://github.com/windofwind/pureMVC-for-Qooxdoo/


qooxdoo 에 pureMVC 적용하고 싶으신 분들은 프로젝트 라이브러리에 추가하세요.

https://simplapi.wordpress.com/2012/07/02/linking-socket-io-to-qooxdoo/


Qooxdoo is a great framework, but sometimes you need to add extra content to it, and this is not so simple.

Here is a basic class and idea to link Socket.IO client API to Qooxdoo framework :

Before playing

Before doing anything with Socket.IO, you first need to include thooses files into your project.
Start getting Node.JS, and installing Socket.IO using « npm install socket.io ». This should install in node_module (in node.js root folder) socket.io folder. Inside this node_module, you should find the client API of Socket.IO here :
%NODE_ROOT%/node_modules/socket.io/node_modules/socket.io-client/dist

The dist folder should contains 4 files :

  • socket.io.js
  • socket.io.min.js
  • WebSocketMain.swf
  • WebSocketMainInsecure.swf

Regarding what you want, you need only 3 files : choose between the socket.io.js and the min version. I will prefer here the minimal but it does not change so much things after all.

I didn’t find the good way to put thooses files in the qooxdoo main project, but this should do the trick :
On resource folder, create a script folder, create inside this folder a « socket » (what you want for this one) folder. Put 3 files into this one.

Now you have the socket.io resource folder on your Qooxdoo app. But it’s not enough for now.

On the config.json file, you need to force the system to copy it, I use here the « build-script » which is the remapped default build folder :

1
2
3
4
5
6
7
8
9
10
11
12
13
"jobs":{
    "build-script":{
        "copy-files" :{
            "files":[
                "./script/socket/"
            ],
            "source" : "./source/resource/",
            "target"  : "./build/"
        },
        "add-script":[{
            "uri":"script/socket/socketio.js"
        }]
(...)

The add-script is the most important part, it force the system to load the script as part of the qooxdoo launch. The script will be launched around Application.main start (I didn’t check exactly but before it’s too early and at the end of main it’s available).

Now you can play with Socket.IO over Qooxdoo, here is a basic class to deal with inside Qooxdoo system (under LGPLv3, like all sources I post here) :

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
189
190
191
/**
 * This class is a direct link with socket.io.
 */
qx.Class.define("myapp.api.WebSocket",{
    extend : qx.core.Object,
 
    //Socket.io events
    events :{
        /** socket.io connect event */
        "connect"           : "qx.event.type.Event",
        /** socket.io connecting event */
        "connecting"        : "qx.event.type.Data",
        /** socket.io connect_failed event */
        "connect_failed"    : "qx.event.type.Event",
        /** socket.io message event */
        "message"           : "qx.event.type.Data",
        /** socket.io close event */
        "close"             : "qx.event.type.Data",
        /** socket.io disconnect event */
        "disconnect"        : "qx.event.type.Event",
        /** socket.io reconnect event */
        "reconnect"         : "qx.event.type.Data",
        /** socket.io reconnecting event */
        "reconnecting"      : "qx.event.type.Data",
        /** socket.io reconnect_failed event */
        "reconnect_failed"  : "qx.event.type.Event",
        /** socket.io error event */
        "error"             : "qx.event.type.Data"
    },
 
    properties:{
        /**
         * The url used to connect to socket.io
         */
        url:{
            nullable:   false,
            init:       "http://"+window.location.hostname+"/",
            check:      "String"
        },
        /** The port used to connect */
        port:{
            nullable:   false,
            init:       8080,
            check:      "Number"
        },
        /** The namespace (socket.io namespace), can be empty */
        namespace:{
            nullable:   true,
            init:       "",
            check:      "String"
        },
        /** The socket (socket.io), can be null */
        socket:{
            nullable:   true,
            init:       null,
            check:      "Object"
        },
        /** Parameter for socket.io indicating if we should reconnect or not */
        reconnect:{
            nullable:   true,
            init:       true,
            check:      "Boolean"
        },
        connectTimeout:{
            nullable:   true,
            init:       10000,
            check:      "Number"
        },
        /** Reconnection delay for socket.io. */
        reconnectionDelay:{
            nullable:   false,
            init:       500,
            check:      "Number"
        },
        /** Max reconnection attemps */
        maxReconnectionAttemps:{
            nullable:   false,
            init:       1000,
            check:      "Number"
        }
    },
 
    /** Constructor
     *
     * @param namespace {string ? null} The namespace to connect on
    */
    construct: function(namespace){
        this.base(arguments);
        if(namespace !== null){
            this.setNamespace(namespace);
        }
        this.__name = [];
    },
 
    members:{
        //The name store an array of events
        __name : null,
 
        /**
         * Trying to using socket.io to connect and plug every event from socket.io to qooxdoo one
        */
        connect:function(){
            if(this.getSocket() != null){
                this.getSocket().removeAllListeners();
                this.getSocket().disconnect();
            }
            this.setSocket(io.connect(this.getUrl()+this.getNamespace(), {
                'port': this.getPort(),
                'reconnect': this.getReconnect(),
                'connect timeout' : this.getConnectTimeout(),
                'reconnection delay': this.getReconnectionDelay(),
                'max reconnection attempts': this.getMaxReconnectionAttemps(),
                'force new connection':true
            }));
 
            this.on("connect",          function(){     this.fireEvent("connect");                  }, this);
            this.on("connecting",       function(e){    this.fireDataEvent("connecting", e);        }, this);
            this.on("connect_failed",   function(){     this.fireEvent("connect_failed");           }, this);
            this.on("message",          function(e){    this.fireDataEvent("message", e);           }, this);
            this.on("close",            function(e){    this.fireDataEvent("close", e);             }, this);
            this.on("disconnect",       function(){     this.fireEvent("disconnect");               }, this);
            this.on("reconnect",        function(e){    this.fireDataEvent("reconnect", e);         }, this);
            this.on("reconnecting",     function(e){    this.fireDataEvent("reconnecting", e);      }, this);
            this.on("reconnect_failed", function(){     this.fireEvent("reconnect_failed");         }, this);
            this.on("error",            function(e){    this.fireDataEvent("error", e);             }, this);
        },
 
        /**
         * Emit an event using socket.io
         *
         * @param name {string} The event name to send to Node.JS
         * @param jsonObject {object} The JSON object to send to socket.io as parameters
        */
        emit:function(name, jsonObject){
            this.getSocket().emit(name, jsonObject);
        },
 
        /**
         * Connect and event from socket.io like qooxdoo event
         *
         * @param name {string} The event name to watch
         * @param fn {function} The function wich will catch event response
         * @param that {mixed} A link to this
        */
        on:function(name, fn, that){
            this.__name.push(name);
            if(typeof(that) !== "undefined" && that !== null){
                this.getSocket().on(name, qx.lang.Function.bind(fn, that));
            }else{
                this.getSocket().on(name, fn);
            }
        }
    },
 
    /**
     * Destructor
     */
    destruct : function(){
        if(this.getSocket() != null){
            //Deleting listeners
            if(this.__name !== null && this.__name.length >= 1){
                for(var i=0; i<this.__name.length; ++i){
                    this.getSocket().removeAllListeners(this.__name[i]);
                }
            }
            this.__name = null;
 
            this.removeAllBindings();
 
            //Disconnecting socket.io
            try {
                this.getSocket().socket.disconnect();
            } catch(e) {}
 
            try {
                this.getSocket().disconnect();
            } catch(e) {}
 
            this.getSocket().removeAllListeners("connect");
            this.getSocket().removeAllListeners("connecting");
            this.getSocket().removeAllListeners("connect_failed");
            this.getSocket().removeAllListeners("message");
            this.getSocket().removeAllListeners("close");
            this.getSocket().removeAllListeners("disconnect");
            this.getSocket().removeAllListeners("reconnect");
            this.getSocket().removeAllListeners("reconnecting");
            this.getSocket().removeAllListeners("reconnect_failed");
            this.getSocket().removeAllListeners("error");
        }
    }
});

This class can be used like this :

1
2
3
4
5
6
7
8
9
10
var ws = new myapp.api.WebSocket();
//Here you should customize port, hostname, ...
 
//Connect with previous setted properties
ws.connect();
 
ws.emit("achannel", "hello");
ws.on("achannel", function(result){
  console.log(result);
}, this);

Simple as this !

1. 프로젝트 만들기


qooxdoo/tool/bin> python create-application.py 를 하면 아래와 같이 설명이 나온다.

Usage: create-application.py --name APPLICATIONNAME [--out DIRECTORY]
                             [--namespace NAMESPACE] [--type TYPE]
                             [-logfile LOGFILE] [--skeleton-path PATH]

Script to create a new qooxdoo application.

Example: For creating a regular GUI application 'myapp' you could execute:
  create-application.py --name myapp

Options:
  -h, --help            show this help message and exit
  -n APPLICATIONNAME, --name=APPLICATIONNAME
                        Name of the application. An application folder with
                        identical name will be created. (Required)
  -o DIRECTORY, --out=DIRECTORY
                        Output directory for the application folder. (Default:
                        .)
  -s NAMESPACE, --namespace=NAMESPACE
                        Applications's top-level namespace. (Default:
                        APPLICATIONNAME)
  -t TYPE, --type=TYPE  Type of the application to create, one of:
                        ['contribution', 'desktop', 'inline', 'mobile',
                        'native', 'server', 'website'].'contribution' -- is
                        suitable for qooxdoo-contrib; 'desktop' -- is a
                        standard qooxdoo GUI application; 'inline' -- is an
                        inline qooxdoo GUI application; 'mobile' -- is a
                        qooxdoo mobile application with full OO support and
                        mobile GUI classes; 'native' -- is a qooxdoo
                        application with full OO support but no GUI classes;
                        'server' -- for non-browser run times like Rhino,
                        node.js; 'website' -- can be used to build low-level
                        qooxdoo applications. (Default: desktop)
  -l LOGFILE, --logfile=LOGFILE
                        Log file
  -p PATH, --skeleton-path=PATH
                        (Advanced) Path where the script looks for skeletons.
                        The directory must contain sub directories named by
                        the application types. (Default: /Library/WebServer/Do
                        cuments/Quad/qooxdoo-2.0.1-sdk/component/skeleton)
  --cache=PATH          Path to the cache directory; will be entered into
                        config.json's CACHE macro (Default:
                        ${TMPDIR}/qx${QOOXDOO_VERSION}/cache)



데스크탑 웹페이지를 기준으로 프로젝트 생성을 하는 기준으로 설명한다. ( 다른것을 원한다면 type를 변경하면된다.)

applicationName : "testproject",

path:"/Document/projectRoot"

python create-application.py -n testproject -p /Document/projectRoot


라고 입력하면 "/Document/projectRoot/testproject/" 에 파일들이 생성된다.


주의: applicationName 은 소문자로 만드세요


           // 스크롤 을 움직이는 예제

var control = this.getChildControl("scrollpane");


            if (control) {

                if (!this.__isAnimate) {

                    var self = this,

                        element = control.getContainerElement().getDomElement();


                    self.__isAnimate = true;


                    var ani = jQuery(element);


                    var pos;

                    if (this.getOrientation() === "horizontal") {

                        element.style.scrollAnimationPositon = control.getScrollX();

                        pos = control.getScrollX();

                    } else {

                        element.style.scrollAnimationPositon = control.getScrollY();

                        pos = control.getScrollY();

                    }


                    ani.animate(

                        {   scrollAnimationPositon: option + self.getScrollStep() },

                        {   duration: 500,

//                            easing: "easeInBack",

                            step: function(now, fx) {

// now는 애니메이션 이동 텀을 나타낸다.

                                self.scrollTo(parseFloat(pos) + parseFloat(now)); 

                            },

                            complete:function () {

                                self.__isAnimate = false;

                            }

                        }

                    );

                }

            }

'Dev > Qooxdoo' 카테고리의 다른 글

Qooxdoo Class 만들기  (0) 2015.04.01
랩핑했어요. pureMVC-for-Qooxdoo  (0) 2015.03.03
qooxdoo로 만든 socket class  (0) 2015.03.03
1. qooxdoo Project 만들기  (0) 2012.07.27
Qooxdoo를 이용한 객체 생성 및 해제 예제  (0) 2012.07.09
appearances, decorations 추가 하기 (예-버튼)  (0) 2012.05.30
이미지 미리받아놓기  (0) 2012.05.23
다국어 지원  (0) 2012.05.18
해제 관련  (0) 2012.05.09
qooxdoo 오른쪽 버튼 활성화  (0) 2012.05.09

참고 자료

void 

_disposeArray(String field)

Disposes all members of the given array and deletes the field which refers to the array afterwards.

void 

_disposeMap(String field)

Disposes all members of the given map and deletes the field which refers to the map afterwards.

void 

_disposeObjects(arguments varargs)

Disconnects and disposes given objects from instance.

void 

_disposeSingletonObjects(arguments varargs)

Disconnects and disposes given singleton objects from instance.


/*

 * class  

 */


qx.Class.define("mc.testClass",

{

    extend:qx.ui.core.Widget,


    /*

     *****************************************************************************

     CONSTRUCTOR

     *****************************************************************************

     */

    construct:function (eventContext) {

        this.base(arguments);


/*destruct에 추가 될부분*/

        this.__array = qx.data.Array();

        this.__map = [];

this.__map['testKey'] = new qx.ui.form.Button("MyObject");

        this.__myObject = new qx.ui.form.Button("MyObject");

        this.__layout = new qx.ui.layout.Canvas();

/*------------------------*/

        this._setLayout(this.__layout);


        // 이벤트를 호출할 객체.

        if (eventContext) {

            this.setEventTarget(eventContext);

        }



        this._createChildControl("layout_main"); // getChildControl 대신 _CreateChildControl 사용

    },


    /*

     *****************************************************************************

     EVENTS

     *****************************************************************************

     */

    events:{

    },


    /*

     *****************************************************************************

     PROPERTY

     *****************************************************************************

     */

    properties:{

        eventTarget:{

            init:null,

            nullable : true

        },


        preloader:{

            init:mc.util.PreLoader.getInstance(),

            nullable : true

        }

    },


    /*

     *****************************************************************************

     STATICS

     *****************************************************************************

     */

    statics:{

    },


    /*

     *****************************************************************************

     MEMBERS

     *****************************************************************************

     */

    members:{

        __array: null,

        __map:null,

        __myObject:null,

        __layout:null,


        //override 

_createChildControlImpl 에서 생성된놈은 this가 해제시 자동 해제 됨

// new 될때마다 id가 생겨야됨.

        _createChildControlImpl : function(id, hash)

        {

            var control,

                preloader = mc.util.PreLoader.getInstance();


            switch(id)

            {

                // 레이아웃 생성

                case "layout_UserInfo":

                    var layout = new qx.ui.layout.VBox();

                    control = new qx.ui.container.Composite(layout);

                    control.add(this.getChildControl("control_UserInfoLabel")); // _createChildContrl; 대신 getControl 를 사용


                    // 아이템 여러개 생성시

                    for (var i = 0; i < 10; i++) {

                        control.add(this.getChildControl("control_test#"+i)); // i 대신 스트링이든 뭐든 가능

                    }


                    this._add(control, {left:0, top:0});

                    break;


                // 콘트롤 생성

                case "control_UserInfoLabel":

                    control = new qx.ui.form.Button(this.tr("my Button")); // 다국어 설정시 예제

                    break;


                case "control_test":

                    control = new qx.ui.form.Button("SHOP");

                    break;


// 조사중 하면 될까?

case "myArray":

control = qx.data.Array();

break;

            }


            return control || this.base(arguments, id);

        }

    },


    /*

     *****************************************************************************

     DESTRUCT

     *****************************************************************************

     */

    destruct:function () {

        try {

       

            this.setPreloader(null);

            this.setEventTarget(null);

        }

        finally {

// 직접 생성한 객체 해제 _createChildControlImpl 에서 생성된놈은 this가 해제시 자동 해제 됨

            this._disposeMap("__map");

            this._disposeObjects("__myObject", "__layout");

            this._disposeArray("__array");

            // this._disposeSingletonObjects();

        }

    }

});

// Decoration

            var id, image0, image1, image2, image3

            var deco = qx.theme.manager.Decoration.getInstance();

            var decotheme = deco.getTheme();


            decotheme.decorations[id] = {

                decorator : [qx.ui.decoration.Background],

                style : {backgroundImage: image1}

            }


            decotheme.decorations[id + "-disabled"] = {

                include : "testButton",

                style : {backgroundImage: image2}

            }


            decotheme.decorations[id + "-focused"] = {

                include : "testButton",

                style : {backgroundImage: image1}

            }


            decotheme.decorations[id + "-hovered"] = {

                include : "testButton",

                style : {backgroundImage: image0}

            }


            decotheme.decorations[id + "-pressed"] = {

                include : "testButton",

                style : {backgroundImage: image3}

            }


            // testButton

            var appr = qx.theme.manager.testButton.getInstance();

            var apprtheme = appr.getTheme();

            apprtheme.appearances[id] = {

                alias : "atom",


                style : function(states)

                {

                    var decorator, textColor;

                    var padding = [3, 9]; // default padding css-case


                    if (states.checked && states.focused && !states.inner)

                    {

                        decorator = "button-checked-focused";

                        textColor = undefined;

                        padding = [1, 7];

                    }

                    else if (states.disabled)

                    {

                        decorator = id + "-disabled";

                        textColor = undefined;

                    }

                    else if (states.pressed)

                    {

                        decorator = id + "-pressed";

                        textColor = "text-hovered";

                    }

                    else if (states.hovered)

                    {

                        decorator = id + "-focused";

                        textColor = "text-hovered";

                    }

                    else if (states.focused && !states.inner)

                    {

                        decorator = id + "-focused";

                        textColor = undefined;

                        padding = [1, 7];

                    }

                    else

                    {

                        decorator = id;

                        textColor = undefined;

                    }


                    return {

                        decorator : decorator,

                        textColor : textColor,

                        padding : padding,

                        margin : [1, 0],

                        center : true

                    };

                }

            }


this.getRoot().add(new qx.ui.form.Button("testButton").setApperance("testButton"));


추가 정보 : 모든 값은 qx.theme.manager 를 통해서 변경 가능하다.


Appearance  

qx.theme.manager.Appearance

Manager for appearance themes

Color  

qx.theme.manager.Color

Manager for color themes

Decoration  

qx.theme.manager.Decoration

Manager for decoration themes

Font  

qx.theme.manager.Font

Manager for font themes

Icon  

qx.theme.manager.Icon

Manager for icon themes

Meta  

qx.theme.manager.Meta

Manager for meta themes


// 외부 이미지 미리 받아 놓기

            var imgList = [];

            imgList.push("http://www.onlifezone.com/files/attach/images/116/908/737/011/111.gif");

            imgList.push("http://t2.gstatic.com/images?q=tbn:ANd9GcSJo1HQiuwDIklcOZG1Puq2iO5h79emfGuQV0_4JIUMgVXvpVPCMii8aXdcNw");

            imgList.push("http://www.v3wall.com/wallpaper/1680_1050/1108/1680_1050_20110809091524388043.jpg");

            imgList.push("http://www.v3wall.com/wallpaper/medium/1108/medium_20110809091236292253.jpg");

            imgList.push("http://www.v3wall.com/wallpaper/medium/1108/medium_20110809091550345142.jpg");

            imgList.push("http://www.v3wall.com/wallpaper/1600_1200/1108/1600_1200_20110809091508200270.jpg");

            imgList.push("http://www.v3wall.com/wallpaper/1920_1080/1108/1920_1080_20110809091410556289.jpg");

            imgList.push("http://www.v3wall.com/wallpaper/1920_1080/1108/1920_1080_20110809091324246399.jpg");

            imgList.push("http://www.v3wall.com/wallpaper/1920_1080/1102/1920_1080_20110204103714496177.jpg");

            imgList.push("http://www.v3wall.com/wallpaper/1920_1080/1102/1920_1080_20110204103756281487.jpg");

            imgList.push("http://www.v3wall.com/wallpaper/1920_1080/1102/1920_1080_20110204104030521738.jpg");

            imgList.push("mc/1920_1080_20110204104030521738.jpg");


            for (var i = 0; i < imgList.length; i++) {

                var imgLoader = qx.io.ImageLoader;

                imgLoader.load(imgList[i], function (source, entry) {

                    // TODO

                });

            }


// 내부 이미지 미리 받아 놓기.

for (var i=0; i<count; i++) { var icon = "icon/32/places/" + iconImages[Math.floor(Math.random() * iconImages.length)]; var resolved = aliasManager.resolve(icon); var url = resourceManager.toUri(resolved); items[i] = { label: "Icon #" + (i+1), icon: icon, resolvedIcon: url }; }

1

1. 위치: {$project}/config.json 

"let" :

{

...

"LOCALES"      : ["en", "ko"], 

...

}


2.  위치: {$project} /source/translation/

"en.po", "ko.po" 등 언어 추가된 파일을 추가한다.

(추가 내용 : qooxdoo-1.6-sdk\tool\data\cldr\main\ 안에 xml 파일이 있어야 생성이 된다.)


3. 위치: {$project}/ 

cmd 창을 열고 


>> python generate.py translation 



소스 코드 쓸때 예제처럼(빨간줄) 적어 놓으면 된다.



소스 코드 안의 코드의 추가 수정이 일어났을 경우는 1-3을 다시 한번 적용하고, 그 다음 qooxdoo의 generate 과정을 거치면 된다.

해제관련 유틸 제공


widget 일경우.

 Methods

void 

_disposeArray(String field)

Disposes all members of the given array and deletes the field which refers to the array afterwards.

void 

_disposeMap(String field)

Disposes all members of the given map and deletes the field which refers to the map afterwards.

void 

_disposeObjects(arguments varargs)

Disconnects and disposes given objects from instance.

void 

_disposeSingletonObjects(arguments varargs)

Disconnects and disposes given singleton objects from instance.


그 외

qx.util.DisposeUtil


 Static methods

void 

destroyContainer((Composite | Scroll | SlideBar | Stack) container)

Destroys a container and all of its children recursivly.

void 

disposeArray(Object obj, String field)

Disposes all members of the given array and deletes the field which refers to the array afterwards.

void 

disposeMap(Object obj, String field)

Disposes all members of the given map and deletes the field which refers to the map afterwards.

void 

disposeObjects(Object obj, Array arr, Boolean disposeSingletons?)

Disconnects and disposes given objects from instance.

void 

disposeTriggeredBy(Object disposeMe, Object trigger)

Disposes a given object when another object is disposed

+ Recent posts