├── .gitignore ├── LICENSE ├── README.md ├── TODO ├── binding.gyp ├── configure ├── dev ├── FLDev │ ├── .gitignore │ ├── FLDev.as3proj │ ├── build.sh │ ├── build_hello.sh │ ├── lib │ │ ├── assets │ │ │ └── pf_ronda_seven.ttf │ │ └── com │ │ │ └── bit101 │ │ │ └── components │ │ │ ├── Accordion.as │ │ │ ├── CheckBox.as │ │ │ ├── ComboBox.as │ │ │ ├── Component.as │ │ │ ├── FPSMeter.as │ │ │ ├── HBox.as │ │ │ ├── HRangeSlider.as │ │ │ ├── HScrollBar.as │ │ │ ├── HSlider.as │ │ │ ├── HUISlider.as │ │ │ ├── IndicatorLight.as │ │ │ ├── InputText.as │ │ │ ├── Knob.as │ │ │ ├── Label.as │ │ │ ├── List.as │ │ │ ├── ListItem.as │ │ │ ├── Meter.as │ │ │ ├── NumericStepper.as │ │ │ ├── Panel.as │ │ │ ├── ProgressBar.as │ │ │ ├── PushButton.as │ │ │ ├── RadioButton.as │ │ │ ├── RangeSlider.as │ │ │ ├── RotarySelector.as │ │ │ ├── ScrollBar.as │ │ │ ├── ScrollPane.as │ │ │ ├── Slider.as │ │ │ ├── Style.as │ │ │ ├── Text.as │ │ │ ├── TextArea.as │ │ │ ├── UISlider.as │ │ │ ├── VBox.as │ │ │ ├── VRangeSlider.as │ │ │ ├── VScrollBar.as │ │ │ ├── VSlider.as │ │ │ ├── VUISlider.as │ │ │ ├── WheelMenu.as │ │ │ └── Window.as │ └── src │ │ ├── CommandTest.as │ │ ├── Connection.as │ │ ├── Hello.as │ │ └── Main.as ├── clienttest.js └── middle.js ├── examples ├── README.md ├── auth.js ├── callbacks.js └── close.js ├── lib ├── .gitignore ├── amf.js ├── amf0.js ├── amf3.js ├── arcus_node.js ├── helper.js ├── logger.js ├── map.js ├── net_connection.js ├── net_group.js ├── packet.js ├── peer_proxy.js ├── plugins │ └── repl.js ├── proxy_net_connection.js └── rtmfp.js ├── package.json ├── service.js ├── src ├── keyexchange.cc └── rtmfp.cc ├── test.js └── wscript /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .lock-wscript 3 | *.log 4 | *.sublime-project 5 | *.sublime-workspace 6 | ._* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ArcusNode 2 | #### A RTMFP Rendevouz Server For Peer Assisted Networking With Adobe Flash on NodeJS 3 | ArcusNode aims to assist P2P networking with ease of extendability due to Javascript glue with NodeJS. 4 | ArcusNode is a standalone RTMFP implementation. 5 | We want to thank [Cumulus](http://github.com/OpenRTMFP/Cumulus), a standalone C++ implementation of the _RTMFP Protocol_ and much more. 6 | 7 | Author: arcusdev [arcus.node@gmail.com] 8 | License: [GPL](http://www.gnu.org/licenses/) 9 | 10 | ## Issues 11 | If you have an **issue** with ArcusNode, please use the Github issue tracker! 12 | 13 | 14 | ## Status 15 | ArcusNode is still under heavy development and much work remains to be done. 16 | It covers the following features already: 17 | 18 | * P2P Rendezvouz service 19 | * NetGroups 20 | * Remote Methods / Commands 21 | * Authentication 22 | * Plugins 23 | 24 | 25 | ## Build & Installation 26 | ArcusNode runs on Node v0.5.5 and higher. To use ArcusNode as a service, get it from [github](http://github.com/OpenRTMFP/ArcusNode) and run: 27 |
 28 | $> node-waf configure build
 29 | $> node service.js
 30 | 
31 | You then should see something like: 32 |
 33 | Starting up ArcusNode RTMFP Service.
 34 | Copyright (C) 2011 OpenRTMFP
 35 | This program comes with ABSOLUTELY NO WARRANTY.
 36 | This is free software, and you are welcome to redistribute it under certain conditions.
 37 | (For usage help type "node service.js -h")
 38 | ArcusNode RTMFP Service running at 0.0.0.0:1935
 39 | 
40 | 1935 is the default port for RTMFP communication and you should now be able to connect to the server, create groups and get peers connected. 41 | 42 | #### Cygwin 43 | If you run into problems building node on Cygwin, checkout _https://github.com/joyent/node/wiki/Building-node.js-on-Cygwin-(Windows)_. 44 | If you consider using rebase, use both _./rebaseall_ and _./perlrebase_. 45 | 46 | ## Usage 47 | ### Basic 48 | As you can see in the service.js, it is very easy to use ArcusNode in your own project. 49 |
 50 | var ArcusNode = require('./lib/arcus_node.js');
 51 | var arcusService = new ArcusNode();
 52 | arcusService.run();
 53 | 
54 | 55 | ### Customization 56 | ArcusNode uses a mixture of Events and registered command callbacks. Events behave like known Node core events. 57 | Commands are called by a connected client through its NetConnection#call and can be registered on ArcusNode. 58 | Commands on the server behave almost exactly the same as described in the Flash Documentation, 59 | except that ArcusNode command callbacks always get the NetConnection which called the command as first argument, then the arguments from the Client. 60 | 61 | ### Events 62 | 63 | At this moment, ArcusNode emits the following events: 64 | 65 | * start 66 | * stop 67 | * handshake 68 | * connect 69 | * disconnect 70 | * command 71 | 72 | ArcusNode uses the Node [EventEmitter](http://nodejs.org/docs/v0.5.3/api/events.html#events.EventEmitter) API 73 | 74 | Example for a connect event listener: 75 |
 76 | var ArcusNode = require('./lib/arcus_node.js');
 77 | var arcusService = new ArcusNode();
 78 | 
 79 | arcusService.on('connect', function(nc, obj){
 80 |   console.log('Received a connection request for Connection ' + nc.id + ' with the properties', obj);
 81 | });
 82 | 
 83 | arcusService.run();
 84 | 
85 | 86 | 87 | ### Commands 88 | [todo] 89 | 90 | Example for a command Client side: 91 |
 92 | var responder:Responder = new Responder(function(response) {
 93 |   trace(response.what); //-> 'ArcusNode rocks!'
 94 | });
 95 | connection.call('sayWhat', responder, { name: 'ArcusNode' });
 96 | 
97 | 98 | Example for a command Server side: 99 |
100 | arcusService.onCommand('sayWhat', function(nc, obj){
101 |   return { what: obj.name + ' rocks!' };
102 | });
103 | 
104 | 105 | ### ArcusNode Settings 106 | 107 | The ArcusNode constructor takes a settings object with the following attributes: 108 | 109 |
110 | .port
111 |   Type: Integer
112 |   Default: 1935
113 |   The port that ArcusNode will listen for UDP connections.
114 |   
115 | .address
116 |   Type: String
117 |   Default: ''
118 |   ArcusNode can be run on a specific interface if wanted.
119 |   
120 | .logLevel
121 |   Type: String
122 |   Default: 'warn'
123 |   Can be one of ['fatal', 'error', 'warn', 'info', 'debug'].
124 |   
125 | .logFile:
126 |   Type: String, path
127 |   Default: ''
128 |   If a path for a log file is specified, all logging will be written to that file.
129 | 
130 | .manageInterval 
131 |   Type: Integer, seconds 
132 |   default: 60 
133 |   The interval for the management cycle to do cleanup
134 | 
135 | .connectionTimeout 
136 |   Type: Integer, milliseconds 
137 |   Default: 120000 
138 |   The timeout for a NetConnection. The connections is dropped after the NetConnection was unused for that amount of time. 
139 | 
140 | .groupTimeout
141 |   Type: Integer, milliseconds
142 |   Default: 360000
143 |   The timeout for a NetGroup. The group is dropped afer there was no interaction for that amount of time.
144 | 
145 | .serverKeepalive
146 |   Type: Integer, milliseconds
147 |   Default: 60000
148 |   The timeout before the server sends a keepalive command to the client.
149 |   Should be less then connectionTimeout.
150 | 
151 | .clientKeepalive
152 |   Type: Integer, milliseconds
153 |   Default: 60000
154 |   Will tell the client in what interval it should send keepalive messages
155 | 
156 | .maxKeepalives
157 |   Type: Integer
158 |   Default: 3
159 |   How often to max keepalive the connection before dropping it.
160 | 
161 | 162 | ## Roadmap 163 | To reach version 0.1: 164 | 165 | * Add testing scripts and a Flash testing project 166 | * Complete AMF reading/writing (70%) 167 | 168 | ## Development 169 | If you have ideas, suggestions, bugfixes or just want to yell a little at the author, 170 | feel free to contact arcus.node@gmail.com 171 | 172 | 173 | © Copyright 2011 OpenRTMFP 174 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | ### TODO 2 | 3 | * IPv6 support 4 | * SharedObjects 5 | * Applications (auto load from dir, natively supported) 6 | * force application option, to refuse connections to _root 7 | * Load balancing (RTMFP internally) 8 | * Child processes / Clusterize, self managing / self healing, redundant -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "rtmfp", 5 | "sources": [ "src/rtmfp.cc" ] 6 | }, 7 | { 8 | "target_name": "keyexchange", 9 | "sources": [ "src/keyexchange.cc" ] 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # init and update git submodules 4 | git submodule init 5 | git submodule update -------------------------------------------------------------------------------- /dev/FLDev/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | -------------------------------------------------------------------------------- /dev/FLDev/FLDev.as3proj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 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 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /dev/FLDev/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit on error 4 | set -e 5 | 6 | BUILD_PATH="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | 8 | # Checking path to repository 9 | echo "Build path directory: $BUILD_PATH" 10 | 11 | echo "Executing as user $(whoami)" 12 | 13 | # Create build dir 14 | if [ ! -d "$BUILD_PATH/bin" ]; then 15 | mkdir "$BUILD_PATH/bin" && chown -R "$(whoami).$(whoami)" "$BUILD_PATH/bin" 16 | fi 17 | 18 | # Remove previous build 19 | rm -f "$BUILD_PATH/bin/fldev.swf" 20 | 21 | mxmlc -output="$BUILD_PATH/bin/fldev.swf" -source-path+="$BUILD_PATH/lib" --target-player=11.2 -debug -swf-version 16 "$BUILD_PATH/src/Main.as" -static-link-runtime-shared-libraries=true -------------------------------------------------------------------------------- /dev/FLDev/build_hello.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit on error 4 | set -e 5 | 6 | BUILD_PATH="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | 8 | # Checking path to repository 9 | echo "Build path directory: $BUILD_PATH" 10 | 11 | echo "Executing as user $(whoami)" 12 | 13 | # Create build dir 14 | if [ ! -d "$BUILD_PATH/bin" ]; then 15 | mkdir "$BUILD_PATH/bin" && chown -R "$(whoami).$(whoami)" "$BUILD_PATH/bin" 16 | fi 17 | 18 | # Remove previous build 19 | rm -f "$BUILD_PATH/bin/hello.swf" 20 | 21 | mxmlc -output="$BUILD_PATH/bin/hello.swf" -source-path+="$BUILD_PATH/lib" --target-player=11.2 -debug -swf-version 16 "$BUILD_PATH/src/Hello.as" -static-link-runtime-shared-libraries=true -------------------------------------------------------------------------------- /dev/FLDev/lib/assets/pf_ronda_seven.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRTMFP/ArcusNode/4320e6bce84127c955f5c3dd90172bbc657daf72/dev/FLDev/lib/assets/pf_ronda_seven.ttf -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/Accordion.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Accordion.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * Essentially a VBox full of Windows. Only one Window will be expanded at any time. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | 30 | package com.bit101.components 31 | { 32 | import flash.display.DisplayObjectContainer; 33 | import flash.events.Event; 34 | 35 | public class Accordion extends Component 36 | { 37 | protected var _windows:Array; 38 | protected var _winWidth:Number = 100; 39 | protected var _winHeight:Number = 100; 40 | protected var _vbox:VBox; 41 | 42 | /** 43 | * Constructor 44 | * @param parent The parent DisplayObjectContainer on which to add this Panel. 45 | * @param xpos The x position to place this component. 46 | * @param ypos The y position to place this component. 47 | */ 48 | public function Accordion(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0) 49 | { 50 | super(parent, xpos, ypos); 51 | } 52 | 53 | /** 54 | * Initializes the component. 55 | */ 56 | protected override function init():void 57 | { 58 | super.init(); 59 | setSize(100, 120); 60 | } 61 | 62 | /** 63 | * Creates and adds the child display objects of this component. 64 | */ 65 | protected override function addChildren() : void 66 | { 67 | _vbox = new VBox(this); 68 | _vbox.spacing = 0; 69 | 70 | _windows = new Array(); 71 | for(var i:int = 0; i < 2; i++) 72 | { 73 | var window:Window = new Window(_vbox, 0, 0, "Section " + (i + 1)); 74 | window.grips.visible = false; 75 | window.draggable = false; 76 | window.addEventListener(Event.SELECT, onWindowSelect); 77 | if(i != 0) window.minimized = true; 78 | _windows.push(window); 79 | } 80 | } 81 | 82 | /////////////////////////////////// 83 | // public methods 84 | /////////////////////////////////// 85 | 86 | /** 87 | * Adds a new window to the bottom of the accordion. 88 | * @param title The title of the new window. 89 | */ 90 | public function addWindow(title:String):void 91 | { 92 | addWindowAt(title, _windows.length); 93 | } 94 | 95 | public function addWindowAt(title:String, index:int):void 96 | { 97 | index = Math.min(index, _windows.length); 98 | index = Math.max(index, 0); 99 | var window:Window = new Window(null, 0, 0, title); 100 | _vbox.addChildAt(window, index); 101 | window.minimized = true; 102 | window.draggable = false; 103 | window.grips.visible = false; 104 | window.addEventListener(Event.SELECT, onWindowSelect); 105 | _windows.splice(index, 0, window); 106 | _winHeight = _height - (_windows.length - 1) * 20; 107 | setSize(_winWidth, _winHeight); 108 | } 109 | 110 | /** 111 | * Sets the size of the component. 112 | * @param w The width of the component. 113 | * @param h The height of the component. 114 | */ 115 | override public function setSize(w:Number, h:Number) : void 116 | { 117 | super.setSize(w, h); 118 | _winWidth = w; 119 | _winHeight = h - (_windows.length - 1) * 20; 120 | draw(); 121 | } 122 | 123 | override public function draw():void 124 | { 125 | _winHeight = Math.max(_winHeight, 40); 126 | for(var i:int = 0; i < _windows.length; i++) 127 | { 128 | _windows[i].setSize(_winWidth, _winHeight); 129 | _vbox.draw(); 130 | } 131 | } 132 | 133 | /** 134 | * Returns the Window at the specified index. 135 | * @param index The index of the Window you want to get access to. 136 | */ 137 | public function getWindowAt(index:int):Window 138 | { 139 | return _windows[index]; 140 | } 141 | 142 | 143 | /////////////////////////////////// 144 | // event handlers 145 | /////////////////////////////////// 146 | 147 | /** 148 | * Called when any window is resized. If the window has been expanded, it closes all other windows. 149 | */ 150 | protected function onWindowSelect(event:Event):void 151 | { 152 | var window:Window = event.target as Window; 153 | if(window.minimized) 154 | { 155 | for(var i:int = 0; i < _windows.length; i++) 156 | { 157 | _windows[i].minimized = true; 158 | } 159 | window.minimized = false; 160 | } 161 | _vbox.draw(); 162 | } 163 | 164 | public override function set width(w:Number):void 165 | { 166 | _winWidth = w; 167 | super.width = w; 168 | } 169 | 170 | public override function set height(h:Number):void 171 | { 172 | _winHeight = h - (_windows.length - 1) * 20; 173 | super.height = h; 174 | } 175 | 176 | } 177 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/CheckBox.as: -------------------------------------------------------------------------------- 1 | /** 2 | * CheckBox.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A basic CheckBox component. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.display.Sprite; 33 | import flash.events.MouseEvent; 34 | 35 | public class CheckBox extends Component 36 | { 37 | protected var _back:Sprite; 38 | protected var _button:Sprite; 39 | protected var _label:Label; 40 | protected var _labelText:String = ""; 41 | protected var _selected:Boolean = false; 42 | 43 | 44 | /** 45 | * Constructor 46 | * @param parent The parent DisplayObjectContainer on which to add this CheckBox. 47 | * @param xpos The x position to place this component. 48 | * @param ypos The y position to place this component. 49 | * @param label String containing the label for this component. 50 | * @param defaultHandler The event handling function to handle the default event for this component (click in this case). 51 | */ 52 | public function CheckBox(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, label:String = "", defaultHandler:Function = null) 53 | { 54 | _labelText = label; 55 | super(parent, xpos, ypos); 56 | if(defaultHandler != null) 57 | { 58 | addEventListener(MouseEvent.CLICK, defaultHandler); 59 | } 60 | } 61 | 62 | /** 63 | * Initializes the component. 64 | */ 65 | override protected function init():void 66 | { 67 | super.init(); 68 | buttonMode = true; 69 | useHandCursor = true; 70 | mouseChildren = false; 71 | } 72 | 73 | /** 74 | * Creates the children for this component 75 | */ 76 | override protected function addChildren():void 77 | { 78 | _back = new Sprite(); 79 | _back.filters = [getShadow(2, true)]; 80 | addChild(_back); 81 | 82 | _button = new Sprite(); 83 | _button.filters = [getShadow(1)]; 84 | _button.visible = false; 85 | addChild(_button); 86 | 87 | _label = new Label(this, 0, 0, _labelText); 88 | draw(); 89 | 90 | addEventListener(MouseEvent.CLICK, onClick); 91 | } 92 | 93 | 94 | 95 | 96 | /////////////////////////////////// 97 | // public methods 98 | /////////////////////////////////// 99 | 100 | /** 101 | * Draws the visual ui of the component. 102 | */ 103 | override public function draw():void 104 | { 105 | super.draw(); 106 | _back.graphics.clear(); 107 | _back.graphics.beginFill(Style.BACKGROUND); 108 | _back.graphics.drawRect(0, 0, 10, 10); 109 | _back.graphics.endFill(); 110 | 111 | _button.graphics.clear(); 112 | _button.graphics.beginFill(Style.BUTTON_FACE); 113 | _button.graphics.drawRect(2, 2, 6, 6); 114 | 115 | _label.text = _labelText; 116 | _label.draw(); 117 | _label.x = 12; 118 | _label.y = (10 - _label.height) / 2; 119 | _width = _label.width + 12; 120 | _height = 10; 121 | } 122 | 123 | 124 | 125 | 126 | /////////////////////////////////// 127 | // event handler 128 | /////////////////////////////////// 129 | 130 | /** 131 | * Internal click handler. 132 | * @param event The MouseEvent passed by the system. 133 | */ 134 | protected function onClick(event:MouseEvent):void 135 | { 136 | _selected = !_selected; 137 | _button.visible = _selected; 138 | } 139 | 140 | 141 | 142 | 143 | /////////////////////////////////// 144 | // getter/setters 145 | /////////////////////////////////// 146 | 147 | /** 148 | * Sets / gets the label text shown on this CheckBox. 149 | */ 150 | public function set label(str:String):void 151 | { 152 | _labelText = str; 153 | invalidate(); 154 | } 155 | public function get label():String 156 | { 157 | return _labelText; 158 | } 159 | 160 | /** 161 | * Sets / gets the selected state of this CheckBox. 162 | */ 163 | public function set selected(s:Boolean):void 164 | { 165 | _selected = s; 166 | _button.visible = _selected; 167 | } 168 | public function get selected():Boolean 169 | { 170 | return _selected; 171 | } 172 | 173 | /** 174 | * Sets/gets whether this component will be enabled or not. 175 | */ 176 | public override function set enabled(value:Boolean):void 177 | { 178 | super.enabled = value; 179 | mouseChildren = false; 180 | } 181 | 182 | } 183 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/Component.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Component.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * Base class for all components 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | * 28 | * 29 | * 30 | * Components with text make use of the font PF Ronda Seven by Yuusuke Kamiyamane 31 | * This is a free font obtained from http://www.dafont.com/pf-ronda-seven.font 32 | */ 33 | 34 | package com.bit101.components 35 | { 36 | import flash.display.DisplayObjectContainer; 37 | import flash.display.Sprite; 38 | import flash.display.Stage; 39 | import flash.display.StageAlign; 40 | import flash.display.StageScaleMode; 41 | import flash.events.Event; 42 | import flash.filters.DropShadowFilter; 43 | 44 | [Event(name="resize", type="flash.events.Event")] 45 | [Event(name="draw", type="flash.events.Event")] 46 | public class Component extends Sprite 47 | { 48 | // NOTE: Flex 4 introduces DefineFont4, which is used by default and does not work in native text fields. 49 | // Use the embedAsCFF="false" param to switch back to DefineFont4. In earlier Flex 4 SDKs this was cff="false". 50 | // So if you are using the Flex 3.x sdk compiler, switch the embed statment below to expose the correct version. 51 | 52 | // Flex 4.x sdk: 53 | [Embed(source="/assets/pf_ronda_seven.ttf", embedAsCFF="false", fontName="PF Ronda Seven", mimeType="application/x-font")] 54 | // Flex 3.x sdk: 55 | // [Embed(source="/assets/pf_ronda_seven.ttf", fontName="PF Ronda Seven", mimeType="application/x-font")] 56 | protected var Ronda:Class; 57 | 58 | protected var _width:Number = 0; 59 | protected var _height:Number = 0; 60 | protected var _tag:int = -1; 61 | protected var _enabled:Boolean = true; 62 | 63 | public static const DRAW:String = "draw"; 64 | 65 | /** 66 | * Constructor 67 | * @param parent The parent DisplayObjectContainer on which to add this component. 68 | * @param xpos The x position to place this component. 69 | * @param ypos The y position to place this component. 70 | */ 71 | public function Component(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0) 72 | { 73 | move(xpos, ypos); 74 | init(); 75 | if(parent != null) 76 | { 77 | parent.addChild(this); 78 | } 79 | } 80 | 81 | /** 82 | * Initilizes the component. 83 | */ 84 | protected function init():void 85 | { 86 | addChildren(); 87 | invalidate(); 88 | } 89 | 90 | /** 91 | * Overriden in subclasses to create child display objects. 92 | */ 93 | protected function addChildren():void 94 | { 95 | 96 | } 97 | 98 | /** 99 | * DropShadowFilter factory method, used in many of the components. 100 | * @param dist The distance of the shadow. 101 | * @param knockout Whether or not to create a knocked out shadow. 102 | */ 103 | protected function getShadow(dist:Number, knockout:Boolean = false):DropShadowFilter 104 | { 105 | return new DropShadowFilter(dist, 45, Style.DROPSHADOW, 1, dist, dist, .3, 1, knockout); 106 | } 107 | 108 | /** 109 | * Marks the component to be redrawn on the next frame. 110 | */ 111 | protected function invalidate():void 112 | { 113 | // draw(); 114 | addEventListener(Event.ENTER_FRAME, onInvalidate); 115 | } 116 | 117 | 118 | 119 | 120 | /////////////////////////////////// 121 | // public methods 122 | /////////////////////////////////// 123 | 124 | /** 125 | * Utility method to set up usual stage align and scaling. 126 | */ 127 | public static function initStage(stage:Stage):void 128 | { 129 | stage.align = StageAlign.TOP_LEFT; 130 | stage.scaleMode = StageScaleMode.NO_SCALE; 131 | } 132 | 133 | /** 134 | * Moves the component to the specified position. 135 | * @param xpos the x position to move the component 136 | * @param ypos the y position to move the component 137 | */ 138 | public function move(xpos:Number, ypos:Number):void 139 | { 140 | x = Math.round(xpos); 141 | y = Math.round(ypos); 142 | } 143 | 144 | /** 145 | * Sets the size of the component. 146 | * @param w The width of the component. 147 | * @param h The height of the component. 148 | */ 149 | public function setSize(w:Number, h:Number):void 150 | { 151 | _width = w; 152 | _height = h; 153 | dispatchEvent(new Event(Event.RESIZE)); 154 | invalidate(); 155 | } 156 | 157 | /** 158 | * Abstract draw function. 159 | */ 160 | public function draw():void 161 | { 162 | dispatchEvent(new Event(Component.DRAW)); 163 | } 164 | 165 | 166 | 167 | 168 | /////////////////////////////////// 169 | // event handlers 170 | /////////////////////////////////// 171 | 172 | /** 173 | * Called one frame after invalidate is called. 174 | */ 175 | protected function onInvalidate(event:Event):void 176 | { 177 | removeEventListener(Event.ENTER_FRAME, onInvalidate); 178 | draw(); 179 | } 180 | 181 | 182 | 183 | 184 | /////////////////////////////////// 185 | // getter/setters 186 | /////////////////////////////////// 187 | 188 | /** 189 | * Sets/gets the width of the component. 190 | */ 191 | override public function set width(w:Number):void 192 | { 193 | _width = w; 194 | invalidate(); 195 | dispatchEvent(new Event(Event.RESIZE)); 196 | } 197 | override public function get width():Number 198 | { 199 | return _width; 200 | } 201 | 202 | /** 203 | * Sets/gets the height of the component. 204 | */ 205 | override public function set height(h:Number):void 206 | { 207 | _height = h; 208 | invalidate(); 209 | dispatchEvent(new Event(Event.RESIZE)); 210 | } 211 | override public function get height():Number 212 | { 213 | return _height; 214 | } 215 | 216 | /** 217 | * Sets/gets in integer that can identify the component. 218 | */ 219 | public function set tag(value:int):void 220 | { 221 | _tag = value; 222 | } 223 | public function get tag():int 224 | { 225 | return _tag; 226 | } 227 | 228 | /** 229 | * Overrides the setter for x to always place the component on a whole pixel. 230 | */ 231 | override public function set x(value:Number):void 232 | { 233 | super.x = Math.round(value); 234 | } 235 | 236 | /** 237 | * Overrides the setter for y to always place the component on a whole pixel. 238 | */ 239 | override public function set y(value:Number):void 240 | { 241 | super.y = Math.round(value); 242 | } 243 | 244 | /** 245 | * Sets/gets whether this component is enabled or not. 246 | */ 247 | public function set enabled(value:Boolean):void 248 | { 249 | _enabled = value; 250 | mouseEnabled = mouseChildren = _enabled; 251 | tabEnabled = value; 252 | alpha = _enabled ? 1.0 : 0.5; 253 | } 254 | public function get enabled():Boolean 255 | { 256 | return _enabled; 257 | } 258 | 259 | } 260 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/FPSMeter.as: -------------------------------------------------------------------------------- 1 | /** 2 | * FPSMeter.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * An simple component showing the frames per second the current movie is running at. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.events.Event; 33 | import flash.utils.getTimer; 34 | 35 | 36 | public class FPSMeter extends Component 37 | { 38 | protected var _label:Label; 39 | protected var _startTime:int; 40 | protected var _frames:int; 41 | protected var _prefix:String = ""; 42 | protected var _fps:int = 0; 43 | 44 | /** 45 | * Constructor 46 | * @param parent The parent DisplayObjectContainer on which to add this ColorChooser. 47 | * @param xpos The x position to place this component. 48 | * @param ypos The y position to place this component. 49 | * @param prefix A string to put in front of the number value shown. Default is "FPS:". 50 | */ 51 | 52 | public function FPSMeter(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, prefix:String="FPS:") 53 | { 54 | super(parent, xpos, ypos); 55 | _prefix = prefix; 56 | _frames = 0; 57 | _startTime = getTimer(); 58 | setSize(50, 20); 59 | if(stage != null) 60 | { 61 | addEventListener(Event.ENTER_FRAME, onEnterFrame); 62 | } 63 | addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage); 64 | } 65 | 66 | protected override function addChildren():void 67 | { 68 | super.addChildren(); 69 | _label = new Label(this, 0, 0); 70 | } 71 | 72 | 73 | public override function draw():void 74 | { 75 | _label.text = _prefix + _fps.toString(); 76 | } 77 | 78 | /** 79 | * Internal enterFrame handler to measure fps and update label. 80 | */ 81 | protected function onEnterFrame(event:Event):void 82 | { 83 | // Increment frame count each frame. When more than a second has passed, 84 | // display number of accumulated frames and reset. 85 | // Thus FPS will only be calculated and displayed once per second. 86 | // There are more responsive methods that calculate FPS on every frame. 87 | // This method is uses less CPU and avoids the "jitter" of those other methods. 88 | _frames++; 89 | var time:int = getTimer(); 90 | var elapsed:int = time - _startTime; 91 | if(elapsed >= 1000) 92 | { 93 | _fps = Math.round(_frames * 1000 / elapsed); 94 | _frames = 0; 95 | _startTime = time; 96 | draw(); 97 | } 98 | } 99 | 100 | /** 101 | * Stops the meter if it is removed from stage. 102 | */ 103 | protected function onRemovedFromStage(event:Event):void 104 | { 105 | stop(); 106 | } 107 | 108 | /** 109 | * Stops the meter by removing the enterFrame listener. 110 | */ 111 | public function stop():void 112 | { 113 | removeEventListener(Event.ENTER_FRAME, onEnterFrame); 114 | } 115 | 116 | /** 117 | * Starts the meter again if it has been stopped. 118 | */ 119 | public function start():void 120 | { 121 | addEventListener(Event.ENTER_FRAME, onEnterFrame); 122 | } 123 | 124 | /** 125 | * Sets or gets the prefix shown before the number. Defaults to "FPS:". 126 | */ 127 | public function set prefix(value:String):void 128 | { 129 | _prefix = value; 130 | } 131 | public function get prefix():String 132 | { 133 | return _prefix; 134 | } 135 | 136 | /** 137 | * Returns the current calculated FPS. 138 | */ 139 | public function get fps():int 140 | { 141 | return _fps; 142 | } 143 | } 144 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/HBox.as: -------------------------------------------------------------------------------- 1 | /** 2 | * VBox.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A layout container for vertically aligning other components. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | 30 | package com.bit101.components 31 | { 32 | import flash.display.DisplayObject; 33 | import flash.display.DisplayObjectContainer; 34 | import flash.events.Event; 35 | 36 | [Event(name="resize", type="flash.events.Event")] 37 | public class HBox extends Component 38 | { 39 | protected var _spacing:Number = 5; 40 | private var _alignment:String = NONE; 41 | 42 | public static const TOP:String = "top"; 43 | public static const BOTTOM:String = "bottom"; 44 | public static const MIDDLE:String = "middle"; 45 | public static const NONE:String = "none"; 46 | 47 | 48 | /** 49 | * Constructor 50 | * @param parent The parent DisplayObjectContainer on which to add this PushButton. 51 | * @param xpos The x position to place this component. 52 | * @param ypos The y position to place this component. 53 | */ 54 | public function HBox(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0) 55 | { 56 | super(parent, xpos, ypos); 57 | } 58 | 59 | /** 60 | * Override of addChild to force layout; 61 | */ 62 | override public function addChild(child:DisplayObject) : DisplayObject 63 | { 64 | super.addChild(child); 65 | child.addEventListener(Event.RESIZE, onResize); 66 | draw(); 67 | return child; 68 | } 69 | 70 | /** 71 | * Override of addChildAt to force layout; 72 | */ 73 | override public function addChildAt(child:DisplayObject, index:int) : DisplayObject 74 | { 75 | super.addChildAt(child, index); 76 | child.addEventListener(Event.RESIZE, onResize); 77 | draw(); 78 | return child; 79 | } 80 | 81 | /** 82 | * Override of removeChild to force layout; 83 | */ 84 | override public function removeChild(child:DisplayObject):DisplayObject 85 | { 86 | super.removeChild(child); 87 | child.removeEventListener(Event.RESIZE, onResize); 88 | draw(); 89 | return child; 90 | } 91 | 92 | /** 93 | * Override of removeChild to force layout; 94 | */ 95 | override public function removeChildAt(index:int):DisplayObject 96 | { 97 | var child:DisplayObject = super.removeChildAt(index); 98 | child.removeEventListener(Event.RESIZE, onResize); 99 | draw(); 100 | return child; 101 | } 102 | 103 | protected function onResize(event:Event):void 104 | { 105 | invalidate(); 106 | } 107 | 108 | protected function doAlignment():void 109 | { 110 | if(_alignment != NONE) 111 | { 112 | for(var i:int = 0; i < numChildren; i++) 113 | { 114 | var child:DisplayObject = getChildAt(i); 115 | if(_alignment == TOP) 116 | { 117 | child.y = 0; 118 | } 119 | else if(_alignment == BOTTOM) 120 | { 121 | child.y = _height - child.height; 122 | } 123 | else if(_alignment == MIDDLE) 124 | { 125 | child.y = (_height - child.height) / 2; 126 | } 127 | } 128 | } 129 | } 130 | 131 | /** 132 | * Draws the visual ui of the component, in this case, laying out the sub components. 133 | */ 134 | override public function draw() : void 135 | { 136 | _width = 0; 137 | _height = 0; 138 | var xpos:Number = 0; 139 | for(var i:int = 0; i < numChildren; i++) 140 | { 141 | var child:DisplayObject = getChildAt(i); 142 | child.x = xpos; 143 | xpos += child.width; 144 | xpos += _spacing; 145 | _width += child.width; 146 | _height = Math.max(_height, child.height); 147 | } 148 | doAlignment(); 149 | _width += _spacing * (numChildren - 1); 150 | dispatchEvent(new Event(Event.RESIZE)); 151 | } 152 | 153 | /** 154 | * Gets / sets the spacing between each sub component. 155 | */ 156 | public function set spacing(s:Number):void 157 | { 158 | _spacing = s; 159 | invalidate(); 160 | } 161 | public function get spacing():Number 162 | { 163 | return _spacing; 164 | } 165 | 166 | /** 167 | * Gets / sets the vertical alignment of components in the box. 168 | */ 169 | public function set alignment(value:String):void 170 | { 171 | _alignment = value; 172 | invalidate(); 173 | } 174 | public function get alignment():String 175 | { 176 | return _alignment; 177 | } 178 | } 179 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/HRangeSlider.as: -------------------------------------------------------------------------------- 1 | /** 2 | * HRangeSlider.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A horizontal slider with two handles for selecting a range of values. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | 33 | public class HRangeSlider extends RangeSlider 34 | { 35 | public function HRangeSlider(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, defaultHandler:Function = null) 36 | { 37 | super(HORIZONTAL, parent, xpos, ypos, defaultHandler); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/HScrollBar.as: -------------------------------------------------------------------------------- 1 | /** 2 | * HScrollBar.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A horizontal scroll bar for use in other components. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | 33 | /** 34 | * Constructor 35 | * @param parent The parent DisplayObjectContainer on which to add this ScrollBar. 36 | * @param xpos The x position to place this component. 37 | * @param ypos The y position to place this component. 38 | * @param defaultHandler The event handling function to handle the default event for this component (change in this case). 39 | */ 40 | public class HScrollBar extends ScrollBar 41 | { 42 | public function HScrollBar(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, defaultHandler:Function=null) 43 | { 44 | super(Slider.HORIZONTAL, parent, xpos, ypos, defaultHandler); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/HSlider.as: -------------------------------------------------------------------------------- 1 | /** 2 | * HSlider.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A Horizontal Slider component for choosing values. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | 33 | public class HSlider extends Slider 34 | { 35 | /** 36 | * Constructor 37 | * @param parent The parent DisplayObjectContainer on which to add this HSlider. 38 | * @param xpos The x position to place this component. 39 | * @param ypos The y position to place this component. 40 | * @param defaultHandler The event handling function to handle the default event for this component. 41 | */ 42 | public function HSlider(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, defaultHandler:Function = null) 43 | { 44 | super(Slider.HORIZONTAL, parent, xpos, ypos, defaultHandler); 45 | } 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/HUISlider.as: -------------------------------------------------------------------------------- 1 | /** 2 | * HUISlider.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A Horizontal slider with a label and a value label. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | 33 | public class HUISlider extends UISlider 34 | { 35 | 36 | /** 37 | * Constructor 38 | * @param parent The parent DisplayObjectContainer on which to add this HUISlider. 39 | * @param x The x position to place this component. 40 | * @param y The y position to place this component. 41 | * @param label The string to use as the label for this component. 42 | * @param defaultHandler The event handling function to handle the default event for this component. 43 | */ 44 | public function HUISlider(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, label:String = "", defaultHandler:Function = null) 45 | { 46 | _sliderClass = HSlider; 47 | super(parent, xpos, ypos, label, defaultHandler); 48 | } 49 | 50 | /** 51 | * Initializes the component. 52 | */ 53 | override protected function init():void 54 | { 55 | super.init(); 56 | setSize(200, 18); 57 | } 58 | 59 | /** 60 | * Centers the label when label text is changed. 61 | */ 62 | override protected function positionLabel():void 63 | { 64 | _valueLabel.x = _slider.x + _slider.width + 5; 65 | } 66 | 67 | 68 | 69 | 70 | /////////////////////////////////// 71 | // public methods 72 | /////////////////////////////////// 73 | 74 | /** 75 | * Draws the visual ui of this component. 76 | */ 77 | override public function draw():void 78 | { 79 | super.draw(); 80 | _slider.x = _label.width + 5; 81 | _slider.y = height / 2 - _slider.height / 2; 82 | _slider.width = width - _label.width - 50 - 10; 83 | 84 | _valueLabel.x = _slider.x + _slider.width + 5; 85 | } 86 | 87 | /////////////////////////////////// 88 | // event handlers 89 | /////////////////////////////////// 90 | 91 | /////////////////////////////////// 92 | // getter/setters 93 | /////////////////////////////////// 94 | 95 | } 96 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/IndicatorLight.as: -------------------------------------------------------------------------------- 1 | /** 2 | * IndicatorLight.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * An indicator light that can be turned on, off, or set to flash. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.display.GradientType; 33 | import flash.display.Shape; 34 | import flash.events.TimerEvent; 35 | import flash.geom.Matrix; 36 | import flash.utils.Timer; 37 | 38 | public class IndicatorLight extends Component 39 | { 40 | protected var _color:uint; 41 | protected var _lit:Boolean = false; 42 | protected var _label:Label; 43 | protected var _labelText:String = ""; 44 | protected var _lite:Shape; 45 | protected var _timer:Timer; 46 | 47 | 48 | 49 | /** 50 | * Constructor 51 | * @param parent The parent DisplayObjectContainer on which to add this CheckBox. 52 | * @param xpos The x position to place this component. 53 | * @param ypos The y position to place this component. 54 | * @param color The color of this light. 55 | * @param label String containing the label for this component. 56 | */ 57 | public function IndicatorLight(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, color:uint = 0xff0000, label:String = "") 58 | { 59 | _color = color; 60 | _labelText = label; 61 | super(parent, xpos, ypos); 62 | } 63 | 64 | /** 65 | * Initializes the component. 66 | */ 67 | override protected function init():void 68 | { 69 | super.init(); 70 | _timer = new Timer(500); 71 | _timer.addEventListener(TimerEvent.TIMER, onTimer); 72 | } 73 | 74 | /** 75 | * Creates the children for this component 76 | */ 77 | override protected function addChildren():void 78 | { 79 | _lite = new Shape(); 80 | addChild(_lite); 81 | 82 | _label = new Label(this, 0, 0, _labelText); 83 | draw(); 84 | } 85 | 86 | /** 87 | * Draw the light. 88 | */ 89 | protected function drawLite():void 90 | { 91 | var colors:Array; 92 | if(_lit) 93 | { 94 | colors = [0xffffff, _color]; 95 | } 96 | else 97 | { 98 | colors = [0xffffff, 0]; 99 | } 100 | 101 | _lite.graphics.clear(); 102 | var matrix:Matrix = new Matrix(); 103 | matrix.createGradientBox(10, 10, 0, -2.5, -2.5); 104 | _lite.graphics.beginGradientFill(GradientType.RADIAL, colors, [1, 1], [0, 255], matrix); 105 | _lite.graphics.drawCircle(5, 5, 5); 106 | _lite.graphics.endFill(); 107 | } 108 | 109 | 110 | 111 | /////////////////////////////////// 112 | // event handler 113 | /////////////////////////////////// 114 | 115 | /** 116 | * Internal timer handler. 117 | * @param event The TimerEvent passed by the system. 118 | */ 119 | protected function onTimer(event:TimerEvent):void 120 | { 121 | _lit = !_lit; 122 | draw(); 123 | } 124 | 125 | 126 | 127 | 128 | /////////////////////////////////// 129 | // public methods 130 | /////////////////////////////////// 131 | 132 | /** 133 | * Draws the visual ui of the component. 134 | */ 135 | override public function draw():void 136 | { 137 | super.draw(); 138 | drawLite(); 139 | 140 | _label.text = _labelText; 141 | _label.x = 12; 142 | _label.y = (10 - _label.height) / 2; 143 | _width = _label.width + 12; 144 | _height = 10; 145 | } 146 | 147 | /** 148 | * Causes the light to flash on and off at the specified interval (milliseconds). A value less than 1 stops the flashing. 149 | */ 150 | public function flash(interval:int = 500):void 151 | { 152 | if(interval < 1) 153 | { 154 | _timer.stop(); 155 | isLit = false; 156 | return; 157 | } 158 | _timer.delay = interval; 159 | _timer.start(); 160 | } 161 | 162 | 163 | 164 | 165 | /////////////////////////////////// 166 | // getter/setters 167 | /////////////////////////////////// 168 | 169 | /** 170 | * Sets or gets whether or not the light is lit. 171 | */ 172 | public function set isLit(value:Boolean):void 173 | { 174 | _timer.stop(); 175 | _lit = value; 176 | drawLite(); 177 | } 178 | public function get isLit():Boolean 179 | { 180 | return _lit; 181 | } 182 | 183 | /** 184 | * Sets / gets the color of this light (when lit). 185 | */ 186 | public function set color(value:uint):void 187 | { 188 | _color = value; 189 | draw(); 190 | } 191 | public function get color():uint 192 | { 193 | return _color; 194 | } 195 | 196 | /** 197 | * Returns whether or not the light is currently flashing. 198 | */ 199 | public function get isFlashing():Boolean 200 | { 201 | return _timer.running; 202 | } 203 | 204 | /** 205 | * Sets / gets the label text shown on this component. 206 | */ 207 | public function set label(str:String):void 208 | { 209 | _labelText = str; 210 | draw(); 211 | } 212 | public function get label():String 213 | { 214 | return _labelText; 215 | } 216 | 217 | 218 | } 219 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/InputText.as: -------------------------------------------------------------------------------- 1 | /** 2 | * InputText.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * Copyright (c) 2011 Keith Peters 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | package com.bit101.components 28 | { 29 | import flash.display.DisplayObjectContainer; 30 | import flash.display.Sprite; 31 | import flash.events.Event; 32 | import flash.text.TextField; 33 | import flash.text.TextFieldType; 34 | import flash.text.TextFormat; 35 | 36 | public class InputText extends Component 37 | { 38 | protected var _back:Sprite; 39 | protected var _password:Boolean = false; 40 | protected var _text:String = ""; 41 | protected var _tf:TextField; 42 | 43 | /** 44 | * Constructor 45 | * @param parent The parent DisplayObjectContainer on which to add this InputText. 46 | * @param xpos The x position to place this component. 47 | * @param ypos The y position to place this component. 48 | * @param text The string containing the initial text of this component. 49 | * @param defaultHandler The event handling function to handle the default event for this component (change in this case). 50 | */ 51 | public function InputText(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, text:String = "", defaultHandler:Function = null) 52 | { 53 | this.text = text; 54 | super(parent, xpos, ypos); 55 | if(defaultHandler != null) 56 | { 57 | addEventListener(Event.CHANGE, defaultHandler); 58 | } 59 | } 60 | 61 | /** 62 | * Initializes the component. 63 | */ 64 | override protected function init():void 65 | { 66 | super.init(); 67 | setSize(100, 16); 68 | } 69 | 70 | /** 71 | * Creates and adds child display objects. 72 | */ 73 | override protected function addChildren():void 74 | { 75 | _back = new Sprite(); 76 | _back.filters = [getShadow(2, true)]; 77 | addChild(_back); 78 | 79 | _tf = new TextField(); 80 | _tf.embedFonts = Style.embedFonts; 81 | _tf.selectable = true; 82 | _tf.type = TextFieldType.INPUT; 83 | _tf.defaultTextFormat = new TextFormat(Style.fontName, Style.fontSize, Style.INPUT_TEXT); 84 | addChild(_tf); 85 | _tf.addEventListener(Event.CHANGE, onChange); 86 | 87 | } 88 | 89 | 90 | 91 | 92 | /////////////////////////////////// 93 | // public methods 94 | /////////////////////////////////// 95 | 96 | /** 97 | * Draws the visual ui of the component. 98 | */ 99 | override public function draw():void 100 | { 101 | super.draw(); 102 | _back.graphics.clear(); 103 | _back.graphics.beginFill(Style.BACKGROUND); 104 | _back.graphics.drawRect(0, 0, _width, _height); 105 | _back.graphics.endFill(); 106 | 107 | _tf.displayAsPassword = _password; 108 | 109 | if(_text != null) 110 | { 111 | _tf.text = _text; 112 | } 113 | else 114 | { 115 | _tf.text = ""; 116 | } 117 | _tf.width = _width - 4; 118 | if(_tf.text == "") 119 | { 120 | _tf.text = "X"; 121 | _tf.height = Math.min(_tf.textHeight + 4, _height); 122 | _tf.text = ""; 123 | } 124 | else 125 | { 126 | _tf.height = Math.min(_tf.textHeight + 4, _height); 127 | } 128 | _tf.x = 2; 129 | _tf.y = Math.round(_height / 2 - _tf.height / 2); 130 | } 131 | 132 | 133 | 134 | 135 | /////////////////////////////////// 136 | // event handlers 137 | /////////////////////////////////// 138 | 139 | /** 140 | * Internal change handler. 141 | * @param event The Event passed by the system. 142 | */ 143 | protected function onChange(event:Event):void 144 | { 145 | _text = _tf.text; 146 | event.stopImmediatePropagation(); 147 | dispatchEvent(event); 148 | } 149 | 150 | 151 | 152 | 153 | /////////////////////////////////// 154 | // getter/setters 155 | /////////////////////////////////// 156 | 157 | /** 158 | * Gets / sets the text shown in this InputText. 159 | */ 160 | public function set text(t:String):void 161 | { 162 | _text = t; 163 | if(_text == null) _text = ""; 164 | invalidate(); 165 | } 166 | public function get text():String 167 | { 168 | return _text; 169 | } 170 | 171 | /** 172 | * Returns a reference to the internal text field in the component. 173 | */ 174 | public function get textField():TextField 175 | { 176 | return _tf; 177 | } 178 | 179 | /** 180 | * Gets / sets the list of characters that are allowed in this TextInput. 181 | */ 182 | public function set restrict(str:String):void 183 | { 184 | _tf.restrict = str; 185 | } 186 | public function get restrict():String 187 | { 188 | return _tf.restrict; 189 | } 190 | 191 | /** 192 | * Gets / sets the maximum number of characters that can be shown in this InputText. 193 | */ 194 | public function set maxChars(max:int):void 195 | { 196 | _tf.maxChars = max; 197 | } 198 | public function get maxChars():int 199 | { 200 | return _tf.maxChars; 201 | } 202 | 203 | /** 204 | * Gets / sets whether or not this input text will show up as password (asterisks). 205 | */ 206 | public function set password(b:Boolean):void 207 | { 208 | _password = b; 209 | invalidate(); 210 | } 211 | public function get password():Boolean 212 | { 213 | return _password; 214 | } 215 | 216 | /** 217 | * Sets/gets whether this component is enabled or not. 218 | */ 219 | public override function set enabled(value:Boolean):void 220 | { 221 | super.enabled = value; 222 | _tf.tabEnabled = value; 223 | } 224 | 225 | } 226 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/Label.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Label.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A Label component for displaying a single line of text. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.events.Event; 33 | import flash.text.TextField; 34 | import flash.text.TextFieldAutoSize; 35 | import flash.text.TextFormat; 36 | 37 | [Event(name="resize", type="flash.events.Event")] 38 | public class Label extends Component 39 | { 40 | protected var _autoSize:Boolean = true; 41 | protected var _text:String = ""; 42 | protected var _tf:TextField; 43 | 44 | /** 45 | * Constructor 46 | * @param parent The parent DisplayObjectContainer on which to add this Label. 47 | * @param xpos The x position to place this component. 48 | * @param ypos The y position to place this component. 49 | * @param text The string to use as the initial text in this component. 50 | */ 51 | public function Label(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, text:String = "") 52 | { 53 | this.text = text; 54 | super(parent, xpos, ypos); 55 | } 56 | 57 | /** 58 | * Initializes the component. 59 | */ 60 | override protected function init():void 61 | { 62 | super.init(); 63 | mouseEnabled = false; 64 | mouseChildren = false; 65 | } 66 | 67 | /** 68 | * Creates and adds the child display objects of this component. 69 | */ 70 | override protected function addChildren():void 71 | { 72 | _height = 18; 73 | _tf = new TextField(); 74 | _tf.height = _height; 75 | _tf.embedFonts = Style.embedFonts; 76 | _tf.selectable = false; 77 | _tf.mouseEnabled = false; 78 | _tf.defaultTextFormat = new TextFormat(Style.fontName, Style.fontSize, Style.LABEL_TEXT); 79 | _tf.text = _text; 80 | addChild(_tf); 81 | draw(); 82 | } 83 | 84 | 85 | 86 | 87 | /////////////////////////////////// 88 | // public methods 89 | /////////////////////////////////// 90 | 91 | /** 92 | * Draws the visual ui of the component. 93 | */ 94 | override public function draw():void 95 | { 96 | super.draw(); 97 | _tf.text = _text; 98 | if(_autoSize) 99 | { 100 | _tf.autoSize = TextFieldAutoSize.LEFT; 101 | _width = _tf.width; 102 | dispatchEvent(new Event(Event.RESIZE)); 103 | } 104 | else 105 | { 106 | _tf.autoSize = TextFieldAutoSize.NONE; 107 | _tf.width = _width; 108 | } 109 | _height = _tf.height = 18; 110 | } 111 | 112 | /////////////////////////////////// 113 | // event handlers 114 | /////////////////////////////////// 115 | 116 | /////////////////////////////////// 117 | // getter/setters 118 | /////////////////////////////////// 119 | 120 | /** 121 | * Gets / sets the text of this Label. 122 | */ 123 | public function set text(t:String):void 124 | { 125 | _text = t; 126 | if(_text == null) _text = ""; 127 | invalidate(); 128 | } 129 | public function get text():String 130 | { 131 | return _text; 132 | } 133 | 134 | /** 135 | * Gets / sets whether or not this Label will autosize. 136 | */ 137 | public function set autoSize(b:Boolean):void 138 | { 139 | _autoSize = b; 140 | } 141 | public function get autoSize():Boolean 142 | { 143 | return _autoSize; 144 | } 145 | 146 | /** 147 | * Gets the internal TextField of the label if you need to do further customization of it. 148 | */ 149 | public function get textField():TextField 150 | { 151 | return _tf; 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/ListItem.as: -------------------------------------------------------------------------------- 1 | /** 2 | * ListItem.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A single item in a list. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | 30 | package com.bit101.components 31 | { 32 | import flash.display.DisplayObjectContainer; 33 | import flash.events.MouseEvent; 34 | 35 | public class ListItem extends Component 36 | { 37 | protected var _data:Object; 38 | protected var _label:Label; 39 | protected var _defaultColor:uint = 0xffffff; 40 | protected var _selectedColor:uint = 0xdddddd; 41 | protected var _rolloverColor:uint = 0xeeeeee; 42 | protected var _selected:Boolean; 43 | protected var _mouseOver:Boolean = false; 44 | 45 | /** 46 | * Constructor 47 | * @param parent The parent DisplayObjectContainer on which to add this ListItem. 48 | * @param xpos The x position to place this component. 49 | * @param ypos The y position to place this component. 50 | * @param data The string to display as a label or object with a label property. 51 | */ 52 | public function ListItem(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, data:Object = null) 53 | { 54 | _data = data; 55 | super(parent, xpos, ypos); 56 | } 57 | 58 | /** 59 | * Initilizes the component. 60 | */ 61 | protected override function init() : void 62 | { 63 | super.init(); 64 | addEventListener(MouseEvent.MOUSE_OVER, onMouseOver); 65 | setSize(100, 20); 66 | } 67 | 68 | /** 69 | * Creates and adds the child display objects of this component. 70 | */ 71 | protected override function addChildren() : void 72 | { 73 | super.addChildren(); 74 | _label = new Label(this, 5, 0); 75 | _label.draw(); 76 | } 77 | 78 | /////////////////////////////////// 79 | // public methods 80 | /////////////////////////////////// 81 | 82 | /** 83 | * Draws the visual ui of the component. 84 | */ 85 | public override function draw() : void 86 | { 87 | super.draw(); 88 | graphics.clear(); 89 | 90 | if(_selected) 91 | { 92 | graphics.beginFill(_selectedColor); 93 | } 94 | else if(_mouseOver) 95 | { 96 | graphics.beginFill(_rolloverColor); 97 | } 98 | else 99 | { 100 | graphics.beginFill(_defaultColor); 101 | } 102 | graphics.drawRect(0, 0, width, height); 103 | graphics.endFill(); 104 | 105 | if(_data == null) return; 106 | 107 | if(_data is String) 108 | { 109 | _label.text = _data as String; 110 | } 111 | else if(_data.hasOwnProperty("label") && _data.label is String) 112 | { 113 | _label.text = _data.label; 114 | } 115 | else 116 | { 117 | _label.text = _data.toString(); 118 | } 119 | } 120 | 121 | 122 | 123 | 124 | /////////////////////////////////// 125 | // event handlers 126 | /////////////////////////////////// 127 | 128 | /** 129 | * Called when the user rolls the mouse over the item. Changes the background color. 130 | */ 131 | protected function onMouseOver(event:MouseEvent):void 132 | { 133 | addEventListener(MouseEvent.MOUSE_OUT, onMouseOut); 134 | _mouseOver = true; 135 | invalidate(); 136 | } 137 | 138 | /** 139 | * Called when the user rolls the mouse off the item. Changes the background color. 140 | */ 141 | protected function onMouseOut(event:MouseEvent):void 142 | { 143 | removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut); 144 | _mouseOver = false; 145 | invalidate(); 146 | } 147 | 148 | 149 | 150 | /////////////////////////////////// 151 | // getter/setters 152 | /////////////////////////////////// 153 | 154 | /** 155 | * Sets/gets the string that appears in this item. 156 | */ 157 | public function set data(value:Object):void 158 | { 159 | _data = value; 160 | invalidate(); 161 | } 162 | public function get data():Object 163 | { 164 | return _data; 165 | } 166 | 167 | /** 168 | * Sets/gets whether or not this item is selected. 169 | */ 170 | public function set selected(value:Boolean):void 171 | { 172 | _selected = value; 173 | invalidate(); 174 | } 175 | public function get selected():Boolean 176 | { 177 | return _selected; 178 | } 179 | 180 | /** 181 | * Sets/gets the default background color of list items. 182 | */ 183 | public function set defaultColor(value:uint):void 184 | { 185 | _defaultColor = value; 186 | invalidate(); 187 | } 188 | public function get defaultColor():uint 189 | { 190 | return _defaultColor; 191 | } 192 | 193 | /** 194 | * Sets/gets the selected background color of list items. 195 | */ 196 | public function set selectedColor(value:uint):void 197 | { 198 | _selectedColor = value; 199 | invalidate(); 200 | } 201 | public function get selectedColor():uint 202 | { 203 | return _selectedColor; 204 | } 205 | 206 | /** 207 | * Sets/gets the rollover background color of list items. 208 | */ 209 | public function set rolloverColor(value:uint):void 210 | { 211 | _rolloverColor = value; 212 | invalidate(); 213 | } 214 | public function get rolloverColor():uint 215 | { 216 | return _rolloverColor; 217 | } 218 | 219 | } 220 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/Panel.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Panel.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A rectangular panel. Can be used as a container for other components. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObject; 32 | import flash.display.DisplayObjectContainer; 33 | import flash.display.Sprite; 34 | 35 | public class Panel extends Component 36 | { 37 | protected var _mask:Sprite; 38 | protected var _background:Sprite; 39 | protected var _color:int = -1; 40 | protected var _shadow:Boolean = true; 41 | protected var _gridSize:int = 10; 42 | protected var _showGrid:Boolean = false; 43 | protected var _gridColor:uint = 0xd0d0d0; 44 | 45 | 46 | /** 47 | * Container for content added to this panel. This is masked, so best to add children to content, rather than directly to the panel. 48 | */ 49 | public var content:Sprite; 50 | 51 | 52 | /** 53 | * Constructor 54 | * @param parent The parent DisplayObjectContainer on which to add this Panel. 55 | * @param xpos The x position to place this component. 56 | * @param ypos The y position to place this component. 57 | */ 58 | public function Panel(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0) 59 | { 60 | super(parent, xpos, ypos); 61 | } 62 | 63 | 64 | /** 65 | * Initializes the component. 66 | */ 67 | override protected function init():void 68 | { 69 | super.init(); 70 | setSize(100, 100); 71 | } 72 | 73 | /** 74 | * Creates and adds the child display objects of this component. 75 | */ 76 | override protected function addChildren():void 77 | { 78 | _background = new Sprite(); 79 | super.addChild(_background); 80 | 81 | _mask = new Sprite(); 82 | _mask.mouseEnabled = false; 83 | super.addChild(_mask); 84 | 85 | content = new Sprite(); 86 | super.addChild(content); 87 | content.mask = _mask; 88 | 89 | filters = [getShadow(2, true)]; 90 | } 91 | 92 | 93 | 94 | 95 | /////////////////////////////////// 96 | // public methods 97 | /////////////////////////////////// 98 | 99 | /** 100 | * Overridden to add new child to content. 101 | */ 102 | public override function addChild(child:DisplayObject):DisplayObject 103 | { 104 | content.addChild(child); 105 | return child; 106 | } 107 | 108 | /** 109 | * Access to super.addChild 110 | */ 111 | public function addRawChild(child:DisplayObject):DisplayObject 112 | { 113 | super.addChild(child); 114 | return child; 115 | } 116 | 117 | /** 118 | * Draws the visual ui of the component. 119 | */ 120 | override public function draw():void 121 | { 122 | super.draw(); 123 | _background.graphics.clear(); 124 | _background.graphics.lineStyle(1, 0, 0.1); 125 | if(_color == -1) 126 | { 127 | _background.graphics.beginFill(Style.PANEL); 128 | } 129 | else 130 | { 131 | _background.graphics.beginFill(_color); 132 | } 133 | _background.graphics.drawRect(0, 0, _width, _height); 134 | _background.graphics.endFill(); 135 | 136 | drawGrid(); 137 | 138 | _mask.graphics.clear(); 139 | _mask.graphics.beginFill(0xff0000); 140 | _mask.graphics.drawRect(0, 0, _width, _height); 141 | _mask.graphics.endFill(); 142 | } 143 | 144 | protected function drawGrid():void 145 | { 146 | if(!_showGrid) return; 147 | 148 | _background.graphics.lineStyle(0, _gridColor); 149 | for(var i:int = 0; i < _width; i += _gridSize) 150 | { 151 | _background.graphics.moveTo(i, 0); 152 | _background.graphics.lineTo(i, _height); 153 | } 154 | for(i = 0; i < _height; i += _gridSize) 155 | { 156 | _background.graphics.moveTo(0, i); 157 | _background.graphics.lineTo(_width, i); 158 | } 159 | } 160 | 161 | 162 | 163 | /////////////////////////////////// 164 | // event handlers 165 | /////////////////////////////////// 166 | 167 | /////////////////////////////////// 168 | // getter/setters 169 | /////////////////////////////////// 170 | 171 | /** 172 | * Gets / sets whether or not this Panel will have an inner shadow. 173 | */ 174 | public function set shadow(b:Boolean):void 175 | { 176 | _shadow = b; 177 | if(_shadow) 178 | { 179 | filters = [getShadow(2, true)]; 180 | } 181 | else 182 | { 183 | filters = []; 184 | } 185 | } 186 | public function get shadow():Boolean 187 | { 188 | return _shadow; 189 | } 190 | 191 | /** 192 | * Gets / sets the backgrond color of this panel. 193 | */ 194 | public function set color(c:int):void 195 | { 196 | _color = c; 197 | invalidate(); 198 | } 199 | public function get color():int 200 | { 201 | return _color; 202 | } 203 | 204 | /** 205 | * Sets / gets the size of the grid. 206 | */ 207 | public function set gridSize(value:int):void 208 | { 209 | _gridSize = value; 210 | invalidate(); 211 | } 212 | public function get gridSize():int 213 | { 214 | return _gridSize; 215 | } 216 | 217 | /** 218 | * Sets / gets whether or not the grid will be shown. 219 | */ 220 | public function set showGrid(value:Boolean):void 221 | { 222 | _showGrid = value; 223 | invalidate(); 224 | } 225 | public function get showGrid():Boolean 226 | { 227 | return _showGrid; 228 | } 229 | 230 | /** 231 | * Sets / gets the color of the grid lines. 232 | */ 233 | public function set gridColor(value:uint):void 234 | { 235 | _gridColor = value; 236 | invalidate(); 237 | } 238 | public function get gridColor():uint 239 | { 240 | return _gridColor; 241 | } 242 | } 243 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/ProgressBar.as: -------------------------------------------------------------------------------- 1 | /** 2 | * ProgressBar.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A progress bar component for showing a changing value in relation to a total. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.display.Sprite; 33 | 34 | public class ProgressBar extends Component 35 | { 36 | protected var _back:Sprite; 37 | protected var _bar:Sprite; 38 | protected var _value:Number = 0; 39 | protected var _max:Number = 1; 40 | 41 | /** 42 | * Constructor 43 | * @param parent The parent DisplayObjectContainer on which to add this ProgressBar. 44 | * @param xpos The x position to place this component. 45 | * @param ypos The y position to place this component. 46 | */ 47 | public function ProgressBar(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0) 48 | { 49 | super(parent, xpos, ypos); 50 | } 51 | 52 | 53 | /** 54 | * Initializes the component. 55 | */ 56 | override protected function init():void 57 | { 58 | super.init(); 59 | setSize(100, 10); 60 | } 61 | 62 | /** 63 | * Creates and adds the child display objects of this component. 64 | */ 65 | override protected function addChildren():void 66 | { 67 | _back = new Sprite(); 68 | _back.filters = [getShadow(2, true)]; 69 | addChild(_back); 70 | 71 | _bar = new Sprite(); 72 | _bar.x = 1; 73 | _bar.y = 1; 74 | _bar.filters = [getShadow(1)]; 75 | addChild(_bar); 76 | } 77 | 78 | /** 79 | * Updates the size of the progress bar based on the current value. 80 | */ 81 | protected function update():void 82 | { 83 | _bar.scaleX = _value / _max; 84 | } 85 | 86 | 87 | 88 | 89 | /////////////////////////////////// 90 | // public methods 91 | /////////////////////////////////// 92 | 93 | /** 94 | * Draws the visual ui of the component. 95 | */ 96 | override public function draw():void 97 | { 98 | super.draw(); 99 | _back.graphics.clear(); 100 | _back.graphics.beginFill(Style.BACKGROUND); 101 | _back.graphics.drawRect(0, 0, _width, _height); 102 | _back.graphics.endFill(); 103 | 104 | _bar.graphics.clear(); 105 | _bar.graphics.beginFill(Style.PROGRESS_BAR); 106 | _bar.graphics.drawRect(0, 0, _width - 2, _height - 2); 107 | _bar.graphics.endFill(); 108 | update(); 109 | } 110 | 111 | 112 | 113 | 114 | /////////////////////////////////// 115 | // event handlers 116 | /////////////////////////////////// 117 | 118 | /////////////////////////////////// 119 | // getter/setters 120 | /////////////////////////////////// 121 | 122 | /** 123 | * Gets / sets the maximum value of the ProgressBar. 124 | */ 125 | public function set maximum(m:Number):void 126 | { 127 | _max = m; 128 | _value = Math.min(_value, _max); 129 | update(); 130 | } 131 | public function get maximum():Number 132 | { 133 | return _max; 134 | } 135 | 136 | /** 137 | * Gets / sets the current value of the ProgressBar. 138 | */ 139 | public function set value(v:Number):void 140 | { 141 | _value = Math.min(v, _max); 142 | update(); 143 | } 144 | public function get value():Number 145 | { 146 | return _value; 147 | } 148 | 149 | } 150 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/PushButton.as: -------------------------------------------------------------------------------- 1 | /** 2 | * PushButton.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A basic button component with a label. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.display.Sprite; 33 | import flash.events.MouseEvent; 34 | 35 | public class PushButton extends Component 36 | { 37 | protected var _back:Sprite; 38 | protected var _face:Sprite; 39 | protected var _label:Label; 40 | protected var _labelText:String = ""; 41 | protected var _over:Boolean = false; 42 | protected var _down:Boolean = false; 43 | protected var _selected:Boolean = false; 44 | protected var _toggle:Boolean = false; 45 | 46 | /** 47 | * Constructor 48 | * @param parent The parent DisplayObjectContainer on which to add this PushButton. 49 | * @param xpos The x position to place this component. 50 | * @param ypos The y position to place this component. 51 | * @param label The string to use for the initial label of this component. 52 | * @param defaultHandler The event handling function to handle the default event for this component (click in this case). 53 | */ 54 | public function PushButton(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, label:String = "", defaultHandler:Function = null) 55 | { 56 | super(parent, xpos, ypos); 57 | if(defaultHandler != null) 58 | { 59 | addEventListener(MouseEvent.CLICK, defaultHandler); 60 | } 61 | this.label = label; 62 | } 63 | 64 | /** 65 | * Initializes the component. 66 | */ 67 | override protected function init():void 68 | { 69 | super.init(); 70 | buttonMode = true; 71 | useHandCursor = true; 72 | setSize(100, 20); 73 | } 74 | 75 | /** 76 | * Creates and adds the child display objects of this component. 77 | */ 78 | override protected function addChildren():void 79 | { 80 | _back = new Sprite(); 81 | _back.filters = [getShadow(2, true)]; 82 | _back.mouseEnabled = false; 83 | addChild(_back); 84 | 85 | _face = new Sprite(); 86 | _face.mouseEnabled = false; 87 | _face.filters = [getShadow(1)]; 88 | _face.x = 1; 89 | _face.y = 1; 90 | addChild(_face); 91 | 92 | _label = new Label(); 93 | addChild(_label); 94 | 95 | addEventListener(MouseEvent.MOUSE_DOWN, onMouseGoDown); 96 | addEventListener(MouseEvent.ROLL_OVER, onMouseOver); 97 | } 98 | 99 | /** 100 | * Draws the face of the button, color based on state. 101 | */ 102 | protected function drawFace():void 103 | { 104 | _face.graphics.clear(); 105 | if(_down) 106 | { 107 | _face.graphics.beginFill(Style.BUTTON_DOWN); 108 | } 109 | else 110 | { 111 | _face.graphics.beginFill(Style.BUTTON_FACE); 112 | } 113 | _face.graphics.drawRect(0, 0, _width - 2, _height - 2); 114 | _face.graphics.endFill(); 115 | } 116 | 117 | 118 | /////////////////////////////////// 119 | // public methods 120 | /////////////////////////////////// 121 | 122 | /** 123 | * Draws the visual ui of the component. 124 | */ 125 | override public function draw():void 126 | { 127 | super.draw(); 128 | _back.graphics.clear(); 129 | _back.graphics.beginFill(Style.BACKGROUND); 130 | _back.graphics.drawRect(0, 0, _width, _height); 131 | _back.graphics.endFill(); 132 | 133 | drawFace(); 134 | 135 | _label.text = _labelText; 136 | _label.autoSize = true; 137 | _label.draw(); 138 | if(_label.width > _width - 4) 139 | { 140 | _label.autoSize = false; 141 | _label.width = _width - 4; 142 | } 143 | else 144 | { 145 | _label.autoSize = true; 146 | } 147 | _label.draw(); 148 | _label.move(_width / 2 - _label.width / 2, _height / 2 - _label.height / 2); 149 | 150 | } 151 | 152 | 153 | 154 | 155 | /////////////////////////////////// 156 | // event handlers 157 | /////////////////////////////////// 158 | 159 | /** 160 | * Internal mouseOver handler. 161 | * @param event The MouseEvent passed by the system. 162 | */ 163 | protected function onMouseOver(event:MouseEvent):void 164 | { 165 | _over = true; 166 | addEventListener(MouseEvent.ROLL_OUT, onMouseOut); 167 | } 168 | 169 | /** 170 | * Internal mouseOut handler. 171 | * @param event The MouseEvent passed by the system. 172 | */ 173 | protected function onMouseOut(event:MouseEvent):void 174 | { 175 | _over = false; 176 | if(!_down) 177 | { 178 | _face.filters = [getShadow(1)]; 179 | } 180 | removeEventListener(MouseEvent.ROLL_OUT, onMouseOut); 181 | } 182 | 183 | /** 184 | * Internal mouseOut handler. 185 | * @param event The MouseEvent passed by the system. 186 | */ 187 | protected function onMouseGoDown(event:MouseEvent):void 188 | { 189 | _down = true; 190 | drawFace(); 191 | _face.filters = [getShadow(1, true)]; 192 | stage.addEventListener(MouseEvent.MOUSE_UP, onMouseGoUp); 193 | } 194 | 195 | /** 196 | * Internal mouseUp handler. 197 | * @param event The MouseEvent passed by the system. 198 | */ 199 | protected function onMouseGoUp(event:MouseEvent):void 200 | { 201 | if(_toggle && _over) 202 | { 203 | _selected = !_selected; 204 | } 205 | _down = _selected; 206 | drawFace(); 207 | _face.filters = [getShadow(1, _selected)]; 208 | stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseGoUp); 209 | } 210 | 211 | 212 | 213 | 214 | /////////////////////////////////// 215 | // getter/setters 216 | /////////////////////////////////// 217 | 218 | /** 219 | * Sets / gets the label text shown on this Pushbutton. 220 | */ 221 | public function set label(str:String):void 222 | { 223 | _labelText = str; 224 | draw(); 225 | } 226 | public function get label():String 227 | { 228 | return _labelText; 229 | } 230 | 231 | public function set selected(value:Boolean):void 232 | { 233 | if(!_toggle) 234 | { 235 | value = false; 236 | } 237 | 238 | _selected = value; 239 | _down = _selected; 240 | _face.filters = [getShadow(1, _selected)]; 241 | drawFace(); 242 | } 243 | public function get selected():Boolean 244 | { 245 | return _selected; 246 | } 247 | 248 | public function set toggle(value:Boolean):void 249 | { 250 | _toggle = value; 251 | } 252 | public function get toggle():Boolean 253 | { 254 | return _toggle; 255 | } 256 | 257 | 258 | } 259 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/RadioButton.as: -------------------------------------------------------------------------------- 1 | /** 2 | * RadioButton.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A basic radio button component, meant to be used in groups, where only one button in the group can be selected. 7 | * Currently only one group can be created. 8 | * 9 | * Copyright (c) 2011 Keith Peters 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | */ 29 | 30 | package com.bit101.components 31 | { 32 | import flash.display.DisplayObjectContainer; 33 | import flash.display.Sprite; 34 | import flash.events.MouseEvent; 35 | 36 | public class RadioButton extends Component 37 | { 38 | protected var _back:Sprite; 39 | protected var _button:Sprite; 40 | protected var _selected:Boolean = false; 41 | protected var _label:Label; 42 | protected var _labelText:String = ""; 43 | protected var _groupName:String = "defaultRadioGroup"; 44 | 45 | protected static var buttons:Array; 46 | 47 | 48 | /** 49 | * Constructor 50 | * @param parent The parent DisplayObjectContainer on which to add this RadioButton. 51 | * @param xpos The x position to place this component. 52 | * @param ypos The y position to place this component. 53 | * @param label The string to use for the initial label of this component. 54 | * @param defaultHandler The event handling function to handle the default event for this component (click in this case). 55 | */ 56 | public function RadioButton(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, label:String = "", checked:Boolean = false, defaultHandler:Function = null) 57 | { 58 | RadioButton.addButton(this); 59 | _selected = checked; 60 | _labelText = label; 61 | super(parent, xpos, ypos); 62 | if(defaultHandler != null) 63 | { 64 | addEventListener(MouseEvent.CLICK, defaultHandler); 65 | } 66 | } 67 | 68 | /** 69 | * Static method to add the newly created RadioButton to the list of buttons in the group. 70 | * @param rb The RadioButton to add. 71 | */ 72 | protected static function addButton(rb:RadioButton):void 73 | { 74 | if(buttons == null) 75 | { 76 | buttons = new Array(); 77 | } 78 | buttons.push(rb); 79 | } 80 | 81 | /** 82 | * Unselects all RadioButtons in the group, except the one passed. 83 | * This could use some rethinking or better naming. 84 | * @param rb The RadioButton to remain selected. 85 | */ 86 | protected static function clear(rb:RadioButton):void 87 | { 88 | for(var i:uint = 0; i < buttons.length; i++) 89 | { 90 | if(buttons[i] != rb && buttons[i].groupName == rb.groupName) 91 | { 92 | buttons[i].selected = false; 93 | } 94 | } 95 | } 96 | 97 | /** 98 | * Initializes the component. 99 | */ 100 | override protected function init():void 101 | { 102 | super.init(); 103 | 104 | buttonMode = true; 105 | useHandCursor = true; 106 | 107 | addEventListener(MouseEvent.CLICK, onClick, false, 1); 108 | selected = _selected; 109 | } 110 | 111 | /** 112 | * Creates and adds the child display objects of this component. 113 | */ 114 | override protected function addChildren():void 115 | { 116 | _back = new Sprite(); 117 | _back.filters = [getShadow(2, true)]; 118 | addChild(_back); 119 | 120 | _button = new Sprite(); 121 | _button.filters = [getShadow(1)]; 122 | _button.visible = false; 123 | addChild(_button); 124 | 125 | _label = new Label(this, 0, 0, _labelText); 126 | draw(); 127 | 128 | mouseChildren = false; 129 | } 130 | 131 | 132 | 133 | 134 | /////////////////////////////////// 135 | // public methods 136 | /////////////////////////////////// 137 | 138 | /** 139 | * Draws the visual ui of the component. 140 | */ 141 | override public function draw():void 142 | { 143 | super.draw(); 144 | _back.graphics.clear(); 145 | _back.graphics.beginFill(Style.BACKGROUND); 146 | _back.graphics.drawCircle(5, 5, 5); 147 | _back.graphics.endFill(); 148 | 149 | _button.graphics.clear(); 150 | _button.graphics.beginFill(Style.BUTTON_FACE); 151 | _button.graphics.drawCircle(5, 5, 3); 152 | 153 | _label.x = 12; 154 | _label.y = (10 - _label.height) / 2; 155 | _label.text = _labelText; 156 | _label.draw(); 157 | _width = _label.width + 12; 158 | _height = 10; 159 | } 160 | 161 | 162 | 163 | 164 | /////////////////////////////////// 165 | // event handlers 166 | /////////////////////////////////// 167 | 168 | /** 169 | * Internal click handler. 170 | * @param event The MouseEvent passed by the system. 171 | */ 172 | protected function onClick(event:MouseEvent):void 173 | { 174 | selected = true; 175 | } 176 | 177 | 178 | 179 | 180 | /////////////////////////////////// 181 | // getter/setters 182 | /////////////////////////////////// 183 | 184 | /** 185 | * Sets / gets the selected state of this CheckBox. 186 | */ 187 | public function set selected(s:Boolean):void 188 | { 189 | _selected = s; 190 | _button.visible = _selected; 191 | if(_selected) 192 | { 193 | RadioButton.clear(this); 194 | } 195 | } 196 | public function get selected():Boolean 197 | { 198 | return _selected; 199 | } 200 | 201 | /** 202 | * Sets / gets the label text shown on this CheckBox. 203 | */ 204 | public function set label(str:String):void 205 | { 206 | _labelText = str; 207 | invalidate(); 208 | } 209 | public function get label():String 210 | { 211 | return _labelText; 212 | } 213 | 214 | /** 215 | * Sets / gets the group name, which allows groups of RadioButtons to function seperately. 216 | */ 217 | public function get groupName():String 218 | { 219 | return _groupName; 220 | } 221 | 222 | public function set groupName(value:String):void 223 | { 224 | _groupName = value; 225 | } 226 | 227 | 228 | } 229 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/RotarySelector.as: -------------------------------------------------------------------------------- 1 | /** 2 | * RotarySelector.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A rotary selector component for choosing among different values. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.display.Sprite; 33 | import flash.events.Event; 34 | import flash.events.MouseEvent; 35 | 36 | [Event(name="change", type="flash.events.Event")] 37 | public class RotarySelector extends Component 38 | { 39 | public static const ALPHABETIC:String = "alphabetic"; 40 | public static const NUMERIC:String = "numeric"; 41 | public static const NONE:String = "none"; 42 | public static const ROMAN:String = "roman"; 43 | 44 | 45 | protected var _label:Label; 46 | protected var _labelText:String = ""; 47 | protected var _knob:Sprite; 48 | protected var _numChoices:int = 2; 49 | protected var _choice:Number = 0; 50 | protected var _labels:Sprite; 51 | protected var _labelMode:String = ALPHABETIC; 52 | 53 | 54 | /** 55 | * Constructor 56 | * @param parent The parent DisplayObjectContainer on which to add this CheckBox. 57 | * @param xpos The x position to place this component. 58 | * @param ypos The y position to place this component. 59 | * @param label String containing the label for this component. 60 | * @param defaultHandler The event handling function to handle the default event for this component (change in this case). 61 | */ 62 | public function RotarySelector(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, label:String = "", defaultHandler:Function = null) 63 | { 64 | _labelText = label; 65 | super(parent, xpos, ypos); 66 | if(defaultHandler != null) 67 | { 68 | addEventListener(Event.CHANGE, defaultHandler); 69 | } 70 | } 71 | 72 | /** 73 | * Initializes the component. 74 | */ 75 | override protected function init():void 76 | { 77 | super.init(); 78 | setSize(60, 60); 79 | } 80 | 81 | /** 82 | * Creates the children for this component 83 | */ 84 | override protected function addChildren():void 85 | { 86 | _knob = new Sprite(); 87 | _knob.buttonMode = true; 88 | _knob.useHandCursor = true; 89 | addChild(_knob); 90 | 91 | _label = new Label(); 92 | _label.autoSize = true; 93 | addChild(_label); 94 | 95 | _labels = new Sprite(); 96 | addChild(_labels); 97 | 98 | _knob.addEventListener(MouseEvent.CLICK, onClick); 99 | } 100 | 101 | /** 102 | * Decrements the index of the current choice. 103 | */ 104 | protected function decrement():void 105 | { 106 | if(_choice > 0) 107 | { 108 | _choice--; 109 | draw(); 110 | dispatchEvent(new Event(Event.CHANGE)); 111 | } 112 | } 113 | 114 | /** 115 | * Increments the index of the current choice. 116 | */ 117 | protected function increment():void 118 | { 119 | if(_choice < _numChoices - 1) 120 | { 121 | _choice++; 122 | draw(); 123 | dispatchEvent(new Event(Event.CHANGE)); 124 | } 125 | } 126 | 127 | /** 128 | * Removes old labels. 129 | */ 130 | protected function resetLabels():void 131 | { 132 | while(_labels.numChildren > 0) 133 | { 134 | _labels.removeChildAt(0); 135 | } 136 | _labels.x = _width / 2 - 5; 137 | _labels.y = _height / 2 - 10; 138 | } 139 | 140 | /** 141 | * Draw the knob at the specified radius. 142 | * @param radius The radius with which said knob will be drawn. 143 | */ 144 | protected function drawKnob(radius:Number):void 145 | { 146 | _knob.graphics.clear(); 147 | _knob.graphics.beginFill(Style.BACKGROUND); 148 | _knob.graphics.drawCircle(0, 0, radius); 149 | _knob.graphics.endFill(); 150 | 151 | _knob.graphics.beginFill(Style.BUTTON_FACE); 152 | _knob.graphics.drawCircle(0, 0, radius - 2); 153 | 154 | _knob.x = _width / 2; 155 | _knob.y = _height / 2; 156 | } 157 | 158 | /////////////////////////////////// 159 | // public methods 160 | /////////////////////////////////// 161 | 162 | /** 163 | * Draws the visual ui of the component. 164 | */ 165 | override public function draw():void 166 | { 167 | super.draw(); 168 | 169 | var radius:Number = Math.min(_width, _height) / 2; 170 | drawKnob(radius); 171 | resetLabels(); 172 | 173 | var arc:Number = Math.PI * 1.5 / _numChoices; // the angle between each choice 174 | var start:Number = - Math.PI / 2 - arc * (_numChoices - 1) / 2; // the starting angle for choice 0 175 | 176 | graphics.clear(); 177 | graphics.lineStyle(4, Style.BACKGROUND, .5); 178 | for(var i:int = 0; i < _numChoices; i++) 179 | { 180 | var angle:Number = start + arc * i; 181 | var sin:Number = Math.sin(angle); 182 | var cos:Number = Math.cos(angle); 183 | 184 | graphics.moveTo(_knob.x, _knob.y); 185 | graphics.lineTo(_knob.x + cos * (radius + 2), _knob.y + sin * (radius + 2)); 186 | 187 | var lab:Label = new Label(_labels, cos * (radius + 10), sin * (radius + 10)); 188 | lab.mouseEnabled = true; 189 | lab.buttonMode = true; 190 | lab.useHandCursor = true; 191 | lab.addEventListener(MouseEvent.CLICK, onLabelClick); 192 | if(_labelMode == ALPHABETIC) 193 | { 194 | lab.text = String.fromCharCode(65 + i); 195 | } 196 | else if(_labelMode == NUMERIC) 197 | { 198 | lab.text = (i + 1).toString(); 199 | } 200 | else if(_labelMode == ROMAN) 201 | { 202 | var chars:Array = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"]; 203 | lab.text = chars[i]; 204 | } 205 | if(i != _choice) 206 | { 207 | lab.alpha = 0.5; 208 | } 209 | } 210 | 211 | angle = start + arc * _choice; 212 | graphics.lineStyle(4, Style.LABEL_TEXT); 213 | graphics.moveTo(_knob.x, _knob.y); 214 | graphics.lineTo(_knob.x + Math.cos(angle) * (radius + 2), _knob.y + Math.sin(angle) * (radius + 2)); 215 | 216 | 217 | _label.text = _labelText; 218 | _label.draw(); 219 | _label.x = _width / 2 - _label.width / 2; 220 | _label.y = _height + 2; 221 | } 222 | 223 | 224 | 225 | /////////////////////////////////// 226 | // event handler 227 | /////////////////////////////////// 228 | 229 | /** 230 | * Internal click handler. 231 | * @param event The MouseEvent passed by the system. 232 | */ 233 | protected function onClick(event:MouseEvent):void 234 | { 235 | if(mouseX < _width / 2) 236 | { 237 | decrement(); 238 | } 239 | else 240 | { 241 | increment(); 242 | } 243 | } 244 | 245 | protected function onLabelClick(event:Event):void 246 | { 247 | var lab:Label = event.target as Label; 248 | choice = _labels.getChildIndex(lab); 249 | } 250 | 251 | 252 | 253 | 254 | /////////////////////////////////// 255 | // getter/setters 256 | /////////////////////////////////// 257 | 258 | /** 259 | * Gets / sets the number of available choices (maximum of 10). 260 | */ 261 | public function set numChoices(value:uint):void 262 | { 263 | _numChoices = Math.min(value, 10); 264 | draw(); 265 | } 266 | public function get numChoices():uint 267 | { 268 | return _numChoices; 269 | } 270 | 271 | /** 272 | * Gets / sets the current choice, keeping it in range of 0 to numChoices - 1. 273 | */ 274 | public function set choice(value:uint):void 275 | { 276 | _choice = Math.max(0, Math.min(_numChoices - 1, value)); 277 | draw(); 278 | dispatchEvent(new Event(Event.CHANGE)); 279 | } 280 | public function get choice():uint 281 | { 282 | return _choice; 283 | } 284 | 285 | /** 286 | * Specifies what will be used as labels for each choice. Valid values are "alphabetic", "numeric", and "none". 287 | */ 288 | public function set labelMode(value:String):void 289 | { 290 | _labelMode = value; 291 | draw(); 292 | } 293 | public function get labelMode():String 294 | { 295 | return _labelMode; 296 | } 297 | } 298 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/ScrollPane.as: -------------------------------------------------------------------------------- 1 | /** 2 | * ScrollPane.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A panel with scroll bars for scrolling content that is larger. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | 32 | import flash.display.DisplayObjectContainer; 33 | import flash.display.Shape; 34 | import flash.events.Event; 35 | import flash.events.MouseEvent; 36 | import flash.geom.Rectangle; 37 | 38 | public class ScrollPane extends Panel 39 | { 40 | protected var _vScrollbar:VScrollBar; 41 | protected var _hScrollbar:HScrollBar; 42 | protected var _corner:Shape; 43 | protected var _dragContent:Boolean = true; 44 | 45 | /** 46 | * Constructor 47 | * @param parent The parent DisplayObjectContainer on which to add this ScrollPane. 48 | * @param xpos The x position to place this component. 49 | * @param ypos The y position to place this component. 50 | */ 51 | public function ScrollPane(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0) 52 | { 53 | super(parent, xpos, ypos); 54 | } 55 | 56 | /** 57 | * Initializes this component. 58 | */ 59 | override protected function init():void 60 | { 61 | super.init(); 62 | addEventListener(Event.RESIZE, onResize); 63 | _background.addEventListener(MouseEvent.MOUSE_DOWN, onMouseGoDown); 64 | _background.useHandCursor = true; 65 | _background.buttonMode = true; 66 | setSize(100, 100); 67 | } 68 | 69 | /** 70 | * Creates and adds the child display objects of this component. 71 | */ 72 | override protected function addChildren():void 73 | { 74 | super.addChildren(); 75 | _vScrollbar = new VScrollBar(null, width - 10, 0, onScroll); 76 | _hScrollbar = new HScrollBar(null, 0, height - 10, onScroll); 77 | addRawChild(_vScrollbar); 78 | addRawChild(_hScrollbar); 79 | _corner = new Shape(); 80 | _corner.graphics.beginFill(Style.BUTTON_FACE); 81 | _corner.graphics.drawRect(0, 0, 10, 10); 82 | _corner.graphics.endFill(); 83 | addRawChild(_corner); 84 | } 85 | 86 | 87 | 88 | 89 | 90 | /////////////////////////////////// 91 | // public methods 92 | /////////////////////////////////// 93 | 94 | /** 95 | * Draws the visual ui of the component. 96 | */ 97 | override public function draw():void 98 | { 99 | super.draw(); 100 | 101 | var vPercent:Number = (_height - 10) / content.height; 102 | var hPercent:Number = (_width - 10) / content.width; 103 | 104 | _vScrollbar.x = width - 10; 105 | _hScrollbar.y = height - 10; 106 | 107 | if(hPercent >= 1) 108 | { 109 | _vScrollbar.height = height; 110 | _mask.height = height; 111 | } 112 | else 113 | { 114 | _vScrollbar.height = height - 10; 115 | _mask.height = height - 10; 116 | } 117 | if(vPercent >= 1) 118 | { 119 | _hScrollbar.width = width; 120 | _mask.width = width; 121 | } 122 | else 123 | { 124 | _hScrollbar.width = width - 10; 125 | _mask.width = width - 10; 126 | } 127 | _vScrollbar.setThumbPercent(vPercent); 128 | _vScrollbar.maximum = Math.max(0, content.height - _height + 10); 129 | _vScrollbar.pageSize = _height - 10; 130 | 131 | _hScrollbar.setThumbPercent(hPercent); 132 | _hScrollbar.maximum = Math.max(0, content.width - _width + 10); 133 | _hScrollbar.pageSize = _width - 10; 134 | 135 | _corner.x = width - 10; 136 | _corner.y = height - 10; 137 | _corner.visible = (hPercent < 1) && (vPercent < 1); 138 | content.x = -_hScrollbar.value; 139 | content.y = -_vScrollbar.value; 140 | } 141 | 142 | /** 143 | * Updates the scrollbars when content is changed. Needs to be done manually. 144 | */ 145 | public function update():void 146 | { 147 | invalidate(); 148 | } 149 | 150 | 151 | /////////////////////////////////// 152 | // event handlers 153 | /////////////////////////////////// 154 | 155 | /** 156 | * Called when either scroll bar is scrolled. 157 | */ 158 | protected function onScroll(event:Event):void 159 | { 160 | content.x = -_hScrollbar.value; 161 | content.y = -_vScrollbar.value; 162 | } 163 | 164 | protected function onResize(event:Event):void 165 | { 166 | invalidate(); 167 | } 168 | 169 | protected function onMouseGoDown(event:MouseEvent):void 170 | { 171 | content.startDrag(false, new Rectangle(0, 0, Math.min(0, _width - content.width - 10), Math.min(0, _height - content.height - 10))); 172 | stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); 173 | stage.addEventListener(MouseEvent.MOUSE_UP, onMouseGoUp); 174 | } 175 | 176 | protected function onMouseMove(event:MouseEvent):void 177 | { 178 | _hScrollbar.value = -content.x; 179 | _vScrollbar.value = -content.y; 180 | } 181 | 182 | protected function onMouseGoUp(event:MouseEvent):void 183 | { 184 | content.stopDrag(); 185 | stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); 186 | stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseGoUp); 187 | } 188 | 189 | public function set dragContent(value:Boolean):void 190 | { 191 | _dragContent = value; 192 | if(_dragContent) 193 | { 194 | _background.addEventListener(MouseEvent.MOUSE_DOWN, onMouseGoDown); 195 | _background.useHandCursor = true; 196 | _background.buttonMode = true; 197 | } 198 | else 199 | { 200 | _background.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseGoDown); 201 | _background.useHandCursor = false; 202 | _background.buttonMode = false; 203 | } 204 | } 205 | public function get dragContent():Boolean 206 | { 207 | return _dragContent; 208 | } 209 | 210 | /** 211 | * Sets / gets whether the scrollbar will auto hide when there is nothing to scroll. 212 | */ 213 | public function set autoHideScrollBar(value:Boolean):void 214 | { 215 | _vScrollbar.autoHide = value; 216 | _hScrollbar.autoHide = value; 217 | } 218 | public function get autoHideScrollBar():Boolean 219 | { 220 | return _vScrollbar.autoHide; 221 | } 222 | 223 | 224 | } 225 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/Style.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Style.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A collection of style variables used by the components. 7 | * If you want to customize the colors of your components, change these values BEFORE instantiating any components. 8 | * 9 | * Copyright (c) 2011 Keith Peters 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | */ 29 | 30 | package com.bit101.components 31 | { 32 | 33 | public class Style 34 | { 35 | public static var TEXT_BACKGROUND:uint = 0xFFFFFF; 36 | public static var BACKGROUND:uint = 0xCCCCCC; 37 | public static var BUTTON_FACE:uint = 0xFFFFFF; 38 | public static var BUTTON_DOWN:uint = 0xEEEEEE; 39 | public static var INPUT_TEXT:uint = 0x333333; 40 | public static var LABEL_TEXT:uint = 0x666666; 41 | public static var DROPSHADOW:uint = 0x000000; 42 | public static var PANEL:uint = 0xF3F3F3; 43 | public static var PROGRESS_BAR:uint = 0xFFFFFF; 44 | public static var LIST_DEFAULT:uint = 0xFFFFFF; 45 | public static var LIST_ALTERNATE:uint = 0xF3F3F3; 46 | public static var LIST_SELECTED:uint = 0xCCCCCC; 47 | public static var LIST_ROLLOVER:uint = 0XDDDDDD; 48 | 49 | public static var embedFonts:Boolean = true; 50 | public static var fontName:String = "PF Ronda Seven"; 51 | public static var fontSize:Number = 8; 52 | 53 | public static const DARK:String = "dark"; 54 | public static const LIGHT:String = "light"; 55 | 56 | /** 57 | * Applies a preset style as a list of color values. Should be called before creating any components. 58 | */ 59 | public static function setStyle(style:String):void 60 | { 61 | switch(style) 62 | { 63 | case DARK: 64 | Style.BACKGROUND = 0x444444; 65 | Style.BUTTON_FACE = 0x666666; 66 | Style.BUTTON_DOWN = 0x222222; 67 | Style.INPUT_TEXT = 0xBBBBBB; 68 | Style.LABEL_TEXT = 0xCCCCCC; 69 | Style.PANEL = 0x666666; 70 | Style.PROGRESS_BAR = 0x666666; 71 | Style.TEXT_BACKGROUND = 0x555555; 72 | Style.LIST_DEFAULT = 0x444444; 73 | Style.LIST_ALTERNATE = 0x393939; 74 | Style.LIST_SELECTED = 0x666666; 75 | Style.LIST_ROLLOVER = 0x777777; 76 | break; 77 | case LIGHT: 78 | default: 79 | Style.BACKGROUND = 0xCCCCCC; 80 | Style.BUTTON_FACE = 0xFFFFFF; 81 | Style.BUTTON_DOWN = 0xEEEEEE; 82 | Style.INPUT_TEXT = 0x333333; 83 | Style.LABEL_TEXT = 0x666666; 84 | Style.PANEL = 0xF3F3F3; 85 | Style.PROGRESS_BAR = 0xFFFFFF; 86 | Style.TEXT_BACKGROUND = 0xFFFFFF; 87 | Style.LIST_DEFAULT = 0xFFFFFF; 88 | Style.LIST_ALTERNATE = 0xF3F3F3; 89 | Style.LIST_SELECTED = 0xCCCCCC; 90 | Style.LIST_ROLLOVER = 0xDDDDDD; 91 | break; 92 | } 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/Text.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Text.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A Text component for displaying multiple lines of text. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.events.Event; 33 | import flash.text.TextField; 34 | import flash.text.TextFieldType; 35 | import flash.text.TextFormat; 36 | 37 | [Event(name="change", type="flash.events.Event")] 38 | public class Text extends Component 39 | { 40 | protected var _tf:TextField; 41 | protected var _text:String = ""; 42 | protected var _editable:Boolean = true; 43 | protected var _panel:Panel; 44 | protected var _selectable:Boolean = true; 45 | protected var _html:Boolean = false; 46 | protected var _format:TextFormat; 47 | 48 | /** 49 | * Constructor 50 | * @param parent The parent DisplayObjectContainer on which to add this Label. 51 | * @param xpos The x position to place this component. 52 | * @param ypos The y position to place this component. 53 | * @param text The initial text to display in this component. 54 | */ 55 | public function Text(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, text:String = "") 56 | { 57 | this.text = text; 58 | super(parent, xpos, ypos); 59 | setSize(200, 100); 60 | } 61 | 62 | /** 63 | * Initializes the component. 64 | */ 65 | override protected function init():void 66 | { 67 | super.init(); 68 | } 69 | 70 | /** 71 | * Creates and adds the child display objects of this component. 72 | */ 73 | override protected function addChildren():void 74 | { 75 | _panel = new Panel(this); 76 | _panel.color = Style.TEXT_BACKGROUND; 77 | 78 | _format = new TextFormat(Style.fontName, Style.fontSize, Style.LABEL_TEXT); 79 | 80 | _tf = new TextField(); 81 | _tf.x = 2; 82 | _tf.y = 2; 83 | _tf.height = _height; 84 | _tf.embedFonts = Style.embedFonts; 85 | _tf.multiline = true; 86 | _tf.wordWrap = true; 87 | _tf.selectable = true; 88 | _tf.type = TextFieldType.INPUT; 89 | _tf.defaultTextFormat = _format; 90 | _tf.addEventListener(Event.CHANGE, onChange); 91 | addChild(_tf); 92 | } 93 | 94 | 95 | 96 | 97 | /////////////////////////////////// 98 | // public methods 99 | /////////////////////////////////// 100 | 101 | /** 102 | * Draws the visual ui of the component. 103 | */ 104 | override public function draw():void 105 | { 106 | super.draw(); 107 | 108 | _panel.setSize(_width, _height); 109 | _panel.draw(); 110 | 111 | _tf.width = _width - 4; 112 | _tf.height = _height - 4; 113 | if(_html) 114 | { 115 | _tf.htmlText = _text; 116 | } 117 | else 118 | { 119 | _tf.text = _text; 120 | } 121 | if(_editable) 122 | { 123 | _tf.mouseEnabled = true; 124 | _tf.selectable = true; 125 | _tf.type = TextFieldType.INPUT; 126 | } 127 | else 128 | { 129 | _tf.mouseEnabled = _selectable; 130 | _tf.selectable = _selectable; 131 | _tf.type = TextFieldType.DYNAMIC; 132 | } 133 | _tf.setTextFormat(_format); 134 | } 135 | 136 | 137 | 138 | 139 | /////////////////////////////////// 140 | // event handlers 141 | /////////////////////////////////// 142 | 143 | /** 144 | * Called when the text in the text field is manually changed. 145 | */ 146 | protected function onChange(event:Event):void 147 | { 148 | _text = _tf.text; 149 | dispatchEvent(event); 150 | } 151 | 152 | /////////////////////////////////// 153 | // getter/setters 154 | /////////////////////////////////// 155 | 156 | /** 157 | * Gets / sets the text of this Label. 158 | */ 159 | public function set text(t:String):void 160 | { 161 | _text = t; 162 | if(_text == null) _text = ""; 163 | invalidate(); 164 | } 165 | public function get text():String 166 | { 167 | return _text; 168 | } 169 | 170 | /** 171 | * Returns a reference to the internal text field in the component. 172 | */ 173 | public function get textField():TextField 174 | { 175 | return _tf; 176 | } 177 | 178 | /** 179 | * Gets / sets whether or not this text component will be editable. 180 | */ 181 | public function set editable(b:Boolean):void 182 | { 183 | _editable = b; 184 | invalidate(); 185 | } 186 | public function get editable():Boolean 187 | { 188 | return _editable; 189 | } 190 | 191 | /** 192 | * Gets / sets whether or not this text component will be selectable. Only meaningful if editable is false. 193 | */ 194 | public function set selectable(b:Boolean):void 195 | { 196 | _selectable = b; 197 | invalidate(); 198 | } 199 | public function get selectable():Boolean 200 | { 201 | return _selectable; 202 | } 203 | 204 | /** 205 | * Gets / sets whether or not text will be rendered as HTML or plain text. 206 | */ 207 | public function set html(b:Boolean):void 208 | { 209 | _html = b; 210 | invalidate(); 211 | } 212 | public function get html():Boolean 213 | { 214 | return _html; 215 | } 216 | 217 | /** 218 | * Sets/gets whether this component is enabled or not. 219 | */ 220 | public override function set enabled(value:Boolean):void 221 | { 222 | super.enabled = value; 223 | _tf.tabEnabled = value; 224 | } 225 | 226 | } 227 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/TextArea.as: -------------------------------------------------------------------------------- 1 | /** 2 | * TextArea.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A Text component for displaying multiple lines of text with a scrollbar. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.events.Event; 33 | import flash.events.MouseEvent; 34 | 35 | public class TextArea extends Text 36 | { 37 | protected var _scrollbar:VScrollBar; 38 | 39 | /** 40 | * Constructor 41 | * @param parent The parent DisplayObjectContainer on which to add this Label. 42 | * @param xpos The x position to place this component. 43 | * @param ypos The y position to place this component. 44 | * @param text The initial text to display in this component. 45 | */ 46 | public function TextArea(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, text:String="") 47 | { 48 | super(parent, xpos, ypos, text); 49 | } 50 | 51 | /** 52 | * Initilizes the component. 53 | */ 54 | protected override function init() : void 55 | { 56 | super.init(); 57 | addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel); 58 | } 59 | /** 60 | * Creates and adds the child display objects of this component. 61 | */ 62 | override protected function addChildren():void 63 | { 64 | super.addChildren(); 65 | _scrollbar = new VScrollBar(this, 0, 0, onScrollbarScroll); 66 | _tf.addEventListener(Event.SCROLL, onTextScroll); 67 | } 68 | 69 | /** 70 | * Changes the thumb percent of the scrollbar based on how much text is shown in the text area. 71 | */ 72 | protected function updateScrollbar():void 73 | { 74 | var visibleLines:int = _tf.numLines - _tf.maxScrollV + 1; 75 | var percent:Number = visibleLines / _tf.numLines; 76 | _scrollbar.setSliderParams(1, _tf.maxScrollV, _tf.scrollV); 77 | _scrollbar.setThumbPercent(percent); 78 | _scrollbar.pageSize = visibleLines; 79 | } 80 | 81 | 82 | 83 | 84 | /////////////////////////////////// 85 | // public methods 86 | /////////////////////////////////// 87 | 88 | /** 89 | * Draws the visual ui of the component. 90 | */ 91 | override public function draw():void 92 | { 93 | super.draw(); 94 | 95 | _tf.width = _width - _scrollbar.width - 4; 96 | _scrollbar.x = _width - _scrollbar.width; 97 | _scrollbar.height = _height; 98 | _scrollbar.draw(); 99 | addEventListener(Event.ENTER_FRAME, onTextScrollDelay); 100 | } 101 | 102 | 103 | 104 | /////////////////////////////////// 105 | // event handlers 106 | /////////////////////////////////// 107 | 108 | /** 109 | * Waits one more frame before updating scroll bar. 110 | * It seems that numLines and maxScrollV are not valid immediately after changing a TextField's size. 111 | */ 112 | protected function onTextScrollDelay(event:Event):void 113 | { 114 | removeEventListener(Event.ENTER_FRAME, onTextScrollDelay); 115 | updateScrollbar(); 116 | } 117 | 118 | /** 119 | * Called when the text in the text field is manually changed. 120 | */ 121 | protected override function onChange(event:Event):void 122 | { 123 | super.onChange(event); 124 | updateScrollbar(); 125 | } 126 | 127 | /** 128 | * Called when the scroll bar is moved. Scrolls text accordingly. 129 | */ 130 | protected function onScrollbarScroll(event:Event):void 131 | { 132 | _tf.scrollV = Math.round(_scrollbar.value); 133 | } 134 | 135 | /** 136 | * Called when the text is scrolled manually. Updates the position of the scroll bar. 137 | */ 138 | protected function onTextScroll(event:Event):void 139 | { 140 | _scrollbar.value = _tf.scrollV; 141 | updateScrollbar(); 142 | } 143 | 144 | /** 145 | * Called when the mouse wheel is scrolled over the component. 146 | */ 147 | protected function onMouseWheel(event:MouseEvent):void 148 | { 149 | _scrollbar.value -= event.delta; 150 | _tf.scrollV = Math.round(_scrollbar.value); 151 | } 152 | 153 | /** 154 | * Sets/gets whether this component is enabled or not. 155 | */ 156 | public override function set enabled(value:Boolean):void 157 | { 158 | super.enabled = value; 159 | _tf.tabEnabled = value; 160 | } 161 | 162 | /** 163 | * Sets / gets whether the scrollbar will auto hide when there is nothing to scroll. 164 | */ 165 | public function set autoHideScrollBar(value:Boolean):void 166 | { 167 | _scrollbar.autoHide = value; 168 | } 169 | public function get autoHideScrollBar():Boolean 170 | { 171 | return _scrollbar.autoHide; 172 | } 173 | 174 | } 175 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/UISlider.as: -------------------------------------------------------------------------------- 1 | /** 2 | * UISlider.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A Slider with a label and value label. Abstract base class for VUISlider and HUISlider 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | import flash.events.Event; 33 | 34 | [Event(name="change", type="flash.events.Event")] 35 | public class UISlider extends Component 36 | { 37 | protected var _label:Label; 38 | protected var _valueLabel:Label; 39 | protected var _slider:Slider; 40 | protected var _precision:int = 1; 41 | protected var _sliderClass:Class; 42 | protected var _labelText:String; 43 | protected var _tick:Number = 1; 44 | 45 | 46 | /** 47 | * Constructor 48 | * @param parent The parent DisplayObjectContainer on which to add this UISlider. 49 | * @param xpos The x position to place this component. 50 | * @param ypos The y position to place this component. 51 | * @param label The initial string to display as this component's label. 52 | * @param defaultHandler The event handling function to handle the default event for this component (change in this case). 53 | */ 54 | public function UISlider(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, label:String = "", defaultHandler:Function = null) 55 | { 56 | _labelText = label; 57 | super(parent, xpos, ypos); 58 | if(defaultHandler != null) 59 | { 60 | addEventListener(Event.CHANGE, defaultHandler); 61 | } 62 | formatValueLabel(); 63 | } 64 | 65 | /** 66 | * Creates and adds the child display objects of this component. 67 | */ 68 | override protected function addChildren():void 69 | { 70 | _label = new Label(this, 0, 0); 71 | _slider = new _sliderClass(this, 0, 0, onSliderChange); 72 | _valueLabel = new Label(this); 73 | } 74 | 75 | /** 76 | * Formats the value of the slider to a string based on the current level of precision. 77 | */ 78 | protected function formatValueLabel():void 79 | { 80 | if(isNaN(_slider.value)) 81 | { 82 | _valueLabel.text = "NaN"; 83 | return; 84 | } 85 | var mult:Number = Math.pow(10, _precision); 86 | var val:String = (Math.round(_slider.value * mult) / mult).toString(); 87 | var parts:Array = val.split("."); 88 | if(parts[1] == null) 89 | { 90 | if(_precision > 0) 91 | { 92 | val += "."; 93 | } 94 | for(var i:uint = 0; i < _precision; i++) 95 | { 96 | val += "0"; 97 | } 98 | } 99 | else if(parts[1].length < _precision) 100 | { 101 | for(i = 0; i < _precision - parts[1].length; i++) 102 | { 103 | val += "0"; 104 | } 105 | } 106 | _valueLabel.text = val; 107 | positionLabel(); 108 | } 109 | 110 | /** 111 | * Positions the label when it has changed. Implemented in child classes. 112 | */ 113 | protected function positionLabel():void 114 | { 115 | 116 | } 117 | 118 | 119 | 120 | 121 | /////////////////////////////////// 122 | // public methods 123 | /////////////////////////////////// 124 | 125 | /** 126 | * Draws the visual ui of this component. 127 | */ 128 | override public function draw():void 129 | { 130 | super.draw(); 131 | _label.text = _labelText; 132 | _label.draw(); 133 | formatValueLabel(); 134 | } 135 | 136 | /** 137 | * Convenience method to set the three main parameters in one shot. 138 | * @param min The minimum value of the slider. 139 | * @param max The maximum value of the slider. 140 | * @param value The value of the slider. 141 | */ 142 | public function setSliderParams(min:Number, max:Number, value:Number):void 143 | { 144 | _slider.setSliderParams(min, max, value); 145 | } 146 | 147 | 148 | 149 | 150 | /////////////////////////////////// 151 | // event handlers 152 | /////////////////////////////////// 153 | 154 | /** 155 | * Handler called when the slider's value changes. 156 | * @param event The Event passed by the slider. 157 | */ 158 | protected function onSliderChange(event:Event):void 159 | { 160 | formatValueLabel(); 161 | dispatchEvent(new Event(Event.CHANGE)); 162 | } 163 | 164 | 165 | 166 | 167 | /////////////////////////////////// 168 | // getter/setters 169 | /////////////////////////////////// 170 | 171 | /** 172 | * Sets / gets the current value of this slider. 173 | */ 174 | public function set value(v:Number):void 175 | { 176 | _slider.value = v; 177 | formatValueLabel(); 178 | } 179 | public function get value():Number 180 | { 181 | return _slider.value; 182 | } 183 | 184 | /** 185 | * Gets / sets the maximum value of this slider. 186 | */ 187 | public function set maximum(m:Number):void 188 | { 189 | _slider.maximum = m; 190 | } 191 | public function get maximum():Number 192 | { 193 | return _slider.maximum; 194 | } 195 | 196 | /** 197 | * Gets / sets the minimum value of this slider. 198 | */ 199 | public function set minimum(m:Number):void 200 | { 201 | _slider.minimum = m; 202 | } 203 | public function get minimum():Number 204 | { 205 | return _slider.minimum; 206 | } 207 | 208 | /** 209 | * Gets / sets the number of decimals to format the value label. Does not affect the actual value of the slider, just the number shown. 210 | */ 211 | public function set labelPrecision(decimals:int):void 212 | { 213 | _precision = decimals; 214 | } 215 | public function get labelPrecision():int 216 | { 217 | return _precision; 218 | } 219 | 220 | /** 221 | * Gets / sets the text shown in this component's label. 222 | */ 223 | public function set label(str:String):void 224 | { 225 | _labelText = str; 226 | // invalidate(); 227 | draw(); 228 | } 229 | public function get label():String 230 | { 231 | return _labelText; 232 | } 233 | 234 | /** 235 | * Gets / sets the tick value of this slider. This round the value to the nearest multiple of this number. 236 | */ 237 | public function set tick(t:Number):void 238 | { 239 | _tick = t; 240 | _slider.tick = _tick; 241 | } 242 | public function get tick():Number 243 | { 244 | return _tick; 245 | } 246 | 247 | 248 | } 249 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/VBox.as: -------------------------------------------------------------------------------- 1 | /** 2 | * VBox.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A layout container for vertically aligning other components. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | 30 | package com.bit101.components 31 | { 32 | import flash.display.DisplayObject; 33 | import flash.display.DisplayObjectContainer; 34 | import flash.events.Event; 35 | 36 | [Event(name="resize", type="flash.events.Event")] 37 | public class VBox extends Component 38 | { 39 | protected var _spacing:Number = 5; 40 | private var _alignment:String = NONE; 41 | 42 | public static const LEFT:String = "left"; 43 | public static const RIGHT:String = "right"; 44 | public static const CENTER:String = "center"; 45 | public static const NONE:String = "none"; 46 | 47 | /** 48 | * Constructor 49 | * @param parent The parent DisplayObjectContainer on which to add this PushButton. 50 | * @param xpos The x position to place this component. 51 | * @param ypos The y position to place this component. 52 | */ 53 | public function VBox(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0) 54 | { 55 | super(parent, xpos, ypos); 56 | } 57 | 58 | /** 59 | * Override of addChild to force layout; 60 | */ 61 | override public function addChild(child:DisplayObject) : DisplayObject 62 | { 63 | super.addChild(child); 64 | child.addEventListener(Event.RESIZE, onResize); 65 | draw(); 66 | return child; 67 | } 68 | 69 | /** 70 | * Override of addChildAt to force layout; 71 | */ 72 | override public function addChildAt(child:DisplayObject, index:int) : DisplayObject 73 | { 74 | super.addChildAt(child, index); 75 | child.addEventListener(Event.RESIZE, onResize); 76 | draw(); 77 | return child; 78 | } 79 | 80 | /** 81 | * Override of removeChild to force layout; 82 | */ 83 | override public function removeChild(child:DisplayObject):DisplayObject 84 | { 85 | super.removeChild(child); 86 | child.removeEventListener(Event.RESIZE, onResize); 87 | draw(); 88 | return child; 89 | } 90 | 91 | /** 92 | * Override of removeChild to force layout; 93 | */ 94 | override public function removeChildAt(index:int):DisplayObject 95 | { 96 | var child:DisplayObject = super.removeChildAt(index); 97 | child.removeEventListener(Event.RESIZE, onResize); 98 | draw(); 99 | return child; 100 | } 101 | 102 | /** 103 | * Internal handler for resize event of any attached component. Will redo the layout based on new size. 104 | */ 105 | protected function onResize(event:Event):void 106 | { 107 | invalidate(); 108 | } 109 | 110 | /** 111 | * Sets element's x positions based on alignment value. 112 | */ 113 | protected function doAlignment():void 114 | { 115 | if(_alignment != NONE) 116 | { 117 | for(var i:int = 0; i < numChildren; i++) 118 | { 119 | var child:DisplayObject = getChildAt(i); 120 | if(_alignment == LEFT) 121 | { 122 | child.x = 0; 123 | } 124 | else if(_alignment == RIGHT) 125 | { 126 | child.x = _width - child.width; 127 | } 128 | else if(_alignment == CENTER) 129 | { 130 | child.x = (_width - child.width) / 2; 131 | } 132 | } 133 | } 134 | } 135 | 136 | /** 137 | * Draws the visual ui of the component, in this case, laying out the sub components. 138 | */ 139 | override public function draw() : void 140 | { 141 | _width = 0; 142 | _height = 0; 143 | var ypos:Number = 0; 144 | for(var i:int = 0; i < numChildren; i++) 145 | { 146 | var child:DisplayObject = getChildAt(i); 147 | child.y = ypos; 148 | ypos += child.height; 149 | ypos += _spacing; 150 | _height += child.height; 151 | _width = Math.max(_width, child.width); 152 | } 153 | 154 | doAlignment(); 155 | _height += _spacing * (numChildren - 1); 156 | } 157 | 158 | /** 159 | * Gets / sets the spacing between each sub component. 160 | */ 161 | public function set spacing(s:Number):void 162 | { 163 | _spacing = s; 164 | invalidate(); 165 | } 166 | public function get spacing():Number 167 | { 168 | return _spacing; 169 | } 170 | 171 | /** 172 | * Gets / sets the horizontal alignment of components in the box. 173 | */ 174 | public function set alignment(value:String):void 175 | { 176 | _alignment = value; 177 | invalidate(); 178 | } 179 | public function get alignment():String 180 | { 181 | return _alignment; 182 | } 183 | 184 | } 185 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/VRangeSlider.as: -------------------------------------------------------------------------------- 1 | /** 2 | * VRangeSlider.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A vertical slider with two handles for selecting a range of values. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | 33 | public class VRangeSlider extends RangeSlider 34 | { 35 | public function VRangeSlider(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, defaultHandler:Function = null) 36 | { 37 | super(VERTICAL, parent, xpos, ypos, defaultHandler); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/VScrollBar.as: -------------------------------------------------------------------------------- 1 | /** 2 | * VScrollBar.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A vertical scroll bar for use in other components. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | 33 | public class VScrollBar extends ScrollBar 34 | { 35 | /** 36 | * Constructor 37 | * @param parent The parent DisplayObjectContainer on which to add this ScrollBar. 38 | * @param xpos The x position to place this component. 39 | * @param ypos The y position to place this component. 40 | * @param defaultHandler The event handling function to handle the default event for this component (change in this case). 41 | */ 42 | public function VScrollBar(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, defaultHandler:Function=null) 43 | { 44 | super(Slider.VERTICAL, parent, xpos, ypos, defaultHandler); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/VSlider.as: -------------------------------------------------------------------------------- 1 | /** 2 | * VSlider.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A Vertical Slider component for choosing values. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | 33 | public class VSlider extends Slider 34 | { 35 | /** 36 | * Constructor 37 | * @param parent The parent DisplayObjectContainer on which to add this Slider. 38 | * @param xpos The x position to place this component. 39 | * @param ypos The y position to place this component. 40 | * @param defaultHandler The event handling function to handle the default event for this component. 41 | */ 42 | public function VSlider(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, defaultHandler:Function = null) 43 | { 44 | super(Slider.VERTICAL, parent, xpos, ypos, defaultHandler); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /dev/FLDev/lib/com/bit101/components/VUISlider.as: -------------------------------------------------------------------------------- 1 | /** 2 | * VUISlider.as 3 | * Keith Peters 4 | * version 0.9.10 5 | * 6 | * A vertical Slider with a label and value label. 7 | * 8 | * Copyright (c) 2011 Keith Peters 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | package com.bit101.components 30 | { 31 | import flash.display.DisplayObjectContainer; 32 | 33 | public class VUISlider extends UISlider 34 | { 35 | 36 | 37 | /** 38 | * Constructor 39 | * @param parent The parent DisplayObjectContainer on which to add this VUISlider. 40 | * @param x The x position to place this component. 41 | * @param y The y position to place this component. 42 | * @param label The string to use as the label for this component. 43 | * @param defaultHandler The event handling function to handle the default event for this component. 44 | */ 45 | public function VUISlider(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, label:String = "", defaultHandler:Function = null) 46 | { 47 | _sliderClass = VSlider; 48 | super(parent, xpos, ypos, label, defaultHandler); 49 | } 50 | 51 | /** 52 | * Initializes this component. 53 | */ 54 | protected override function init():void 55 | { 56 | super.init(); 57 | setSize(20, 146); 58 | } 59 | 60 | 61 | 62 | 63 | /////////////////////////////////// 64 | // public methods 65 | /////////////////////////////////// 66 | 67 | override public function draw():void 68 | { 69 | super.draw(); 70 | _label.x = width / 2 - _label.width / 2; 71 | 72 | _slider.x = width / 2 - _slider.width / 2; 73 | _slider.y = _label.height + 5; 74 | _slider.height = height - _label.height - _valueLabel.height - 10; 75 | 76 | _valueLabel.x = width / 2 - _valueLabel.width / 2; 77 | _valueLabel.y = _slider.y + _slider.height + 5; 78 | } 79 | 80 | override protected function positionLabel():void 81 | { 82 | _valueLabel.x = width / 2 - _valueLabel.width / 2; 83 | } 84 | 85 | 86 | 87 | 88 | /////////////////////////////////// 89 | // event handlers 90 | /////////////////////////////////// 91 | 92 | /////////////////////////////////// 93 | // getter/setters 94 | /////////////////////////////////// 95 | 96 | override public function get width():Number 97 | { 98 | if(_label == null) return _width; 99 | return Math.max(_width, _label.width); 100 | } 101 | 102 | } 103 | } -------------------------------------------------------------------------------- /dev/FLDev/src/CommandTest.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import flash.display.Sprite; 4 | import flash.events.Event; 5 | import flash.events.NetStatusEvent; 6 | import flash.net.NetConnection; 7 | import flash.net.Responder; 8 | 9 | /** 10 | * ... 11 | * @author Sebastian Herrlinger 12 | */ 13 | public class CommandTest extends Sprite 14 | { 15 | private var nc:NetConnection = null; 16 | 17 | public function CommandTest() 18 | { 19 | if (stage) init(); 20 | else addEventListener(Event.ADDED_TO_STAGE, init); 21 | } 22 | 23 | private function init(e:Event = null):void 24 | { 25 | nc = new NetConnection(); 26 | nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus); 27 | nc.connect('rtmfp://192.168.73.129'); 28 | } 29 | 30 | private function netStatus(evt:NetStatusEvent):void 31 | { 32 | var responder:Responder = new Responder(function(response) { 33 | trace(response.what); //-> 'ArcusNode rocks!' 34 | }); 35 | nc.call('sayWhat', responder, { name: 'ArcusNode' }); 36 | } 37 | 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /dev/FLDev/src/Connection.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import flash.net.NetConnection; 4 | 5 | /** 6 | * ... 7 | * @author me 8 | */ 9 | public class Connection extends NetConnection 10 | { 11 | private static var counter:Number = 0; 12 | 13 | public var num:Number = 0; 14 | public var label:String = ''; 15 | 16 | public function Connection() 17 | { 18 | counter++; 19 | num = counter; 20 | label = 'Connection ' + num; 21 | } 22 | 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /dev/FLDev/src/Main.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import com.bit101.components.HBox; 4 | import com.bit101.components.InputText; 5 | import com.bit101.components.Label; 6 | import com.bit101.components.List; 7 | import com.bit101.components.ListItem; 8 | import com.bit101.components.Panel; 9 | import com.bit101.components.PushButton; 10 | import com.bit101.components.ScrollPane; 11 | import com.bit101.components.Style; 12 | import com.bit101.components.TextArea; 13 | import com.bit101.components.VBox; 14 | import com.bit101.components.Window; 15 | import flash.display.Sprite; 16 | import flash.display.StageAlign; 17 | import flash.display.StageScaleMode; 18 | import flash.events.Event; 19 | import flash.events.MouseEvent; 20 | import flash.events.NetStatusEvent; 21 | import flash.net.NetConnection; 22 | 23 | /** 24 | * ... 25 | * @author me 26 | */ 27 | public class Main extends Sprite 28 | { 29 | //Connections 30 | private var connectionWindow:Window; 31 | private var serverURI:InputText; 32 | private var connectionArgs:InputText; 33 | private var connectionsList:List; 34 | private var connections:Array = new Array(); 35 | 36 | //Menu 37 | private var leftMenu:VBox; 38 | private var bottomMenu:HBox; 39 | private var output:TextArea; 40 | 41 | //left menu buttons 42 | private var showHideConnections:PushButton; 43 | private var showHideMethod:PushButton; 44 | 45 | //bottom menu buttons 46 | private var clearOutputButton:PushButton; 47 | 48 | public function Main():void 49 | { 50 | if (stage) init(); 51 | else addEventListener(Event.ADDED_TO_STAGE, init); 52 | } 53 | 54 | private function init(e:Event = null):void 55 | { 56 | removeEventListener(Event.ADDED_TO_STAGE, init); 57 | stage.scaleMode = StageScaleMode.NO_SCALE; 58 | stage.align = StageAlign.TOP_LEFT; 59 | 60 | stage.addEventListener(Event.RESIZE, resize); 61 | 62 | //Init components 63 | Style.LABEL_TEXT = 0x086A87; 64 | 65 | //Button list on the left 66 | leftMenu = new VBox(this, 10, 10); 67 | bottomMenu = new HBox(this, 0, stage.stageHeight - 20); 68 | clearOutputButton = new PushButton(bottomMenu, 0, 0, 'clear output'); 69 | clearOutputButton.addEventListener(MouseEvent.CLICK, function():void { 70 | output.text = ''; 71 | }); 72 | 73 | //Connections 74 | connectionWindow = new Window(this, 120, 10, 'Connections'); 75 | connectionWindow.color = 0xffffff; 76 | connectionWindow.setSize(250, 400); 77 | var uriLabel:Label = new Label(connectionWindow, 5, 5, 'Server Address'); 78 | serverURI = new InputText(connectionWindow, 95, 5, 'rtmfp://'); 79 | serverURI.width = 150 80 | var argsLabel:Label = new Label(connectionWindow, 5, 25, 'Arguments'); 81 | connectionArgs = new InputText(connectionWindow, 95, 25, ''); 82 | connectionArgs.width = 150 83 | var connect:PushButton = new PushButton(connectionWindow, 5, 50, 'Create New Connection'); 84 | connect.width = 240; 85 | connect.addEventListener(MouseEvent.CLICK, addConnection); 86 | connectionsList = new List(connectionWindow, 5, 75); 87 | connectionsList.setSize(240, 275); 88 | var closeConnectionButton:PushButton = new PushButton(connectionWindow, 5, 355, 'Close selected Connection'); 89 | closeConnectionButton.width = 240; 90 | closeConnectionButton.addEventListener(MouseEvent.CLICK, function():void 91 | { 92 | if(connectionsList.selectedItem != null){ 93 | writeOut('Closing connection ' + connectionsList.selectedItem.num); 94 | connectionsList.selectedItem.close(); 95 | } 96 | }); 97 | 98 | showHideConnections = new PushButton(leftMenu, 0, 0, 'Connections'); 99 | showHideConnections.toggle = true; 100 | showHideConnections.selected = true; 101 | showHideConnections.addEventListener(MouseEvent.CLICK, function():void { 102 | connectionWindow.visible = !connectionWindow.visible; 103 | }); 104 | 105 | output = new TextArea(this, 0, stage.stageHeight - 200); 106 | output.height = 200; 107 | 108 | showHideMethod = new PushButton(leftMenu, 0, 0, 'Method'); 109 | showHideMethod.toggle = true; 110 | showHideMethod.enabled = false; 111 | 112 | resize(null); 113 | } 114 | 115 | private function addConnection(evt:MouseEvent):void 116 | { 117 | var nc:Connection = new Connection(); 118 | nc.addEventListener(NetStatusEvent.NET_STATUS, connectionStatusListener); 119 | 120 | var args:Array = connectionArgs.text.split(','); 121 | 122 | nc.connect.apply(this, [serverURI.text].concat(args)); 123 | nc.label = nc.num + ' to ' + serverURI.text; 124 | connections.push(nc); 125 | connectionsList.addItem(nc); 126 | }; 127 | 128 | private function connectionStatusListener(evt:NetStatusEvent):void 129 | { 130 | writeOut('Connection ' + evt.target.num + ' status: ' + evt.info.code); 131 | if (evt.info.code == 'NetConnection.Connect.Closed' || evt.info.code == 'NetConnection.Connect.Failed') 132 | { 133 | connectionsList.removeItemAt(connectionsList.items.indexOf(evt.target)); 134 | } 135 | } 136 | 137 | private function writeOut(str:String):void { 138 | output.text = str + '\n' + output.text; 139 | } 140 | 141 | private function resize(evt:Event):void 142 | { 143 | output.width = stage.stageWidth; 144 | output.y = stage.stageHeight - 220; 145 | bottomMenu.y = stage.stageHeight - 20; 146 | } 147 | 148 | } 149 | 150 | } -------------------------------------------------------------------------------- /dev/clienttest.js: -------------------------------------------------------------------------------- 1 | var dgram = require('dgram'); 2 | var RTMFP = require('../lib/rtmfp.js'); 3 | var NetConnection = require('../lib/net_connection'); 4 | var Arcus = require('../lib/arcus_node'); 5 | var Packet = require('../lib/packet.js'); 6 | //var cirrus = { address: '50.57.90.201', port: '1935' }; 7 | //var cirrus = { address: '50.56.33.168', port: '10001', url: 'p2p.rtmfp.net', app: '9f562071a62ee15bc91c8eec-4b461ed21d0f'}; 8 | //var cirrus = { address: '0.0.0.0', port: '19350', url: '0.0.0.0', app: 'vod/test' }; 9 | var cirrus = { address: '192.168.73.129', port: '1935', url: 'some.awesome-service.org', app: '23502305u2a35u9jfih209th02h3g0000000000012' }; 10 | var arcus = new Arcus(); 11 | var nc = new NetConnection(arcus, 33554432); 12 | 13 | var rtmfp = new RTMFP(); 14 | var cpkt = null; 15 | 16 | _socket = dgram.createSocket('udp4', function(buffer, remoteInfo){ 17 | 18 | var pkt = new Packet(buffer, buffer.length); 19 | 20 | var id = rtmfp.decodePacket(pkt); 21 | 22 | console.log(id); 23 | 24 | if(id != 0 && nc.state != NetConnection.HANDSHAKE){ 25 | rtmfp.decryptPacket(pkt, nc.__p.decryptKey); 26 | } else { 27 | rtmfp.decryptPacket(pkt, RTMFP.SYMETRIC_KEY); 28 | } 29 | 30 | console.log('RECEIVED: ', pkt.toString()); 31 | 32 | var msgs = rtmfp.readPacket(pkt); 33 | for(k in msgs){ 34 | var msg = msgs[k]; 35 | console.log('GOT MESSAGE ', msg.type); 36 | // FORWARD 37 | if(msg.type == RTMFP.FORWARD_REQUEST){ 38 | for(k in msg.addresses){ 39 | console.log('FORWARD ADDRESS: ', msg.addresses[k]); 40 | } 41 | } 42 | else if(msg.type == RTMFP.HANDSHAKE_RESPONSE){ 43 | console.log('HANDSHAKE_RESPONSE: ', msg); 44 | // SEND KEY_REQUEST 45 | msg.type = RTMFP.KEY_REQUEST; 46 | 47 | msg.connectionId = nc.id; 48 | msg.publicKey = nc.publicKey; 49 | msg.certificate = nc.certificate; 50 | console.log('client pub key: ', msg.publicKey.length); 51 | var pkt = new Packet(new Buffer(200), 0).clear(); 52 | 53 | rtmfp.writePacket(pkt, msg); 54 | console.log('KEY_REQUEST PACKET: ', pkt.toString()); 55 | 56 | rtmfp.encryptPacket(pkt, RTMFP.SYMETRIC_KEY); 57 | rtmfp.encodePacket(pkt, 0); 58 | 59 | send(pkt, cirrus); 60 | } 61 | else if(msg.type == RTMFP.KEY_RESPONSE){ 62 | console.log('KEY RESPONSE', msg, 'pub key length: ', msg.publicKey.length); 63 | 64 | nc.computeSharedSecret(msg.publicKey); 65 | 66 | var serverNonce = new Packet(new Buffer(msg.signature.length + msg.publicKey.length)); 67 | serverNonce.writeBuffer(msg.signature); 68 | serverNonce.writeBuffer(msg.publicKey); 69 | 70 | //Working key generation 71 | nc.computeAsymetricKeys(serverNonce.buffer(), rtmfp.createClientNonce(nc.certificate)); 72 | 73 | nc.__p.state = NetConnection.CONNECTING; 74 | 75 | msg.type = RTMFP.NET_CONNECTION_REQUEST; 76 | msg.url = 'rtmfp://' + cirrus.url + '/' + cirrus.app; 77 | msg.app = cirrus.app; 78 | msg.echoTime = msg.sentTime; 79 | 80 | cpkt = new Packet(255).clear(); 81 | rtmfp.writePacket(cpkt, msg); 82 | console.log('NET CONNECTION REQUEST PACKET: ', cpkt.toString()); 83 | 84 | nc.__p.clientConnectionId = msg.connectionId; 85 | 86 | rtmfp.encryptPacket(cpkt, nc.__p.encryptKey); 87 | rtmfp.encodePacket(cpkt, msg.connectionId); 88 | 89 | send(cpkt, cirrus); 90 | 91 | } 92 | else if(msg.type == RTMFP.NC_FAILED_REQUEST){ 93 | var pkt = new Packet(32).clear(); 94 | rtmfp.writePacket(pkt, {type: RTMFP.NC_FAILED_RESPONSE, flow: 2, stage: 2, echoTime: msg.sentTime}); 95 | console.log('RECEIVED 0x5e, answering...', pkt.toString()); 96 | 97 | rtmfp.encryptPacket(pkt, nc.__p.encryptKey); 98 | rtmfp.encodePacket(pkt, nc.__p.clientConnectionId); 99 | 100 | send(pkt, cirrus); 101 | 102 | } 103 | } 104 | 105 | }); 106 | _socket.bind(57032); 107 | 108 | var send = function(packet, endpoint) { 109 | _socket.send(packet.buffer(), 0, packet.size(), endpoint.port, endpoint.address, function (err, bytes) { 110 | if (err) { 111 | //TODO: Handle error and recover 112 | throw err; 113 | } 114 | console.log('Wrote ' + bytes + ' bytes to socket.'); 115 | }); 116 | }; 117 | 118 | 119 | // SEND HANDSHAKE 120 | var message = {}; 121 | message.type = RTMFP.HANDSHAKE_REQUEST; 122 | message.url = 'rtmfp://' + cirrus.url + '/' + cirrus.app; 123 | message.tag = Packet.randomBytes(16, new Buffer(16), 0); 124 | 125 | var pkt = new Packet(new Buffer(64), 0).clear(); 126 | 127 | //Testing faulty handshake packet 128 | var buf = new Buffer('0000000000000B6E4C30002A19180A72746D66703A2F2F78756761722E6E65743A313938352F1FE2AE6A5D9D24BC3C965EB985F4EDDD', 'hex'); 129 | var pkt = new Packet(buf, buf.length); 130 | 131 | //rtmfp.writePacket(pkt, message); 132 | console.log('URL LENGTH: ' + message.url.length); 133 | console.log('HANDSHAKE PACKET: ', pkt.toString()); 134 | 135 | rtmfp.encryptPacket(pkt, RTMFP.SYMETRIC_KEY); 136 | rtmfp.encodePacket(pkt, 0); 137 | 138 | send(pkt, cirrus); 139 | 140 | setTimeout(function(){ 141 | //var buf = new Buffer('0000000000000D42513FE810003B8003010103004743020A0200012D10473A303130313031306331303065366336353734373336323663363936653731356636373732366637353730', 'hex'); 142 | var buf = new Buffer('0000000000004D40547DEC10000403030201'); 143 | var pkt = new Packet(buf, buf.length); 144 | rtmfp.encryptPacket(pkt, nc.__p.encryptKey); 145 | rtmfp.encodePacket(pkt, nc.__p.clientConnectionId); 146 | send(pkt, cirrus); 147 | }, 2000); -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | #### using ArcusNode 3 | 4 | ## auth.js 5 | Here you find an example for a possible user authentication, 6 | failing the connection if the username and password are not given, 7 | rejecting the connection if the given credentials do not match 8 | and finally accepting the connection if the credentials are ok. 9 | 10 | To test this example, use the FLDev Flash project from the repository. 11 | With it you can specify comma separated arguments for a NetConnection. 12 | Run the auth example with 13 |
14 | $> node example/auth.js
15 | 
16 | and then try connecting to the ip you are running the example on. 17 | You should the a message like _Connection 4 status: NetConnection.Connect.Failed_ in the bottom console. 18 | Now try giving the connection the arguments _"name,password"_ and you should be successfully connected. 19 | Try specifiying wrong credentials and you should see a _NetConnection.Connect.Rejected_ message. -------------------------------------------------------------------------------- /examples/auth.js: -------------------------------------------------------------------------------- 1 | var ArcusNode = require('../lib/arcus_node.js'); 2 | 3 | //Create a new ArcusNode instance 4 | var arc = new ArcusNode(null); 5 | 6 | arc.on('connect', function(nc, options, username, password){ 7 | // Let the connection wait for auth, 8 | // if we need to authenticate the connection with data elsewhere 9 | nc.wait(); 10 | 11 | var users = { 12 | foo: 'bar', 13 | name: 'password' 14 | } 15 | 16 | //Make sure the username and password are given 17 | if(typeof(username) == 'undefined' || typeof(password) == 'undefined'){ 18 | //If not, let the connection fail -> NetConnection.Connect.Failed 19 | nc.fail(); 20 | return; 21 | } 22 | 23 | //Check the credentials 24 | if(users[username] === password){ 25 | //Accept the connection if credentials are correct -> NetConnection.Connect.Success 26 | //The specified argument is a description which can be accessed in the client at NetStatusEvent|info.description 27 | nc.accept('Authentication successfull.'); 28 | } else { 29 | //Reject the connection with the given message -> NetConnection.Connect.Rejected 30 | nc.reject('Wrong credentials'); 31 | } 32 | 33 | }); 34 | 35 | //Start the server 36 | arc.run(); -------------------------------------------------------------------------------- /examples/callbacks.js: -------------------------------------------------------------------------------- 1 | var ArcusNode = require('../lib/arcus_node.js'); 2 | 3 | //Create a new ArcusNode instance 4 | var arc = new ArcusNode(null); 5 | 6 | //Listen to events 7 | arc.on('handshake', function(){ 8 | console.log('EVENT handshake works.'); 9 | }); 10 | 11 | arc.on('connect', function(){ 12 | console.log('EVENT connect works.'); 13 | }); 14 | 15 | arc.on('address', function(){ 16 | console.log('EVENT address works.'); 17 | }); 18 | 19 | arc.on('command', function(){ 20 | console.log('EVENT commands works.'); 21 | }); 22 | 23 | arc.on('disconnect', function(){ 24 | console.log('EVENT disconnect works.'); 25 | }); 26 | 27 | //Add a command and handle it 28 | arc.command('sayWhat', function(){ 29 | console.log('Got command sayWhat: ', Array.prototype.slice.call(arguments, 1)); 30 | return { what: arguments[1].name + ' rocks!' }; 31 | }); 32 | 33 | //Start the server 34 | arc.run(); -------------------------------------------------------------------------------- /examples/close.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Close a NetConnection 3 | */ 4 | var ArcusNode = require('../lib/arcus_node.js'); 5 | 6 | //Create a new ArcusNode instance 7 | var arc = ArcusNode.createServer(); 8 | 9 | arc.on('connect', function(nc, options, username, password){ 10 | nc.on('close', function(){ 11 | console.log('Connection ' + nc.id + ' was closed.'); 12 | }); 13 | 14 | // Close the connection after 30 seconds 15 | setTimeout(function() { 16 | nc.close(function(success){ 17 | if(success){ 18 | console.log('Connection close attempt successful.'); 19 | } else { 20 | console.log('ERROR: Connection could not be closed.'); 21 | } 22 | }); 23 | }, 3000); 24 | }); 25 | 26 | //Start the server 27 | arc.run(); -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRTMFP/ArcusNode/4320e6bce84127c955f5c3dd90172bbc657daf72/lib/.gitignore -------------------------------------------------------------------------------- /lib/amf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * AMF 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | var AMF0 = require('./amf0.js'); 21 | var AMF3 = require('./amf3.js'); 22 | 23 | var AMF0TypesArr = []; 24 | for(k in AMF0.TYPE){ 25 | AMF0TypesArr.push(AMF0.TYPE[k]); 26 | } 27 | 28 | /** 29 | * Reads AMF0 Values into an array until no AMF type marker is found anymore 30 | */ 31 | exports.readAMF0 = function(pkt) { 32 | var data = []; 33 | var value = null; 34 | while(pkt.available() > 0 && AMF0TypesArr.indexOf(pkt.peek()) != -1) { 35 | value = AMF0.readValue(pkt); 36 | if(value != null){ 37 | data.push(value); 38 | } 39 | } 40 | return data; 41 | } -------------------------------------------------------------------------------- /lib/amf0.js: -------------------------------------------------------------------------------- 1 | /** 2 | * AMF0 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | var AMF3 = require('./amf3.js'); 21 | 22 | //AMF0 Format Types 23 | var AMF0 = { 24 | 'NUMBER_MARKER': 0x00, 25 | 'BOOLEAN_MARKER': 0x01, 26 | 'STRING_MARKER': 0x02, 27 | 'BEGIN_OBJECT_MARKER': 0x03, 28 | 'NULL_MARKER': 0x05, 29 | 'UNDEFINED_MARKER': 0x06, 30 | 'ECMA_ARRAY_MARKER': 0x08, 31 | 'END_OBJECT_MARKER': 0x09, 32 | 'STRICT_ARRAY_MARKER': 0x0A, 33 | 'LONG_STRING_MARKER': 0x0C, 34 | 'AVMPLUS_OBJECT_MARKER': 0x11 35 | }; 36 | exports.TYPE = AMF0; 37 | 38 | // 39 | // READING 40 | // 41 | 42 | /** 43 | * Reads an AMF0 value from the current position in the packet 44 | */ 45 | exports.readValue = function(pkt){ 46 | switch(pkt.peek()) { 47 | case AMF0.NUMBER_MARKER: 48 | return exports.readNumber(pkt); 49 | break; 50 | case AMF0.BOOLEAN_MARKER: 51 | return exports.readBool(pkt); 52 | break; 53 | case AMF0.STRING_MARKER: 54 | return exports.readString(pkt); 55 | break; 56 | case AMF0.BEGIN_OBJECT_MARKER: 57 | return exports.readObject(pkt); 58 | break; 59 | case AMF0.UNDEFINED_MARKER: 60 | pkt.skip(1); 61 | return undefined; 62 | break; 63 | case AMF0.NULL_MARKER: 64 | pkt.skip(1); 65 | return null; 66 | break; 67 | case AMF0.AVMPLUS_OBJECT_MARKER: 68 | pkt.skip(1); 69 | return AMF3.readValue(pkt); 70 | break; 71 | default: 72 | throw new Error('Unhandled AMF0 value: ' + pkt.peek()); 73 | } 74 | }; 75 | 76 | /** 77 | * Reads an AMF0 encoded string from the current position in the packet 78 | */ 79 | exports.readString = function(pkt){ 80 | if(pkt.readInt8() != AMF0.STRING_MARKER){ 81 | throw new Error('Not an AMF0 string marker.'); 82 | } 83 | return pkt.readBytes(pkt.readInt16()).toString('ascii'); 84 | }; 85 | 86 | /** 87 | * Reads an AMF0 encoded object from the current position in the packet 88 | */ 89 | exports.readObject = function(pkt){ 90 | if(pkt.readInt8() != AMF0.BEGIN_OBJECT_MARKER){ 91 | throw new Error('Not an AMF0 object marker.'); 92 | } 93 | var object = {}; 94 | while(pkt.peek() != AMF0.END_OBJECT_MARKER) { 95 | var key = pkt.readBytes(pkt.readInt16()).toString('ascii'); 96 | if(key != '') { 97 | object[key] = exports.readValue(pkt); 98 | } 99 | } 100 | if(pkt.readInt8() != AMF0.END_OBJECT_MARKER){ 101 | throw new Error('No AMF0 object close marker found.'); 102 | } 103 | return object; 104 | }; 105 | 106 | /** 107 | * Reads an AMF0 encoded boolean value from the current position in the packet 108 | */ 109 | exports.readBool = function(pkt){ 110 | if(pkt.readInt8() != AMF0.BOOLEAN_MARKER){ 111 | throw new Error('Not an AMF0 boolean marker.'); 112 | } 113 | return (pkt.readInt8() == 0x00) ? false : true; 114 | }; 115 | 116 | /** 117 | * Reads an AMF0 encoded double value from the current position in the packet 118 | */ 119 | exports.readNumber = function(pkt){ 120 | if(pkt.readInt8() != AMF0.NUMBER_MARKER){ 121 | throw new Error('Not an AMF0 number marker.'); 122 | } 123 | return pkt.readDouble(); 124 | }; 125 | 126 | // 127 | // WRITING 128 | // 129 | 130 | /** 131 | * Writes an AMF0 value to the current position in the packet 132 | */ 133 | exports.writeValue = function(pkt, value){ 134 | switch(typeof value) { 135 | case 'string': 136 | exports.writeString(pkt, value); 137 | break; 138 | case 'number': 139 | exports.writeNumber(pkt, value); 140 | break; 141 | case 'boolean': 142 | exports.writeBoolean(pkt, value); 143 | break; 144 | case 'object': 145 | if(Array.isArray(value)){ 146 | throw new Error('AMF0 array writing not implemented'); 147 | } else { 148 | exports.writeObject(pkt, value); 149 | } 150 | break; 151 | case 'undefined': 152 | exports.writeUndefined(pkt); 153 | break; 154 | default: 155 | throw new Error('Unhandled AMF0 value to write: ' + value + '(' + typeof(value) + ')'); 156 | } 157 | return pkt; 158 | }; 159 | 160 | /** 161 | * Writes the AMF0 undefined marker to the packet 162 | */ 163 | exports.writeUndefined = function(pkt, value){ 164 | pkt.writeInt8(AMF0.UNDEFINED_MARKER); 165 | return pkt; 166 | }; 167 | 168 | /** 169 | * Writes an AMF0 encoded boolean value to the current position in the packet 170 | */ 171 | exports.writeBoolean = function(pkt, value){ 172 | pkt.writeInt8(AMF0.BOOLEAN_MARKER); 173 | pkt.writeInt8((value) ? 0xFF : 0x00); 174 | return pkt; 175 | }; 176 | 177 | /** 178 | * Writes an AMF0 encoded double value to the current position in the packet 179 | */ 180 | exports.writeNumber = function(pkt, number){ 181 | pkt.writeInt8(AMF0.NUMBER_MARKER); 182 | pkt.writeDouble(number); 183 | return pkt; 184 | }; 185 | 186 | /** 187 | * Writes an AMF0 encoded string to the current position in the packet 188 | */ 189 | exports.writeString = function(pkt, str){ 190 | pkt.writeInt8(AMF0.STRING_MARKER); 191 | pkt.writeInt16(str.length); 192 | pkt.writeBuffer(new Buffer(str)); 193 | return pkt; 194 | }; 195 | 196 | /** 197 | * Writes an AMF0 encoded object to the current position in the packet 198 | */ 199 | exports.writeObject = function(pkt, object){ 200 | pkt.writeInt8(AMF0.BEGIN_OBJECT_MARKER); 201 | for(k in object){ 202 | //write key 203 | if(typeof k !== 'string'){ 204 | throw new Error('AMF0 object key can only be a string.'); 205 | } 206 | pkt.writeInt16(k.length); 207 | pkt.writeBuffer(new Buffer(k)); 208 | 209 | //write value 210 | exports.writeValue(pkt, object[k]); 211 | } 212 | pkt.writeInt16(0x00); 213 | pkt.writeInt8(AMF0.END_OBJECT_MARKER); 214 | return pkt; 215 | }; 216 | 217 | /** 218 | * Writes AMF0 NULL marker to the current position in the packet 219 | */ 220 | exports.writeNull = function(pkt){ 221 | pkt.writeInt8(AMF0.NULL_MARKER); 222 | return pkt; 223 | }; -------------------------------------------------------------------------------- /lib/amf3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * AMF3 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | //AMF3 Format Types 21 | var AMF3 = { 22 | 'UNDEFINED_MARKER': 0x00, 23 | 'NULL_MARKER': 0x01, 24 | 'FALSE_MARKER': 0x02, 25 | 'TRUE_MARKER': 0x03, 26 | 'INTEGER_MARKER': 0x04, 27 | 'DOUBLE_MARKER': 0x05, 28 | 'STRING_MARKER': 0x06, 29 | 'XML_DOC_MARKER': 0x07, 30 | 'DATE_MARKER': 0x08, 31 | 'ARRAY_MARKER': 0x09, 32 | 'OBJECT_MARKER': 0x0A, 33 | 'XML_MARKER': 0x0B, 34 | 'BYTE_ARRAY_MARKER': 0x0C 35 | }; 36 | exports.TYPE = AMF3; 37 | 38 | /** 39 | * Reads an AMF3 value from the current position in the packet 40 | */ 41 | exports.readValue = function(pkt){ 42 | switch(pkt.peek()) { 43 | case AMF3.INTEGER_MARKER: 44 | return exports.readInteger(pkt); 45 | break; 46 | case AMF3.DOUBLE_MARKER: 47 | return exports.readDouble(pkt); 48 | break; 49 | case AMF3.FALSE_MARKER: 50 | return false; 51 | break; 52 | case AMF3.TRUE_MARKER: 53 | return true; 54 | break; 55 | case AMF3.STRING_MARKER: 56 | return exports.readString(pkt); 57 | break; 58 | case AMF3.OBJECT_MARKER: 59 | return exports.readObject(pkt); 60 | break; 61 | case AMF3.NULL_MARKER: 62 | case AMF3.UNDEFINED_MARKER: 63 | pkt.skip(1); 64 | return null; 65 | break; 66 | default: 67 | throw new Error('Unhandled AMF3 value: ' + pkt.peek()); 68 | } 69 | }; 70 | 71 | /** 72 | * Reads an AMF3 encoded string from the current position in the packet 73 | */ 74 | exports.readString = function(pkt){ 75 | if(pkt.readInt8() != AMF3.STRING_MARKER){ 76 | throw new Error('Not an AMF3 string marker.'); 77 | } 78 | return _readString(pkt); 79 | }; 80 | 81 | var _readString = function(pkt) { 82 | var tmp = pkt.readU29(); 83 | 84 | if ((tmp & 0x01) == 1) { 85 | //value 86 | return pkt.readBytes((tmp >> 1)).toString('utf8'); 87 | } else { 88 | //reference 89 | throw new Error("String reference not implemented."); 90 | } 91 | }; 92 | 93 | /** 94 | * Reads an AMF3 encoded integer from the current position in the packet 95 | */ 96 | exports.readInteger = function(pkt){ 97 | throw new Error('Not implemented.'); 98 | }; 99 | 100 | /** 101 | * Reads an AMF3 encoded double from the current position in the packet 102 | */ 103 | exports.readDouble = function(pkt){ 104 | throw new Error('Not implemented.'); 105 | }; 106 | 107 | /** 108 | * Reads an AMF3 encoded object from the current position in the packet 109 | */ 110 | exports.readObject = function(pkt){ 111 | if(pkt.readInt8() != AMF3.OBJECT_MARKER){ 112 | throw new Error('Not an AMF3 object marker.'); 113 | } 114 | 115 | var object = {}, headU29 = pkt.readU29(); 116 | 117 | if ((headU29 & 0x01) == 0) { 118 | //Object reference 119 | var objectRefIdx = headU29 >> 1; 120 | 121 | throw new Error("Not implemented."); 122 | 123 | } else if ((headU29 & 0x02) == 0) { 124 | //Traits reference 125 | var traitsRefIdx = headU29 >> 2; 126 | 127 | throw new Error("Not implemented."); 128 | 129 | } else if ((headU29 & 0x07) == 0x07) { 130 | //Traits externalizable 131 | 132 | throw new Error("Not implemented."); 133 | 134 | } else if((headU29 & 0x08) != 0) { 135 | //Dynamic 136 | pkt.skip(1); 137 | 138 | while(pkt.peek() != AMF3.NULL_MARKER) { 139 | var key = _readString(pkt); 140 | if(key != '') { 141 | object[key] = exports.readValue(pkt); 142 | } 143 | } 144 | if(pkt.readInt8() != AMF3.NULL_MARKER){ 145 | throw new Error('No AMF3 object close marker found.'); 146 | } 147 | 148 | } else { 149 | return null; 150 | } 151 | 152 | return object; 153 | }; -------------------------------------------------------------------------------- /lib/helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper - utilities for ArcusNode (to not conflict with nodes util module) 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | /** 21 | * Formats a number with lapsed seconds to a string 22 | * 23 | * @param {Integer} seconds The time lapsed in seconds to be formated 24 | * @return {String} "[%i years][%i months][%i days][%i hours][%i minutes] %i seconds" 25 | */ 26 | var formatLapsed = module.exports.formatLapsed = function(seconds){ 27 | var str = ''; 28 | var interval = Math.floor(seconds / 31536000); 29 | if (interval >= 1) { 30 | str += interval + " years "; 31 | seconds = seconds % 31536000; 32 | } 33 | interval = Math.floor(seconds / 2592000); 34 | if (interval >= 1) { 35 | str += interval + " months "; 36 | seconds = seconds % 2592000; 37 | } 38 | interval = Math.floor(seconds / 86400); 39 | if (interval >= 1) { 40 | str += interval + " days "; 41 | seconds = seconds % 86400; 42 | } 43 | interval = Math.floor(seconds / 3600); 44 | if (interval >= 1) { 45 | str += interval + " hours "; 46 | seconds = seconds % 3600; 47 | } 48 | interval = Math.floor(seconds / 60); 49 | if (interval >= 1) { 50 | str += interval + " minutes "; 51 | seconds = seconds % 60; 52 | } 53 | return str += Math.floor(seconds) + " seconds"; 54 | }; -------------------------------------------------------------------------------- /lib/logger.js: -------------------------------------------------------------------------------- 1 | // name: logger.js 2 | // version: 0.1.1 3 | // Original: http://github.com/quirkey/node-logger 4 | // Fork: http://github.com/kommander/node-logger 5 | /* 6 | 7 | Copyright (c) 2010 Aaron Quint 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | var path = require('path'), 33 | util = require('util'), 34 | fs = require('fs'); 35 | 36 | /** 37 | * Create a new instance of Logger, logging to the stream at logStream 38 | * if logStream is a string it is asumed to be a file path 39 | * if logStream is an object, it is asumed to have a write method which will be used 40 | * if logStream is null, log to STDOUT. 41 | */ 42 | var Logger = function(logStream, level) { 43 | this.setLevel((level) ? level : 'debug'); 44 | 45 | // if a path is given, try to write to it 46 | if (typeof logStream === 'string') { 47 | // Write to a file 48 | logStream = path.normalize(logStream); 49 | this.stream = fs.createWriteStream(logStream, {flags: 'a', encoding: 'utf8', mode: 0666}); 50 | this.stream.on('error', function(e){ 51 | throw new Error('Log file stream not writeable: ' + util.inspect(logStream)); 52 | }); 53 | 54 | } else if(logStream != null && typeof logStream == 'object'){ 55 | // Try to use provided object with write method 56 | 57 | // Check for write method 58 | if(typeof logStream.write !== 'function'){ 59 | throw new Error('Log stream needs write(text) method.'); 60 | } 61 | 62 | this.stream = logStream; 63 | 64 | } else { 65 | // default write is STDOUT 66 | this.stream = {}; 67 | this.stream.write = util.print; 68 | } 69 | 70 | // Start log 71 | this.debug("start log"); 72 | }; 73 | 74 | Logger.levels = ['fatal', 'error', 'warn', 'info', 'debug']; 75 | 76 | /** 77 | * The default log formatting function. The default format looks something like: 78 | * error [Sat Jun 12 2010 01:12:05 GMT-0400 (EDT)] message 79 | * 80 | * @param {String} level 81 | * @param {Date} date 82 | * @param {String} message 83 | * @return {String} 84 | */ 85 | Logger.prototype.format = function(level, date, message) { 86 | return [level, ' [', date, '] ', message].join(''); 87 | }; 88 | 89 | /** 90 | * Set the maximum log level. The default level is "info". 91 | */ 92 | Logger.prototype.setLevel = function(newLevel) { 93 | var index = Logger.levels.indexOf(newLevel); 94 | this.levelIndex = (index != -1) ? index : false; 95 | setupLevels.call(this); 96 | return this.levelIndex; 97 | }; 98 | 99 | /** 100 | * The base logging method. If the first argument is one of the levels, it logs 101 | * to that level, otherwise, logs to the default level. Can take n arguments 102 | * and joins them by ' '. If the argument is not a string, it runs util.inspect() 103 | * to print a string representation of the object. 104 | */ 105 | Logger.prototype.log = function() { 106 | var args = Array.prototype.slice.call(arguments), 107 | logIndex = Logger.levels.indexOf(args[0]), 108 | message = ''; 109 | 110 | // if you're just default logging 111 | if (logIndex === -1) { 112 | logIndex = this.levelIndex; 113 | } else { 114 | // the first arguement actually was the log level 115 | args.shift(); 116 | } 117 | if (logIndex <= this.levelIndex) { 118 | // join the arguments into a loggable string 119 | args.forEach(function(arg) { 120 | if (typeof arg === 'string') { 121 | message += ' ' + arg; 122 | } else { 123 | message += ' ' + util.inspect(arg, false, null); 124 | } 125 | }); 126 | message = this.format(Logger.levels[logIndex], new Date(), message); 127 | this.stream.write(message + "\n"); 128 | return message; 129 | } 130 | return false; 131 | }; 132 | 133 | /** 134 | * Creates prototype methods for used log levels e.g. logger.debug() 135 | */ 136 | var setupLevels = function() { 137 | for(k in Logger.levels) { 138 | if(k <= this.levelIndex) { 139 | Logger.prototype[Logger.levels[k]] = (function(level){ 140 | return function() { 141 | var args = Array.prototype.slice.call(arguments); 142 | args.unshift(level); 143 | return this.log.apply(this, args); 144 | }; 145 | })(Logger.levels[k]); 146 | } else { 147 | Logger.prototype[Logger.levels[k]] = function(){ return false; }; 148 | } 149 | } 150 | }; 151 | 152 | //Export 153 | exports.Logger = Logger; 154 | exports.createLogger = function(logFilePath, level) { 155 | return new Logger(logFilePath, level); 156 | }; 157 | -------------------------------------------------------------------------------- /lib/map.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Every good System has its own Map implementation :D 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | /** 21 | * A very basic Map implementation 22 | */ 23 | var Map = module.exports = function(){ 24 | this.wipe(); 25 | }; 26 | 27 | /** 28 | * Wipe out the map 29 | */ 30 | Map.prototype.wipe = function() { 31 | this.map = {}; 32 | this.keys = []; 33 | this._length = 0; 34 | }; 35 | 36 | /** 37 | * Add a key value pair 38 | * 39 | * @param {mixed} key 40 | * @param {mixed} value 41 | * @return {Map} for chaining 42 | */ 43 | Map.prototype.add = function(key, value){ 44 | if(!this.has(key)){ 45 | this._length++; 46 | this.keys.push(key); 47 | } 48 | this.map[key] = value; 49 | return this; 50 | }; 51 | 52 | /** 53 | * Remove a Map entry with the given key 54 | * 55 | * @param {mixed} key 56 | * @return {Boolean} true if entry was removed, false otherwise 57 | */ 58 | Map.prototype.remove = function(key){ 59 | if(typeof this.map[key] !== 'undefined'){ 60 | this._length--; 61 | delete this.map[key]; 62 | this.keys.splice(this.keys.indexOf(key), 1); 63 | return true; 64 | } 65 | return false; 66 | }; 67 | 68 | /** 69 | * Get the value for the given key 70 | * 71 | * @param {mixed} key 72 | * @return {mixed} the value for the key 73 | */ 74 | Map.prototype.get = function(key){ 75 | return this.map[key]; 76 | }; 77 | 78 | /** 79 | * Get the value for a given position 80 | * 81 | * @param {number} position 82 | * @return {mixed} the value for the position 83 | */ 84 | Map.prototype.getAt = function(pos){ 85 | return this.map[this.keys[pos]]; 86 | }; 87 | 88 | /** 89 | * Check if the given key is available in the Map and return exact boolean 90 | * 91 | * @param {mixed} key 92 | * @return {Boolean} 93 | */ 94 | Map.prototype.has = function(key){ 95 | return typeof this.map[key] !== 'undefined'; 96 | }; 97 | 98 | /** 99 | * Iterate over Map entries, invoking the give function for each entry 100 | * 101 | * @param {Function} fn Will get two arguments "key" and "value" 102 | */ 103 | Map.prototype.forEach = function(fn, context){ 104 | for(var i = 0; i < this.keys.length; i++) { 105 | if(typeof this.keys[i] !== 'undefined'){ 106 | fn.call(context, this.keys[i], this.map[this.keys[i]]); 107 | } 108 | } 109 | }; 110 | 111 | /** 112 | * Get the number of key/value pairs in this Map 113 | */ 114 | Map.prototype.__defineGetter__('length', function(){ 115 | return this._length; 116 | }); 117 | 118 | /** 119 | * Get a string representation of the key/value pairs in this map 120 | */ 121 | Map.prototype.toString = function() { 122 | return 'Map Object (' + this.keys.length + ') [' + this.keys.join(', ') + ']'; 123 | }; -------------------------------------------------------------------------------- /lib/net_group.js: -------------------------------------------------------------------------------- 1 | /** 2 | * NetGroup 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | /** 21 | * Represents a group of connection in ArcusNode (Client NetGroup) 22 | * TODO: Make group join/leave more usable for events 23 | * TODO: Let grou inherit from Map 24 | */ 25 | module.exports = function(id, settings){ 26 | if(!id) 27 | throw new Error('NetGroup needs an id.'); 28 | 29 | var _id = id; 30 | var _size = 0; 31 | var _connections = {}; 32 | var _touchTime = new Date().getTime(); 33 | 34 | this.id = function() { 35 | return _id; 36 | }; 37 | 38 | /** 39 | * Add a NetConnection to this group 40 | */ 41 | this.add = function(nc) { 42 | if(!_connections[nc.id]) 43 | _size++; 44 | _connections[nc.id] = nc; 45 | }; 46 | 47 | /** 48 | * Remove a NetConnection from this group 49 | */ 50 | this.remove = function(ncId) { 51 | if(_connections[ncId]){ 52 | _size--; 53 | } 54 | delete _connections[ncId]; 55 | }; 56 | 57 | /** 58 | * How many members does this group have? 59 | */ 60 | this.size = function() { 61 | return _size; 62 | }; 63 | 64 | /** 65 | * Reset the group timeout, after which the group gets deleted 66 | */ 67 | this.touch = function() { 68 | _touchTime = new Date().getTime(); 69 | }; 70 | 71 | /** 72 | * When was this group last touched? 73 | */ 74 | this.touched = function() { 75 | return _touchTime; 76 | }; 77 | 78 | /** 79 | * The connections in this group (the members) 80 | */ 81 | this.connections = function() { 82 | return _connections; 83 | }; 84 | 85 | /** 86 | * Returns the connections ordered by their latency 87 | */ 88 | this.fastest = function(excludeNc) { 89 | var sorted = []; 90 | for(k in _connections){ 91 | if(_connections[k] != excludeNc) 92 | sorted.push(_connections[k]); 93 | } 94 | sorted.sort(function(a, b) { 95 | return (a.latency < b.latency); 96 | }); 97 | return sorted; 98 | }; 99 | }; 100 | 101 | //States 102 | module.exports.CLOSING = 0x00; 103 | module.exports.HANDSHAKE = 0x01; 104 | module.exports.CONNECTING = 0x02; 105 | module.exports.CONNECTED = 0x03; 106 | -------------------------------------------------------------------------------- /lib/peer_proxy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ArcusNode PeerProxy 3 | */ 4 | var EventEmitter = require('events').EventEmitter; 5 | var util = require('util'); 6 | var dgram = require('dgram'); 7 | var Map = require('./map.js'); 8 | var Packet = require('./packet.js'); 9 | var RTMFP = require('./rtmfp.js'); 10 | 11 | var PeerProxy = module.exports = function(settings) { 12 | 13 | var _self = this; 14 | 15 | this.settings = { 16 | port: 9000, 17 | logLevel: "warn" 18 | } 19 | 20 | //Merge Settings 21 | for(k in settings){ 22 | this.settings[k] = settings[k]; 23 | } 24 | 25 | // Create logger if not given 26 | if(settings.logger) { 27 | this.logger = settings.logger; 28 | } else { 29 | this.logger = require('./logger.js').createLogger(settings.logFile, settings.logLevel); 30 | } 31 | 32 | // 33 | this.socket = null; 34 | this._end2end = new Map(); 35 | this.rtmfp = new RTMFP(); 36 | 37 | } 38 | 39 | PeerProxy.prototype.listen = function(port, address) { 40 | var self = this; 41 | 42 | //Listen for connections 43 | //TODO: Support IPv6 44 | this.socket = dgram.createSocket('udp4', function(buffer, remoteInfo){ 45 | // Pipe 46 | try { 47 | 48 | self.logger.debug('PeerProxy data from', remoteInfo) 49 | 50 | if(self.settings.logPackets === true){ 51 | // Duplicate Buffer 52 | var packetBuffer = new Buffer(buffer.length); 53 | buffer.copy(packetBuffer, 0, 0, buffer.length) 54 | 55 | var pkt = new Packet(packetBuffer, buffer.length); 56 | var connectionId = self.rtmfp.decodePacket(pkt); 57 | 58 | if(connectionId == 0) 59 | { 60 | if(!self.rtmfp.decryptPacket(pkt, RTMFP.SYMETRIC_KEY)) 61 | { 62 | self.logger.warn('PeerProxy handshake decryption failed!'); 63 | return; 64 | } 65 | self.logger.debug('PeerProxy decrypted Handshake Packet: \n' + pkt.toString()); 66 | 67 | var messages = self.rtmfp.readPacket(pkt); 68 | 69 | self.logger.debug('PeerProxy handshake messages: \n', messages); 70 | 71 | } 72 | 73 | } 74 | 75 | var remoteEndpoint = remoteInfo.address + ':' + remoteInfo.port; 76 | if(self._end2end.has(remoteEndpoint)){ 77 | var endpoint = self._end2end.get(remoteEndpoint); 78 | self.socket.send(buffer, 0, buffer.length, endpoint.port, endpoint.address, function (err, bytes) { 79 | if (err) { 80 | self.logger.error('PeerProxy send error: ', err.stack); 81 | } 82 | }); 83 | } 84 | } catch(e) { 85 | self.logger.error('Peer proxy error: ' + e.stack); 86 | } 87 | }); 88 | this.socket.bind(port || this.settings.port, address || (this.settings.address || null)); 89 | 90 | }; 91 | 92 | PeerProxy.prototype.addPair = function(endpoint1, endpoint2) { 93 | // Add to end2end 94 | this._end2end.add(endpoint1.address + ':' + endpoint1.port, endpoint2); 95 | this._end2end.add(endpoint2.address + ':' + endpoint2.port, endpoint1); 96 | }; 97 | 98 | PeerProxy.prototype.removeEndpoint = function(endpoint) { 99 | var end = endpoint.address + ':' + endpoint.port; 100 | if(this._end2end.has(end)){ 101 | this._end2end.remove(this._end2end.get(end)); 102 | this._end2end.remove(end); 103 | } 104 | }; 105 | 106 | PeerProxy.prototype.address = function() { 107 | if(!this._endpoint){ 108 | this._endpoint = { address: this.settings.publicAddress || (this.socket != null ? this.socket.address().address : null), port: this.settings.port || (this.socket != null ? this.socket.address().port : null) }; 109 | } 110 | return this._endpoint; 111 | }; 112 | 113 | /** 114 | * Create an PeerProxy instance and return it 115 | */ 116 | PeerProxy.createServer = function(settings) { 117 | return new PeerProxy(settings); 118 | }; 119 | 120 | 121 | //Inherit from EventEmitter 122 | PeerProxy.prototype.__proto__ = EventEmitter.prototype; 123 | 124 | -------------------------------------------------------------------------------- /lib/plugins/repl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * REPL Plugin for ArcusNode 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | var net = require('net') 21 | var repl = require('repl'); 22 | var Helper = require('../helper.js'); 23 | 24 | /** 25 | * REPL Plugin for ArcusNode 26 | * 27 | * usage: 28 | * var arc = new ArcusNode(); 29 | * arc.use('repl', 4000); 30 | * 31 | * TODO: 32 | * - take settings object from use() arguments { password: x, sessionTimeout: x, maxConnections: 3, blockTimeout: 15 (mins) } 33 | * - add a simple password authentication and block connections from ip after 3x wrong 34 | * - add watch() for realtime log view 35 | * - add stats() for server statistics 36 | * - provide secure REPL 37 | * 38 | * @param {Integer, String} port 39 | */ 40 | module.exports = function(arcus, port){ 41 | if(!port) { 42 | throw new Error('The repl plugin needs a port or unix socket'); 43 | } 44 | 45 | var _sockets = []; 46 | var _server = null; 47 | 48 | arcus.on('stop', function(){ 49 | _sockets.forEach(function(socket){ 50 | socket.fd && socket.end(); 51 | }); 52 | if (_server.fd) _server.close(); 53 | }); 54 | 55 | arcus.on('start', function(){ 56 | _server = net.createServer(function(socket){ 57 | _sockets.push(socket); 58 | 59 | var ctx = repl.start('Arcus> ', socket).context; 60 | 61 | // augment socket to provide some formatting methods 62 | socket.title = function(str){ this.write('\n \033[36m' + str + '\033[0m\n'); } 63 | socket.row = function(key, val){ this.write(' \033[90m' + key + ':\033[0m ' + val + '\n'); } 64 | socket.writeln = function(str){ this.write(str + '\n'); } 65 | 66 | 67 | // 68 | // Commands 69 | // 70 | 71 | /** 72 | * Restart ArcusNode 73 | */ 74 | ctx.restart = function(){ 75 | socket.writeln('Restarting...'); 76 | setTimeout(function(){ 77 | arcus.restart(); 78 | }, 50); 79 | }; 80 | 81 | /** 82 | * The current status of ArcusNode 83 | */ 84 | ctx.status = function(){ 85 | socket.writeln('Status: ' + arcus.status); 86 | } 87 | 88 | /** 89 | * Reset stats 90 | */ 91 | ctx.resetStats = function(){ 92 | arcus.resetStats(); 93 | socket.writeln('Stats reset.'); 94 | } 95 | 96 | /** 97 | * Some stats about arcus node (still to come...) 98 | */ 99 | ctx.stats = function(){ 100 | socket.title('ArcusNode Stats'); 101 | var mem = process.memoryUsage(); 102 | for(k in mem){ 103 | socket.row(k, mem[k]); 104 | } 105 | socket.writeln(''); 106 | socket.row('Arcus uptime', Helper.formatLapsed(arcus.uptime[0])); 107 | socket.row('Process uptime', Helper.formatLapsed(arcus.uptime[1])); 108 | socket.writeln(''); 109 | socket.row('Connections', arcus.connections.length); 110 | socket.row('Groups', arcus.groups.length); 111 | socket.writeln(''); 112 | socket.row('Dropped Connections', arcus.stats.droppedConnections); 113 | socket.row('Dropped Groups', arcus.stats.droppedGroups); 114 | socket.row('Dropped Handshakes', arcus.stats.droppedHandshakes); 115 | socket.writeln(''); 116 | } 117 | 118 | }); 119 | 120 | _server.listen(port); 121 | }); 122 | 123 | } -------------------------------------------------------------------------------- /lib/proxy_net_connection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Proxy NetConnection 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | var NetConnection = require('./net_connection.js'); 21 | 22 | /** 23 | * Represents a proxy peer connection to ArcusNode 24 | */ 25 | var ProxyNetConnection = module.exports = function(arcus, id, socket, settings){ 26 | this.init(arcus, id, socket, settings); 27 | this._isProxy = true; 28 | 29 | arcus.__p.logger.debug('PNC: Created Peer NetConnection', id); 30 | }; 31 | 32 | //Inherit from NetConnection 33 | ProxyNetConnection.prototype.__proto__ = NetConnection.prototype; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ArcusNode", 3 | "version": "0.0.6", 4 | "author": "arcusdev ", 5 | "description": "A RTMFP Rendevouz Server For Peer Assisted Networking With Adobe Flash", 6 | "main": "service", 7 | "keywords":[ 8 | "rtmfp", 9 | "flash", 10 | "p2p", 11 | "networking", 12 | "rendezvouz", 13 | "rtmp", 14 | "RPC" 15 | ], 16 | "directories": { 17 | "lib": "./lib", 18 | "src": "./src" 19 | }, 20 | "maintainers": [{ 21 | "name":"arcusdev", 22 | "email":"arcus.node@gmail.com", 23 | "web":"http://github.com/OpenRTMFP" 24 | },{ 25 | "name":"kommander", 26 | "web":"http://github.com/kommander" 27 | }], 28 | "bugs" : { 29 | "mail" : "arcus.node@gmail.com", 30 | "web" : "https://github.com/OpenRTMFP/ArcusNode/issues" 31 | }, 32 | "engines" : { "node" : "~0.10.0", "npm" : "1" }, 33 | "licenses": [{ 34 | "type": "GPL", 35 | "url": "http://www.gnu.org/licenses/" 36 | }], 37 | "repositories": [{ 38 | "type": "git" 39 | , "url" : "http://github.com/OpenRTMFP/ArcusNode.git" 40 | }], 41 | "dependencies": { 42 | "node-gyp": "0.9" 43 | }, 44 | "scripts" : { 45 | "preinstall" : "", 46 | "install" : "node-gyp configure build", 47 | "test" : "node test.js", 48 | "start" : "node service.js" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ArcusNode Service 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * Author: arcusdev 18 | * 19 | * This file is a part of ArcusNode. 20 | */ 21 | 22 | var util = require('util'); 23 | var ArcusNode = require('./lib/arcus_node.js'); 24 | 25 | //Take command line arguments 26 | var settings = {}; 27 | process.argv.forEach(function (val, index, array) { 28 | if(index < 2) 29 | return; 30 | var valArr = val.split('='); 31 | switch(valArr[0]){ 32 | case 'logLevel': 33 | settings.logLevel = valArr[1]; 34 | util.print('Setting logLevel to ' + valArr[1] + '\n'); 35 | break; 36 | case 'logFile': 37 | settings.logFile = valArr[1]; 38 | util.print('Setting logFile to ' + valArr[1] + '\n'); 39 | break; 40 | case '-h': 41 | case '-help': 42 | util.print( 43 | '### USAGE ###\n\n' + 44 | 'node service.js [argument1 argument2 ...]\n\n' + 45 | 'Arguments:\n' + 46 | 'logLevel=[level] [level] can be one of: fatal, error, warn, info, debug' + 47 | 'logFile=[path] [path] The path to a file to log output to' + 48 | '\n\n' 49 | ); 50 | process.exit(); 51 | break; 52 | default: 53 | util.print('Argument unknown or malformed: ' + val + '\nStopping process.'); 54 | process.exit(); 55 | } 56 | }); 57 | 58 | //Startup 59 | util.print( 60 | 'Starting up ArcusNode RTMFP Service.\nCopyright (C) 2011 OpenRTMFP \n' + 61 | 'This program comes with ABSOLUTELY NO WARRANTY.\n' + 62 | 'This is free software, and you are welcome to redistribute it under certain conditions.\n' + 63 | '(For usage help type "node service.js -h")\n' 64 | ); 65 | 66 | var arc = new ArcusNode(settings); 67 | arc.run(); 68 | 69 | process.on('SIGINT', function () { 70 | util.print('\033[36mArcusNode shutting down...\033[0m\n'); 71 | arc.stop(); 72 | }); 73 | process.on('exit', function(){ 74 | util.print('\033[36mArcusNode stopped.\033[0m\n'); 75 | }); 76 | 77 | util.print('ArcusNode RTMFP Service running at ' + arc.address.address + ((arc.address.port != '') ? ':' + arc.address.port : '') + '\n'); 78 | -------------------------------------------------------------------------------- /src/keyexchange.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * KeyExchange - Diffie-Hellman Key Exchange Module for Node 3 | * 4 | * Copyright 2011 OpenRTMFP 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License received along this program for more 15 | * details (or else see http://www.gnu.org/licenses/). 16 | * 17 | * This file is a part of ArcusNode. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | using namespace v8; 29 | using namespace node; 30 | 31 | #define AES_KEY_SIZE 0x20 32 | 33 | uint8_t g_dh1024p[] = { 34 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 35 | 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 36 | 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 37 | 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 38 | 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 39 | 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 40 | 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 41 | 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 42 | 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 43 | 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 44 | 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 45 | 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 46 | 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 47 | 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 48 | 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 49 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 50 | }; 51 | 52 | class KeyExchange: ObjectWrap 53 | { 54 | private: 55 | 56 | public: 57 | 58 | static Persistent s_ct; 59 | DH* dh; 60 | 61 | /** 62 | * Node module initialization and method exposure 63 | */ 64 | static void init (Handle target) 65 | { 66 | HandleScope scope; 67 | 68 | target->Set(String::New("version"), String::New("0.1")); 69 | 70 | Local t = FunctionTemplate::New(New); 71 | 72 | s_ct = Persistent::New(t); 73 | s_ct->InstanceTemplate()->SetInternalFieldCount(1); 74 | s_ct->SetClassName(String::NewSymbol("KeyExchange")); 75 | 76 | NODE_SET_PROTOTYPE_METHOD(s_ct, "computeAsymetricKeys", computeAsymetricKeys); 77 | NODE_SET_PROTOTYPE_METHOD(s_ct, "generateKeyPair", generateKeyPair); 78 | NODE_SET_PROTOTYPE_METHOD(s_ct, "computeSharedSecret", computeSharedSecret); 79 | 80 | target->Set(String::NewSymbol("KeyExchange"), s_ct->GetFunction()); 81 | } 82 | 83 | KeyExchange() : ObjectWrap() 84 | { 85 | dh = NULL; 86 | } 87 | 88 | ~KeyExchange(){ 89 | if (dh) DH_free(dh); 90 | } 91 | 92 | /** 93 | * Creates a new KeyExchange instance as a JavaScript Object 94 | */ 95 | static Handle New(const Arguments& args) 96 | { 97 | HandleScope scope; 98 | KeyExchange* hw = new KeyExchange(); 99 | hw->Wrap(args.This()); 100 | return args.This(); 101 | } 102 | 103 | /** 104 | * Generates a private/public keypair for dh key exchange 105 | * 106 | * @return {Array} [privateKey, publicKey] 107 | */ 108 | static Handle generateKeyPair(const Arguments& args) { 109 | KeyExchange *ke = ObjectWrap::Unwrap(args.This()); 110 | HandleScope scope; 111 | 112 | char private_key[128]; 113 | char public_key[128]; 114 | 115 | // Create DH keypair 116 | ke->dh = DH_new(); 117 | ke->dh->p = BN_new(); 118 | ke->dh->g = BN_new(); 119 | 120 | BN_set_word(ke->dh->g, 2); 121 | BN_bin2bn(g_dh1024p, 128, ke->dh->p); 122 | DH_generate_key(ke->dh); 123 | 124 | //Fill the servers public key 125 | BN_bn2bin(ke->dh->pub_key, (uint8_t*)public_key); 126 | BN_bn2bin(ke->dh->priv_key, (uint8_t*)private_key); 127 | 128 | Local keys = Array::New(); 129 | 130 | keys->Set(uint32_t(0), Buffer::New(private_key, 128)->handle_); 131 | keys->Set(uint32_t(1), Buffer::New(public_key, 128)->handle_); 132 | 133 | return scope.Close(keys); 134 | } 135 | 136 | /** 137 | * Computes the shared secret from a public key 138 | */ 139 | static Handle computeSharedSecret(const Arguments& args) { 140 | KeyExchange *ke = ObjectWrap::Unwrap(args.This()); 141 | HandleScope scope; 142 | 143 | Local far_key_obj = args[0]->ToObject(); 144 | 145 | if (args.Length() < 1 || !Buffer::HasInstance(far_key_obj)) { 146 | return ThrowException(Exception::TypeError(String::New("Bad argument"))); 147 | } 148 | 149 | if(DH_size(ke->dh) <= 0){ 150 | return ThrowException(Exception::TypeError(String::New("DH empty. Generate Keypair first."))); 151 | } 152 | 153 | char *far_key = Buffer::Data(far_key_obj); 154 | size_t far_key_size = Buffer::Length(far_key_obj); 155 | 156 | char shared_secret[128]; 157 | BIGNUM *bn_far_key = BN_bin2bn((const uint8_t*)far_key, far_key_size, NULL); 158 | DH_compute_key((unsigned char*)shared_secret, bn_far_key, ke->dh); 159 | 160 | BN_free(bn_far_key); 161 | 162 | return scope.Close(Buffer::New(shared_secret, 128)->handle_); 163 | } 164 | 165 | /** 166 | * Computes the asymetric keys in RTMFP handshake for further communication. 167 | * Returns an array with three values: [decryptKey, encryptKey] 168 | */ 169 | static Handle computeAsymetricKeys(const Arguments& args) { 170 | HandleScope scope; 171 | 172 | Local shared_secret_obj = args[0]->ToObject(); 173 | Local initiator_nonce_obj = args[1]->ToObject(); 174 | Local responder_nonce_obj = args[2]->ToObject(); 175 | 176 | if (args.Length() < 3 || !Buffer::HasInstance(shared_secret_obj) || !Buffer::HasInstance(initiator_nonce_obj) || !Buffer::HasInstance(responder_nonce_obj)) { 177 | return ThrowException(Exception::TypeError(String::New("Bad argument"))); 178 | } 179 | 180 | char *shared_secret = Buffer::Data(shared_secret_obj); 181 | size_t shared_secret_size = Buffer::Length(shared_secret_obj); 182 | char *initiator_nonce = Buffer::Data(initiator_nonce_obj); 183 | size_t initiator_nonce_size = Buffer::Length(initiator_nonce_obj); 184 | char *responder_nonce = Buffer::Data(responder_nonce_obj); 185 | size_t responder_nonce_size = Buffer::Length(responder_nonce_obj); 186 | 187 | uint8_t md1[AES_KEY_SIZE]; 188 | uint8_t md2[AES_KEY_SIZE]; 189 | 190 | // doing HMAC-SHA256 of one side 191 | HMAC(EVP_sha256(), responder_nonce, responder_nonce_size, (const uint8_t*)initiator_nonce, initiator_nonce_size, md1, NULL); 192 | // doing HMAC-SHA256 of the other side 193 | HMAC(EVP_sha256(), initiator_nonce, initiator_nonce_size, (const uint8_t*)responder_nonce, responder_nonce_size, md2, NULL); 194 | 195 | char decrypt_key[128]; 196 | char encrypt_key[128]; 197 | 198 | // now doing HMAC-sha256 of both result with the shared secret DH key 199 | HMAC(EVP_sha256(), shared_secret, shared_secret_size, md1, AES_KEY_SIZE, (uint8_t*)decrypt_key, NULL); 200 | HMAC(EVP_sha256(), shared_secret, shared_secret_size, md2, AES_KEY_SIZE, (uint8_t*)encrypt_key, NULL); 201 | 202 | Local keys = Array::New(); 203 | 204 | keys->Set(uint32_t(0), Buffer::New(decrypt_key, 128)->handle_); 205 | keys->Set(uint32_t(1), Buffer::New(encrypt_key, 128)->handle_); 206 | 207 | return scope.Close(keys); 208 | } 209 | 210 | }; 211 | 212 | Persistent KeyExchange::s_ct; 213 | 214 | //Node module exposure 215 | extern "C" { 216 | 217 | static void init (Handle target) 218 | { 219 | KeyExchange::init(target); 220 | } 221 | NODE_MODULE(keyexchange, init); 222 | } 223 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | //To come... (ja ja, I know...) -------------------------------------------------------------------------------- /wscript: -------------------------------------------------------------------------------- 1 | # wscript 2 | # 3 | # Copyright 2011 OpenRTMFP 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License received along this program for more 14 | # details (or else see http://www.gnu.org/licenses/). 15 | # 16 | # Author: arcusdev 17 | # 18 | # This file is a part of ArcusNode. 19 | 20 | import os, sys 21 | 22 | srcdir = '.' 23 | blddir = './build' 24 | VERSION = '0.0.4' 25 | 26 | def set_options(opt): 27 | opt.tool_options('compiler_cxx') 28 | 29 | def configure(conf): 30 | conf.check_tool('compiler_cxx') 31 | conf.check_tool('node_addon') 32 | 33 | def build(bld): 34 | rtmfp = bld.new_task_gen('cxx', 'shlib', 'node_addon') 35 | 36 | if sys.platform.startswith("cygwin"): 37 | rtmfp.lib = 'crypto'; 38 | 39 | rtmfp.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall", "-L/usr/lib", "-lssl"] 40 | rtmfp.chmod = 0755 41 | rtmfp.target = 'rtmfp' 42 | rtmfp.source = 'src/rtmfp.cc' 43 | 44 | keyExchange = bld.new_task_gen('cxx', 'shlib', 'node_addon') 45 | 46 | if sys.platform.startswith("cygwin"): 47 | keyExchange.lib = 'crypto'; 48 | 49 | keyExchange.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall", "-L/usr/lib", "-lssl"] 50 | keyExchange.chmod = 0755 51 | keyExchange.target = 'keyexchange' 52 | keyExchange.source = 'src/keyexchange.cc' 53 | 54 | def clean(opt): 55 | if os.path.exists(blddir + '/default/keyexchange.node'): os.unlink(blddir + '/default/keyexchange.node') 56 | if os.path.exists(blddir + '/default/rtmfp.node'): os.unlink(blddir + '/default/rtmfp.node') --------------------------------------------------------------------------------