From f37734c53acbf9756214618b87c930b996d38bfc Mon Sep 17 00:00:00 2001
From: egeller <ëlena.geller@gmail.com@>
Date: Sat, 2 Nov 2013 10:45:43 +0100
Subject: [PATCH] first commit
---
.gitignore | 217 ++++++
MapTest.hxproj | 57 ++
application.xml | 27 +
assets/openfl.svg | 17 +
openfl-readme.txt | 68 ++
src/Main.hx | 144 ++++
src/VectorLayer.hx | 84 +++
src/com/.svn/all-wcprops | 35 +
src/com/.svn/entries | 198 +++++
src/com/.svn/text-base/Button.hx.svn-base | 431 +++++++++++
src/com/.svn/text-base/Component.hx.svn-base | 74 ++
src/com/.svn/text-base/InfoBox.hx.svn-base | 86 +++
src/com/.svn/text-base/StatusBar.hx.svn-base | 94 +++
src/com/.svn/text-base/ToolBar.hx.svn-base | 153 ++++
src/com/Button.hx | 431 +++++++++++
src/com/Component.hx | 74 ++
src/com/InfoBox.hx | 86 +++
src/com/StatusBar.hx | 94 +++
src/com/ToolBar.hx | 153 ++++
src/map/.svn/all-wcprops | 59 ++
src/map/.svn/entries | 334 +++++++++
src/map/.svn/text-base/Canvas.hx.svn-base | 666 +++++++++++++++++
src/map/.svn/text-base/Layer.hx.svn-base | 522 ++++++++++++++
src/map/.svn/text-base/LngLat.hx.svn-base | 85 +++
src/map/.svn/text-base/MapService.hx.svn-base | 211 ++++++
src/map/.svn/text-base/QuadTree.hx.svn-base | 240 +++++++
src/map/.svn/text-base/Tile.hx.svn-base | 173 +++++
src/map/.svn/text-base/TileLayer.hx.svn-base | 546 ++++++++++++++
src/map/.svn/text-base/TileLoader.hx.svn-base | 547 ++++++++++++++
src/map/.svn/text-base/Utils.hx.svn-base | 74 ++
src/map/Canvas.hx | 676 ++++++++++++++++++
src/map/Layer.hx | 522 ++++++++++++++
src/map/LngLat.hx | 85 +++
src/map/MapService.hx | 215 ++++++
src/map/QuadTree.hx | 240 +++++++
src/map/Tile.hx | 174 +++++
src/map/TileLayer.hx | 546 ++++++++++++++
src/map/TileLoader.hx | 547 ++++++++++++++
src/map/Utils.hx | 74 ++
39 files changed, 9059 insertions(+)
create mode 100644 .gitignore
create mode 100644 MapTest.hxproj
create mode 100644 application.xml
create mode 100644 assets/openfl.svg
create mode 100644 openfl-readme.txt
create mode 100644 src/Main.hx
create mode 100644 src/VectorLayer.hx
create mode 100644 src/com/.svn/all-wcprops
create mode 100644 src/com/.svn/entries
create mode 100644 src/com/.svn/text-base/Button.hx.svn-base
create mode 100644 src/com/.svn/text-base/Component.hx.svn-base
create mode 100644 src/com/.svn/text-base/InfoBox.hx.svn-base
create mode 100644 src/com/.svn/text-base/StatusBar.hx.svn-base
create mode 100644 src/com/.svn/text-base/ToolBar.hx.svn-base
create mode 100644 src/com/Button.hx
create mode 100644 src/com/Component.hx
create mode 100644 src/com/InfoBox.hx
create mode 100644 src/com/StatusBar.hx
create mode 100644 src/com/ToolBar.hx
create mode 100644 src/map/.svn/all-wcprops
create mode 100644 src/map/.svn/entries
create mode 100644 src/map/.svn/text-base/Canvas.hx.svn-base
create mode 100644 src/map/.svn/text-base/Layer.hx.svn-base
create mode 100644 src/map/.svn/text-base/LngLat.hx.svn-base
create mode 100644 src/map/.svn/text-base/MapService.hx.svn-base
create mode 100644 src/map/.svn/text-base/QuadTree.hx.svn-base
create mode 100644 src/map/.svn/text-base/Tile.hx.svn-base
create mode 100644 src/map/.svn/text-base/TileLayer.hx.svn-base
create mode 100644 src/map/.svn/text-base/TileLoader.hx.svn-base
create mode 100644 src/map/.svn/text-base/Utils.hx.svn-base
create mode 100644 src/map/Canvas.hx
create mode 100644 src/map/Layer.hx
create mode 100644 src/map/LngLat.hx
create mode 100644 src/map/MapService.hx
create mode 100644 src/map/QuadTree.hx
create mode 100644 src/map/Tile.hx
create mode 100644 src/map/TileLayer.hx
create mode 100644 src/map/TileLoader.hx
create mode 100644 src/map/Utils.hx
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..90eada1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,217 @@
+#################
+## Eclipse
+#################
+
+*.pydevproject
+.project
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+
+obj/
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+
+#################
+## Visual Studio
+#################
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+
+[Dd]ebug/
+[Rr]elease/
+x64/
+build/
+[Bb]in/
+[Oo]bj/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.log
+*.scc
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+*.ncrunch*
+.*crunch*.local.xml
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.Publish.xml
+*.pubxml
+
+# NuGet Packages Directory
+## TODO: If you have NuGet Package Restore enabled, uncomment the next line
+#packages/
+
+# Windows Azure Build Output
+csx
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.[Pp]ublish.xml
+*.pfx
+*.publishsettings
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+App_Data/*.mdf
+App_Data/*.ldf
+
+#############
+## Windows detritus
+#############
+
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Mac crap
+.DS_Store
+
+
+#############
+## Python
+#############
+
+*.py[co]
+
+# Packages
+*.egg
+*.egg-info
+dist/
+build/
+eggs/
+parts/
+var/
+sdist/
+develop-eggs/
+.installed.cfg
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+
+#Translations
+*.mo
+
+#Mr Developer
+.mr.developer.cfg
diff --git a/MapTest.hxproj b/MapTest.hxproj
new file mode 100644
index 0000000..9e9c471
--- /dev/null
+++ b/MapTest.hxproj
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application.xml b/application.xml
new file mode 100644
index 0000000..178f9ea
--- /dev/null
+++ b/application.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/openfl.svg b/assets/openfl.svg
new file mode 100644
index 0000000..506f61d
--- /dev/null
+++ b/assets/openfl.svg
@@ -0,0 +1,17 @@
+
+
+
+
diff --git a/openfl-readme.txt b/openfl-readme.txt
new file mode 100644
index 0000000..035191d
--- /dev/null
+++ b/openfl-readme.txt
@@ -0,0 +1,68 @@
+About OpenFL
+
+ OpenFL is the successor of NME, for Haxe 3+.
+
+ Building a game or application with OpenFL is almost like writing for a single platform. However,
+ when you are ready to publish your application, you can choose between targets like iOS, webOS,
+ Android, Windows, Mac, Linux and Flash Player.
+
+ Instead of using the lowest common denominator between platforms with a "universal" runtime,
+ OpenFL projects are compiled as SWF bytecode or C++ applications, using the Haxe language compiler
+ and the standard C++ compiler toolchain for each platform.
+
+ Read more:
+ http://openfl.org/
+
+Project configuration, libraries, classpaths
+
+ OpenFL configuration is based on a XML file - it allows you very complex
+ configurations depending on the target platform. There is no GUI for it.
+
+ DO NOT modify FlashDevelop project properties as they will automatically be synchronized with the
+ XML when you modify it.
+
+Development
+
+ OpenFL is encouraging to develop using the Flash API (ie. flash.display.Sprite) as in ActionScript 3.
+
+ Just code like you would code a Flash application, with the limitation that you can only use
+ the drawing API, bitmaps (see below) and TextFields.
+
+ However test often all the platforms you plan to target!
+
+ In OpenFL 3.x, SWFs and videos aren't supported yet.
+
+Assets
+
+ Place all your images, sounds, fonts in /assets and access them in your code using the
+ global Assets class which abstracts assets management for all platforms:
+
+ var img = new Bitmap(Assets.getBitmapData("assets/my-image.png"));
+ addChild(img);
+
+ Tutorials:
+ https://github.com/openfl/openfl/wiki/Get-Started
+
+Debugging
+
+ By default your project targets Flash so you'll be able to add breakpoints and debug your app
+ like any AS3 project.
+ HTML5 target can be debugged in the browser - some browsers, like Chrome, support "script maps"
+ which let you interactively debug .hx code directly instead of the generated JS.
+ There is however no interactive debugger yet for native targets.
+
+Changing target platform
+
+ For OpenFL projects, an additional drop-down menu appears in the main toolbar where you can choose
+ a supported targets on Windows: flash, html5, windows, neko, android, webos, blackberry.
+ You can also manually enter a custom target not in the list.
+
+ Attention, for native targets you'll need to install additional compilers & SDKs. The compiler
+ will tell you in the Output panel what command to execute for that. More information here:
+ https://github.com/openfl/openfl/wiki/Get-Started
+
+Tips:
+ - in C++ expect first compilation to be very long as it first compiles the whole OpenFL API,
+ - if a change is not taken in account, delete everything in /bin to start a fresh compilation,
+ - on mobile, Bitmap blitting is NOT performant,
+ - use spritesheets and Tilesheet.drawTiles for optimal rendering performance.
diff --git a/src/Main.hx b/src/Main.hx
new file mode 100644
index 0000000..1e715e1
--- /dev/null
+++ b/src/Main.hx
@@ -0,0 +1,144 @@
+package ;
+
+import flash.display.Sprite;
+import flash.events.Event;
+import flash.Lib;
+
+import map.Canvas;
+import map.LngLat;
+import map.MapService;
+import com.Button;
+import com.ToolBar;
+
+/**
+ * ...
+ * @author eg
+ */
+
+class Main extends Sprite
+{
+ var inited:Bool;
+ var canvas:Canvas;
+ var toolbar:ToolBar;
+ var layer_osm:map.TileLayer;
+
+
+ /* ENTRY POINT */
+
+ function resize(e)
+ {
+ if (!inited) init();
+ // else (resize or orientation change)
+ }
+
+ function init()
+ {
+ if (inited) return;
+ inited = true;
+
+ // (your code here)
+ toolbar = new ToolBar();
+ canvas = new Canvas();
+
+ toolbar.move(0, 0);
+ canvas.move(0, 0);
+// canvas.setCenter(new LngLat(15.5, 49.5));
+ canvas.setCenter(new LngLat(7.4635729, 51.5120542 ));
+ layer_osm = new map.TileLayer(new OpenStreetMapService(12), 8);
+ canvas.addLayer(layer_osm);
+ canvas.addLayer(new VectorLayer(new OpenStreetMapService(12)));
+ canvas.setZoom(2);
+ stageResized(null);
+
+ initToolbar();
+
+ addChild(canvas);
+ addChild(toolbar);
+
+ canvas.initialize();
+ // Stage:
+ // stage.stageWidth x stage.stageHeight @ stage.dpiScale
+
+ // Assets:
+ // nme.Assets.getBitmapData("img/assetname.jpg");
+ }
+
+ /* SETUP */
+
+ public function new()
+ {
+ super();
+ addEventListener(Event.ADDED_TO_STAGE, added);
+ }
+
+ function added(e)
+ {
+ removeEventListener(Event.ADDED_TO_STAGE, added);
+ stage.addEventListener(Event.RESIZE, resize);
+ #if ios
+ haxe.Timer.delay(init, 100); // iOS 6
+ #else
+ init();
+ #end
+ }
+ public function stageResized(e:Event)
+ {
+ toolbar.setSize(flash.Lib.current.stage.stageWidth, 30);
+ canvas.setSize(flash.Lib.current.stage.stageWidth, flash.Lib.current.stage.stageHeight);
+ }
+
+ function initToolbar()
+ {
+ var me = this;
+ toolbar.addButton(new ZoomOutButton(), "Zoom Out", function(b:CustomButton) { me.canvas.zoomOut(); });
+ toolbar.addButton(new ZoomInButton(), "Zoom In", function(b:CustomButton) { me.canvas.zoomIn(); });
+ toolbar.addSeparator(30);
+
+ //pan buttons
+ toolbar.addButton(new UpButton(), "Move up", function(b:CustomButton) { me.pan(1); });
+ toolbar.addButton(new DownButton(), "Move down", function(b:CustomButton) { me.pan(2); });
+ toolbar.addButton(new LeftButton(), "Move left", function(b:CustomButton) { me.pan(4); });
+ toolbar.addButton(new RightButton(), "Move right", function(b:CustomButton) { me.pan(8); });
+
+ //layer buttons
+ toolbar.addSeparator(50);
+ var me = this;
+ var tbosm = new TextButton("OSM Layer");
+ tbosm.checked = true;
+ toolbar.addButton(tbosm, "Open Street Map Layer",
+ function(b:CustomButton)
+ {
+ tbosm.checked = !tbosm.checked;
+ if (tbosm.checked)
+ me.canvas.enableLayer(me.layer_osm);
+ else
+ me.canvas.disableLayer(me.layer_osm);
+ });
+
+ }
+
+ function pan(direction:Int)
+ {
+ var lt:LngLat = canvas.getLeftTopCorner();
+ var br:LngLat = canvas.getRightBottomCorner();
+ var p:LngLat = canvas.getCenter();
+
+ if (direction & 0x3 == 1) p.lat = lt.lat; //up
+ if (direction & 0x3 == 2) p.lat = br.lat; //down
+ if (direction & 0xC == 4) p.lng = lt.lng; //left
+ if (direction & 0xC == 8) p.lng = br.lng; //right
+
+ canvas.panTo(p);
+ }
+
+
+ public static function main()
+ {
+ // static entry point
+ Lib.current.stage.align = flash.display.StageAlign.TOP_LEFT;
+ Lib.current.stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
+ Lib.current.addChild(new Main());
+ }
+}
+
+
diff --git a/src/VectorLayer.hx b/src/VectorLayer.hx
new file mode 100644
index 0000000..cdb7610
--- /dev/null
+++ b/src/VectorLayer.hx
@@ -0,0 +1,84 @@
+package ;
+
+/**
+ * ...
+ * @author eg
+ */
+import flash.net.URLLoader;
+import flash.net.URLRequest;
+import flash.utils.ByteArray;
+import flash.geom.Point;
+import map.Layer;
+import map.QuadTree;
+import map.MapService;
+import map.LngLat;
+
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+
+class VectorLayer extends Layer
+{
+ var data:QuadTree;
+ var ftimer:Timer;
+
+ public static var COLORS = [0xB2182B, 0xD6604D, 0xF4A582, 0xFDDBC7, 0xE0E0E0, 0xBABABA, 0x878787, 0x4D4D4D];
+
+ public function new(map_service:MapService = null)
+ {
+ super(map_service, false);
+
+
+ ftimer = new Timer(100, 1);
+ ftimer.addEventListener(TimerEvent.TIMER_COMPLETE, redraw);
+
+ data = new QuadTree();
+ for (i in 0...100000)
+ {
+ var lng:Float = -30 + Math.random()*100;
+ var lat:Float = Math.random()*80;
+ var clr:Int = Math.floor(Math.random()*8);
+ var r:Int = 5 + (1 << Math.floor(i / 10000));
+ data.push(lng,lat, {color: COLORS[clr], radius: r});
+ }
+ }
+
+ override function updateContent(forceUpdate:Bool=false)
+ {
+ if (ftimer.running)
+ ftimer.stop();
+
+ if (forceUpdate)
+ redraw(null);
+ else
+ ftimer.start();
+ }
+
+ function redraw(e:TimerEvent)
+ {
+
+ var zz:Int = this.mapservice.zoom_def + this.zoom;
+ var scale:Float = Math.pow(2.0, this.zoom);
+ var l2pt = this.mapservice.lonlat2XY;
+ var cpt:Point = l2pt(center.lng, center.lat, zz);
+ var pt:Point;
+
+ graphics.clear();
+ var lt:LngLat = getLeftTopCorner();
+ var rb:LngLat = getRightBottomCorner();
+
+ //var data:Array = data.getData(lt.lng, rb.lat, rb.lng, lt.lat);
+
+ var minsz:Float = 1.0/scale;
+ var data:Array = data.getFilteredData(lt.lng, rb.lat, rb.lng, lt.lat, function(q:QuadData):Bool { return q.data.radius > minsz;}); //return scale*q.data.radius > 0.8;});
+
+ var r:Float;
+ for (d in data)
+ {
+ r = scale*d.data.radius;
+ pt = l2pt(d.x, d.y, zz);
+ graphics.lineStyle(r/2.0, d.data.color);
+ graphics.drawRect((pt.x - cpt.x), (pt.y - cpt.y), r, r);
+ }
+ }
+}
+
diff --git a/src/com/.svn/all-wcprops b/src/com/.svn/all-wcprops
new file mode 100644
index 0000000..e604341
--- /dev/null
+++ b/src/com/.svn/all-wcprops
@@ -0,0 +1,35 @@
+K 25
+svn:wc:ra_dav:version-url
+V 34
+/svn/!svn/ver/2/trunk/haxemaps/com
+END
+ToolBar.hx
+K 25
+svn:wc:ra_dav:version-url
+V 45
+/svn/!svn/ver/2/trunk/haxemaps/com/ToolBar.hx
+END
+Component.hx
+K 25
+svn:wc:ra_dav:version-url
+V 47
+/svn/!svn/ver/2/trunk/haxemaps/com/Component.hx
+END
+InfoBox.hx
+K 25
+svn:wc:ra_dav:version-url
+V 45
+/svn/!svn/ver/2/trunk/haxemaps/com/InfoBox.hx
+END
+StatusBar.hx
+K 25
+svn:wc:ra_dav:version-url
+V 47
+/svn/!svn/ver/2/trunk/haxemaps/com/StatusBar.hx
+END
+Button.hx
+K 25
+svn:wc:ra_dav:version-url
+V 44
+/svn/!svn/ver/2/trunk/haxemaps/com/Button.hx
+END
diff --git a/src/com/.svn/entries b/src/com/.svn/entries
new file mode 100644
index 0000000..b6d0183
--- /dev/null
+++ b/src/com/.svn/entries
@@ -0,0 +1,198 @@
+10
+
+dir
+5
+http://haxemaps.googlecode.com/svn/trunk/haxemaps/com
+http://haxemaps.googlecode.com/svn
+
+
+
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+91f78bee-1f10-11df-98cf-3116c4ba2102
+
+ToolBar.hx
+file
+
+
+
+
+2013-10-31T20:25:13.036822Z
+f63f6e1f506d7050025455765d853700
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4689
+
+Component.hx
+file
+
+
+
+
+2013-10-31T20:25:13.037822Z
+6b0e56f8b02c722dcd3d892d18fcafef
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2492
+
+InfoBox.hx
+file
+
+
+
+
+2013-10-31T20:25:13.039822Z
+f3f33a827212d17d0141fbc7560a062a
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2906
+
+StatusBar.hx
+file
+
+
+
+
+2013-10-31T20:25:13.041822Z
+6cff2c873e5e84bd5523cc0acf268a2a
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3125
+
+Button.hx
+file
+
+
+
+
+2013-10-31T20:25:13.043822Z
+a3ee19a4df6b6daab7e946198e0e89f5
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12485
+
diff --git a/src/com/.svn/text-base/Button.hx.svn-base b/src/com/.svn/text-base/Button.hx.svn-base
new file mode 100644
index 0000000..59f3364
--- /dev/null
+++ b/src/com/.svn/text-base/Button.hx.svn-base
@@ -0,0 +1,431 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+
+import flash.display.Shape;
+import flash.display.Graphics;
+import flash.display.SimpleButton;
+import flash.display.BitmapData;
+import flash.events.MouseEvent;
+import flash.filters.GlowFilter;
+
+
+class UpButton extends CustomButton {
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool) {
+ var h:Float = (2*szh/5.0)/2;
+
+ g.beginFill(color);
+ g.moveTo(midx-4, midy+h);
+ g.lineTo(midx+4, midy+h);
+ g.lineTo(midx, midy-h);
+ g.endFill();
+
+ if (Std.is(this, RightButton)) {
+ curshape.rotation = 90;
+ curshape.x += szh;
+ }
+
+ if (Std.is(this, LeftButton)) {
+ curshape.rotation = 270;
+ curshape.y += szh;
+ }
+
+ if (Std.is(this, DownButton)) {
+ curshape.rotation = 180;
+ curshape.y += szh;
+ curshape.x += szw;
+ }
+
+ }
+}
+
+class RightButton extends UpButton
+{
+}
+
+class LeftButton extends UpButton
+{
+}
+
+class DownButton extends UpButton
+{
+}
+
+class BarButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/2.0)/2;
+
+ g.lineStyle(4, color);
+ g.moveTo(midx, midy-h);
+ g.lineTo(midx, midy+h);
+
+ }
+
+}
+
+class PauseButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/2.5)/2;
+
+ g.lineStyle(2, color);
+ g.moveTo(midx-2, midy-h);
+ g.lineTo(midx-2, midy+h);
+ g.moveTo(midx+2, midy-h);
+ g.lineTo(midx+2, midy+h);
+
+ }
+
+}
+
+
+
+class SaveButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/2.0)/2;
+
+ g.beginFill(color);
+ g.moveTo(midx-h, midy-h);
+ g.lineTo(midx+h, midy-h);
+ g.lineTo(midx+h, midy+h);
+ g.lineTo(midx+h-h/2.0, midy+h);
+ g.lineTo(midx+h-h/2.0, midy+h-h/2);
+ g.lineTo(midx-h+h/2.0, midy+h-h/2);
+ g.lineTo(midx-h+h/2.0, midy+h);
+ g.lineTo(midx-h, midy+h);
+ g.drawRect(midx-h+h/2.0+1, midy+h-h/2+1, h/2, h/2-1);
+ g.endFill();
+ }
+
+}
+
+class PrintButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/1.5)/2;
+ var oy:Float = -3;
+
+ g.beginFill(color);
+ g.moveTo(midx-h, midy+oy);
+ g.lineTo(midx-h+h/2.0, midy+oy);
+ g.lineTo(midx-h+h/2.0, midy+h-h/1.5+oy);
+ g.lineTo(midx+h-h/2.0, midy+h-h/1.5+oy);
+ g.lineTo(midx+h-h/2.0, midy+oy);
+ g.lineTo(midx+h, midy+oy);
+ g.lineTo(midx+h, midy+h+oy);
+ g.lineTo(midx-h, midy+h+oy);
+
+ g.drawRect(midx-h+h/2.0+1, midy-h/2.5+oy, h/2+1, h/2.5+h/1.5-1);
+ g.drawRect(midx-h+h/2.0, midy+h+0.5+oy, h, 2);
+
+ g.endFill();
+ }
+
+}
+
+class MaximizeButton extends CustomButton
+{
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/3.0)/2; // 1/4 vysky zabira symbol
+ g.lineStyle(4, 0x888888);
+ g.drawRect(midx-h-1, midy-h-1,2*h+2,2*h+2);
+
+ g.lineStyle(2, color);
+ g.drawRect(midx-h-1, midy-h-1,2*h+2,2*h+2);
+
+ }
+}
+
+class ZoomInButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/4.0)/2; // 1/4 vysky zabira symbol
+
+ g.lineStyle(2, color);
+ g.moveTo(midx, midy);
+ g.lineTo(midx+h+4, midy+h+4);
+
+ #if flash9
+ g.moveTo(midx,midy); //bugfix
+ #end
+ g.beginFill(0x888888);
+ g.drawCircle(midx, midy, 2*h);
+ g.endFill();
+
+ if (Std.is(this, SearchButton))
+ return;
+
+ g.moveTo(midx-h, midy);
+ g.lineTo(midx+h, midy);
+
+ if (!Std.is(this, ZoomOutButton))
+ {
+ g.moveTo(midx, midy-h);
+ g.lineTo(midx, midy+h);
+ }
+
+ }
+}
+
+class ZoomOutButton extends ZoomInButton
+{
+}
+
+
+class SearchButton extends ZoomInButton
+{
+}
+
+class TextButton extends CustomButton {
+
+ var text:String;
+
+ public function new(text:String = "", width:Int = 45, size:Int = 25, bgColor:Null = null, bgColorHover:Null = null, fgColor:Int = 0xEEEEEE)
+ {
+ this.text = text;
+ super(size, bgColor, bgColorHover, fgColor);
+ this.szw = width;
+ updateShapes();
+ }
+
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ g.clear();
+
+ var tf:flash.text.TextField = new flash.text.TextField();
+ tf.textColor = 0xFFFFFF;
+ tf.background = false;
+ tf.border = false;
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ var fmt = new flash.text.TextFormat();
+ fmt.font = "Arial";
+ fmt.size = 11;
+ fmt.bold = true;
+ tf.defaultTextFormat = fmt;
+ tf.text = this.text;
+
+ var bd:BitmapData = new BitmapData(Std.int(tf.width),Std.int(tf.height), true, 0x00FFFFFF);
+ bd.draw(tf);
+
+ g.lineStyle(Math.NaN);
+ g.beginBitmapFill(bd, null, false);
+ g.drawRect(0, 0, bd.width, bd.height);
+ g.endFill();
+
+ if (checked)
+ {
+ g.lineStyle(2, 0xFFFFFF);
+ g.moveTo(0, bd.height+2);
+ g.lineTo(bd.width, bd.height+2);
+ }
+ }
+}
+
+class CustomButton extends SimpleButton {
+
+ var fgColor:Int;
+ var szw:Float;
+ var szh:Float;
+ var shint:Shape;
+ var curshape:Shape;
+ var canupdate:Bool;
+ public var hint:String;
+ public var checked(default, setChecked):Bool;
+ public var onClick:Dynamic;
+ public var bgColor(default, setBgColor):Null;
+ public var bgColorHover(default, setBgColorHover):Null;
+
+ public function new(size:Int = 25, bgColor:Null = null, bgColorHover:Null = null, fgColor:Int = 0xEEEEEE)//0x007BC8)
+ {
+ super();
+ this.canupdate = false;
+ downState = overState = upState = hitTestState = null;
+ this.bgColor = bgColor;
+ this.bgColorHover = bgColorHover;
+ this.fgColor = fgColor;
+ this.szw = (size == 0) ? 4 : size;
+ this.szh = (size == 0) ? 25 : size;
+ this.shint = null;
+ this.hint = "";
+ this.canupdate = true;
+ updateShapes();
+
+ useHandCursor = true;
+ onClick = null;
+ checked = false;
+
+ addEventListener(MouseEvent.CLICK, clicked);
+ addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
+
+ }
+
+ function mouseOver(e:MouseEvent)
+ {
+ removeEventListener(MouseEvent.MOUSE_OVER, mouseOver);
+ addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
+
+ if (this.hint == "") return;
+
+ var tf:flash.text.TextField = new flash.text.TextField();
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ tf.text = hint;
+
+ var bd:BitmapData = new BitmapData(Std.int(tf.width),Std.int(tf.height), true, 0x00FFFFFF); //w,h
+ bd.draw(tf);
+
+ shint = new Shape();
+ shint.graphics.lineStyle(1,0x808080);
+ shint.graphics.beginFill(0xFDFECB);
+ shint.graphics.drawRect(-2,-2, bd.width+4, bd.height+4);
+ shint.graphics.endFill();
+
+ shint.graphics.lineStyle(Math.NaN);
+ shint.graphics.beginBitmapFill(bd, null, false);
+ shint.graphics.drawRect(0, 0, bd.width, bd.height);
+ shint.graphics.endFill();
+
+ var p:flash.geom.Point = localToGlobal(new flash.geom.Point(szw/2, szh+10));
+ if (p.x + shint.width > flash.Lib.current.stage.stageWidth) p.x = flash.Lib.current.stage.stageWidth - shint.width;
+ if (p.y + shint.height > flash.Lib.current.stage.stageHeight) p.y = flash.Lib.current.stage.stageHeight - shint.height - szh;
+ if (p.y < 2) p.y = 2;
+ shint.x = p.x; shint.y = p.y;
+
+ flash.Lib.current.stage.addChild(shint);
+ }
+
+ function mouseOut(e:MouseEvent)
+ {
+ if (shint != null) {
+ flash.Lib.current.stage.removeChild(shint);
+ shint = null;
+ }
+
+ removeEventListener(MouseEvent.MOUSE_OUT, mouseOut);
+ addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
+ }
+
+ function setBgColor(val:Null) : Null
+ {
+ if (val != bgColor) {
+ bgColor = val;
+ updateShapes();
+ }
+ return val;
+ }
+
+ function setBgColorHover(val:Null) : Null
+ {
+ if (val != bgColorHover) {
+ bgColorHover = val;
+ updateShapes();
+ }
+ return val;
+ }
+
+ function setChecked(val:Bool) : Bool
+ {
+ if (val != checked) {
+ checked = val;
+ updateShapes();
+ }
+ return val;
+ }
+
+ function updateShapes()
+ {
+ if (!this.canupdate) return;
+ downState = getShape(bgColorHover, fgColor, true);
+ overState = getShape(checked ? 0xFF8000 : bgColorHover, 0xeeeeee /*fgColor*/);
+ overState.filters = [new GlowFilter(0xFFFFFF, 0.75, 5, 5, 2, 2, false, false)];
+ upState = getShape(checked ? 0xFF8000 : bgColor, fgColor);
+ hitTestState = getHitTestShape();
+ }
+
+ public function setSize(w:Float, h:Float)
+ {
+ szw = w;
+ szh = h;
+ updateShapes();
+ }
+
+ function clicked(event:MouseEvent) {
+ if (onClick)
+ onClick(this);
+ }
+
+ function getHitTestShape() {
+ var s = new Shape();
+
+ s.graphics.beginFill(0x000000);
+ s.graphics.drawRect(0, 0, szw, szh);
+ s.graphics.endFill();
+
+ return s;
+ }
+
+ function getShape(bgColor:Null, fgColor:Int, ?down:Bool = false):Shape {
+ curshape = new Shape();
+
+ if (bgColor != null)
+ {
+ curshape.graphics.beginFill(bgColor);
+ curshape.graphics.drawRect(0, 0, szw, szh);
+ curshape.graphics.endFill();
+ }
+
+ var x:Float = szw/2;
+ var y:Float = szh/2;
+
+ if (down) { x += 1; y += 1; }
+
+ drawSymbol(curshape.graphics, fgColor, x, y, down);
+
+ return curshape;
+ }
+
+ function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool) {
+ }
+}
diff --git a/src/com/.svn/text-base/Component.hx.svn-base b/src/com/.svn/text-base/Component.hx.svn-base
new file mode 100644
index 0000000..60a6979
--- /dev/null
+++ b/src/com/.svn/text-base/Component.hx.svn-base
@@ -0,0 +1,74 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+
+import flash.display.Sprite;
+import flash.geom.Rectangle;
+
+typedef ComponentSize = {
+ var width : Float;
+ var height : Float;
+};
+
+
+class Component extends Sprite
+{
+ var _size : ComponentSize;
+
+ public function new()
+ {
+ super();
+
+ this._size = {width: 100.0, height:100.0};
+ }
+
+ public function move(x:Float, y:Float)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public function setSize(w:Float, h:Float)
+ {
+ this._size.width = w;
+ this._size.height = h;
+ this.onResize(w, h);
+ }
+
+ public function getSize() : ComponentSize
+ {
+ return this._size;
+ }
+
+ function onResize(w:Float, h:Float)
+ {
+ }
+}
diff --git a/src/com/.svn/text-base/InfoBox.hx.svn-base b/src/com/.svn/text-base/InfoBox.hx.svn-base
new file mode 100644
index 0000000..30e7238
--- /dev/null
+++ b/src/com/.svn/text-base/InfoBox.hx.svn-base
@@ -0,0 +1,86 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+
+import com.Component;
+import flash.text.TextField;
+
+class InfoBox extends Component
+{
+ var ofsy : Float;
+ var maxw : Float;
+
+ public function new()
+ {
+ super();
+ this.ofsy = 0;
+ this.maxw = 0;
+ }
+
+ public function addItem(text:String) : TextField
+ {
+ var sz = getSize();
+
+ var fmt = new flash.text.TextFormat();
+ fmt.font="Arial";
+ fmt.size=12;
+ fmt.color = 0xFFFFFF;
+
+ var tf = new TextField();
+ tf.defaultTextFormat = fmt;
+ tf.x = 2;
+ tf.y = this.ofsy;
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ tf.multiline = false;
+ tf.text = text;
+ tf.border = false;
+ tf.background = false;
+
+ addChild(tf);
+
+ if (tf.width > this.maxw) this.maxw = tf.width;
+
+ this.ofsy += tf.height + 1;
+
+ update();
+
+ return tf;
+ }
+
+ function update()
+ {
+ graphics.clear();
+ graphics.beginFill(0x000000, 0.5);
+ graphics.drawRect(0,0, this.maxw + 4, this.ofsy);
+ graphics.endFill();
+ }
+
+}
diff --git a/src/com/.svn/text-base/StatusBar.hx.svn-base b/src/com/.svn/text-base/StatusBar.hx.svn-base
new file mode 100644
index 0000000..a7833ee
--- /dev/null
+++ b/src/com/.svn/text-base/StatusBar.hx.svn-base
@@ -0,0 +1,94 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+import flash.text.TextField;
+import flash.text.TextFormat;
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+import com.Component;
+
+class StatusBar extends Component
+{
+ var text:TextField;
+ var timer:Timer;
+
+ public function new()
+ {
+ var format = new TextFormat();
+ format.font = "Arial";
+ format.size = 12;
+
+ text = new TextField();
+ text.defaultTextFormat = format;
+ text.selectable = false;
+ text.border = false;
+ text.background = false;
+ text.textColor = 0x444444;
+ text.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ text.text = '';
+ text.x = 2;
+ text.x = 2;
+ this.addChild(text);
+
+ timer = new Timer(2000, 1);
+ timer.addEventListener(TimerEvent.TIMER, timeOut);
+
+ super();
+ }
+
+ public function clear()
+ {
+ text.text = '';
+ }
+
+ public function setText(s:String)
+ {
+ text.text = s;
+
+ if (timer.running)
+ timer.stop();
+ timer.start();
+ }
+
+ function timeOut(e:flash.events.Event)
+ {
+ clear();
+ }
+
+ override function onResize(w:Float, h:Float)
+ {
+ graphics.clear();
+ graphics.beginFill(0xE0E0E0);
+ graphics.drawRect(0,0,w, h);
+ graphics.endFill();
+ }
+
+}
diff --git a/src/com/.svn/text-base/ToolBar.hx.svn-base b/src/com/.svn/text-base/ToolBar.hx.svn-base
new file mode 100644
index 0000000..0773c59
--- /dev/null
+++ b/src/com/.svn/text-base/ToolBar.hx.svn-base
@@ -0,0 +1,153 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+
+import com.Component;
+import com.Button;
+import flash.text.TextField;
+
+class ToolBar extends Component
+{
+ var ofsx: Float;
+ var spacing: Float;
+ var tf: TextField;
+
+ public function new(leftmargin:Float = 10, spacing:Float = 15)
+ {
+ super();
+
+ this.spacing = spacing;
+ this.ofsx = leftmargin;
+
+ tf = new TextField();
+ tf.y = 5;
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ tf.text = "";
+
+ var fmt = new flash.text.TextFormat();
+ fmt.font="Arial";
+ fmt.size=12;
+ fmt.color = 0xFFFFFF;
+ tf.defaultTextFormat = fmt;
+
+ addChild(tf);
+
+ }
+
+ public function addButton(btn:CustomButton, hint:String = "", onClick:CustomButton->Void = null, space:Int = 0) : CustomButton
+ {
+ var sz = getSize();
+
+ btn.x = this.ofsx;
+ btn.y = 2;
+ btn.hint = hint;
+ btn.onClick = onClick;
+ addChild(btn);
+
+ this.ofsx += btn.width + this.spacing + space;
+
+ return btn;
+ }
+
+ public function addTextField(width:Int = 100, text:String = "", label:String = "", space:Int = 0) : TextField
+ {
+ var sz = getSize();
+
+ if (label != "")
+ {
+ var tf = new TextField();
+ tf.y = 5;
+ tf.x = this.ofsx;
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+
+ var fmt = new flash.text.TextFormat();
+ fmt.font="Arial";
+ fmt.size=12;
+ fmt.color = 0xFFFFFF;
+ tf.defaultTextFormat = fmt;
+ tf.text = label;
+
+ addChild(tf);
+
+ this.ofsx += tf.width + 5;
+
+ }
+
+ var tf = new TextField();
+ tf.x = this.ofsx;
+ tf.y = 5;
+ tf.width = width;
+ tf.height = sz.height - 10;
+ tf.autoSize = flash.text.TextFieldAutoSize.NONE;
+ tf.border = false;
+ tf.background = true;
+ tf.backgroundColor = 0xFFFFFF;
+ tf.multiline = false;
+ tf.type = flash.text.TextFieldType.INPUT;
+ tf.mouseWheelEnabled = false;
+
+ var fmt = new flash.text.TextFormat();
+ fmt.font="Arial";
+ fmt.size=12;
+ fmt.color = 0x000000;
+ tf.defaultTextFormat = fmt;
+ tf.text = text;
+
+ addChild(tf);
+ this.ofsx += width + this.spacing + space;
+
+ return tf;
+ }
+
+ public function addSeparator(size:Int = 10)
+ {
+ ofsx += size;
+ }
+
+ public function setText(text:String)
+ {
+ var sz = getSize();
+
+ tf.text = text;
+ tf.x = sz.width - tf.width - 10;
+ }
+
+ override function onResize(w:Float, h:Float)
+ {
+ graphics.clear();
+ graphics.beginFill(0x000000, 0.5);
+ graphics.drawRect(0,0, w, h);
+ graphics.endFill();
+
+ tf.x = w - tf.width - 10;
+ }
+
+}
diff --git a/src/com/Button.hx b/src/com/Button.hx
new file mode 100644
index 0000000..3b275aa
--- /dev/null
+++ b/src/com/Button.hx
@@ -0,0 +1,431 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+
+import flash.display.Shape;
+import flash.display.Graphics;
+import flash.display.SimpleButton;
+import flash.display.BitmapData;
+import flash.events.MouseEvent;
+import flash.filters.GlowFilter;
+
+
+class UpButton extends CustomButton {
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool) {
+ var h:Float = (2*szh/5.0)/2;
+
+ g.beginFill(color);
+ g.moveTo(midx-4, midy+h);
+ g.lineTo(midx+4, midy+h);
+ g.lineTo(midx, midy-h);
+ g.endFill();
+
+ if (Std.is(this, RightButton)) {
+ curshape.rotation = 90;
+ curshape.x += szh;
+ }
+
+ if (Std.is(this, LeftButton)) {
+ curshape.rotation = 270;
+ curshape.y += szh;
+ }
+
+ if (Std.is(this, DownButton)) {
+ curshape.rotation = 180;
+ curshape.y += szh;
+ curshape.x += szw;
+ }
+
+ }
+}
+
+class RightButton extends UpButton
+{
+}
+
+class LeftButton extends UpButton
+{
+}
+
+class DownButton extends UpButton
+{
+}
+
+class BarButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/2.0)/2;
+
+ g.lineStyle(4, color);
+ g.moveTo(midx, midy-h);
+ g.lineTo(midx, midy+h);
+
+ }
+
+}
+
+class PauseButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/2.5)/2;
+
+ g.lineStyle(2, color);
+ g.moveTo(midx-2, midy-h);
+ g.lineTo(midx-2, midy+h);
+ g.moveTo(midx+2, midy-h);
+ g.lineTo(midx+2, midy+h);
+
+ }
+
+}
+
+
+
+class SaveButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/2.0)/2;
+
+ g.beginFill(color);
+ g.moveTo(midx-h, midy-h);
+ g.lineTo(midx+h, midy-h);
+ g.lineTo(midx+h, midy+h);
+ g.lineTo(midx+h-h/2.0, midy+h);
+ g.lineTo(midx+h-h/2.0, midy+h-h/2);
+ g.lineTo(midx-h+h/2.0, midy+h-h/2);
+ g.lineTo(midx-h+h/2.0, midy+h);
+ g.lineTo(midx-h, midy+h);
+ g.drawRect(midx-h+h/2.0+1, midy+h-h/2+1, h/2, h/2-1);
+ g.endFill();
+ }
+
+}
+
+class PrintButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/1.5)/2;
+ var oy:Float = -3;
+
+ g.beginFill(color);
+ g.moveTo(midx-h, midy+oy);
+ g.lineTo(midx-h+h/2.0, midy+oy);
+ g.lineTo(midx-h+h/2.0, midy+h-h/1.5+oy);
+ g.lineTo(midx+h-h/2.0, midy+h-h/1.5+oy);
+ g.lineTo(midx+h-h/2.0, midy+oy);
+ g.lineTo(midx+h, midy+oy);
+ g.lineTo(midx+h, midy+h+oy);
+ g.lineTo(midx-h, midy+h+oy);
+
+ g.drawRect(midx-h+h/2.0+1, midy-h/2.5+oy, h/2+1, h/2.5+h/1.5-1);
+ g.drawRect(midx-h+h/2.0, midy+h+0.5+oy, h, 2);
+
+ g.endFill();
+ }
+
+}
+
+class MaximizeButton extends CustomButton
+{
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/3.0)/2; // 1/4 vysky zabira symbol
+ g.lineStyle(4, 0x888888);
+ g.drawRect(midx-h-1, midy-h-1,2*h+2,2*h+2);
+
+ g.lineStyle(2, color);
+ g.drawRect(midx-h-1, midy-h-1,2*h+2,2*h+2);
+
+ }
+}
+
+class ZoomInButton extends CustomButton
+{
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ var h:Float = (szh/4.0)/2; // 1/4 vysky zabira symbol
+
+ g.lineStyle(2, color);
+ g.moveTo(midx, midy);
+ g.lineTo(midx+h+4, midy+h+4);
+
+ #if flash9
+ g.moveTo(midx,midy); //bugfix
+ #end
+ g.beginFill(0x888888);
+ g.drawCircle(midx, midy, 2*h);
+ g.endFill();
+
+ if (Std.is(this, SearchButton))
+ return;
+
+ g.moveTo(midx-h, midy);
+ g.lineTo(midx+h, midy);
+
+ if (!Std.is(this, ZoomOutButton))
+ {
+ g.moveTo(midx, midy-h);
+ g.lineTo(midx, midy+h);
+ }
+
+ }
+}
+
+class ZoomOutButton extends ZoomInButton
+{
+}
+
+
+class SearchButton extends ZoomInButton
+{
+}
+
+class TextButton extends CustomButton {
+
+ var text:String;
+
+ public function new(text:String = "", width:Int = 45, size:Int = 25, bgColor:Null = null, bgColorHover:Null = null, fgColor:Int = 0xEEEEEE)
+ {
+ this.text = text;
+ super(size, bgColor, bgColorHover, fgColor);
+ this.szw = width;
+ updateShapes();
+ }
+
+
+ override function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool)
+ {
+ g.clear();
+
+ var tf:flash.text.TextField = new flash.text.TextField();
+ tf.textColor = 0xFFFFFF;
+ tf.background = false;
+ tf.border = false;
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ var fmt = new flash.text.TextFormat();
+ fmt.font = "Arial";
+ fmt.size = 11;
+ fmt.bold = true;
+ tf.defaultTextFormat = fmt;
+ tf.text = this.text;
+
+ var bd:BitmapData = new BitmapData(Std.int(tf.width),Std.int(tf.height), true, 0x00FFFFFF);
+ bd.draw(tf);
+
+ g.lineStyle(Math.NaN);
+ g.beginBitmapFill(bd, null, false);
+ g.drawRect(0, 0, bd.width, bd.height);
+ g.endFill();
+
+ if (checked)
+ {
+ g.lineStyle(2, 0xFFFFFF);
+ g.moveTo(0, bd.height+2);
+ g.lineTo(bd.width, bd.height+2);
+ }
+ }
+}
+
+class CustomButton extends SimpleButton {
+
+ var fgColor:Int;
+ var szw:Float;
+ var szh:Float;
+ var shint:Shape;
+ var curshape:Shape;
+ var canupdate:Bool;
+ public var hint:String;
+ public var checked:Bool;
+ public var onClick:Dynamic;
+ public var bgColor:Null;
+ public var bgColorHover:Null;
+
+ public function new(size:Int = 25, bgColor:Null = null, bgColorHover:Null = null, fgColor:Int = 0xEEEEEE)//0x007BC8)
+ {
+ super();
+ this.canupdate = false;
+ downState = overState = upState = hitTestState = null;
+ this.bgColor = bgColor;
+ this.bgColorHover = bgColorHover;
+ this.fgColor = fgColor;
+ this.szw = (size == 0) ? 4 : size;
+ this.szh = (size == 0) ? 25 : size;
+ this.shint = null;
+ this.hint = "";
+ this.canupdate = true;
+ updateShapes();
+
+ useHandCursor = true;
+ onClick = null;
+ checked = false;
+
+ addEventListener(MouseEvent.CLICK, clicked);
+ addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
+
+ }
+
+ function mouseOver(e:MouseEvent)
+ {
+ removeEventListener(MouseEvent.MOUSE_OVER, mouseOver);
+ addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
+
+ if (this.hint == "") return;
+
+ var tf:flash.text.TextField = new flash.text.TextField();
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ tf.text = hint;
+
+ var bd:BitmapData = new BitmapData(Std.int(tf.width),Std.int(tf.height), true, 0x00FFFFFF); //w,h
+ bd.draw(tf);
+
+ shint = new Shape();
+ shint.graphics.lineStyle(1,0x808080);
+ shint.graphics.beginFill(0xFDFECB);
+ shint.graphics.drawRect(-2,-2, bd.width+4, bd.height+4);
+ shint.graphics.endFill();
+
+ shint.graphics.lineStyle(Math.NaN);
+ shint.graphics.beginBitmapFill(bd, null, false);
+ shint.graphics.drawRect(0, 0, bd.width, bd.height);
+ shint.graphics.endFill();
+
+ var p:flash.geom.Point = localToGlobal(new flash.geom.Point(szw/2, szh+10));
+ if (p.x + shint.width > flash.Lib.current.stage.stageWidth) p.x = flash.Lib.current.stage.stageWidth - shint.width;
+ if (p.y + shint.height > flash.Lib.current.stage.stageHeight) p.y = flash.Lib.current.stage.stageHeight - shint.height - szh;
+ if (p.y < 2) p.y = 2;
+ shint.x = p.x; shint.y = p.y;
+
+ flash.Lib.current.stage.addChild(shint);
+ }
+
+ function mouseOut(e:MouseEvent)
+ {
+ if (shint != null) {
+ flash.Lib.current.stage.removeChild(shint);
+ shint = null;
+ }
+
+ removeEventListener(MouseEvent.MOUSE_OUT, mouseOut);
+ addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
+ }
+
+ function set_BgColor(val:Null) : Null
+ {
+ if (val != bgColor) {
+ bgColor = val;
+ updateShapes();
+ }
+ return val;
+ }
+
+ function set_bgColorHover(val:Null) : Null
+ {
+ if (val != bgColorHover) {
+ bgColorHover = val;
+ updateShapes();
+ }
+ return val;
+ }
+
+ function set_checked(val:Bool) : Bool
+ {
+ if (val != checked) {
+ checked = val;
+ updateShapes();
+ }
+ return val;
+ }
+
+ function updateShapes()
+ {
+ if (!this.canupdate) return;
+ downState = getShape(bgColorHover, fgColor, true);
+ overState = getShape(checked ? 0xFF8000 : bgColorHover, 0xeeeeee /*fgColor*/);
+ overState.filters = [new GlowFilter(0xFFFFFF, 0.75, 5, 5, 2, 2, false, false)];
+ upState = getShape(checked ? 0xFF8000 : bgColor, fgColor);
+ hitTestState = getHitTestShape();
+ }
+
+ public function setSize(w:Float, h:Float)
+ {
+ szw = w;
+ szh = h;
+ updateShapes();
+ }
+
+ function clicked(event:MouseEvent) {
+ if (onClick)
+ onClick(this);
+ }
+
+ function getHitTestShape() {
+ var s = new Shape();
+
+ s.graphics.beginFill(0x000000);
+ s.graphics.drawRect(0, 0, szw, szh);
+ s.graphics.endFill();
+
+ return s;
+ }
+
+ function getShape(bgColor:Null, fgColor:Int, ?down:Bool = false):Shape {
+ curshape = new Shape();
+
+ if (bgColor != null)
+ {
+ curshape.graphics.beginFill(bgColor);
+ curshape.graphics.drawRect(0, 0, szw, szh);
+ curshape.graphics.endFill();
+ }
+
+ var x:Float = szw/2;
+ var y:Float = szh/2;
+
+ if (down) { x += 1; y += 1; }
+
+ drawSymbol(curshape.graphics, fgColor, x, y, down);
+
+ return curshape;
+ }
+
+ function drawSymbol(g:Graphics, color:Int, midx:Float, midy:Float, down:Bool) {
+ }
+}
diff --git a/src/com/Component.hx b/src/com/Component.hx
new file mode 100644
index 0000000..60a6979
--- /dev/null
+++ b/src/com/Component.hx
@@ -0,0 +1,74 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+
+import flash.display.Sprite;
+import flash.geom.Rectangle;
+
+typedef ComponentSize = {
+ var width : Float;
+ var height : Float;
+};
+
+
+class Component extends Sprite
+{
+ var _size : ComponentSize;
+
+ public function new()
+ {
+ super();
+
+ this._size = {width: 100.0, height:100.0};
+ }
+
+ public function move(x:Float, y:Float)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public function setSize(w:Float, h:Float)
+ {
+ this._size.width = w;
+ this._size.height = h;
+ this.onResize(w, h);
+ }
+
+ public function getSize() : ComponentSize
+ {
+ return this._size;
+ }
+
+ function onResize(w:Float, h:Float)
+ {
+ }
+}
diff --git a/src/com/InfoBox.hx b/src/com/InfoBox.hx
new file mode 100644
index 0000000..30e7238
--- /dev/null
+++ b/src/com/InfoBox.hx
@@ -0,0 +1,86 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+
+import com.Component;
+import flash.text.TextField;
+
+class InfoBox extends Component
+{
+ var ofsy : Float;
+ var maxw : Float;
+
+ public function new()
+ {
+ super();
+ this.ofsy = 0;
+ this.maxw = 0;
+ }
+
+ public function addItem(text:String) : TextField
+ {
+ var sz = getSize();
+
+ var fmt = new flash.text.TextFormat();
+ fmt.font="Arial";
+ fmt.size=12;
+ fmt.color = 0xFFFFFF;
+
+ var tf = new TextField();
+ tf.defaultTextFormat = fmt;
+ tf.x = 2;
+ tf.y = this.ofsy;
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ tf.multiline = false;
+ tf.text = text;
+ tf.border = false;
+ tf.background = false;
+
+ addChild(tf);
+
+ if (tf.width > this.maxw) this.maxw = tf.width;
+
+ this.ofsy += tf.height + 1;
+
+ update();
+
+ return tf;
+ }
+
+ function update()
+ {
+ graphics.clear();
+ graphics.beginFill(0x000000, 0.5);
+ graphics.drawRect(0,0, this.maxw + 4, this.ofsy);
+ graphics.endFill();
+ }
+
+}
diff --git a/src/com/StatusBar.hx b/src/com/StatusBar.hx
new file mode 100644
index 0000000..a7833ee
--- /dev/null
+++ b/src/com/StatusBar.hx
@@ -0,0 +1,94 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+import flash.text.TextField;
+import flash.text.TextFormat;
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+import com.Component;
+
+class StatusBar extends Component
+{
+ var text:TextField;
+ var timer:Timer;
+
+ public function new()
+ {
+ var format = new TextFormat();
+ format.font = "Arial";
+ format.size = 12;
+
+ text = new TextField();
+ text.defaultTextFormat = format;
+ text.selectable = false;
+ text.border = false;
+ text.background = false;
+ text.textColor = 0x444444;
+ text.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ text.text = '';
+ text.x = 2;
+ text.x = 2;
+ this.addChild(text);
+
+ timer = new Timer(2000, 1);
+ timer.addEventListener(TimerEvent.TIMER, timeOut);
+
+ super();
+ }
+
+ public function clear()
+ {
+ text.text = '';
+ }
+
+ public function setText(s:String)
+ {
+ text.text = s;
+
+ if (timer.running)
+ timer.stop();
+ timer.start();
+ }
+
+ function timeOut(e:flash.events.Event)
+ {
+ clear();
+ }
+
+ override function onResize(w:Float, h:Float)
+ {
+ graphics.clear();
+ graphics.beginFill(0xE0E0E0);
+ graphics.drawRect(0,0,w, h);
+ graphics.endFill();
+ }
+
+}
diff --git a/src/com/ToolBar.hx b/src/com/ToolBar.hx
new file mode 100644
index 0000000..3af5bf2
--- /dev/null
+++ b/src/com/ToolBar.hx
@@ -0,0 +1,153 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package com;
+
+import com.Component;
+import com.Button;
+import flash.text.TextField;
+
+class ToolBar extends Component
+{
+ var ofsx: Float;
+ var spacing: Float;
+ var tf: TextField;
+
+ public function new(leftmargin:Float = 10, spacing:Float = 15)
+ {
+ super();
+
+ this.spacing = spacing;
+ this.ofsx = leftmargin;
+
+ tf = new TextField();
+ tf.y = 5;
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+ tf.text = "";
+
+ var fmt = new flash.text.TextFormat();
+ fmt.font="Arial";
+ fmt.size=12;
+ fmt.color = 0xFFFFFF;
+ tf.defaultTextFormat = fmt;
+
+ addChild(tf);
+
+ }
+
+ public function addButton(btn:CustomButton, hint:String = "", onClick:CustomButton->Void = null, space:Int = 0) : CustomButton
+ {
+ var sz = getSize();
+
+ btn.x = this.ofsx;
+ btn.y = 2;
+ btn.hint = hint;
+ btn.onClick = onClick;
+ addChild(btn);
+
+ this.ofsx += btn.width + this.spacing + space;
+
+ return btn;
+ }
+
+ public function addTextField(width:Int = 100, text:String = "", label:String = "", space:Int = 0) : TextField
+ {
+ var sz = getSize();
+
+ if (label != "")
+ {
+ var tf = new TextField();
+ tf.y = 5;
+ tf.x = this.ofsx;
+ tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
+
+ var fmt = new flash.text.TextFormat();
+ fmt.font="Arial";
+ fmt.size=12;
+ fmt.color = 0xFFFFFF;
+ tf.defaultTextFormat = fmt;
+ tf.text = label;
+
+ addChild(tf);
+
+ this.ofsx += tf.width + 5;
+
+ }
+
+ var tf = new TextField();
+ tf.x = this.ofsx;
+ tf.y = 5;
+ tf.width = width;
+ tf.height = sz.height - 10;
+ tf.autoSize = flash.text.TextFieldAutoSize.NONE;
+ tf.border = false;
+ tf.background = true;
+ tf.backgroundColor = 0xFFFFFF;
+ tf.multiline = false;
+ tf.type = flash.text.TextFieldType.INPUT;
+ // tf.mouseWheelEnabled = false;
+
+ var fmt = new flash.text.TextFormat();
+ fmt.font="Arial";
+ fmt.size=12;
+ fmt.color = 0x000000;
+ tf.defaultTextFormat = fmt;
+ tf.text = text;
+
+ addChild(tf);
+ this.ofsx += width + this.spacing + space;
+
+ return tf;
+ }
+
+ public function addSeparator(size:Int = 10)
+ {
+ ofsx += size;
+ }
+
+ public function setText(text:String)
+ {
+ var sz = getSize();
+
+ tf.text = text;
+ tf.x = sz.width - tf.width - 10;
+ }
+
+ override function onResize(w:Float, h:Float)
+ {
+ graphics.clear();
+ graphics.beginFill(0x000000, 0.5);
+ graphics.drawRect(0,0, w, h);
+ graphics.endFill();
+
+ tf.x = w - tf.width - 10;
+ }
+
+}
diff --git a/src/map/.svn/all-wcprops b/src/map/.svn/all-wcprops
new file mode 100644
index 0000000..c855f45
--- /dev/null
+++ b/src/map/.svn/all-wcprops
@@ -0,0 +1,59 @@
+K 25
+svn:wc:ra_dav:version-url
+V 34
+/svn/!svn/ver/3/trunk/haxemaps/map
+END
+LngLat.hx
+K 25
+svn:wc:ra_dav:version-url
+V 44
+/svn/!svn/ver/2/trunk/haxemaps/map/LngLat.hx
+END
+TileLoader.hx
+K 25
+svn:wc:ra_dav:version-url
+V 48
+/svn/!svn/ver/2/trunk/haxemaps/map/TileLoader.hx
+END
+QuadTree.hx
+K 25
+svn:wc:ra_dav:version-url
+V 46
+/svn/!svn/ver/2/trunk/haxemaps/map/QuadTree.hx
+END
+TileLayer.hx
+K 25
+svn:wc:ra_dav:version-url
+V 47
+/svn/!svn/ver/2/trunk/haxemaps/map/TileLayer.hx
+END
+Canvas.hx
+K 25
+svn:wc:ra_dav:version-url
+V 44
+/svn/!svn/ver/2/trunk/haxemaps/map/Canvas.hx
+END
+Layer.hx
+K 25
+svn:wc:ra_dav:version-url
+V 43
+/svn/!svn/ver/3/trunk/haxemaps/map/Layer.hx
+END
+Tile.hx
+K 25
+svn:wc:ra_dav:version-url
+V 42
+/svn/!svn/ver/2/trunk/haxemaps/map/Tile.hx
+END
+MapService.hx
+K 25
+svn:wc:ra_dav:version-url
+V 48
+/svn/!svn/ver/2/trunk/haxemaps/map/MapService.hx
+END
+Utils.hx
+K 25
+svn:wc:ra_dav:version-url
+V 43
+/svn/!svn/ver/2/trunk/haxemaps/map/Utils.hx
+END
diff --git a/src/map/.svn/entries b/src/map/.svn/entries
new file mode 100644
index 0000000..b95de7f
--- /dev/null
+++ b/src/map/.svn/entries
@@ -0,0 +1,334 @@
+10
+
+dir
+5
+http://haxemaps.googlecode.com/svn/trunk/haxemaps/map
+http://haxemaps.googlecode.com/svn
+
+
+
+2010-04-03T15:29:27.879189Z
+3
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+91f78bee-1f10-11df-98cf-3116c4ba2102
+
+LngLat.hx
+file
+
+
+
+
+2013-10-31T20:25:12.966822Z
+0d948ef67ee65767bba19957173fa83a
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3248
+
+TileLoader.hx
+file
+
+
+
+
+2013-10-31T20:25:12.968822Z
+b5d51e3dc095209a5e815d90c33491a0
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+14780
+
+QuadTree.hx
+file
+
+
+
+
+2013-10-31T20:25:12.970822Z
+27188120784e114b158fe9b5a9a13986
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7971
+
+TileLayer.hx
+file
+
+
+
+
+2013-10-31T20:25:12.978822Z
+bfb7209e02852624fd4326257eaa34f3
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+18922
+
+Canvas.hx
+file
+
+
+
+
+2013-10-31T20:25:12.980822Z
+e9fcf8b1844d9e392f018aa574e5df45
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+19335
+
+Layer.hx
+file
+
+
+
+
+2013-10-31T20:25:12.981822Z
+e4fedb9fb050d1c22c4b3723404e1a12
+2010-04-03T15:29:27.879189Z
+3
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+15302
+
+Tile.hx
+file
+
+
+
+
+2013-10-31T20:25:12.983822Z
+0dbe88817f1d78c0eec00931428612b4
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5331
+
+MapService.hx
+file
+
+
+
+
+2013-10-31T20:25:12.985822Z
+171ec2f13bcd6cb833321e02c4a1a6ed
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7362
+
+Utils.hx
+file
+
+
+
+
+2013-10-31T20:25:12.986822Z
+eb95ae08373af5cf08d9ce98a97e331b
+2010-03-13T13:28:15.676966Z
+2
+vzdenek@seznam.cz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2859
+
diff --git a/src/map/.svn/text-base/Canvas.hx.svn-base b/src/map/.svn/text-base/Canvas.hx.svn-base
new file mode 100644
index 0000000..a0d3987
--- /dev/null
+++ b/src/map/.svn/text-base/Canvas.hx.svn-base
@@ -0,0 +1,666 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import com.Component;
+
+import map.MapService;
+import map.LngLat;
+import flash.events.Event;
+import flash.events.MouseEvent;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+import flash.display.Shape;
+import flash.display.BitmapData;
+
+typedef ALayer = {
+ var layer : Layer;
+ var enabled : Bool;
+}
+
+class MapEvent extends flash.events.Event
+{
+ public static var MAP_CLICKED:String = "mapclicked";
+ public static var MAP_MOUSEMOVE:String = "mapmousemove";
+ public static var MAP_MOVE:String = "mapmove";
+ public static var MAP_ZOOMCHANGED:String = "mapzoom";
+ public static var MAP_CHANGED:String = "mapchanged";
+
+ public var point:LngLat;
+
+ public function new(event:String, point:LngLat = null) {
+ super(event);
+ this.point = point;
+ }
+}
+
+
+class Canvas extends Component
+{
+ var layers:Array;
+ var start:Point;
+ var initialized:Bool;
+ var zoom:Int;
+ var animTimer : Timer;
+ var animTo:LngLat;
+ var center:LngLat;
+ var thpassed:Bool;
+ var thtimer:Timer;
+ var mappoint:LngLat;
+ public var mousethreshold:Int; //the minimal number of pixels that have to be passed in order to start moving
+ public var transparent(default, setTransparent):Bool;
+
+ public function new(interactive:Bool = true)
+ {
+ super();
+
+ this.initialized = false;
+ this.start = null;
+ this.zoom = 0;
+ this.mousethreshold = 5;
+ this.thpassed = false;
+ this.thtimer = null;
+ this.animTimer = new Timer(50, 0);
+ this.center = new LngLat(16.722079,49.577496);
+ this.layers = new Array();
+ this.doubleClickEnabled = true;
+ this.transparent = false;
+
+ contextMenu = new flash.ui.ContextMenu();
+ contextMenu.hideBuiltInItems();
+ var itm = new flash.ui.ContextMenuItem("HaxeMaps");
+ itm.addEventListener(flash.events.ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e) { flash.Lib.getURL(new flash.net.URLRequest("http://code.google.com/p/haxemaps/")); });
+ contextMenu.customItems.push(itm);
+ var itm = new flash.ui.ContextMenuItem(" (C) 2010");
+ itm.enabled = false;
+ contextMenu.customItems.push(itm);
+
+ if (interactive)
+ {
+ addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
+ addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
+ addEventListener(MouseEvent.DOUBLE_CLICK, onMouseDoubleClick);
+
+ var me = this;
+ var itm = new flash.ui.ContextMenuItem("HaxeMaps - zoom in");
+ itm.separatorBefore = true;
+ itm.addEventListener(flash.events.ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e) { me.zoomIn(); });
+ contextMenu.customItems.push(itm);
+ var itm = new flash.ui.ContextMenuItem("HaxeMaps - Zoom out");
+ itm.addEventListener(flash.events.ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e) { me.zoomOut(); });
+ contextMenu.customItems.push(itm);
+
+ }
+ }
+
+ /*==============================================================================================
+ LAYER MANAGEMENT
+ *==============================================================================================*/
+ public function initialize()
+ {
+ if (initialized)
+ return;
+
+ var m:MapService = null;
+
+ //find the first defined service
+ for (l in layers)
+ if (l.layer.mapservice != null)
+ {
+ m = l.layer.mapservice;
+ break;
+ }
+
+ //Check if there is a layer containing mapservice
+ if (m == null)
+ return;
+
+ //initialize the layers
+ for (l in layers)
+ {
+ if (l.layer.mapservice == null)
+ l.layer.mapservice = m;
+
+ if (l.enabled)
+ {
+ initializeLayer(l);
+ addChild(l.layer);
+ }
+ }
+
+ initialized = true;
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+
+ public function addLayer(layer:Layer, enable:Bool=true)
+ {
+ for (l in layers)
+ if (l.layer == layer)
+ return;
+
+ var alayer:ALayer = {layer:layer, enabled:false};
+ layers.push(alayer);
+ layer.addEventListener(Layer.ZOOM_FINISHED, zoomFinished);
+
+ if ((initialized) && (enable)) //synchronize
+ {
+ initializeLayer(alayer);
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+
+ alayer.enabled = enable;
+ }
+
+ public function removeLayer(layer:Layer)
+ {
+ for (l in layers)
+ {
+ if (l.layer == layer)
+ {
+ removeChild(layer);
+ layer.removeEventListener(Layer.ZOOM_FINISHED, zoomFinished);
+ layer.clear();
+ layers.remove(l);
+ return;
+ }
+ }
+ }
+
+ public function enableLayer(layer:Layer)
+ {
+ var childidx = 0;
+ for (i in 0...layers.length)
+ {
+
+ var l:ALayer = layers[i];
+ if (l.layer == layer)
+ {
+ if (l.enabled)
+ break;
+
+ l.enabled = true;
+
+ if (initialized)
+ {
+ initializeLayer(l, false);
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+
+ if (i == layers.length - 1)
+ addChild(l.layer);
+ else
+ addChildAt(l.layer, childidx);
+ return;
+ }
+
+ if (l.enabled)
+ childidx++;
+ }
+ }
+
+ public function disableLayer(layer:Layer)
+ {
+ for (l in layers)
+ if (l.layer == layer)
+ {
+ if (!l.enabled)
+ break;
+
+ removeChild(l.layer);
+ l.layer.clear();
+ l.enabled = false;
+
+ return;
+ }
+ }
+
+ public function updateLayer(layer:Layer)
+ {
+ for (l in layers)
+ if (l.layer == layer)
+ {
+ if (l.enabled)
+ l.layer.update();
+ return;
+ }
+
+ }
+
+ public function layerEnabled(layer:Layer)
+ {
+ for (l in layers)
+ if (l.layer == layer)
+ return l.enabled;
+
+ return false;
+ }
+
+ function initializeLayer(alayer:ALayer, canAdd:Bool = true)
+ {
+ if (alayer.layer.mapservice == null)
+ {
+ for (l in layers)
+ if (l.layer.mapservice != null)
+ {
+ alayer.layer.mapservice = l.layer.mapservice;
+ break;
+ }
+ }
+
+ if (alayer.layer.mapservice == null)
+ return;
+
+ var sz = getSize();
+ var center:LngLat = this.center;
+
+ if (initialized)
+ {
+ //synchronize position
+ for (l in layers)
+ if ((l != alayer) && (l.enabled) && (l.layer.mapservice != null))
+ {
+ center = l.layer.getCenter();
+ //trace("Init new center:"+center);
+ break;
+ }
+ }
+
+ alayer.layer.finalize();
+ alayer.layer.setCenter(center);
+ alayer.layer.setBBox(new Rectangle(0,0,sz.width,sz.height));
+ alayer.layer.setZoom(this.zoom);
+ alayer.layer.initialize();
+
+ if ((!alayer.enabled) && (canAdd))
+ addChild(alayer.layer);
+ }
+
+ /*==============================================================================================
+ POSITION / ZOOM
+ *==============================================================================================*/
+ public function zoomIn()
+ {
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(this.zoom + 1)))
+ return;
+
+ this.zoom += 1;
+ for (l in layers)
+ if (l.enabled)
+ l.layer.zoomIn();
+ }
+
+ public function zoomOut()
+ {
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(this.zoom - 1)))
+ return;
+
+ this.zoom -= 1;
+ for (l in layers)
+ if (l.enabled)
+ l.layer.zoomOut();
+ }
+
+ public function getZoom() : Int
+ {
+ return this.zoom;
+ }
+
+ public function getMinZoom() : Int
+ {
+ var z:Int = this.zoom - 1;
+ while (z > -16)
+ {
+ var vld:Bool = true;
+
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(z)))
+ {
+ vld = false;
+ break;
+ }
+
+ if (!vld)
+ break;
+
+ z--;
+ }
+
+ return z + 1;
+ }
+
+ public function getMaxZoom() : Int
+ {
+ var z:Int = this.zoom + 1;
+ while (z > -16)
+ {
+ var vld:Bool = true;
+
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(z)))
+ {
+ vld = false;
+ break;
+ }
+
+ if (!vld)
+ break;
+
+ z++;
+ }
+
+ return z - 1;
+ }
+
+ public function setZoom(zoom:Int)
+ {
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(zoom)) && (l.layer.mapservice != null))
+ return;
+
+ this.zoom = zoom;
+
+ if (!initialized) return;
+
+ for (l in layers)
+ if (l.enabled)
+ l.layer.setZoom(this.zoom);
+ }
+
+ public function setCenter(point:LngLat)
+ {
+ if (!initialized)
+ {
+ center = point;
+ return;
+ }
+
+ for (l in layers)
+ if (l.enabled)
+ l.layer.setCenter(point);
+
+
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+
+ public function getCenter(): LngLat
+ {
+ var c:LngLat = center.clone();
+ if (initialized)
+ for (l in layers)
+ if (l.enabled)
+ {
+ c = l.layer.getCenter();
+ break;
+ }
+
+ return c;
+ }
+
+ public function getLngLat(global:Point) : LngLat
+ {
+ if (initialized)
+ for (l in layers)
+ if (l.enabled)
+ return l.layer.getLngLat(l.layer.globalToLocal(global));
+ return null;
+ }
+
+ public function getLeftTopCorner() : LngLat
+ {
+ return getLngLat(localToGlobal(new Point(0,0)));
+ }
+
+ public function getRightBottomCorner() : LngLat
+ {
+ var sz = getSize();
+ return getLngLat(localToGlobal(new Point(sz.width,sz.height)));
+ }
+
+ public function panTo(point:LngLat)
+ {
+ if (this.animTimer.running)
+ {
+ this.animTo = point.clone();
+ return;
+ }
+
+ for (l in layers)
+ if (l.enabled)
+ {
+ this.animTo = point.clone();
+ this.animTimer.addEventListener(TimerEvent.TIMER, animStep);
+ this.animTimer.start();
+
+ return;
+ }
+ }
+
+
+ public function getBitmap() : BitmapData
+ {
+ var sz = getSize();
+ var bmp:BitmapData = new BitmapData(Std.int(sz.width), Std.int(sz.height), false, 0x00FFFFFF);
+ bmp.draw(this);
+ return bmp;
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+ function setTransparent(val:Bool): Bool
+ {
+ this.transparent = val;
+
+ graphics.clear();
+ if (this.transparent)
+ return true;
+
+ var sz = getSize();
+ graphics.beginFill(0xFFFFFF);
+ graphics.drawRect(0,0,sz.width,sz.height);
+ graphics.endFill();
+
+ return this.transparent;
+ }
+
+ override function onResize(w:Float, h:Float)
+ {
+ setTransparent(this.transparent);
+ scrollRect = new Rectangle(0, 0, w, h);
+
+ //trace("Canvas resized w:"+w+" h:"+h);
+ for (l in layers)
+ l.layer.setBBox(new Rectangle(0,0,w,h));
+ }
+
+ function onMouseDown(e:MouseEvent)
+ {
+ var tl:Point = localToGlobal(new Point(0,0));
+ var br:Point = localToGlobal(new Point(width, height));
+
+ start = new Point(e.stageX, e.stageY);
+ thpassed = false;
+
+ removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
+ removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
+ flash.Lib.current.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
+ flash.Lib.current.stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
+ }
+
+ function onMouseUp(e:MouseEvent)
+ {
+ addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
+ addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
+ flash.Lib.current.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
+ flash.Lib.current.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
+
+ if ((!thpassed) && (thtimer == null))
+ {
+ mappoint = getLngLat(new Point(e.stageX, e.stageY));
+ thtimer = new Timer(300, 1);
+ thtimer.addEventListener(TimerEvent.TIMER_COMPLETE, fireMapClicked);
+ thtimer.start();
+ }
+ }
+
+ function fireMapClicked(e:TimerEvent)
+ {
+ dispatchEvent(new MapEvent(MapEvent.MAP_CLICKED, mappoint));
+
+ if (thtimer != null)
+ {
+ thtimer.stop();
+ thtimer.removeEventListener(TimerEvent.TIMER_COMPLETE, fireMapClicked);
+ thtimer = null;
+ }
+ }
+
+ function onMouseDoubleClick(e:MouseEvent)
+ {
+ if (!doubleClickEnabled) return;
+
+ if (thtimer != null)
+ {
+ thtimer.stop();
+ thtimer.removeEventListener(TimerEvent.TIMER_COMPLETE, fireMapClicked);
+ thtimer = null;
+ }
+
+ if (e.ctrlKey)
+ zoomOut()
+ else
+ zoomIn();
+ }
+
+ function onMouseMove(e:MouseEvent)
+ {
+ for (l in layers)
+ if (l.enabled)
+ {
+ var pt = l.layer.globalToLocal(new Point(e.stageX, e.stageY));
+ dispatchEvent(new MapEvent(MapEvent.MAP_MOUSEMOVE, l.layer.getLngLat(pt)));
+ return;
+ }
+ }
+
+ function onStageMouseMove(e:MouseEvent)
+ {
+ var pt:Point = new Point(e.stageX, e.stageY);
+
+ if (!thpassed)
+ {
+ if (Point.distance(pt, start) < this.mousethreshold)
+ return;
+ start = pt;
+ thpassed = true;
+ return;
+ }
+
+ animStop();
+
+ var diff = pt.subtract(start);
+ var cntr:LngLat = null;
+
+ for (l in layers)
+ if (l.enabled)
+ {
+ try
+ {
+ l.layer.moveRelative(diff.x, diff.y);
+ cntr = l.layer.getCenter();
+ center = cntr;
+ }
+ catch (unknown : Dynamic)
+ {}
+ }
+
+ if (cntr != null)
+ {
+ dispatchEvent(new MapEvent(MapEvent.MAP_MOVE, cntr));
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+ start = pt;
+ }
+
+
+ function animStop()
+ {
+ if (animTimer.running)
+ {
+ animTimer.stop();
+ animTimer.removeEventListener(TimerEvent.TIMER, animStep);
+ }
+ }
+
+ function animStep(e:flash.events.Event)
+ {
+ for (l in layers)
+ if (l.enabled)
+ {
+ try {
+ var a:Point = l.layer.getCenterXY();
+ var b:Point = l.layer.getPointXY(animTo);
+ var dist:Float = Point.distance(a, b);
+ if (dist < 1.0)
+ animStop();
+ a = a.subtract(b);
+
+ var k:Float = (dist < 5) ? 1.0 : ((dist < 10) ? 5.0 : 10.0);
+ a.x = a.x / k;
+ if (a.x < -64) a.x = -64;
+ if (a.x > 64) a.x = 64;
+ a.y = a.y / k;
+ if (a.y < -64) a.y = -64;
+ if (a.y > 64) a.y = 64;
+
+ l.layer.moveRelative(a.x, a.y);
+
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+ catch (unknown : Dynamic)
+ {}
+ }
+ }
+
+
+ function zoomFinished(e:Event)
+ {
+ dispatchEvent(new MapEvent(MapEvent.MAP_ZOOMCHANGED, null));
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+}
diff --git a/src/map/.svn/text-base/Layer.hx.svn-base b/src/map/.svn/text-base/Layer.hx.svn-base
new file mode 100644
index 0000000..21dafa6
--- /dev/null
+++ b/src/map/.svn/text-base/Layer.hx.svn-base
@@ -0,0 +1,522 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import flash.display.Sprite;
+import flash.events.Event;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+import map.Utils;
+import map.LngLat;
+
+class Layer extends Sprite
+{
+ public static var ZOOM_FINISHED:String = "zoomfinished";
+
+ public var bbox(default, null):Rectangle;
+ var zoom:Int;
+ var animTimer:Timer;
+ var animState:Int;
+ var animTmp:Float;
+ var initialized:Bool;
+ var updateEnabled:Bool;
+ var center:LngLat;
+ var lastcenter:LngLat;
+ var canvascenter:Point;
+ var lastxy:Point;
+ var lastcxy:Point;
+ var scalable:Bool;
+ public var mapservice:MapService;
+
+ public function new(map_service:MapService = null, scalable:Bool = false)
+ {
+ super();
+
+ this.scalable = scalable;
+ this.mapservice = map_service;
+ this.initialized = false;
+ this.updateEnabled = false;
+ this.bbox = new Rectangle(0,0,flash.Lib.current.stage.width, flash.Lib.current.stage.height);
+ this.canvascenter = new Point(this.bbox.width/2.0,this.bbox.height/2.0);
+ this.center = null;
+ this.zoom = 0;
+ this.lastxy = null;
+ this.lastcxy = null;
+
+ animTimer = new Timer(15, 0);
+ animTimer.addEventListener(TimerEvent.TIMER, animStep);
+
+ mouseEnabled = false;
+
+ }
+
+ /*==============================================================================================
+ INITIALIZATION / FINALIZATION / MISC
+ *==============================================================================================*/
+
+ public function initialize(update:Bool=true) : Int
+ {
+
+ if (mapservice == null)
+ return 1;
+
+ if (this.initialized)
+ finalize();
+
+ this.x = this.canvascenter.x;
+ this.y = this.canvascenter.y;
+
+ synchronizeScale(true);
+
+ if (Std.is(this, Layer))
+ {
+ this.initialized = true;
+ if (!this.updateEnabled)
+ {
+ this.updateEnabled = true;
+ updateChanged();
+ }
+
+ if (update)
+ updateContent(true);
+ }
+
+ return 0;
+ }
+
+ public function finalize()
+ {
+ if (this.initialized)
+ clear();
+
+ this.initialized = false;
+ }
+
+
+ public function setBBox(bbox:Rectangle)
+ {
+ if (bbox == null)
+ return;
+
+ var actcenter:LngLat = null;
+ if ((this.bbox != null) && (this.initialized))
+ actcenter = this.getCenter();
+
+ this.bbox = bbox;
+ this.canvascenter = new Point(this.bbox.x + this.bbox.width/2.0, this.bbox.y + this.bbox.height/2.0);
+
+ if (actcenter != null)
+ this.setCenter(actcenter);
+ }
+
+
+ public function clear()
+ {
+ }
+
+ /*==============================================================================================
+ POSITION
+ *==============================================================================================*/
+
+ public function getOriginXY() : Point
+ {
+ if (this.mapservice == null)
+ return new Point(0,0);
+
+ return mapservice.lonlat2XY(center.lng, center.lat, mapservice.zoom_def + zoom);
+ }
+
+ public function getCenterXY() : Point
+ {
+ var pta:Point = getOriginXY();
+ pta.offset(-x + this.canvascenter.x, - y + this.canvascenter.y);
+ return pta;
+ }
+
+ public function getPointXY(point:LngLat) : Point
+ {
+ if (this.mapservice == null)
+ return new Point(0,0);
+
+ return mapservice.lonlat2XY(point.lng, point.lat, mapservice.zoom_def + zoom);
+ }
+
+ public function getCenter() : LngLat
+ {
+ if (this.mapservice == null)
+ return null;
+
+ if ((x == this.canvascenter.x) && (y == this.canvascenter.y))
+ return center.clone();
+
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = getCenterXY();
+ var ptb:LonLat = mapservice.XY2lonlat(pta.x, pta.y, z);
+
+ return new LngLat(ptb.x, ptb.y);
+ }
+
+ public function getXY(local:Point) : Point
+ {
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = mapservice.lonlat2XY(center.lng, center.lat, z);
+ pta.offset(scaleX*local.x, scaleY*local.y);
+ return pta;
+ }
+
+ public function getLngLat(local:Point) : LngLat
+ {
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = mapservice.lonlat2XY(center.lng, center.lat, z);
+ var ptb:Point = mapservice.XY2lonlat(pta.x + scaleX*local.x, pta.y + scaleY*local.y, z);
+ return new LngLat(ptb.x, ptb.y);
+ }
+
+ public function setCenter(point:LngLat)
+ {
+ if ((this.scalable) && (initialized))
+ synchronizeCenter(point);
+ else
+ this.center = point.clone();
+ centerUpdated(true);
+ }
+
+ public function moveTo(x:Float, y:Float)
+ {
+ if ((this.animTimer.running) || ((this.x == x) && (this.y == y)))
+ return;
+
+
+ this.x = x;
+ this.y = y;
+
+ if (this.updateEnabled)
+ updateContent();
+ }
+
+ public function moveRelative(dx:Float, dy:Float)
+ {
+ if ((this.animTimer.running) || ((dx == 0) && (dy == 0)))
+ return;
+
+ this.x += dx;
+ this.y += dy;
+
+ if (this.updateEnabled)
+ updateContent();
+ }
+
+ public function getOffset() : Point
+ {
+ return new Point(this.x - this.canvascenter.x, this.y - this.canvascenter.y);
+ }
+
+ public function getLeftTopCorner(margin:Float = 0.0) : LngLat
+ {
+ if (!initialized) return null;
+
+ var x:Float = this.canvascenter.x - this.x - this.bbox.width/2.0 + margin;
+ var y:Float = this.canvascenter.y - this.y - this.bbox.height/2.0 + margin;
+
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = mapservice.lonlat2XY(center.lng, center.lat, z);
+ var ptb:Point = mapservice.XY2lonlat(pta.x + scaleX*x, pta.y + scaleY*y, z);
+
+ return new LngLat(ptb.x, ptb.y);
+ }
+
+ public function getRightBottomCorner(margin:Float = 0.0) : LngLat
+ {
+ if (!initialized) return null;
+
+ var x:Float = this.canvascenter.x - this.x + this.bbox.width/2.0 + margin;
+ var y:Float = this.canvascenter.y - this.y + this.bbox.height/2.0 + margin;
+
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = mapservice.lonlat2XY(center.lng, center.lat, z);
+ var ptb:Point = mapservice.XY2lonlat(pta.x + scaleX*x, pta.y + scaleY*y, z);
+
+ return new LngLat(ptb.x, ptb.y);
+ }
+
+
+ /*==============================================================================================
+ ZOOM
+ *==============================================================================================*/
+
+ public function validZoom(zoom:Int) : Bool
+ {
+ return ((!this.animTimer.running) && (this.mapservice != null) && (this.mapservice.validZoom(zoom)));
+ }
+
+ public function setZoom(zoom:Int)
+ {
+ if (!validZoom(zoom)) return;
+
+ this.zoom = zoom;
+ if (this.scalable)
+ synchronizeScale();
+
+ if (!this.initialized)
+ return;
+
+ this.center = getCenter(); //get actual center & update layer content
+ centerUpdated(true);
+ }
+
+ public function zoomIn(animate:Bool = true)
+ {
+ if ((this.animTimer.running) || (!this.initialized) || (this.mapservice == null) || (!this.mapservice.validZoom(zoom+1)))
+ return;
+
+ this.lastxy = new Point(x,y);
+ this.lastcenter = getCenter();
+ this.lastcxy = new Point(this.canvascenter.x, this.canvascenter.y);
+
+ if (!animate)
+ {
+ scaleX = scaleX * 2.0;
+ scaleY = scaleY * 2.0;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) * 2.0;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) * 2.0;
+
+ zoomChanged(this.updateEnabled, zoom + 1);
+
+ return;
+ }
+
+
+ this.animState = 0x0000;
+
+ if (this.updateEnabled)
+ {
+ this.updateEnabled = false;
+ updateChanged();
+ this.animState += 0x0100;
+ }
+
+ this.animTmp = scaleX;
+ this.animTimer.start();
+ }
+
+ public function zoomOut(animate:Bool = true)
+ {
+ if ((this.animTimer.running) || (!this.initialized) || (this.mapservice == null) || (!this.mapservice.validZoom(zoom-1)))
+ return;
+
+ this.lastxy = new Point(x,y);
+ this.lastcenter = getCenter();
+ this.lastcxy = new Point(this.canvascenter.x, this.canvascenter.y);
+
+ if (!animate)
+ {
+ scaleX = scaleX / 2.0;
+ scaleY = scaleY / 2.0;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) / 2.0;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) / 2.0;
+
+ zoomChanged(this.updateEnabled, zoom - 1);
+
+ return;
+ }
+
+ this.animState = 0x1000;
+ if (this.updateEnabled)
+ {
+ this.updateEnabled = false;
+ updateChanged();
+ this.animState += 0x0100;
+ }
+
+ this.animTmp = scaleX;
+ this.animTimer.start();
+ }
+
+ public function update()
+ {
+ updateContent(true);
+ }
+
+ /*==============================================================================================
+ PRIVATE
+ *==============================================================================================*/
+ function updateContent(forceUpdate:Bool=false)
+ {
+ }
+
+ function updateChanged()
+ {
+ }
+
+ function zoomChanged(prevEnabled:Bool, newZoom:Int)
+ {
+ this.zoom = newZoom;
+ if (!scalable)
+ {
+ scaleX = scaleY = 1.0;
+
+ center = this.lastcenter;
+ centerUpdated(false);
+ }
+ else
+ synchronizeCenter(this.lastcenter);
+
+ dispatchEvent(new Event(ZOOM_FINISHED));
+
+ if ((prevEnabled) && (!this.updateEnabled))
+ {
+ this.updateEnabled = true;
+ updateContent(!scalable);
+ updateChanged();
+ }
+ }
+
+ /*==============================================================================================
+ PRIVATE
+ *==============================================================================================*/
+
+ function synchronizeCenter(point:LngLat)
+ {
+ if (!this.scalable)
+ return;
+
+ var pta:Point = getOriginXY();
+ var ptb:Point = getPointXY(point);
+ this.x = pta.x - ptb.x + canvascenter.x;
+ this.y = pta.y - ptb.y + canvascenter.y;
+ }
+
+ function synchronizeScale(init:Bool=false)
+ {
+
+ if (this.scalable)
+ {
+ if (this.zoom < 0) {
+ scaleX = 1.0 / (1 << (-this.zoom));
+ scaleY = 1.0 / (1 << (-this.zoom));
+ } else {
+ scaleX = (1 << this.zoom);
+ scaleY = (1 << this.zoom);
+ }
+
+ }
+ else if ((!this.scalable) && (init))
+ {
+ this.scaleX = 1.0;
+ this.scaleY = 1.0;
+ }
+
+ }
+
+ function centerUpdated(clearQueue:Bool)
+ {
+ if (!this.initialized)
+ return;
+
+ if (!this.scalable)
+ {
+ this.x = this.canvascenter.x;
+ this.y = this.canvascenter.y;
+ }
+
+ if (this.updateEnabled)
+ updateContent((clearQueue) && (!scalable));
+ }
+
+ function animStep(e:flash.events.Event)
+ {
+ var steps:Float = 10.0;
+
+ var act = (animState >> 12) & 0x0F;
+ var en = (animState >> 8) & 0x0F;
+ var st = (animState & 0xFF);
+
+ if (act == 0)
+ {
+ if (st < steps)
+ {
+ var scale:Float = (1.0 + (st + 1)/steps);
+
+ scaleX = animTmp * scale;
+ scaleY = scaleX;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) * scale;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) * scale;
+
+ animState += 1;
+ }
+ else if (st == steps)
+ {
+ animTimer.stop();
+
+ scaleX = animTmp * 2.0;
+ scaleY = animTmp * 2.0;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) * 2.0;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) * 2.0;
+
+ zoomChanged(en == 1, zoom + 1);
+ }
+ }
+ else if (act == 1)
+ {
+ if (st < steps)
+ {
+ var scale:Float = (1.0 + (st + 1)/steps);
+
+ scaleX = animTmp / scale;
+ scaleY = scaleX;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) / scale;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) / scale;
+
+ animState += 1;
+ }
+ else if (st == steps)
+ {
+ animTimer.stop();
+
+ scaleX = animTmp / 2.0;
+ scaleY = animTmp / 2.0;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) / 2.0;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) / 2.0;
+
+ zoomChanged(en == 1, zoom - 1);
+ }
+ }
+ }
+
+}
diff --git a/src/map/.svn/text-base/LngLat.hx.svn-base b/src/map/.svn/text-base/LngLat.hx.svn-base
new file mode 100644
index 0000000..7d16363
--- /dev/null
+++ b/src/map/.svn/text-base/LngLat.hx.svn-base
@@ -0,0 +1,85 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+class LngLat
+{
+ public var lat: Float;
+ public var lng: Float;
+
+ public function new(lng:Float, lat:Float)
+ {
+ this.lng = lng;
+ this.lat = lat;
+ }
+
+ inline public function clone()
+ {
+ return new LngLat(this.lng, this.lat);
+ }
+
+ public function toString():String
+ {
+
+ return "[LngLat] lng:" + fmtCoordinate(this.lng) + " lat:" + fmtCoordinate(this.lat);
+ }
+
+ //convert coordinate to string (format %.6f)
+ static public function fmtCoordinate(value:Float) : String
+ {
+ var valuef:Float = Math.floor(value);
+ var f:Float = value - valuef;
+ var s:String = Std.string(valuef) + ".";
+ for (i in 0...6)
+ {
+ f *= 10.0;
+ s += Std.string(Math.floor(f));
+ f = f - Math.floor(f);
+ }
+ return s;
+ }
+
+ //distance between two points in meters
+ static public function distance(a:LngLat, b:LngLat) : Float
+ {
+ var dlat:Float = (b.lat - a.lat) * Math.PI / 180;
+ var dlon:Float = (b.lng - a.lng) * Math.PI / 180;
+
+ dlat = Math.sin(dlat/2);
+ dlon = Math.sin(dlon/2);
+ var a:Float = dlat*dlat + Math.cos(a.lat * Math.PI / 180 ) * Math.cos(b.lat * Math.PI / 180 ) * dlon*dlon;
+ var c:Float = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
+ c = 6371000.0 * c; //avg. radius of the earth in meters
+
+ return c;
+ }
+
+}
diff --git a/src/map/.svn/text-base/MapService.hx.svn-base b/src/map/.svn/text-base/MapService.hx.svn-base
new file mode 100644
index 0000000..80c555e
--- /dev/null
+++ b/src/map/.svn/text-base/MapService.hx.svn-base
@@ -0,0 +1,211 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import map.Utils;
+import flash.geom.Point;
+
+interface MapService
+{
+ var id(default,null):String;
+ var zoom_min(default,null):Int;
+ var zoom_max(default,null):Int;
+ var zoom_def(default,null):Int;
+ var tile_size(default,null):Int;
+ var invert_x(default,null):Bool;
+ var invert_y(default,null):Bool;
+
+ function lonlat2tile(lon:Float, lat:Float, zoom:Int) : TileID;
+ function tile2lonlat(t:TileID) : LonLat;
+ function lonlat2XY(lon:Float, lat:Float, zoom:Int) : Point;
+ function XY2lonlat(x:Float, y:Float, zoom:Int) : LonLat;
+ function validZoom(z:Int) : Bool;
+ function tile2url(t:TileID) : String;
+}
+
+class BaseMapService {
+
+ public var id(default,null):String;
+ public var zoom_min(default,null):Int;
+ public var zoom_max(default,null):Int;
+ public var zoom_def(default,null):Int;
+ public var tile_size(default,null):Int;
+ public var invert_x(default,null):Bool;
+ public var invert_y(default,null):Bool;
+
+ var proxy:Bool;
+ var proxy_url:String;
+
+ public function new(id:String, abbrev:String, zoom_min:Int, zoom_max:Int, zoom_def:Int, tile_size:Int=256)
+ {
+ setInfo(id, abbrev, zoom_min, zoom_max, zoom_def, tile_size);
+ }
+
+ function setInfo(id:String, abbrev:String, zoom_min:Int, zoom_max:Int, zoom_def:Int, tile_size:Int=256)
+ {
+ this.id = id;
+ this.zoom_min = zoom_min;
+ this.zoom_max = zoom_max;
+ this.zoom_def = zoom_def;
+ this.tile_size = tile_size;
+ this.invert_x = false;
+ this.invert_y = false;
+ this.proxy = false;
+
+ //check if the proxy parameter is set
+ var params = flash.Lib.current.loaderInfo.parameters;
+ if ((params != null) && (params.proxy != null) && (params.proxy != ""))
+ {
+ this.proxy_url = params.proxy;
+ if (this.proxy_url.charAt(proxy_url.length-1) != '/')
+ this.proxy_url += '/';
+ this.proxy_url += abbrev + "/";
+ this.id += " (Proxy)";
+ this.proxy = true;
+ }
+ }
+
+ public function validZoom(z:Int) : Bool
+ {
+ return (((zoom_def + z) >= zoom_min) && ((zoom_def + z) <= zoom_max));
+ }
+
+}
+
+class OpenStreetMapService extends BaseMapService, implements MapService
+{
+ // Details:
+ // ---------------------------------------------------------
+ // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
+
+ override public function new(default_zoom:Int = 13)
+ {
+ super("Open Street Map", "osm", 0, 18, default_zoom, 256);
+ }
+
+ public inline function lonlat2tile(lon:Float, lat:Float, zoom:Int) : TileID
+ {
+ var z:Float = Math.pow(2,zoom);
+ var lr:Float = lat*Math.PI/180;
+ return {x: (Math.floor((lon+180)/360*z)),
+ y: (Math.floor(z*(1-Math.log(Math.tan(lr) + 1/Math.cos(lr))/Math.PI)/2)),
+ z: zoom};
+ }
+
+ public inline function lonlat2XY(lon:Float, lat:Float, zoom:Int) : Point
+ {
+ var z:Float = tile_size * Math.pow(2,zoom);
+ var lr:Float = lat*Math.PI/180;
+ return new Point((Math.floor(z*(lon+180)/360)),
+ (Math.floor(z*(1-Math.log(Math.tan(lr) + 1/Math.cos(lr))/Math.PI)/2)));
+ }
+
+ public inline function tile2lonlat(t:TileID) : LonLat
+ {
+ var z = Math.pow(2,t.z);
+ var n = Math.PI-2*Math.PI*t.y/z;
+ return new LonLat(t.x/z*360-180, 180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
+ }
+
+ public inline function XY2lonlat(x:Float, y:Float, zoom:Int) : LonLat
+ {
+ var z = tile_size * Math.pow(2, zoom);
+ var n = Math.PI-2*Math.PI*y/z;
+ return new LonLat(x/z*360-180, 180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
+ }
+
+ public function tile2url(t:TileID) : String
+ {
+ if (!isValid(t)) return "";
+
+ if (!proxy)
+ return "http://tile.openstreetmap.org/" + (t.z) + "/" + (t.x) + "/" + (t.y) + ".png";
+
+ return this.proxy_url + (t.z) + "_" + (t.x) + "_" + (t.y);
+ }
+
+ function isValid(t:TileID) : Bool
+ {
+ //check zoom
+ if ((t.z < zoom_min) || (t.z > zoom_max)) return false;
+
+ //check bounds
+ var z:Float = Math.pow(2, t.z);
+ if ((t.x < 0) || (t.x >= z) || (t.y < 0) || (t.y >= z)) return false;
+
+ return true;
+ }
+
+}
+
+class BingMapService extends OpenStreetMapService
+{
+
+ // Details:
+ // ---------------------------------------------------------
+ // http://msdn.microsoft.com/en-us/library/bb545006.aspx
+
+ var hybrid:Bool;
+
+ override public function new(default_zoom:Int = 13, hybrid:Bool = false)
+ {
+ super();
+ this.hybrid = hybrid;
+ setInfo("Bink Maps", "bnk", 1, 18, default_zoom, 256);
+
+ }
+
+ override public function tile2url(t:TileID) : String
+ {
+ if (!isValid(t)) return "";
+
+ if (!proxy)
+ {
+ var xx:Int = t.x;
+ var yy:Int = t.y;
+ var tid:String = "";
+ for (i in 0...t.z)
+ {
+ var q:Int = 0;
+ if ((xx & 1) == 1) q += 1;
+ if ((yy & 1) == 1) q += 2;
+ tid = q + tid;
+
+ xx = xx >> 1;
+ yy = yy >> 1;
+ }
+ return "http://tiles.virtualearth.net/tiles/"+(hybrid ? "h" : "r")+tid+".png?g=414&mkt=en-us&shading=hill&n=z";
+ }
+
+ return this.proxy_url + (t.z) + "_" + (t.x) + "_" + (t.y);
+ }
+
+}
diff --git a/src/map/.svn/text-base/QuadTree.hx.svn-base b/src/map/.svn/text-base/QuadTree.hx.svn-base
new file mode 100644
index 0000000..45a789a
--- /dev/null
+++ b/src/map/.svn/text-base/QuadTree.hx.svn-base
@@ -0,0 +1,240 @@
+/*******************************************************************************
+Copyright (c) 2010, Karel Slany (slany AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+typedef QuadData = {
+ public var x:Float;
+ public var y:Float;
+ public var data:Dynamic;
+}
+
+class QuadLeaf {
+ public var x:Float;
+ public var y:Float;
+ public var data:Array;
+ public var ll:Dynamic; // < x, < y
+ public var lg:Dynamic; // < x, >= y
+ public var gl:Dynamic; // >= x, < y
+ public var gg:Dynamic; // >= x, >= y
+
+ public function new(xv:Float, yv:Float, d:Dynamic, optfast:Bool) {
+ x = xv;
+ y = yv;
+ data = new Array();
+ if (optfast) {
+ var qd:QuadData = {x:xv, y:yv, data:d};
+ data.push(qd);
+ } else {
+ data.push(d);
+ }
+ ll = lg = gl = gg = null;
+ }
+
+ public function push(d:Dynamic, optfast:Bool) {
+ if (optfast) {
+ var qd:QuadData = {x:x, y:y, data:d};
+ data.push(qd);
+ } else {
+ data.push(data);
+ }
+ }
+
+ public function remove(d:Dynamic, optfast:Bool):Bool {
+ if (optfast) {
+ for (itm in data)
+ if (itm.data == d)
+ return data.remove(itm);
+ } else {
+ return data.remove(d);
+ }
+ return false;
+ }
+
+ public function getData(data:Array, optfast:Bool, filter:QuadData->Bool) {
+ var qd:QuadData = null;// = {x:0.0, y:0.0, data:null};
+ if (optfast) {
+ for (qd in this.data) {
+ if ((filter == null) || (filter(qd)))
+ data.push(qd);
+ }
+ } else {
+ for (i in 0...this.data.length) {
+ qd.x = x;
+ qd.y = y;
+ qd.data = this.data[i];
+ if ((filter == null) || (filter(qd)))
+ data.push(qd);
+ }
+ }
+ }
+}
+
+class QuadTree {
+
+ public var qroot:Dynamic;
+ var optfast:Bool;
+
+ public function new() {
+ optfast = true; //true - optimized for maximal speed,
+ //false - optimized for mimimal memory footprint
+ qroot = null;
+ }
+
+ /*==============================================================================================
+ PUBLIC methods
+ *==============================================================================================*/
+ public function clear() {
+ qroot = null;
+ }
+
+ public function isEmpty() {
+ return qroot == null;
+ }
+
+ public function push(x:Float, y:Float, data:Dynamic) {
+ if (qroot != null) {
+ push_recursive(qroot, x, y, data);
+ } else {
+ qroot = new QuadLeaf(x, y, data, optfast);
+ }
+ }
+
+ public function remove(x:Float, y:Float, data:Dynamic) : Bool {
+ // return true if found and removed
+ if (qroot != null) {
+ return remove_recursive(qroot, x, y, data);
+ }
+ return false;
+ }
+
+ public function getData(minx:Float, miny:Float, maxx:Float, maxy:Float) : Array {
+ var data = new Array();
+ if (qroot == null) return data;
+ get_data_recursive(qroot, data, minx, miny, maxx, maxy, null);
+ return data;
+ }
+
+ public function getFilteredData(minx:Float, miny:Float, maxx:Float, maxy:Float, filter:QuadData->Bool) : Array {
+ var data = new Array();
+ if (qroot == null) return data;
+ get_data_recursive(qroot, data, minx, miny, maxx, maxy, filter);
+ return data;
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+
+ function push_recursive(root:QuadLeaf, x:Float, y:Float, data:Dynamic) {
+ if ((x == root.x) && (y == root.y)) {
+ // allows multiple entries
+ root.push(data, optfast);
+ } else if (x < root.x) {
+ if (y < root.y) {
+ if (root.ll != null) {
+ push_recursive(root.ll, x, y, data);
+ } else {
+ root.ll = new QuadLeaf(x, y, data, optfast);
+ }
+ } else {
+ if (root.lg != null) {
+ push_recursive(root.lg, x, y, data);
+ } else {
+ root.lg = new QuadLeaf(x, y, data, optfast);
+ }
+ }
+ } else {
+ if (y < root.y) {
+ if (root.gl != null) {
+ push_recursive(root.gl, x, y, data);
+ } else {
+ root.gl = new QuadLeaf(x, y, data, optfast);
+ }
+ } else {
+ if (root.gg != null) {
+ push_recursive(root.gg, x, y, data);
+ } else {
+ root.gg = new QuadLeaf(x, y, data, optfast);
+ }
+ }
+ }
+ }
+
+ function remove_recursive(root:QuadLeaf, x:Float, y:Float, data:Dynamic) : Bool {
+ // does not remove nodes, only removes data entries
+ if ((x == root.x) && (y == root.y)) {
+ return root.remove(data, optfast);
+ } else if (x < root.x) {
+ if (y < root.y) {
+ if (root.ll != null) {
+ return remove_recursive(root.ll, x, y, data);
+ }
+ return false;
+ } else {
+ if (root.lg != null) {
+ return remove_recursive(root.lg, x, y, data);
+ }
+ return false;
+ }
+ } else {
+ if (y < root.y) {
+ if (root.gl != null) {
+ return remove_recursive(root.gl, x, y, data);
+ }
+ return false;
+ } else {
+ if (root.gg != null) {
+ return remove_recursive(root.gg, x, y, data);
+ }
+ return false;
+ }
+ }
+ }
+
+ function get_data_recursive(root:QuadLeaf, data:Array, minx:Float, miny:Float, maxx:Float, maxy:Float, filter:QuadData->Bool) {
+ if ((minx <= root.x) && (miny <= root.y) && (maxx >= root.x) && (maxy >= root.y)) {
+ root.getData(data, optfast, filter);
+ }
+ if ((root.ll != null) && (minx <= root.x) && (miny <= root.y)) {
+ get_data_recursive(root.ll, data, minx, miny, maxx, maxy, filter);
+ }
+ if ((root.lg != null) && (minx <= root.x) && (maxy >= root.y)) {
+ get_data_recursive(root.lg, data, minx, miny, maxx, maxy, filter);
+ }
+ if ((root.gl != null) && (maxx >= root.x) && (miny <= root.y)) {
+ get_data_recursive(root.gl, data, minx, miny, maxx, maxy, filter);
+ }
+ if ((root.gg != null) && (maxx >= root.x) && (maxy >= root.y)) {
+ get_data_recursive(root.gg, data, minx, miny, maxx, maxy, filter);
+ }
+ }
+
+}
diff --git a/src/map/.svn/text-base/Tile.hx.svn-base b/src/map/.svn/text-base/Tile.hx.svn-base
new file mode 100644
index 0000000..81958d5
--- /dev/null
+++ b/src/map/.svn/text-base/Tile.hx.svn-base
@@ -0,0 +1,173 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import flash.display.Sprite;
+import flash.display.Bitmap;
+import flash.text.TextField;
+import flash.text.TextFieldAutoSize;
+
+class Tile extends Sprite
+{
+ #if TILE_DBG
+ var t:TextField;
+ #end
+
+ var size:Int;
+ var valid:Bool;
+ public var tx(default, settx):Int;
+ public var ty(default, setty):Int;
+ public var tidx(default, null):Int;
+ public var image(default, null):Bitmap;
+
+ public var rtidx:Int; //right neighbour tidx
+ public var ltidx:Int; //left neighbour tidx
+ public var ttidx:Int; //top neighbour tidx
+ public var btidx:Int; //bottom neighbour tidx
+
+ override public function new(tidx:Int, size:Int = 256, x:Int = 0, y:Int = 0)
+ {
+ super();
+
+ #if TILE_DBG
+ var s:Sprite = new Sprite();
+ s.graphics.lineStyle(2, (tidx == 0) ? 0xFF0000 : 0x008000);
+ s.graphics.moveTo(0,0);
+ s.graphics.lineTo(size,size);
+ s.graphics.moveTo(size,0);
+ s.graphics.lineTo(0,size);
+ s.graphics.moveTo(size-1,0);
+ s.graphics.lineTo(size-1,size);
+ s.graphics.moveTo(0,size-1);
+ s.graphics.lineTo(size,size-1);
+ addChild(s);
+
+ t = new TextField();
+ t.autoSize = TextFieldAutoSize.LEFT;
+ t.mouseEnabled = false;
+ addChild(t);
+ #end
+
+ this.tidx = tidx;
+ this.rtidx = -1;
+ this.ltidx = -1;
+ this.ttidx = -1;
+ this.btidx = -1;
+
+ this.tx = x;
+ this.ty = y;
+ this.size = size;
+ this.image = null;
+ this.valid = false;
+ mouseEnabled = false;
+
+ update();
+ }
+
+ /*==============================================================================================
+ PUBLIC methods
+ *==============================================================================================*/
+ public function assignImage(image:Bitmap)
+ {
+ graphics.clear();
+
+ if (this.image != null)
+ {
+ removeChild(this.image);
+ this.image = null;
+ }
+
+ if (image != null)
+ {
+ this.image = image;
+ addChildAt(this.image, 0);
+ }
+ else
+ {
+ graphics.lineStyle(2, 0xF0F0F0);
+ graphics.drawCircle(size/2,size/2, 10);
+ }
+
+ this.valid = (this.image != null);
+ }
+
+ //returns True iff the tile waits for an image
+ public function needImage():Bool
+ {
+ return !this.valid;
+ }
+
+ //tile is being loaded
+ public function waitForImage()
+ {
+ }
+
+ public function invalidate()
+ {
+ this.valid = false;
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+ function update()
+ {
+ #if TILE_DBG
+ t.text = "("+tx+","+ty+")";
+ t.x = (size - t.width)/2;
+ t.y = (size - t.height)/2;
+ #end
+ }
+
+
+ function settx(val:Int) : Int
+ {
+ if (val != tx)
+ {
+ tx = val;
+ update();
+ assignImage(null);
+ }
+ return val;
+ }
+
+ function setty(val:Int) : Int
+ {
+ if (val != ty)
+ {
+ ty = val;
+ update();
+ assignImage(null);
+ }
+ return val;
+ }
+
+}
diff --git a/src/map/.svn/text-base/TileLayer.hx.svn-base b/src/map/.svn/text-base/TileLayer.hx.svn-base
new file mode 100644
index 0000000..fe35261
--- /dev/null
+++ b/src/map/.svn/text-base/TileLayer.hx.svn-base
@@ -0,0 +1,546 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import map.Tile;
+import map.TileLoader;
+import map.Layer;
+import map.Utils;
+import flash.events.Event;
+import flash.geom.Point;
+import flash.display.Bitmap;
+
+#if TILE_EVT_DBG
+import flash.external.ExternalInterface;
+#end
+
+class TileLayer extends Layer
+{
+ var tiles:Array;
+ var tilecnt:Int;
+ var loader:TileLoader;
+
+ var tofs:Int; /* kdy presunout tiles zprava doleva (kolik za obrazem musi min. byt) */
+ var lx:Int;
+ var rx:Int;
+ var ty:Int;
+ var by:Int;
+ var tilesize:Int;
+ var basetid:TileID;
+ var ofsx:Float;
+ var ofsy:Float;
+ var smooth:Bool;
+
+ public function new(map_service:MapService = null, tiles:Int = 8, smooth_zoom:Bool = true)
+ {
+ super(map_service);
+
+ this.tilecnt = tiles;
+ this.tiles = new Array();
+ this.tilesize = 256;
+ this.tofs = 1;
+ this.basetid = {x:0,y:0,z:0};
+ this.ofsx = this.ofsy = 0;
+ this.tofs = 0;
+ this.smooth = smooth_zoom;
+
+ while (this.tiles.length < this.tilecnt*this.tilecnt)
+ {
+ var t:Tile = new Tile(this.tiles.length, this.tilesize);
+ this.tiles.push(t);
+ addChild(t);
+ }
+ initTile();
+
+ this.loader = new TileLoader();
+ this.loader.addEventListener(TileLoadedEvent.TILE_LOADED, tileLoaded);
+ }
+
+ /*==============================================================================================
+ PUBLIC methods
+ *==============================================================================================*/
+ override public function initialize(update:Bool=true) : Int
+ {
+ var res = super.initialize(false);
+ if (res != 0)
+ return res;
+
+ loader.mapservice = mapservice;
+ basetid.z = mapservice.zoom_def;
+ tilesize = mapservice.tile_size;
+
+ alignLayer();
+
+ initialized = true;
+ updateEnabled = true;
+
+ if (update)
+ updateContent(true);
+
+ return 0;
+ }
+
+ override public function clear()
+ {
+ //clean loader queue
+ loader.clear();
+
+ //release used images
+ for (t in tiles)
+ t.assignImage(null);
+ }
+
+ override public function getOffset() : Point
+ {
+ var tp = tiles.length >> 1;
+ return new Point(this.x - (this.canvascenter.x - (scaleX*this.tilesize)/2), this.y - (this.canvascenter.y - (scaleY*this.tilesize)/2));
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+ function initTile()
+ {
+ this.lx = -this.tofs;
+ this.rx = this.tilecnt-1-this.tofs;
+ this.ty = -this.tofs;
+ this.by = this.tilecnt-1-this.tofs;
+
+ var tp = this.tilecnt >> 1;
+ this.lx = -tp;
+ this.ty = -tp;
+ tp = this.tilecnt - tp;
+ this.rx = tp-1;
+ this.by = tp-1;
+
+ var i:Int = 0;
+ var j:Int = 0;
+ var idx:Int = 0;
+
+ for (t in tiles)
+ {
+ if (i == this.tilecnt)
+ {
+ i = 0;
+ j++;
+ }
+
+ t.tx = this.lx + i;
+ t.ty = this.ty + j;
+
+ t.ltidx = (i == 0) ? idx + this.tilecnt - 1 : idx - 1;
+ t.rtidx = (i < this.tilecnt-1) ? idx + 1 : idx - this.tilecnt + 1;
+ t.ttidx = (j == 0) ? idx + ((this.tilecnt-1) * this.tilecnt) : idx - this.tilecnt;
+ t.btidx = (j < this.tilecnt-1) ? idx + this.tilecnt : idx;
+
+ t.x = tilesize*t.tx + ofsx;
+ t.y = tilesize*t.ty + ofsy;
+
+ i++;
+ idx++;
+ }
+
+ }
+
+ override function centerUpdated(clearQueue:Bool)
+ {
+ if (!this.initialized)
+ return;
+
+ if (clearQueue)
+ {
+ saveImages();
+ clear();
+ }
+
+ alignLayer();
+
+ initTile();
+ emitRequests();
+ }
+
+
+
+ override function updateContent(forceUpdate:Bool=false)
+ {
+ var i = 0;
+
+ //move tiles if it is needed
+ while (i < tiles.length / 2)
+ {
+ if (!testAndShift())
+ break;
+
+ i++;
+ }
+
+ if ((i == 0) && (!forceUpdate))
+ return;
+
+ //update tile positions
+ for (t in tiles)
+ {
+ t.x = tilesize*t.tx + ofsx;
+ t.y = tilesize*t.ty + ofsy;
+ }
+
+ //load required images
+ emitRequests();
+ }
+
+ override function updateChanged()
+ {
+ if (!this.updateEnabled)
+ loader.clear();
+ }
+
+ override function zoomChanged(prevEnabled:Bool, newZoom:Int)
+ {
+ var lp:Int = 0;
+ var tp:Int = 0;
+ var tilehsize:Float = tilesize / 2;
+
+ if (this.zoom > newZoom)
+ {
+
+ if (smooth) {
+ //smooth zoom - combines four tiles into one
+
+ var bx:Int = (basetid.x & 1) ^ 1;
+ var by:Int = (basetid.y & 1) ^ 1;
+
+ for (t in tiles)
+ {
+ if ((t.tx & 1 == bx) || (t.ty & 1 == by)) continue;
+
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0xFFFFFF);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(0.5, 0.5);
+ if (t.image != null)
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilehsize,tilehsize), false);
+
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(0.5, 0.5);
+ scaleMatrix.translate(tilehsize,0);
+ var tt = tiles[t.rtidx];
+ if ((tt.tx != this.lx) && (tt.image != null))
+ bd.draw(tt.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(tilehsize,0,tilehsize,tilehsize), false);
+
+
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(0.5, 0.5);
+ scaleMatrix.translate(0,tilehsize);
+ var tt = tiles[t.btidx];
+ if ((tt.ty != this.ty) && (tt.image != null))
+ bd.draw(tt.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,tilehsize,tilehsize,tilehsize), false);
+
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(0.5, 0.5);
+ scaleMatrix.translate(tilehsize,tilehsize);
+ var tt = tiles[tiles[t.btidx].rtidx];
+ if ((tt.tx != this.lx) && (tt.ty != this.ty) && (tt.image != null))
+ bd.draw(tt.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(tilehsize,tilehsize,tilehsize,tilehsize), false);
+
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x) >> 1,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y) >> 1,
+ newZoom + basetid.z,
+ bd, false
+ );
+
+ }
+ }
+
+ //zoom out
+ if (basetid.x & 1 == 1) x -= tilesize/2;
+ if (basetid.y & 1 == 1) y -= tilesize/2;
+ basetid.x = basetid.x >> 1;
+ basetid.y = basetid.y >> 1;
+
+ ofsx = ofsx / 2.0;
+ ofsy = ofsy / 2.0;
+
+ //coeficients for the /2 transformation
+ // x' = x/2 == x - x/2
+ // y' = y/2 == y - y/2
+ lp = - Std.int(this.lx/2);
+ tp = - Std.int(this.ty/2);
+
+ }
+ else
+ {
+
+ if (smooth)
+ {
+ //smooth zoom - each tile is splited into the four tiles
+ var mintx:Int = Std.int((3*this.lx + this.rx + 1) / 4);
+ var maxtx:Int = Std.int((3*this.rx + this.lx + 3) / 4);
+ var minty:Int = Std.int((3*this.ty + this.by + 1) / 4);
+ var maxty:Int = Std.int((3*this.by + this.ty + 3) / 4);
+ for (t in tiles)
+ if ((t.image != null) && (t.tx >= mintx) && (t.tx <= maxtx) && (t.ty >= minty) && (t.ty <= maxty))
+ {
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0xFFFFFF);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(2, 2);
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilesize,tilesize), false);
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x)*2,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y)*2,
+ newZoom + basetid.z, bd, false
+ );
+
+
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0xFFFFFF);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(2, 2);
+ scaleMatrix.translate(-tilesize,0);
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilesize,tilesize), false);
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x)*2 + 1,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y)*2,
+ newZoom + basetid.z, bd, false
+ );
+
+
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0xFFFFFF);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(2, 2);
+ scaleMatrix.translate(0,-tilesize);
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilesize,tilesize), false);
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x)*2,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y)*2 + 1,
+ newZoom + basetid.z, bd, false
+ );
+
+
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0x00FF00);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(2, 2);
+ scaleMatrix.translate(-tilesize,-tilesize);
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilesize,tilesize), false);
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x)*2 + 1,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y)*2 + 1,
+ newZoom + basetid.z, bd, false
+ );
+
+ }
+ }
+
+ //zoom in
+ basetid.x = basetid.x << 1;
+ basetid.y = basetid.y << 1;
+
+ ofsx = ofsx * 2.0;
+ ofsy = ofsy * 2.0;
+
+ //coeficients for the *2 transformation
+ // x' = x*2 == x + x
+ // y' = y*2 == y + y
+ lp = this.lx;
+ tp = this.ty;
+
+
+ }
+
+ //transform tile id's
+ for (t in tiles)
+ {
+ t.tx += lp;
+ t.ty += tp;
+ }
+
+ this.rx += lp;
+ this.by += tp;
+ this.lx += lp;
+ this.ty += tp;
+
+ //update zoom, reset scale
+ this.zoom = newZoom;
+
+ scaleX = 1;
+ scaleY = 1;
+
+ clear();
+ center = this.lastcenter;
+ centerUpdated(false);
+
+ dispatchEvent(new Event(Layer.ZOOM_FINISHED));
+
+ if ((prevEnabled) && (!this.updateEnabled))
+ {
+ this.updateEnabled = true;
+ updateChanged();
+ }
+
+ updateContent(true);
+ }
+
+ function testAndShift() : Bool
+ {
+ var mv_left = ((this.lx+this.tofs)*tilesize*scaleX + this.x > bbox.x);
+ var mv_right = ((this.rx-this.tofs)*tilesize*scaleX + this.x < (bbox.x+bbox.width));
+ var mv_up = ((this.ty+this.tofs)*tilesize*scaleY + this.y > bbox.y);
+ var mv_down = ((this.by-this.tofs)*tilesize*scaleY + this.y < (bbox.y+bbox.height));
+
+ if ((mv_left) && ((this.rx-1)*tilesize*scaleX + this.x < (bbox.x+bbox.width)))
+ mv_left = false;
+ if ((mv_up) && ((this.by-1)*tilesize*scaleY + this.y < (bbox.y+bbox.height)))
+ mv_up = false;
+ if ((mv_right) && ((this.lx+1)*tilesize*scaleX + this.x > bbox.x))
+ mv_right = false;
+ if ((mv_down) && ((this.ty+1)*tilesize*scaleY + this.y > bbox.y))
+ mv_down = false;
+
+ if (mv_left && mv_right) mv_right = false;
+ if (mv_up && mv_down) mv_down = false;
+
+ if (!(mv_left || mv_right || mv_up || mv_down)) return false;
+
+ for (t in tiles)
+ {
+ if ((mv_left) && (t.tx == rx))
+ t.tx = lx - 1;
+ if ((mv_right) && (t.tx == lx))
+ t.tx = rx + 1;
+ if ((mv_up) && (t.ty == by))
+ t.ty = ty - 1;
+ if ((mv_down) && (t.ty == ty))
+ t.ty = by + 1;
+ }
+ var dx = (mv_left) ? -1 : ((mv_right) ? 1 : 0);
+ var dy = (mv_up) ? -1 : ((mv_down) ? 1 : 0);
+
+ lx += dx;
+ rx += dx;
+ ty += dy;
+ by += dy;
+
+ return true;
+ }
+
+ function alignLayer()
+ {
+
+ if (center == null) return;
+
+ x = this.canvascenter.x;
+ y = this.canvascenter.y;
+
+ basetid = mapservice.lonlat2tile(center.lng, center.lat, basetid.z+zoom);
+ var ptc = mapservice.lonlat2XY(center.lng, center.lat, basetid.z);
+ var ll = mapservice.tile2lonlat(basetid);
+ var ptt = mapservice.lonlat2XY(ll.x, ll.y, basetid.z);
+ basetid.z -= zoom;
+ ptt = ptt.subtract(ptc);
+ ofsx = ptt.x;
+ ofsy = ptt.y;
+ }
+
+
+ function emitRequests()
+ {
+ var prio:Int = 0;
+ var xx:Float;
+ var yy:Float;
+
+ loader.disable();
+
+ try
+ {
+ loader.tidyQueue(((mapservice.invert_x) ? -lx : lx) + basetid.x, ((mapservice.invert_x) ? -rx : rx) + basetid.x,
+ ((mapservice.invert_y) ? -ty : ty) + basetid.y, ((mapservice.invert_y) ? -by : by) + basetid.y,
+ zoom + basetid.z
+ );
+
+ for (tile in tiles)
+ {
+ if (tile.needImage())
+ {
+
+
+ xx = (tile.x + x - ofsx - this.canvascenter.x);
+ yy = (tile.y + y - ofsy - this.canvascenter.y);
+ prio = Std.int(Math.sqrt(xx*xx + yy*yy));
+
+ loader.addRequest( ((mapservice.invert_x) ? -tile.tx : tile.tx) + basetid.x,
+ ((mapservice.invert_y) ? -tile.ty : tile.ty) + basetid.y,
+ zoom + basetid.z,
+ tile.tidx,
+ prio
+ );
+
+ tile.waitForImage();
+ }
+ }
+
+ } catch (unknown : Dynamic) {};
+
+ loader.enable();
+ }
+
+
+ function tileLoaded(e:TileLoadedEvent)
+ {
+ if ((e.tidx >= 0) && (e.tidx < tiles.length))
+ {
+
+ var t:Tile = tiles[e.tidx];
+ if ((t != null) &&
+ (((mapservice.invert_x) ? -t.tx : t.tx) == e.x - basetid.x) && //check x-id
+ (((mapservice.invert_y) ? -t.ty : t.ty) == e.y - basetid.y) && //check y-id
+ (e.z - basetid.z == zoom) //check z
+ )
+ {
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "tileLoaded "+e.data+" x:"+t.tx+" y:"+t.ty+" ("+e.x+","+e.y+","+e.z+") priority:"+e.p);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ t.assignImage(e.data);
+ }
+ }
+ }
+
+
+ function saveImages()
+ {
+ for (t in tiles)
+ if (t.image != null)
+ loader.addTile(((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x,
+ ((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y,
+ zoom + basetid.z,
+ t.image.bitmapData
+ );
+
+
+ }
+
+}
diff --git a/src/map/.svn/text-base/TileLoader.hx.svn-base b/src/map/.svn/text-base/TileLoader.hx.svn-base
new file mode 100644
index 0000000..fd960a9
--- /dev/null
+++ b/src/map/.svn/text-base/TileLoader.hx.svn-base
@@ -0,0 +1,547 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import map.Utils;
+
+import flash.events.Event;
+import flash.events.EventDispatcher;
+import flash.events.IOErrorEvent;
+import flash.display.Loader;
+import flash.display.Bitmap;
+import flash.display.BitmapData;
+import flash.net.URLRequest;
+import flash.system.LoaderContext;
+
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+
+#if TILE_EVT_DBG
+import flash.external.ExternalInterface;
+#end
+
+typedef TileIDT = {
+ var x : Int;
+ var y : Int;
+ var z : Int;
+ var tidx : Int;
+ var ttl : Int;
+ var priority: Int;
+};
+
+
+class TileLoadedEvent extends flash.events.Event
+{
+ public static var TILE_LOADED:String = "tileLoaded";
+
+ public var x:Int;
+ public var y:Int;
+ public var z:Int;
+ public var p:Int;
+ public var tidx:Int;
+ public var data:Bitmap;
+
+ public function new(x:Int, y:Int, z:Int, tidx:Int, p:Int, data:Bitmap) {
+ super(TILE_LOADED);
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.p = p;
+ this.tidx = tidx;
+ this.data = data;
+ }
+}
+
+class ImageLoader extends Loader
+{
+ static var TIMEOUT:Int = 5; //10 sec
+
+ public var used:Bool;
+ public var ignore:Bool;
+ public var id:Int;
+ public var ttl:Int;
+ public var tid:TileIDT;
+
+
+ public function new(id:Int)
+ {
+ super();
+ this.used = false;
+ this.ignore = false;
+ this.id = id;
+ this.ttl = TIMEOUT;
+ }
+
+ public function loadImage(tid:TileIDT, url:String) {
+ var urlRequest:URLRequest = new URLRequest(url);
+ this.tid = tid;
+ try {
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "loadImage "+id+" ("+tid.x+","+tid.y+","+tid.z+") prio:"+tid.priority);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ this.load(urlRequest, new LoaderContext(true));
+ this.used = true;
+ this.ttl = TIMEOUT;
+
+ }
+ catch (unknown : Dynamic)
+ {
+ this.used = false;
+ }
+ }
+
+ override public function toString()
+ {
+ return "[ImageLoader id:" + id + "]";
+ }
+
+}
+
+typedef TempTile = {
+ var x : Int;
+ var y : Int;
+ var z : Int;
+ var img : BitmapData;
+ var ttl : Int;
+ var original : Bool;
+};
+
+class TileLoader extends EventDispatcher
+{
+ public static var DEFAULT_TTL:Int = 3;
+ public var mapservice:MapService;
+ var loaders:Array;
+ var queue:Array;
+ var tempqueue:Array;
+ var enabled:Int;
+ var watchdog:Timer;
+
+ public function new(threads:Int = 8)
+ {
+ super();
+
+ mapservice = null;
+ enabled = 0;
+
+ watchdog = new Timer(1000, 0);
+ watchdog.addEventListener(TimerEvent.TIMER, checkLoaders);
+ watchdog.stop();
+
+ loaders = new Array();
+ queue = new Array();
+ tempqueue = new Array();
+
+ for (i in 0...threads)
+ {
+ var l = new ImageLoader(i);
+ l.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, loaderComplete);
+ l.contentLoaderInfo.addEventListener(flash.events.IOErrorEvent.IO_ERROR, loaderError);
+ loaders.push(l);
+
+ }
+ }
+
+ /*==============================================================================================
+ PUBLIC methods
+ *==============================================================================================*/
+
+ public function clear()
+ {
+ clearQueue();
+
+ for (l in loaders)
+ if (l.used)
+ {
+ l.ignore = true;
+ try {
+ //l.close(); //BUGGY!
+ //l.unload();
+ }
+ catch (unknown : Dynamic)
+ { };
+ }
+
+ }
+
+ public function enable()
+ {
+ if (enabled > 0)
+ enabled--;
+
+ if (enabled == 0)
+ {
+ sortQueue();
+ processQueue();
+
+ if (!watchdog.running)
+ watchdog.start();
+ }
+ }
+
+ public function disable()
+ {
+ if (watchdog.running)
+ watchdog.stop();
+
+ enabled++;
+ }
+
+
+ public function tidyQueue(minx:Int, maxx:Int, miny:Int, maxy:Int, z:Int)
+ {
+ var i:Int = 0;
+ while (i < queue.length)
+ {
+ var tid:TileIDT = queue[i];
+ if (tid.z == z)
+ {
+ if ((tid.x < minx) || (tid.x > maxx) || (tid.y < miny) || (tid.y > maxy))
+ queue.remove(tid);
+ else
+ i += 1;
+ }
+ else
+ queue.remove(tid);
+ }
+ }
+
+ public function addRequest(x:Int, y:Int, z:Int, tidx:Int, priority:Int = 0)
+ {
+ if ((x < 0) || (y < 0) || (z < 0)) return;
+
+ var q:TempTile = getTile(x, y, z);
+ if (q != null)
+ {
+ tempqueue.remove(q);
+ dispatchEvent(new TileLoadedEvent(x,y,z,tidx,priority, new Bitmap(q.img)));
+ if (q.original)
+ return;
+ }
+
+ for (l in loaders)
+ if ((l.used) && (!l.ignore) && (l.tid.x == x) && (l.tid.y == y) && (l.tid.z == z))
+ return; //request already served, return
+
+ var exists:Bool = false;
+ for (tid in queue)
+ if ((tid.x == x) && (tid.y == y) && (tid.z == z))
+ {
+ //request already in queue, update priority
+ tid.priority = priority;
+ exists = true;
+ break;
+ }
+
+ if (!exists)
+ queue.push({x:x,y:y,z:z,tidx:tidx,priority:priority,ttl:DEFAULT_TTL});
+
+ if (enabled == 0)
+ {
+ sortQueue();
+ processQueue();
+ }
+
+ }
+
+ public function addTile(x:Int, y:Int, z:Int, img:BitmapData, original:Bool = true)
+ {
+ //check if the tile image is not already in queue
+ var tmp:TempTile = getTile(x,y,z);
+ if (tmp != null)
+ {
+ if (((!tmp.original) && (original)) || ((!tmp.original) && (!original)))
+ {
+ tmp.img = img;
+ tmp.original = original;
+ tmp.ttl = DEFAULT_TTL;
+ }
+ return;
+ }
+
+ insertTile({x: x, y: y, z: z, img: img, ttl:DEFAULT_TTL, original:original});
+ }
+
+ override public function toString() : String
+ {
+ var used = 0;
+ for (l in loaders)
+ if (l.used)
+ used++;
+
+ return "[TileLoader] threads total:" + loaders.length + ", active threads:" + used + ", enabled threads:" + enabled;
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+ function clearQueue()
+ {
+ while (queue.length > 0)
+ queue.pop();
+ }
+
+ function checkLoaders(e:TimerEvent)
+ {
+ //watchdog timer event
+
+ //check for broken loaders
+ var used = 0;
+ for (l in loaders)
+ if (l.used)
+ {
+ if (l.ttl > 0)
+ l.ttl--;
+ else if (l.ttl == 0)
+ loaderFailed(l);
+ used++;
+ }
+
+ var i=0;
+ var q:TempTile;
+ //remove unused tiles in tempqueue
+ while (i < tempqueue.length)
+ {
+ q = tempqueue[i];
+
+ if (q.ttl > 0)
+ q.ttl--;
+ else if (q.ttl == 0)
+ {
+ tempqueue.remove(q);
+ continue;
+ }
+
+ i++;
+ used++;
+ }
+
+ if ((used == 0) && (watchdog.running))
+ watchdog.stop();
+
+ }
+
+
+ function sortQueue()
+ {
+ queue.sort(function(x:TileIDT,y:TileIDT):Int { return x.priority - y.priority;});
+ }
+
+
+ function processQueue()
+ {
+
+ if ((enabled != 0) || (queue.length == 0) || (mapservice == null))
+ return;
+
+ if (queue.length == 0)
+ return;
+
+ var tid:TileIDT;
+ for (l in loaders)
+ {
+ if (l.used)
+ continue;
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "processQueue qlen:"+queue.length);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ if (queue.length == 0) return;
+
+ tid = queue.shift();
+
+ var url:String = mapservice.tile2url(tid);
+ if (url != "")
+ l.loadImage(tid, url);
+
+ if (!watchdog.running)
+ watchdog.start();
+
+ }
+
+ }
+
+ function loaderComplete(e:Event)
+ {
+
+ if ((e.target == null) || (e.target.loader == null))
+ return;
+
+ var loader:ImageLoader = e.target.loader;
+
+ if (!loader.ignore)
+ {
+ try {
+ var x:Int = loader.tid.x;
+ var y:Int = loader.tid.y;
+ var z:Int = loader.tid.z;
+ var t:Int = loader.tid.tidx;
+ var p:Int = loader.tid.priority;
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "tileLoaded ("+x+","+y+","+z+") priority:"+p);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ var bitmapc:Bitmap = new Bitmap(cast(loader.content, Bitmap).bitmapData.clone());
+ dispatchEvent(new TileLoadedEvent(x,y,z,t,p, bitmapc));
+
+ }
+ catch (unknown : Dynamic)
+ {
+
+ //chyba, znovu do fronty, pokud jiz neni vycerpan poc. pokusu
+ if (loader.tid.ttl > 0)
+ {
+ queue.push({x:loader.tid.x, y:loader.tid.y, z:loader.tid.z,
+ tidx:loader.tid.tidx,
+ ttl:loader.tid.ttl - 1,
+ priority:loader.tid.priority
+ });
+ if (enabled == 0)
+ sortQueue();
+ }
+
+ };
+ }
+ else
+ {
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "tileIgnored");
+ } catch (unknown : Dynamic) { };
+ #end
+ }
+
+ try {
+ loader.unload();
+ } catch (unknown : Dynamic) {};
+
+ loader.used = false;
+ loader.ignore = false;
+
+ processQueue();
+ }
+
+ function loaderFailed(l:ImageLoader)
+ {
+ l.used = false;
+ l.ignore = false;
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "tileError " + l.tid.x + ","+l.tid.y+","+l.tid.z);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ if ((l.tid.ttl > 0) && (!l.ignore))
+ {
+ //loading failed, return request back to the queue
+ queue.push({x:l.tid.x,y:l.tid.y,z:l.tid.z,tidx:l.tid.tidx,ttl:l.tid.ttl - 1,priority:l.tid.priority});
+
+ if (enabled == 0)
+ sortQueue();
+ }
+
+ processQueue();
+ }
+
+
+ function loaderError(e:IOErrorEvent)
+ {
+
+ for (l in loaders)
+ if (l.contentLoaderInfo == e.target)
+ loaderFailed(l);
+ }
+
+ function getTile(x:Int, y:Int, z:Int) : TempTile
+ {
+ //looking for a tile in the sorted array
+
+ var min:Int = 0;
+ var max:Int = tempqueue.length-1;
+ var mid:Int;
+ var val:Int; var cmp:Int;
+ while (min <= max) {
+ mid = Math.floor((min + max) / 2);
+
+ cmp = (x - tempqueue[mid].x);
+ if (cmp == 0) cmp = (y - tempqueue[mid].y);
+ if (cmp == 0) cmp = (z - tempqueue[mid].z);
+
+ if (cmp == 0)
+ return tempqueue[mid]
+ else if (cmp > 0)
+ min = mid + 1;
+ else
+ max = mid - 1;
+
+ }
+
+ return null;
+ }
+
+ function insertTile(t:TempTile)
+ {
+ //insert TempTile into the sorted array
+
+ var min:Int = 0;
+ var max:Int = tempqueue.length-1;
+ var mid:Int;
+ var val:Int; var cmp:Int;
+
+ while (min <= max) {
+ mid = Math.floor((min + max) / 2);
+
+ cmp = (t.x - tempqueue[mid].x);
+ if (cmp == 0) cmp = (t.y - tempqueue[mid].y);
+ if (cmp == 0) cmp = (t.z - tempqueue[mid].z);
+
+ if (cmp > 0)
+ min = mid + 1;
+ else
+ max = mid - 1;
+
+ }
+
+ tempqueue.insert(min, t);
+ }
+
+}
+
diff --git a/src/map/.svn/text-base/Utils.hx.svn-base b/src/map/.svn/text-base/Utils.hx.svn-base
new file mode 100644
index 0000000..5f9b407
--- /dev/null
+++ b/src/map/.svn/text-base/Utils.hx.svn-base
@@ -0,0 +1,74 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import flash.geom.Point;
+import flash.filters.ColorMatrixFilter;
+
+class Utils
+{
+ public static function dec2hex(i:Int, digits:Int)
+ {
+ var c = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
+ var s:String = '';
+ var val = i;
+ for (j in 0...digits)
+ {
+ s = c[val % 16] + s;
+ val = val >> 4;
+ }
+ return s;
+ }
+
+ public static function desaturationFilter(sat:Float = 1.0) : ColorMatrixFilter
+ {
+ var r = 0.212671;
+ var g = 0.715160;
+ var b = 0.072169;
+ return new ColorMatrixFilter(
+ [/* R */ sat*r+1-sat, sat*g, sat*b, 0, 0,
+ /* G */ sat*r, sat*g+1-sat, sat*b, 0, 0,
+ /* B */ sat*r, sat*g, sat*b+1-sat, 0, 0,
+ /* A */ 0, 0, 0, 1, 0
+ ]
+ );
+ }
+
+}
+
+typedef LonLat = Point; /* for internal usage */
+
+typedef TileID = {
+ var x : Int;
+ var y : Int;
+ var z : Int;
+};
+
diff --git a/src/map/Canvas.hx b/src/map/Canvas.hx
new file mode 100644
index 0000000..d631463
--- /dev/null
+++ b/src/map/Canvas.hx
@@ -0,0 +1,676 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import com.Component;
+
+import map.MapService;
+import map.LngLat;
+import flash.events.Event;
+import flash.events.MouseEvent;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+import flash.display.Shape;
+import flash.display.BitmapData;
+
+
+typedef ALayer = {
+ var layer : Layer;
+ var enabled : Bool;
+}
+
+class MapEvent extends flash.events.Event
+{
+ public static var MAP_CLICKED:String = "mapclicked";
+ public static var MAP_MOUSEMOVE:String = "mapmousemove";
+ public static var MAP_MOVE:String = "mapmove";
+ public static var MAP_ZOOMCHANGED:String = "mapzoom";
+ public static var MAP_CHANGED:String = "mapchanged";
+
+ public var point:LngLat;
+
+ public function new(event:String, point:LngLat = null) {
+ super(event);
+ this.set_point( point );
+ }
+ public function set_point(point : LngLat)
+ {
+ this.point = point;
+ }
+ public function get_point(t)
+ {
+ return this.point;
+ }
+
+}
+
+
+class Canvas extends Component
+{
+ var layers:Array;
+ var start:Point;
+ var initialized:Bool;
+ var zoom:Int;
+ var animTimer : Timer;
+ var animTo:LngLat;
+ var center:LngLat;
+ var thpassed:Bool;
+ var thtimer:Timer;
+ var mappoint:LngLat;
+ public var mousethreshold:Int; //the minimal number of pixels that have to be passed in order to start moving
+ public var transparent:Bool;
+
+ public function new(interactive:Bool = true)
+ {
+ super();
+
+ this.initialized = false;
+ this.start = null;
+ this.zoom = 0;
+ this.mousethreshold = 5;
+ this.thpassed = false;
+ this.thtimer = null;
+ this.animTimer = new Timer(50, 0);
+ this.center = new LngLat(16.722079,49.577496);
+ this.layers = new Array();
+ this.doubleClickEnabled = true;
+ this.transparent = false;
+/*
+ contextMenu = new flash.ui.ContextMenu();
+ contextMenu.hideBuiltInItems();
+ var itm = new flash.ui.ContextMenuItem("HaxeMaps");
+ itm.addEventListener(flash.events.ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e) { flash.Lib.getURL(new flash.net.URLRequest("http://code.google.com/p/haxemaps/")); });
+ contextMenu.customItems.push(itm);
+ var itm = new flash.ui.ContextMenuItem(" (C) 2013");
+ itm.enabled = false;
+ contextMenu.customItems.push(itm);
+*/
+ if (interactive)
+ {
+ addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
+ addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
+ addEventListener(MouseEvent.DOUBLE_CLICK, onMouseDoubleClick);
+
+ var me = this;
+ /* var itm = new flash.ui.ContextMenuItem("HaxeMaps - zoom in");
+ itm.separatorBefore = true;
+ itm.addEventListener(flash.events.ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e) { me.zoomIn(); });
+ contextMenu.customItems.push(itm);
+ var itm = new flash.ui.ContextMenuItem("HaxeMaps - Zoom out");
+ itm.addEventListener(flash.events.ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e) { me.zoomOut(); });
+ contextMenu.customItems.push(itm);
+*/
+ }
+ }
+
+ /*==============================================================================================
+ LAYER MANAGEMENT
+ *==============================================================================================*/
+ public function initialize()
+ {
+ if (initialized)
+ return;
+
+ var m:MapService = null;
+
+ //find the first defined service
+ for (l in layers)
+ if (l.layer.mapservice != null)
+ {
+ m = l.layer.mapservice;
+ break;
+ }
+
+ //Check if there is a layer containing mapservice
+ if (m == null)
+ return;
+
+ //initialize the layers
+ for (l in layers)
+ {
+ if (l.layer.mapservice == null)
+ l.layer.mapservice = m;
+
+ if (l.enabled)
+ {
+ initializeLayer(l);
+ addChild(l.layer);
+ }
+ }
+
+ initialized = true;
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+
+ public function addLayer(layer:Layer, enable:Bool=true)
+ {
+ for (l in layers)
+ if (l.layer == layer)
+ return;
+
+ var alayer:ALayer = {layer:layer, enabled:false};
+ layers.push(alayer);
+ layer.addEventListener(Layer.ZOOM_FINISHED, zoomFinished);
+
+ if ((initialized) && (enable)) //synchronize
+ {
+ initializeLayer(alayer);
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+
+ alayer.enabled = enable;
+ }
+
+ public function removeLayer(layer:Layer)
+ {
+ for (l in layers)
+ {
+ if (l.layer == layer)
+ {
+ removeChild(layer);
+ layer.removeEventListener(Layer.ZOOM_FINISHED, zoomFinished);
+ layer.clear();
+ layers.remove(l);
+ return;
+ }
+ }
+ }
+
+ public function enableLayer(layer:Layer)
+ {
+ var childidx = 0;
+ for (i in 0...layers.length)
+ {
+
+ var l:ALayer = layers[i];
+ if (l.layer == layer)
+ {
+ if (l.enabled)
+ break;
+
+ l.enabled = true;
+
+ if (initialized)
+ {
+ initializeLayer(l, false);
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+
+ if (i == layers.length - 1)
+ addChild(l.layer);
+ else
+ addChildAt(l.layer, childidx);
+ return;
+ }
+
+ if (l.enabled)
+ childidx++;
+ }
+ }
+
+ public function disableLayer(layer:Layer)
+ {
+ for (l in layers)
+ if (l.layer == layer)
+ {
+ if (!l.enabled)
+ break;
+
+ removeChild(l.layer);
+ l.layer.clear();
+ l.enabled = false;
+
+ return;
+ }
+ }
+
+ public function updateLayer(layer:Layer)
+ {
+ for (l in layers)
+ if (l.layer == layer)
+ {
+ if (l.enabled)
+ l.layer.update();
+ return;
+ }
+
+ }
+
+ public function layerEnabled(layer:Layer)
+ {
+ for (l in layers)
+ if (l.layer == layer)
+ return l.enabled;
+
+ return false;
+ }
+
+ function initializeLayer(alayer:ALayer, canAdd:Bool = true)
+ {
+ if (alayer.layer.mapservice == null)
+ {
+ for (l in layers)
+ if (l.layer.mapservice != null)
+ {
+ alayer.layer.mapservice = l.layer.mapservice;
+ break;
+ }
+ }
+
+ if (alayer.layer.mapservice == null)
+ return;
+
+ var sz = getSize();
+ var center:LngLat = this.center;
+
+ if (initialized)
+ {
+ //synchronize position
+ for (l in layers)
+ if ((l != alayer) && (l.enabled) && (l.layer.mapservice != null))
+ {
+ center = l.layer.getCenter();
+ //trace("Init new center:"+center);
+ break;
+ }
+ }
+
+ alayer.layer.finalize();
+ alayer.layer.setCenter(center);
+ alayer.layer.setBBox(new Rectangle(0,0,sz.width,sz.height));
+ alayer.layer.setZoom(this.zoom);
+ alayer.layer.initialize();
+
+ if ((!alayer.enabled) && (canAdd))
+ addChild(alayer.layer);
+ }
+
+ /*==============================================================================================
+ POSITION / ZOOM
+ *==============================================================================================*/
+ public function zoomIn()
+ {
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(this.zoom + 1)))
+ return;
+
+ this.zoom += 1;
+ for (l in layers)
+ if (l.enabled)
+ l.layer.zoomIn();
+ }
+
+ public function zoomOut()
+ {
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(this.zoom - 1)))
+ return;
+
+ this.zoom -= 1;
+ for (l in layers)
+ if (l.enabled)
+ l.layer.zoomOut();
+ }
+
+ public function getZoom() : Int
+ {
+ return this.zoom;
+ }
+
+ public function getMinZoom() : Int
+ {
+ var z:Int = this.zoom - 1;
+ while (z > -16)
+ {
+ var vld:Bool = true;
+
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(z)))
+ {
+ vld = false;
+ break;
+ }
+
+ if (!vld)
+ break;
+
+ z--;
+ }
+
+ return z + 1;
+ }
+
+ public function getMaxZoom() : Int
+ {
+ var z:Int = this.zoom + 1;
+ while (z > -16)
+ {
+ var vld:Bool = true;
+
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(z)))
+ {
+ vld = false;
+ break;
+ }
+
+ if (!vld)
+ break;
+
+ z++;
+ }
+
+ return z - 1;
+ }
+
+ public function setZoom(zoom:Int)
+ {
+ for (l in layers)
+ if ((l.enabled) && (!l.layer.validZoom(zoom)) && (l.layer.mapservice != null))
+ return;
+
+ this.zoom = zoom;
+
+ if (!initialized) return;
+
+ for (l in layers)
+ if (l.enabled)
+ l.layer.setZoom(this.zoom);
+ }
+
+ public function setCenter(point:LngLat)
+ {
+ if (!initialized)
+ {
+ center = point;
+ return;
+ }
+
+ for (l in layers)
+ if (l.enabled)
+ l.layer.setCenter(point);
+
+
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+
+ public function getCenter(): LngLat
+ {
+ var c:LngLat = center.clone();
+ if (initialized)
+ for (l in layers)
+ if (l.enabled)
+ {
+ c = l.layer.getCenter();
+ break;
+ }
+
+ return c;
+ }
+
+ public function getLngLat(global:Point) : LngLat
+ {
+ if (initialized)
+ for (l in layers)
+ if (l.enabled)
+ return l.layer.getLngLat(l.layer.globalToLocal(global));
+ return null;
+ }
+
+ public function getLeftTopCorner() : LngLat
+ {
+ return getLngLat(localToGlobal(new Point(0,0)));
+ }
+
+ public function getRightBottomCorner() : LngLat
+ {
+ var sz = getSize();
+ return getLngLat(localToGlobal(new Point(sz.width,sz.height)));
+ }
+
+ public function panTo(point:LngLat)
+ {
+ if (this.animTimer.running)
+ {
+ this.animTo = point.clone();
+ return;
+ }
+
+ for (l in layers)
+ if (l.enabled)
+ {
+ this.animTo = point.clone();
+ this.animTimer.addEventListener(TimerEvent.TIMER, animStep);
+ this.animTimer.start();
+
+ return;
+ }
+ }
+
+
+ public function getBitmap() : BitmapData
+ {
+ var sz = getSize();
+ var bmp:BitmapData = new BitmapData(Std.int(sz.width), Std.int(sz.height), false, 0x00FFFFFF);
+ bmp.draw(this);
+ return bmp;
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+ function set_transparent(val:Bool): Bool
+ {
+ this.transparent = val;
+
+ graphics.clear();
+ if (this.transparent)
+ return true;
+
+ var sz = getSize();
+ graphics.beginFill(0xFFFFFF);
+ graphics.drawRect(0,0,sz.width,sz.height);
+ graphics.endFill();
+
+ return this.transparent;
+ }
+
+ override function onResize(w:Float, h:Float)
+ {
+ set_transparent(this.transparent);
+ scrollRect = new Rectangle(0, 0, w, h);
+
+ //trace("Canvas resized w:"+w+" h:"+h);
+ for (l in layers)
+ l.layer.setBBox(new Rectangle(0,0,w,h));
+ }
+
+ function onMouseDown(e:MouseEvent)
+ {
+ var tl:Point = localToGlobal(new Point(0,0));
+ var br:Point = localToGlobal(new Point(width, height));
+
+ start = new Point(e.stageX, e.stageY);
+ thpassed = false;
+
+ removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
+ removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
+ flash.Lib.current.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
+ flash.Lib.current.stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
+ }
+
+ function onMouseUp(e:MouseEvent)
+ {
+ addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
+ addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
+ flash.Lib.current.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
+ flash.Lib.current.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove);
+
+ if ((!thpassed) && (thtimer == null))
+ {
+ mappoint = getLngLat(new Point(e.stageX, e.stageY));
+ thtimer = new Timer(300, 1);
+ thtimer.addEventListener(TimerEvent.TIMER_COMPLETE, fireMapClicked);
+ thtimer.start();
+ }
+ }
+
+ function fireMapClicked(e:TimerEvent)
+ {
+ dispatchEvent(new MapEvent(MapEvent.MAP_CLICKED, mappoint));
+
+ if (thtimer != null)
+ {
+ thtimer.stop();
+ thtimer.removeEventListener(TimerEvent.TIMER_COMPLETE, fireMapClicked);
+ thtimer = null;
+ }
+ }
+
+ function onMouseDoubleClick(e:MouseEvent)
+ {
+ if (!doubleClickEnabled) return;
+
+ if (thtimer != null)
+ {
+ thtimer.stop();
+ thtimer.removeEventListener(TimerEvent.TIMER_COMPLETE, fireMapClicked);
+ thtimer = null;
+ }
+
+ if (e.ctrlKey)
+ zoomOut()
+ else
+ zoomIn();
+ }
+
+ function onMouseMove(e:MouseEvent)
+ {
+ for (l in layers)
+ if (l.enabled)
+ {
+ var pt = l.layer.globalToLocal(new Point(e.stageX, e.stageY));
+ dispatchEvent(new MapEvent(MapEvent.MAP_MOUSEMOVE, l.layer.getLngLat(pt)));
+ return;
+ }
+ }
+
+ function onStageMouseMove(e:MouseEvent)
+ {
+ var pt:Point = new Point(e.stageX, e.stageY);
+
+ if (!thpassed)
+ {
+ if (Point.distance(pt, start) < this.mousethreshold)
+ return;
+ start = pt;
+ thpassed = true;
+ return;
+ }
+
+ animStop();
+
+ var diff = pt.subtract(start);
+ var cntr:LngLat = null;
+
+ for (l in layers)
+ if (l.enabled)
+ {
+ try
+ {
+ l.layer.moveRelative(diff.x, diff.y);
+ cntr = l.layer.getCenter();
+ center = cntr;
+ }
+ catch (unknown : Dynamic)
+ {}
+ }
+
+ if (cntr != null)
+ {
+ dispatchEvent(new MapEvent(MapEvent.MAP_MOVE, cntr));
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+ start = pt;
+ }
+
+
+ function animStop()
+ {
+ if (animTimer.running)
+ {
+ animTimer.stop();
+ animTimer.removeEventListener(TimerEvent.TIMER, animStep);
+ }
+ }
+
+ function animStep(e:flash.events.Event)
+ {
+ for (l in layers)
+ if (l.enabled)
+ {
+ try {
+ var a:Point = l.layer.getCenterXY();
+ var b:Point = l.layer.getPointXY(animTo);
+ var dist:Float = Point.distance(a, b);
+ if (dist < 1.0)
+ animStop();
+ a = a.subtract(b);
+
+ var k:Float = (dist < 5) ? 1.0 : ((dist < 10) ? 5.0 : 10.0);
+ a.x = a.x / k;
+ if (a.x < -64) a.x = -64;
+ if (a.x > 64) a.x = 64;
+ a.y = a.y / k;
+ if (a.y < -64) a.y = -64;
+ if (a.y > 64) a.y = 64;
+
+ l.layer.moveRelative(a.x, a.y);
+
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+ catch (unknown : Dynamic)
+ {}
+ }
+ }
+
+
+ function zoomFinished(e:Event)
+ {
+ dispatchEvent(new MapEvent(MapEvent.MAP_ZOOMCHANGED, null));
+ dispatchEvent(new MapEvent(MapEvent.MAP_CHANGED, null));
+ }
+}
diff --git a/src/map/Layer.hx b/src/map/Layer.hx
new file mode 100644
index 0000000..21dafa6
--- /dev/null
+++ b/src/map/Layer.hx
@@ -0,0 +1,522 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import flash.display.Sprite;
+import flash.events.Event;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+import map.Utils;
+import map.LngLat;
+
+class Layer extends Sprite
+{
+ public static var ZOOM_FINISHED:String = "zoomfinished";
+
+ public var bbox(default, null):Rectangle;
+ var zoom:Int;
+ var animTimer:Timer;
+ var animState:Int;
+ var animTmp:Float;
+ var initialized:Bool;
+ var updateEnabled:Bool;
+ var center:LngLat;
+ var lastcenter:LngLat;
+ var canvascenter:Point;
+ var lastxy:Point;
+ var lastcxy:Point;
+ var scalable:Bool;
+ public var mapservice:MapService;
+
+ public function new(map_service:MapService = null, scalable:Bool = false)
+ {
+ super();
+
+ this.scalable = scalable;
+ this.mapservice = map_service;
+ this.initialized = false;
+ this.updateEnabled = false;
+ this.bbox = new Rectangle(0,0,flash.Lib.current.stage.width, flash.Lib.current.stage.height);
+ this.canvascenter = new Point(this.bbox.width/2.0,this.bbox.height/2.0);
+ this.center = null;
+ this.zoom = 0;
+ this.lastxy = null;
+ this.lastcxy = null;
+
+ animTimer = new Timer(15, 0);
+ animTimer.addEventListener(TimerEvent.TIMER, animStep);
+
+ mouseEnabled = false;
+
+ }
+
+ /*==============================================================================================
+ INITIALIZATION / FINALIZATION / MISC
+ *==============================================================================================*/
+
+ public function initialize(update:Bool=true) : Int
+ {
+
+ if (mapservice == null)
+ return 1;
+
+ if (this.initialized)
+ finalize();
+
+ this.x = this.canvascenter.x;
+ this.y = this.canvascenter.y;
+
+ synchronizeScale(true);
+
+ if (Std.is(this, Layer))
+ {
+ this.initialized = true;
+ if (!this.updateEnabled)
+ {
+ this.updateEnabled = true;
+ updateChanged();
+ }
+
+ if (update)
+ updateContent(true);
+ }
+
+ return 0;
+ }
+
+ public function finalize()
+ {
+ if (this.initialized)
+ clear();
+
+ this.initialized = false;
+ }
+
+
+ public function setBBox(bbox:Rectangle)
+ {
+ if (bbox == null)
+ return;
+
+ var actcenter:LngLat = null;
+ if ((this.bbox != null) && (this.initialized))
+ actcenter = this.getCenter();
+
+ this.bbox = bbox;
+ this.canvascenter = new Point(this.bbox.x + this.bbox.width/2.0, this.bbox.y + this.bbox.height/2.0);
+
+ if (actcenter != null)
+ this.setCenter(actcenter);
+ }
+
+
+ public function clear()
+ {
+ }
+
+ /*==============================================================================================
+ POSITION
+ *==============================================================================================*/
+
+ public function getOriginXY() : Point
+ {
+ if (this.mapservice == null)
+ return new Point(0,0);
+
+ return mapservice.lonlat2XY(center.lng, center.lat, mapservice.zoom_def + zoom);
+ }
+
+ public function getCenterXY() : Point
+ {
+ var pta:Point = getOriginXY();
+ pta.offset(-x + this.canvascenter.x, - y + this.canvascenter.y);
+ return pta;
+ }
+
+ public function getPointXY(point:LngLat) : Point
+ {
+ if (this.mapservice == null)
+ return new Point(0,0);
+
+ return mapservice.lonlat2XY(point.lng, point.lat, mapservice.zoom_def + zoom);
+ }
+
+ public function getCenter() : LngLat
+ {
+ if (this.mapservice == null)
+ return null;
+
+ if ((x == this.canvascenter.x) && (y == this.canvascenter.y))
+ return center.clone();
+
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = getCenterXY();
+ var ptb:LonLat = mapservice.XY2lonlat(pta.x, pta.y, z);
+
+ return new LngLat(ptb.x, ptb.y);
+ }
+
+ public function getXY(local:Point) : Point
+ {
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = mapservice.lonlat2XY(center.lng, center.lat, z);
+ pta.offset(scaleX*local.x, scaleY*local.y);
+ return pta;
+ }
+
+ public function getLngLat(local:Point) : LngLat
+ {
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = mapservice.lonlat2XY(center.lng, center.lat, z);
+ var ptb:Point = mapservice.XY2lonlat(pta.x + scaleX*local.x, pta.y + scaleY*local.y, z);
+ return new LngLat(ptb.x, ptb.y);
+ }
+
+ public function setCenter(point:LngLat)
+ {
+ if ((this.scalable) && (initialized))
+ synchronizeCenter(point);
+ else
+ this.center = point.clone();
+ centerUpdated(true);
+ }
+
+ public function moveTo(x:Float, y:Float)
+ {
+ if ((this.animTimer.running) || ((this.x == x) && (this.y == y)))
+ return;
+
+
+ this.x = x;
+ this.y = y;
+
+ if (this.updateEnabled)
+ updateContent();
+ }
+
+ public function moveRelative(dx:Float, dy:Float)
+ {
+ if ((this.animTimer.running) || ((dx == 0) && (dy == 0)))
+ return;
+
+ this.x += dx;
+ this.y += dy;
+
+ if (this.updateEnabled)
+ updateContent();
+ }
+
+ public function getOffset() : Point
+ {
+ return new Point(this.x - this.canvascenter.x, this.y - this.canvascenter.y);
+ }
+
+ public function getLeftTopCorner(margin:Float = 0.0) : LngLat
+ {
+ if (!initialized) return null;
+
+ var x:Float = this.canvascenter.x - this.x - this.bbox.width/2.0 + margin;
+ var y:Float = this.canvascenter.y - this.y - this.bbox.height/2.0 + margin;
+
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = mapservice.lonlat2XY(center.lng, center.lat, z);
+ var ptb:Point = mapservice.XY2lonlat(pta.x + scaleX*x, pta.y + scaleY*y, z);
+
+ return new LngLat(ptb.x, ptb.y);
+ }
+
+ public function getRightBottomCorner(margin:Float = 0.0) : LngLat
+ {
+ if (!initialized) return null;
+
+ var x:Float = this.canvascenter.x - this.x + this.bbox.width/2.0 + margin;
+ var y:Float = this.canvascenter.y - this.y + this.bbox.height/2.0 + margin;
+
+ var z:Int = mapservice.zoom_def + zoom;
+ var pta:Point = mapservice.lonlat2XY(center.lng, center.lat, z);
+ var ptb:Point = mapservice.XY2lonlat(pta.x + scaleX*x, pta.y + scaleY*y, z);
+
+ return new LngLat(ptb.x, ptb.y);
+ }
+
+
+ /*==============================================================================================
+ ZOOM
+ *==============================================================================================*/
+
+ public function validZoom(zoom:Int) : Bool
+ {
+ return ((!this.animTimer.running) && (this.mapservice != null) && (this.mapservice.validZoom(zoom)));
+ }
+
+ public function setZoom(zoom:Int)
+ {
+ if (!validZoom(zoom)) return;
+
+ this.zoom = zoom;
+ if (this.scalable)
+ synchronizeScale();
+
+ if (!this.initialized)
+ return;
+
+ this.center = getCenter(); //get actual center & update layer content
+ centerUpdated(true);
+ }
+
+ public function zoomIn(animate:Bool = true)
+ {
+ if ((this.animTimer.running) || (!this.initialized) || (this.mapservice == null) || (!this.mapservice.validZoom(zoom+1)))
+ return;
+
+ this.lastxy = new Point(x,y);
+ this.lastcenter = getCenter();
+ this.lastcxy = new Point(this.canvascenter.x, this.canvascenter.y);
+
+ if (!animate)
+ {
+ scaleX = scaleX * 2.0;
+ scaleY = scaleY * 2.0;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) * 2.0;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) * 2.0;
+
+ zoomChanged(this.updateEnabled, zoom + 1);
+
+ return;
+ }
+
+
+ this.animState = 0x0000;
+
+ if (this.updateEnabled)
+ {
+ this.updateEnabled = false;
+ updateChanged();
+ this.animState += 0x0100;
+ }
+
+ this.animTmp = scaleX;
+ this.animTimer.start();
+ }
+
+ public function zoomOut(animate:Bool = true)
+ {
+ if ((this.animTimer.running) || (!this.initialized) || (this.mapservice == null) || (!this.mapservice.validZoom(zoom-1)))
+ return;
+
+ this.lastxy = new Point(x,y);
+ this.lastcenter = getCenter();
+ this.lastcxy = new Point(this.canvascenter.x, this.canvascenter.y);
+
+ if (!animate)
+ {
+ scaleX = scaleX / 2.0;
+ scaleY = scaleY / 2.0;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) / 2.0;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) / 2.0;
+
+ zoomChanged(this.updateEnabled, zoom - 1);
+
+ return;
+ }
+
+ this.animState = 0x1000;
+ if (this.updateEnabled)
+ {
+ this.updateEnabled = false;
+ updateChanged();
+ this.animState += 0x0100;
+ }
+
+ this.animTmp = scaleX;
+ this.animTimer.start();
+ }
+
+ public function update()
+ {
+ updateContent(true);
+ }
+
+ /*==============================================================================================
+ PRIVATE
+ *==============================================================================================*/
+ function updateContent(forceUpdate:Bool=false)
+ {
+ }
+
+ function updateChanged()
+ {
+ }
+
+ function zoomChanged(prevEnabled:Bool, newZoom:Int)
+ {
+ this.zoom = newZoom;
+ if (!scalable)
+ {
+ scaleX = scaleY = 1.0;
+
+ center = this.lastcenter;
+ centerUpdated(false);
+ }
+ else
+ synchronizeCenter(this.lastcenter);
+
+ dispatchEvent(new Event(ZOOM_FINISHED));
+
+ if ((prevEnabled) && (!this.updateEnabled))
+ {
+ this.updateEnabled = true;
+ updateContent(!scalable);
+ updateChanged();
+ }
+ }
+
+ /*==============================================================================================
+ PRIVATE
+ *==============================================================================================*/
+
+ function synchronizeCenter(point:LngLat)
+ {
+ if (!this.scalable)
+ return;
+
+ var pta:Point = getOriginXY();
+ var ptb:Point = getPointXY(point);
+ this.x = pta.x - ptb.x + canvascenter.x;
+ this.y = pta.y - ptb.y + canvascenter.y;
+ }
+
+ function synchronizeScale(init:Bool=false)
+ {
+
+ if (this.scalable)
+ {
+ if (this.zoom < 0) {
+ scaleX = 1.0 / (1 << (-this.zoom));
+ scaleY = 1.0 / (1 << (-this.zoom));
+ } else {
+ scaleX = (1 << this.zoom);
+ scaleY = (1 << this.zoom);
+ }
+
+ }
+ else if ((!this.scalable) && (init))
+ {
+ this.scaleX = 1.0;
+ this.scaleY = 1.0;
+ }
+
+ }
+
+ function centerUpdated(clearQueue:Bool)
+ {
+ if (!this.initialized)
+ return;
+
+ if (!this.scalable)
+ {
+ this.x = this.canvascenter.x;
+ this.y = this.canvascenter.y;
+ }
+
+ if (this.updateEnabled)
+ updateContent((clearQueue) && (!scalable));
+ }
+
+ function animStep(e:flash.events.Event)
+ {
+ var steps:Float = 10.0;
+
+ var act = (animState >> 12) & 0x0F;
+ var en = (animState >> 8) & 0x0F;
+ var st = (animState & 0xFF);
+
+ if (act == 0)
+ {
+ if (st < steps)
+ {
+ var scale:Float = (1.0 + (st + 1)/steps);
+
+ scaleX = animTmp * scale;
+ scaleY = scaleX;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) * scale;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) * scale;
+
+ animState += 1;
+ }
+ else if (st == steps)
+ {
+ animTimer.stop();
+
+ scaleX = animTmp * 2.0;
+ scaleY = animTmp * 2.0;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) * 2.0;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) * 2.0;
+
+ zoomChanged(en == 1, zoom + 1);
+ }
+ }
+ else if (act == 1)
+ {
+ if (st < steps)
+ {
+ var scale:Float = (1.0 + (st + 1)/steps);
+
+ scaleX = animTmp / scale;
+ scaleY = scaleX;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) / scale;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) / scale;
+
+ animState += 1;
+ }
+ else if (st == steps)
+ {
+ animTimer.stop();
+
+ scaleX = animTmp / 2.0;
+ scaleY = animTmp / 2.0;
+
+ x = lastcxy.x + (lastxy.x - lastcxy.x) / 2.0;
+ y = lastcxy.y + (lastxy.y - lastcxy.y) / 2.0;
+
+ zoomChanged(en == 1, zoom - 1);
+ }
+ }
+ }
+
+}
diff --git a/src/map/LngLat.hx b/src/map/LngLat.hx
new file mode 100644
index 0000000..7d16363
--- /dev/null
+++ b/src/map/LngLat.hx
@@ -0,0 +1,85 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+class LngLat
+{
+ public var lat: Float;
+ public var lng: Float;
+
+ public function new(lng:Float, lat:Float)
+ {
+ this.lng = lng;
+ this.lat = lat;
+ }
+
+ inline public function clone()
+ {
+ return new LngLat(this.lng, this.lat);
+ }
+
+ public function toString():String
+ {
+
+ return "[LngLat] lng:" + fmtCoordinate(this.lng) + " lat:" + fmtCoordinate(this.lat);
+ }
+
+ //convert coordinate to string (format %.6f)
+ static public function fmtCoordinate(value:Float) : String
+ {
+ var valuef:Float = Math.floor(value);
+ var f:Float = value - valuef;
+ var s:String = Std.string(valuef) + ".";
+ for (i in 0...6)
+ {
+ f *= 10.0;
+ s += Std.string(Math.floor(f));
+ f = f - Math.floor(f);
+ }
+ return s;
+ }
+
+ //distance between two points in meters
+ static public function distance(a:LngLat, b:LngLat) : Float
+ {
+ var dlat:Float = (b.lat - a.lat) * Math.PI / 180;
+ var dlon:Float = (b.lng - a.lng) * Math.PI / 180;
+
+ dlat = Math.sin(dlat/2);
+ dlon = Math.sin(dlon/2);
+ var a:Float = dlat*dlat + Math.cos(a.lat * Math.PI / 180 ) * Math.cos(b.lat * Math.PI / 180 ) * dlon*dlon;
+ var c:Float = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
+ c = 6371000.0 * c; //avg. radius of the earth in meters
+
+ return c;
+ }
+
+}
diff --git a/src/map/MapService.hx b/src/map/MapService.hx
new file mode 100644
index 0000000..2a151bb
--- /dev/null
+++ b/src/map/MapService.hx
@@ -0,0 +1,215 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import map.Utils;
+import flash.geom.Point;
+
+interface MapService
+{
+ var id(default,null):String;
+ var zoom_min(default,null):Int;
+ var zoom_max(default,null):Int;
+ var zoom_def(default,null):Int;
+ var tile_size(default,null):Int;
+ var invert_x(default,null):Bool;
+ var invert_y(default,null):Bool;
+
+ function lonlat2tile(lon:Float, lat:Float, zoom:Int) : TileID;
+ function tile2lonlat(t:TileID) : LonLat;
+ function lonlat2XY(lon:Float, lat:Float, zoom:Int) : Point;
+ function XY2lonlat(x:Float, y:Float, zoom:Int) : LonLat;
+ function validZoom(z:Int) : Bool;
+ function tile2url(t:TileID) : String;
+}
+
+class BaseMapService {
+
+ public var id(default,null):String;
+ public var zoom_min(default,null):Int;
+ public var zoom_max(default,null):Int;
+ public var zoom_def(default,null):Int;
+ public var tile_size(default,null):Int;
+ public var invert_x(default,null):Bool;
+ public var invert_y(default,null):Bool;
+
+ var proxy:Bool;
+ var proxy_url:String;
+
+ public function new(id:String, abbrev:String, zoom_min:Int, zoom_max:Int, zoom_def:Int, tile_size:Int=256)
+ {
+ setInfo(id, abbrev, zoom_min, zoom_max, zoom_def, tile_size);
+ }
+
+ function setInfo(id:String, abbrev:String, zoom_min:Int, zoom_max:Int, zoom_def:Int, tile_size:Int=256)
+ {
+ this.id = id;
+ this.zoom_min = zoom_min;
+ this.zoom_max = zoom_max;
+ this.zoom_def = zoom_def;
+ this.tile_size = tile_size;
+ this.invert_x = false;
+ this.invert_y = false;
+ this.proxy = false;
+
+ //check if the proxy parameter is set
+ var params = flash.Lib.current.loaderInfo.parameters;
+ if ((params != null) && (params.proxy != null) && (params.proxy != ""))
+ {
+ this.proxy_url = params.proxy;
+ if (this.proxy_url.charAt(proxy_url.length-1) != '/')
+ this.proxy_url += '/';
+ this.proxy_url += abbrev + "/";
+ this.id += " (Proxy)";
+ this.proxy = true;
+ }
+ }
+
+ public function validZoom(z:Int) : Bool
+ {
+ return (((zoom_def + z) >= zoom_min) && ((zoom_def + z) <= zoom_max));
+ }
+
+}
+
+class OpenStreetMapService extends BaseMapService implements MapService
+{
+ // Details:
+ // ---------------------------------------------------------
+ // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
+
+ override public function new(default_zoom:Int = 13)
+ {
+ super("Open Street Map", "osm", 0, 18, default_zoom, 256);
+ }
+
+ public inline function lonlat2tile(lon:Float, lat:Float, zoom:Int) : TileID
+ {
+ var z:Float = Math.pow(2,zoom);
+ var lr:Float = lat*Math.PI/180;
+ return {x: (Math.floor((lon+180)/360*z)),
+ y: (Math.floor(z*(1-Math.log(Math.tan(lr) + 1/Math.cos(lr))/Math.PI)/2)),
+ z: zoom};
+ }
+
+ public inline function lonlat2XY(lon:Float, lat:Float, zoom:Int) : Point
+ {
+ var z:Float = tile_size * Math.pow(2,zoom);
+ var lr:Float = lat*Math.PI/180;
+ return new Point((Math.floor(z*(lon+180)/360)),
+ (Math.floor(z*(1-Math.log(Math.tan(lr) + 1/Math.cos(lr))/Math.PI)/2)));
+ }
+
+ public inline function tile2lonlat(t:TileID) : LonLat
+ {
+ var z = Math.pow(2,t.z);
+ var n = Math.PI-2*Math.PI*t.y/z;
+ return new LonLat(t.x/z*360-180, 180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
+ }
+
+ public inline function XY2lonlat(x:Float, y:Float, zoom:Int) : LonLat
+ {
+ var z = tile_size * Math.pow(2, zoom);
+ var n = Math.PI-2*Math.PI*y/z;
+ return new LonLat(x/z*360-180, 180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
+ }
+
+ public function tile2url(t:TileID) : String
+ {
+ if (!isValid(t)) return "";
+
+ if (!proxy) {
+ return "http://tile.openstreetmap.org/" + (t.z) + "/" + (t.x) + "/" + (t.y) + ".png";
+ // return "http://otile1.mqcdn.com/tiles/1.0.0/map/" + (t.z) + "/" + (t.x) + "/" + (t.y) + ".png";
+
+ }
+
+
+ return this.proxy_url + (t.z) + "_" + (t.x) + "_" + (t.y);
+ }
+
+ function isValid(t:TileID) : Bool
+ {
+ //check zoom
+ if ((t.z < zoom_min) || (t.z > zoom_max)) return false;
+
+ //check bounds
+ var z:Float = Math.pow(2, t.z);
+ if ((t.x < 0) || (t.x >= z) || (t.y < 0) || (t.y >= z)) return false;
+
+ return true;
+ }
+
+}
+
+class BingMapService extends OpenStreetMapService
+{
+
+ // Details:
+ // ---------------------------------------------------------
+ // http://msdn.microsoft.com/en-us/library/bb545006.aspx
+
+ var hybrid:Bool;
+
+ override public function new(default_zoom:Int = 13, hybrid:Bool = false)
+ {
+ super();
+ this.hybrid = hybrid;
+ setInfo("Bink Maps", "bnk", 1, 18, default_zoom, 256);
+
+ }
+
+ override public function tile2url(t:TileID) : String
+ {
+ if (!isValid(t)) return "";
+
+ if (!proxy)
+ {
+ var xx:Int = t.x;
+ var yy:Int = t.y;
+ var tid:String = "";
+ for (i in 0...t.z)
+ {
+ var q:Int = 0;
+ if ((xx & 1) == 1) q += 1;
+ if ((yy & 1) == 1) q += 2;
+ tid = q + tid;
+
+ xx = xx >> 1;
+ yy = yy >> 1;
+ }
+ return "http://tiles.virtualearth.net/tiles/"+(hybrid ? "h" : "r")+tid+".png?g=414&mkt=en-us&shading=hill&n=z";
+ }
+
+ return this.proxy_url + (t.z) + "_" + (t.x) + "_" + (t.y);
+ }
+
+}
diff --git a/src/map/QuadTree.hx b/src/map/QuadTree.hx
new file mode 100644
index 0000000..45a789a
--- /dev/null
+++ b/src/map/QuadTree.hx
@@ -0,0 +1,240 @@
+/*******************************************************************************
+Copyright (c) 2010, Karel Slany (slany AT fit.vutbr.cz)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+typedef QuadData = {
+ public var x:Float;
+ public var y:Float;
+ public var data:Dynamic;
+}
+
+class QuadLeaf {
+ public var x:Float;
+ public var y:Float;
+ public var data:Array;
+ public var ll:Dynamic; // < x, < y
+ public var lg:Dynamic; // < x, >= y
+ public var gl:Dynamic; // >= x, < y
+ public var gg:Dynamic; // >= x, >= y
+
+ public function new(xv:Float, yv:Float, d:Dynamic, optfast:Bool) {
+ x = xv;
+ y = yv;
+ data = new Array();
+ if (optfast) {
+ var qd:QuadData = {x:xv, y:yv, data:d};
+ data.push(qd);
+ } else {
+ data.push(d);
+ }
+ ll = lg = gl = gg = null;
+ }
+
+ public function push(d:Dynamic, optfast:Bool) {
+ if (optfast) {
+ var qd:QuadData = {x:x, y:y, data:d};
+ data.push(qd);
+ } else {
+ data.push(data);
+ }
+ }
+
+ public function remove(d:Dynamic, optfast:Bool):Bool {
+ if (optfast) {
+ for (itm in data)
+ if (itm.data == d)
+ return data.remove(itm);
+ } else {
+ return data.remove(d);
+ }
+ return false;
+ }
+
+ public function getData(data:Array, optfast:Bool, filter:QuadData->Bool) {
+ var qd:QuadData = null;// = {x:0.0, y:0.0, data:null};
+ if (optfast) {
+ for (qd in this.data) {
+ if ((filter == null) || (filter(qd)))
+ data.push(qd);
+ }
+ } else {
+ for (i in 0...this.data.length) {
+ qd.x = x;
+ qd.y = y;
+ qd.data = this.data[i];
+ if ((filter == null) || (filter(qd)))
+ data.push(qd);
+ }
+ }
+ }
+}
+
+class QuadTree {
+
+ public var qroot:Dynamic;
+ var optfast:Bool;
+
+ public function new() {
+ optfast = true; //true - optimized for maximal speed,
+ //false - optimized for mimimal memory footprint
+ qroot = null;
+ }
+
+ /*==============================================================================================
+ PUBLIC methods
+ *==============================================================================================*/
+ public function clear() {
+ qroot = null;
+ }
+
+ public function isEmpty() {
+ return qroot == null;
+ }
+
+ public function push(x:Float, y:Float, data:Dynamic) {
+ if (qroot != null) {
+ push_recursive(qroot, x, y, data);
+ } else {
+ qroot = new QuadLeaf(x, y, data, optfast);
+ }
+ }
+
+ public function remove(x:Float, y:Float, data:Dynamic) : Bool {
+ // return true if found and removed
+ if (qroot != null) {
+ return remove_recursive(qroot, x, y, data);
+ }
+ return false;
+ }
+
+ public function getData(minx:Float, miny:Float, maxx:Float, maxy:Float) : Array {
+ var data = new Array();
+ if (qroot == null) return data;
+ get_data_recursive(qroot, data, minx, miny, maxx, maxy, null);
+ return data;
+ }
+
+ public function getFilteredData(minx:Float, miny:Float, maxx:Float, maxy:Float, filter:QuadData->Bool) : Array {
+ var data = new Array();
+ if (qroot == null) return data;
+ get_data_recursive(qroot, data, minx, miny, maxx, maxy, filter);
+ return data;
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+
+ function push_recursive(root:QuadLeaf, x:Float, y:Float, data:Dynamic) {
+ if ((x == root.x) && (y == root.y)) {
+ // allows multiple entries
+ root.push(data, optfast);
+ } else if (x < root.x) {
+ if (y < root.y) {
+ if (root.ll != null) {
+ push_recursive(root.ll, x, y, data);
+ } else {
+ root.ll = new QuadLeaf(x, y, data, optfast);
+ }
+ } else {
+ if (root.lg != null) {
+ push_recursive(root.lg, x, y, data);
+ } else {
+ root.lg = new QuadLeaf(x, y, data, optfast);
+ }
+ }
+ } else {
+ if (y < root.y) {
+ if (root.gl != null) {
+ push_recursive(root.gl, x, y, data);
+ } else {
+ root.gl = new QuadLeaf(x, y, data, optfast);
+ }
+ } else {
+ if (root.gg != null) {
+ push_recursive(root.gg, x, y, data);
+ } else {
+ root.gg = new QuadLeaf(x, y, data, optfast);
+ }
+ }
+ }
+ }
+
+ function remove_recursive(root:QuadLeaf, x:Float, y:Float, data:Dynamic) : Bool {
+ // does not remove nodes, only removes data entries
+ if ((x == root.x) && (y == root.y)) {
+ return root.remove(data, optfast);
+ } else if (x < root.x) {
+ if (y < root.y) {
+ if (root.ll != null) {
+ return remove_recursive(root.ll, x, y, data);
+ }
+ return false;
+ } else {
+ if (root.lg != null) {
+ return remove_recursive(root.lg, x, y, data);
+ }
+ return false;
+ }
+ } else {
+ if (y < root.y) {
+ if (root.gl != null) {
+ return remove_recursive(root.gl, x, y, data);
+ }
+ return false;
+ } else {
+ if (root.gg != null) {
+ return remove_recursive(root.gg, x, y, data);
+ }
+ return false;
+ }
+ }
+ }
+
+ function get_data_recursive(root:QuadLeaf, data:Array, minx:Float, miny:Float, maxx:Float, maxy:Float, filter:QuadData->Bool) {
+ if ((minx <= root.x) && (miny <= root.y) && (maxx >= root.x) && (maxy >= root.y)) {
+ root.getData(data, optfast, filter);
+ }
+ if ((root.ll != null) && (minx <= root.x) && (miny <= root.y)) {
+ get_data_recursive(root.ll, data, minx, miny, maxx, maxy, filter);
+ }
+ if ((root.lg != null) && (minx <= root.x) && (maxy >= root.y)) {
+ get_data_recursive(root.lg, data, minx, miny, maxx, maxy, filter);
+ }
+ if ((root.gl != null) && (maxx >= root.x) && (miny <= root.y)) {
+ get_data_recursive(root.gl, data, minx, miny, maxx, maxy, filter);
+ }
+ if ((root.gg != null) && (maxx >= root.x) && (maxy >= root.y)) {
+ get_data_recursive(root.gg, data, minx, miny, maxx, maxy, filter);
+ }
+ }
+
+}
diff --git a/src/map/Tile.hx b/src/map/Tile.hx
new file mode 100644
index 0000000..79c913a
--- /dev/null
+++ b/src/map/Tile.hx
@@ -0,0 +1,174 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import flash.display.Sprite;
+import flash.display.Bitmap;
+import flash.text.TextField;
+import flash.text.TextFieldAutoSize;
+
+class Tile extends Sprite
+{
+ #if TILE_DBG
+ var t:TextField;
+ #end
+
+ var size:Int;
+ var valid:Bool;
+ public var tx(default, set_tx):Int;
+ public var ty(default, set_ty):Int;
+ public var tidx(default, null):Int;
+ public var image(default, null):Bitmap;
+
+
+ public var rtidx:Int; //right neighbour tidx
+ public var ltidx:Int; //left neighbour tidx
+ public var ttidx:Int; //top neighbour tidx
+ public var btidx:Int; //bottom neighbour tidx
+
+ override public function new(tidx:Int, size:Int = 256, x:Int = 0, y:Int = 0)
+ {
+ super();
+
+ #if TILE_DBG
+ var s:Sprite = new Sprite();
+ s.graphics.lineStyle(2, (tidx == 0) ? 0xFF0000 : 0x008000);
+ s.graphics.moveTo(0,0);
+ s.graphics.lineTo(size,size);
+ s.graphics.moveTo(size,0);
+ s.graphics.lineTo(0,size);
+ s.graphics.moveTo(size-1,0);
+ s.graphics.lineTo(size-1,size);
+ s.graphics.moveTo(0,size-1);
+ s.graphics.lineTo(size,size-1);
+ addChild(s);
+
+ t = new TextField();
+ t.autoSize = TextFieldAutoSize.LEFT;
+ t.mouseEnabled = false;
+ addChild(t);
+ #end
+
+ this.tidx = tidx;
+ this.rtidx = -1;
+ this.ltidx = -1;
+ this.ttidx = -1;
+ this.btidx = -1;
+
+ this.tx = x;
+ this.ty = y;
+ this.size = size;
+ this.image = null;
+ this.valid = false;
+ mouseEnabled = false;
+
+ update();
+ }
+
+ /*==============================================================================================
+ PUBLIC methods
+ *==============================================================================================*/
+ public function assignImage(image:Bitmap)
+ {
+ graphics.clear();
+
+ if (this.image != null)
+ {
+ removeChild(this.image);
+ this.image = null;
+ }
+
+ if (image != null)
+ {
+ this.image = image;
+ addChildAt(this.image, 0);
+ }
+ else
+ {
+ graphics.lineStyle(2, 0xF0F0F0);
+ graphics.drawCircle(size/2,size/2, 10);
+ }
+
+ this.valid = (this.image != null);
+ }
+
+ //returns True iff the tile waits for an image
+ public function needImage():Bool
+ {
+ return !this.valid;
+ }
+
+ //tile is being loaded
+ public function waitForImage()
+ {
+ }
+
+ public function invalidate()
+ {
+ this.valid = false;
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+ function update()
+ {
+ #if TILE_DBG
+ t.text = "("+tx+","+ty+")";
+ t.x = (size - t.width)/2;
+ t.y = (size - t.height)/2;
+ #end
+ }
+
+
+ function set_tx(val:Int) : Int
+ {
+ if (val != tx)
+ {
+ tx = val;
+ update();
+ assignImage(null);
+ }
+ return val;
+ }
+
+ function set_ty(val:Int) : Int
+ {
+ if (val != ty)
+ {
+ ty = val;
+ update();
+ assignImage(null);
+ }
+ return val;
+ }
+
+}
diff --git a/src/map/TileLayer.hx b/src/map/TileLayer.hx
new file mode 100644
index 0000000..fe35261
--- /dev/null
+++ b/src/map/TileLayer.hx
@@ -0,0 +1,546 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import map.Tile;
+import map.TileLoader;
+import map.Layer;
+import map.Utils;
+import flash.events.Event;
+import flash.geom.Point;
+import flash.display.Bitmap;
+
+#if TILE_EVT_DBG
+import flash.external.ExternalInterface;
+#end
+
+class TileLayer extends Layer
+{
+ var tiles:Array;
+ var tilecnt:Int;
+ var loader:TileLoader;
+
+ var tofs:Int; /* kdy presunout tiles zprava doleva (kolik za obrazem musi min. byt) */
+ var lx:Int;
+ var rx:Int;
+ var ty:Int;
+ var by:Int;
+ var tilesize:Int;
+ var basetid:TileID;
+ var ofsx:Float;
+ var ofsy:Float;
+ var smooth:Bool;
+
+ public function new(map_service:MapService = null, tiles:Int = 8, smooth_zoom:Bool = true)
+ {
+ super(map_service);
+
+ this.tilecnt = tiles;
+ this.tiles = new Array();
+ this.tilesize = 256;
+ this.tofs = 1;
+ this.basetid = {x:0,y:0,z:0};
+ this.ofsx = this.ofsy = 0;
+ this.tofs = 0;
+ this.smooth = smooth_zoom;
+
+ while (this.tiles.length < this.tilecnt*this.tilecnt)
+ {
+ var t:Tile = new Tile(this.tiles.length, this.tilesize);
+ this.tiles.push(t);
+ addChild(t);
+ }
+ initTile();
+
+ this.loader = new TileLoader();
+ this.loader.addEventListener(TileLoadedEvent.TILE_LOADED, tileLoaded);
+ }
+
+ /*==============================================================================================
+ PUBLIC methods
+ *==============================================================================================*/
+ override public function initialize(update:Bool=true) : Int
+ {
+ var res = super.initialize(false);
+ if (res != 0)
+ return res;
+
+ loader.mapservice = mapservice;
+ basetid.z = mapservice.zoom_def;
+ tilesize = mapservice.tile_size;
+
+ alignLayer();
+
+ initialized = true;
+ updateEnabled = true;
+
+ if (update)
+ updateContent(true);
+
+ return 0;
+ }
+
+ override public function clear()
+ {
+ //clean loader queue
+ loader.clear();
+
+ //release used images
+ for (t in tiles)
+ t.assignImage(null);
+ }
+
+ override public function getOffset() : Point
+ {
+ var tp = tiles.length >> 1;
+ return new Point(this.x - (this.canvascenter.x - (scaleX*this.tilesize)/2), this.y - (this.canvascenter.y - (scaleY*this.tilesize)/2));
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+ function initTile()
+ {
+ this.lx = -this.tofs;
+ this.rx = this.tilecnt-1-this.tofs;
+ this.ty = -this.tofs;
+ this.by = this.tilecnt-1-this.tofs;
+
+ var tp = this.tilecnt >> 1;
+ this.lx = -tp;
+ this.ty = -tp;
+ tp = this.tilecnt - tp;
+ this.rx = tp-1;
+ this.by = tp-1;
+
+ var i:Int = 0;
+ var j:Int = 0;
+ var idx:Int = 0;
+
+ for (t in tiles)
+ {
+ if (i == this.tilecnt)
+ {
+ i = 0;
+ j++;
+ }
+
+ t.tx = this.lx + i;
+ t.ty = this.ty + j;
+
+ t.ltidx = (i == 0) ? idx + this.tilecnt - 1 : idx - 1;
+ t.rtidx = (i < this.tilecnt-1) ? idx + 1 : idx - this.tilecnt + 1;
+ t.ttidx = (j == 0) ? idx + ((this.tilecnt-1) * this.tilecnt) : idx - this.tilecnt;
+ t.btidx = (j < this.tilecnt-1) ? idx + this.tilecnt : idx;
+
+ t.x = tilesize*t.tx + ofsx;
+ t.y = tilesize*t.ty + ofsy;
+
+ i++;
+ idx++;
+ }
+
+ }
+
+ override function centerUpdated(clearQueue:Bool)
+ {
+ if (!this.initialized)
+ return;
+
+ if (clearQueue)
+ {
+ saveImages();
+ clear();
+ }
+
+ alignLayer();
+
+ initTile();
+ emitRequests();
+ }
+
+
+
+ override function updateContent(forceUpdate:Bool=false)
+ {
+ var i = 0;
+
+ //move tiles if it is needed
+ while (i < tiles.length / 2)
+ {
+ if (!testAndShift())
+ break;
+
+ i++;
+ }
+
+ if ((i == 0) && (!forceUpdate))
+ return;
+
+ //update tile positions
+ for (t in tiles)
+ {
+ t.x = tilesize*t.tx + ofsx;
+ t.y = tilesize*t.ty + ofsy;
+ }
+
+ //load required images
+ emitRequests();
+ }
+
+ override function updateChanged()
+ {
+ if (!this.updateEnabled)
+ loader.clear();
+ }
+
+ override function zoomChanged(prevEnabled:Bool, newZoom:Int)
+ {
+ var lp:Int = 0;
+ var tp:Int = 0;
+ var tilehsize:Float = tilesize / 2;
+
+ if (this.zoom > newZoom)
+ {
+
+ if (smooth) {
+ //smooth zoom - combines four tiles into one
+
+ var bx:Int = (basetid.x & 1) ^ 1;
+ var by:Int = (basetid.y & 1) ^ 1;
+
+ for (t in tiles)
+ {
+ if ((t.tx & 1 == bx) || (t.ty & 1 == by)) continue;
+
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0xFFFFFF);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(0.5, 0.5);
+ if (t.image != null)
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilehsize,tilehsize), false);
+
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(0.5, 0.5);
+ scaleMatrix.translate(tilehsize,0);
+ var tt = tiles[t.rtidx];
+ if ((tt.tx != this.lx) && (tt.image != null))
+ bd.draw(tt.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(tilehsize,0,tilehsize,tilehsize), false);
+
+
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(0.5, 0.5);
+ scaleMatrix.translate(0,tilehsize);
+ var tt = tiles[t.btidx];
+ if ((tt.ty != this.ty) && (tt.image != null))
+ bd.draw(tt.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,tilehsize,tilehsize,tilehsize), false);
+
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(0.5, 0.5);
+ scaleMatrix.translate(tilehsize,tilehsize);
+ var tt = tiles[tiles[t.btidx].rtidx];
+ if ((tt.tx != this.lx) && (tt.ty != this.ty) && (tt.image != null))
+ bd.draw(tt.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(tilehsize,tilehsize,tilehsize,tilehsize), false);
+
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x) >> 1,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y) >> 1,
+ newZoom + basetid.z,
+ bd, false
+ );
+
+ }
+ }
+
+ //zoom out
+ if (basetid.x & 1 == 1) x -= tilesize/2;
+ if (basetid.y & 1 == 1) y -= tilesize/2;
+ basetid.x = basetid.x >> 1;
+ basetid.y = basetid.y >> 1;
+
+ ofsx = ofsx / 2.0;
+ ofsy = ofsy / 2.0;
+
+ //coeficients for the /2 transformation
+ // x' = x/2 == x - x/2
+ // y' = y/2 == y - y/2
+ lp = - Std.int(this.lx/2);
+ tp = - Std.int(this.ty/2);
+
+ }
+ else
+ {
+
+ if (smooth)
+ {
+ //smooth zoom - each tile is splited into the four tiles
+ var mintx:Int = Std.int((3*this.lx + this.rx + 1) / 4);
+ var maxtx:Int = Std.int((3*this.rx + this.lx + 3) / 4);
+ var minty:Int = Std.int((3*this.ty + this.by + 1) / 4);
+ var maxty:Int = Std.int((3*this.by + this.ty + 3) / 4);
+ for (t in tiles)
+ if ((t.image != null) && (t.tx >= mintx) && (t.tx <= maxtx) && (t.ty >= minty) && (t.ty <= maxty))
+ {
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0xFFFFFF);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(2, 2);
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilesize,tilesize), false);
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x)*2,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y)*2,
+ newZoom + basetid.z, bd, false
+ );
+
+
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0xFFFFFF);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(2, 2);
+ scaleMatrix.translate(-tilesize,0);
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilesize,tilesize), false);
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x)*2 + 1,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y)*2,
+ newZoom + basetid.z, bd, false
+ );
+
+
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0xFFFFFF);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(2, 2);
+ scaleMatrix.translate(0,-tilesize);
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilesize,tilesize), false);
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x)*2,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y)*2 + 1,
+ newZoom + basetid.z, bd, false
+ );
+
+
+ var bd = new flash.display.BitmapData(tilesize, tilesize, false, 0x00FF00);
+ var scaleMatrix = new flash.geom.Matrix();
+ scaleMatrix.scale(2, 2);
+ scaleMatrix.translate(-tilesize,-tilesize);
+ bd.draw(t.image.bitmapData, scaleMatrix, null, null, new flash.geom.Rectangle(0,0,tilesize,tilesize), false);
+ loader.addTile((((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x)*2 + 1,
+ (((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y)*2 + 1,
+ newZoom + basetid.z, bd, false
+ );
+
+ }
+ }
+
+ //zoom in
+ basetid.x = basetid.x << 1;
+ basetid.y = basetid.y << 1;
+
+ ofsx = ofsx * 2.0;
+ ofsy = ofsy * 2.0;
+
+ //coeficients for the *2 transformation
+ // x' = x*2 == x + x
+ // y' = y*2 == y + y
+ lp = this.lx;
+ tp = this.ty;
+
+
+ }
+
+ //transform tile id's
+ for (t in tiles)
+ {
+ t.tx += lp;
+ t.ty += tp;
+ }
+
+ this.rx += lp;
+ this.by += tp;
+ this.lx += lp;
+ this.ty += tp;
+
+ //update zoom, reset scale
+ this.zoom = newZoom;
+
+ scaleX = 1;
+ scaleY = 1;
+
+ clear();
+ center = this.lastcenter;
+ centerUpdated(false);
+
+ dispatchEvent(new Event(Layer.ZOOM_FINISHED));
+
+ if ((prevEnabled) && (!this.updateEnabled))
+ {
+ this.updateEnabled = true;
+ updateChanged();
+ }
+
+ updateContent(true);
+ }
+
+ function testAndShift() : Bool
+ {
+ var mv_left = ((this.lx+this.tofs)*tilesize*scaleX + this.x > bbox.x);
+ var mv_right = ((this.rx-this.tofs)*tilesize*scaleX + this.x < (bbox.x+bbox.width));
+ var mv_up = ((this.ty+this.tofs)*tilesize*scaleY + this.y > bbox.y);
+ var mv_down = ((this.by-this.tofs)*tilesize*scaleY + this.y < (bbox.y+bbox.height));
+
+ if ((mv_left) && ((this.rx-1)*tilesize*scaleX + this.x < (bbox.x+bbox.width)))
+ mv_left = false;
+ if ((mv_up) && ((this.by-1)*tilesize*scaleY + this.y < (bbox.y+bbox.height)))
+ mv_up = false;
+ if ((mv_right) && ((this.lx+1)*tilesize*scaleX + this.x > bbox.x))
+ mv_right = false;
+ if ((mv_down) && ((this.ty+1)*tilesize*scaleY + this.y > bbox.y))
+ mv_down = false;
+
+ if (mv_left && mv_right) mv_right = false;
+ if (mv_up && mv_down) mv_down = false;
+
+ if (!(mv_left || mv_right || mv_up || mv_down)) return false;
+
+ for (t in tiles)
+ {
+ if ((mv_left) && (t.tx == rx))
+ t.tx = lx - 1;
+ if ((mv_right) && (t.tx == lx))
+ t.tx = rx + 1;
+ if ((mv_up) && (t.ty == by))
+ t.ty = ty - 1;
+ if ((mv_down) && (t.ty == ty))
+ t.ty = by + 1;
+ }
+ var dx = (mv_left) ? -1 : ((mv_right) ? 1 : 0);
+ var dy = (mv_up) ? -1 : ((mv_down) ? 1 : 0);
+
+ lx += dx;
+ rx += dx;
+ ty += dy;
+ by += dy;
+
+ return true;
+ }
+
+ function alignLayer()
+ {
+
+ if (center == null) return;
+
+ x = this.canvascenter.x;
+ y = this.canvascenter.y;
+
+ basetid = mapservice.lonlat2tile(center.lng, center.lat, basetid.z+zoom);
+ var ptc = mapservice.lonlat2XY(center.lng, center.lat, basetid.z);
+ var ll = mapservice.tile2lonlat(basetid);
+ var ptt = mapservice.lonlat2XY(ll.x, ll.y, basetid.z);
+ basetid.z -= zoom;
+ ptt = ptt.subtract(ptc);
+ ofsx = ptt.x;
+ ofsy = ptt.y;
+ }
+
+
+ function emitRequests()
+ {
+ var prio:Int = 0;
+ var xx:Float;
+ var yy:Float;
+
+ loader.disable();
+
+ try
+ {
+ loader.tidyQueue(((mapservice.invert_x) ? -lx : lx) + basetid.x, ((mapservice.invert_x) ? -rx : rx) + basetid.x,
+ ((mapservice.invert_y) ? -ty : ty) + basetid.y, ((mapservice.invert_y) ? -by : by) + basetid.y,
+ zoom + basetid.z
+ );
+
+ for (tile in tiles)
+ {
+ if (tile.needImage())
+ {
+
+
+ xx = (tile.x + x - ofsx - this.canvascenter.x);
+ yy = (tile.y + y - ofsy - this.canvascenter.y);
+ prio = Std.int(Math.sqrt(xx*xx + yy*yy));
+
+ loader.addRequest( ((mapservice.invert_x) ? -tile.tx : tile.tx) + basetid.x,
+ ((mapservice.invert_y) ? -tile.ty : tile.ty) + basetid.y,
+ zoom + basetid.z,
+ tile.tidx,
+ prio
+ );
+
+ tile.waitForImage();
+ }
+ }
+
+ } catch (unknown : Dynamic) {};
+
+ loader.enable();
+ }
+
+
+ function tileLoaded(e:TileLoadedEvent)
+ {
+ if ((e.tidx >= 0) && (e.tidx < tiles.length))
+ {
+
+ var t:Tile = tiles[e.tidx];
+ if ((t != null) &&
+ (((mapservice.invert_x) ? -t.tx : t.tx) == e.x - basetid.x) && //check x-id
+ (((mapservice.invert_y) ? -t.ty : t.ty) == e.y - basetid.y) && //check y-id
+ (e.z - basetid.z == zoom) //check z
+ )
+ {
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "tileLoaded "+e.data+" x:"+t.tx+" y:"+t.ty+" ("+e.x+","+e.y+","+e.z+") priority:"+e.p);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ t.assignImage(e.data);
+ }
+ }
+ }
+
+
+ function saveImages()
+ {
+ for (t in tiles)
+ if (t.image != null)
+ loader.addTile(((mapservice.invert_x) ? -t.tx : t.tx) + basetid.x,
+ ((mapservice.invert_y) ? -t.ty : t.ty) + basetid.y,
+ zoom + basetid.z,
+ t.image.bitmapData
+ );
+
+
+ }
+
+}
diff --git a/src/map/TileLoader.hx b/src/map/TileLoader.hx
new file mode 100644
index 0000000..fd960a9
--- /dev/null
+++ b/src/map/TileLoader.hx
@@ -0,0 +1,547 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import map.Utils;
+
+import flash.events.Event;
+import flash.events.EventDispatcher;
+import flash.events.IOErrorEvent;
+import flash.display.Loader;
+import flash.display.Bitmap;
+import flash.display.BitmapData;
+import flash.net.URLRequest;
+import flash.system.LoaderContext;
+
+import flash.utils.Timer;
+import flash.events.TimerEvent;
+
+#if TILE_EVT_DBG
+import flash.external.ExternalInterface;
+#end
+
+typedef TileIDT = {
+ var x : Int;
+ var y : Int;
+ var z : Int;
+ var tidx : Int;
+ var ttl : Int;
+ var priority: Int;
+};
+
+
+class TileLoadedEvent extends flash.events.Event
+{
+ public static var TILE_LOADED:String = "tileLoaded";
+
+ public var x:Int;
+ public var y:Int;
+ public var z:Int;
+ public var p:Int;
+ public var tidx:Int;
+ public var data:Bitmap;
+
+ public function new(x:Int, y:Int, z:Int, tidx:Int, p:Int, data:Bitmap) {
+ super(TILE_LOADED);
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.p = p;
+ this.tidx = tidx;
+ this.data = data;
+ }
+}
+
+class ImageLoader extends Loader
+{
+ static var TIMEOUT:Int = 5; //10 sec
+
+ public var used:Bool;
+ public var ignore:Bool;
+ public var id:Int;
+ public var ttl:Int;
+ public var tid:TileIDT;
+
+
+ public function new(id:Int)
+ {
+ super();
+ this.used = false;
+ this.ignore = false;
+ this.id = id;
+ this.ttl = TIMEOUT;
+ }
+
+ public function loadImage(tid:TileIDT, url:String) {
+ var urlRequest:URLRequest = new URLRequest(url);
+ this.tid = tid;
+ try {
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "loadImage "+id+" ("+tid.x+","+tid.y+","+tid.z+") prio:"+tid.priority);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ this.load(urlRequest, new LoaderContext(true));
+ this.used = true;
+ this.ttl = TIMEOUT;
+
+ }
+ catch (unknown : Dynamic)
+ {
+ this.used = false;
+ }
+ }
+
+ override public function toString()
+ {
+ return "[ImageLoader id:" + id + "]";
+ }
+
+}
+
+typedef TempTile = {
+ var x : Int;
+ var y : Int;
+ var z : Int;
+ var img : BitmapData;
+ var ttl : Int;
+ var original : Bool;
+};
+
+class TileLoader extends EventDispatcher
+{
+ public static var DEFAULT_TTL:Int = 3;
+ public var mapservice:MapService;
+ var loaders:Array;
+ var queue:Array;
+ var tempqueue:Array;
+ var enabled:Int;
+ var watchdog:Timer;
+
+ public function new(threads:Int = 8)
+ {
+ super();
+
+ mapservice = null;
+ enabled = 0;
+
+ watchdog = new Timer(1000, 0);
+ watchdog.addEventListener(TimerEvent.TIMER, checkLoaders);
+ watchdog.stop();
+
+ loaders = new Array();
+ queue = new Array();
+ tempqueue = new Array();
+
+ for (i in 0...threads)
+ {
+ var l = new ImageLoader(i);
+ l.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, loaderComplete);
+ l.contentLoaderInfo.addEventListener(flash.events.IOErrorEvent.IO_ERROR, loaderError);
+ loaders.push(l);
+
+ }
+ }
+
+ /*==============================================================================================
+ PUBLIC methods
+ *==============================================================================================*/
+
+ public function clear()
+ {
+ clearQueue();
+
+ for (l in loaders)
+ if (l.used)
+ {
+ l.ignore = true;
+ try {
+ //l.close(); //BUGGY!
+ //l.unload();
+ }
+ catch (unknown : Dynamic)
+ { };
+ }
+
+ }
+
+ public function enable()
+ {
+ if (enabled > 0)
+ enabled--;
+
+ if (enabled == 0)
+ {
+ sortQueue();
+ processQueue();
+
+ if (!watchdog.running)
+ watchdog.start();
+ }
+ }
+
+ public function disable()
+ {
+ if (watchdog.running)
+ watchdog.stop();
+
+ enabled++;
+ }
+
+
+ public function tidyQueue(minx:Int, maxx:Int, miny:Int, maxy:Int, z:Int)
+ {
+ var i:Int = 0;
+ while (i < queue.length)
+ {
+ var tid:TileIDT = queue[i];
+ if (tid.z == z)
+ {
+ if ((tid.x < minx) || (tid.x > maxx) || (tid.y < miny) || (tid.y > maxy))
+ queue.remove(tid);
+ else
+ i += 1;
+ }
+ else
+ queue.remove(tid);
+ }
+ }
+
+ public function addRequest(x:Int, y:Int, z:Int, tidx:Int, priority:Int = 0)
+ {
+ if ((x < 0) || (y < 0) || (z < 0)) return;
+
+ var q:TempTile = getTile(x, y, z);
+ if (q != null)
+ {
+ tempqueue.remove(q);
+ dispatchEvent(new TileLoadedEvent(x,y,z,tidx,priority, new Bitmap(q.img)));
+ if (q.original)
+ return;
+ }
+
+ for (l in loaders)
+ if ((l.used) && (!l.ignore) && (l.tid.x == x) && (l.tid.y == y) && (l.tid.z == z))
+ return; //request already served, return
+
+ var exists:Bool = false;
+ for (tid in queue)
+ if ((tid.x == x) && (tid.y == y) && (tid.z == z))
+ {
+ //request already in queue, update priority
+ tid.priority = priority;
+ exists = true;
+ break;
+ }
+
+ if (!exists)
+ queue.push({x:x,y:y,z:z,tidx:tidx,priority:priority,ttl:DEFAULT_TTL});
+
+ if (enabled == 0)
+ {
+ sortQueue();
+ processQueue();
+ }
+
+ }
+
+ public function addTile(x:Int, y:Int, z:Int, img:BitmapData, original:Bool = true)
+ {
+ //check if the tile image is not already in queue
+ var tmp:TempTile = getTile(x,y,z);
+ if (tmp != null)
+ {
+ if (((!tmp.original) && (original)) || ((!tmp.original) && (!original)))
+ {
+ tmp.img = img;
+ tmp.original = original;
+ tmp.ttl = DEFAULT_TTL;
+ }
+ return;
+ }
+
+ insertTile({x: x, y: y, z: z, img: img, ttl:DEFAULT_TTL, original:original});
+ }
+
+ override public function toString() : String
+ {
+ var used = 0;
+ for (l in loaders)
+ if (l.used)
+ used++;
+
+ return "[TileLoader] threads total:" + loaders.length + ", active threads:" + used + ", enabled threads:" + enabled;
+ }
+
+ /*==============================================================================================
+ PRIVATE methods
+ *==============================================================================================*/
+ function clearQueue()
+ {
+ while (queue.length > 0)
+ queue.pop();
+ }
+
+ function checkLoaders(e:TimerEvent)
+ {
+ //watchdog timer event
+
+ //check for broken loaders
+ var used = 0;
+ for (l in loaders)
+ if (l.used)
+ {
+ if (l.ttl > 0)
+ l.ttl--;
+ else if (l.ttl == 0)
+ loaderFailed(l);
+ used++;
+ }
+
+ var i=0;
+ var q:TempTile;
+ //remove unused tiles in tempqueue
+ while (i < tempqueue.length)
+ {
+ q = tempqueue[i];
+
+ if (q.ttl > 0)
+ q.ttl--;
+ else if (q.ttl == 0)
+ {
+ tempqueue.remove(q);
+ continue;
+ }
+
+ i++;
+ used++;
+ }
+
+ if ((used == 0) && (watchdog.running))
+ watchdog.stop();
+
+ }
+
+
+ function sortQueue()
+ {
+ queue.sort(function(x:TileIDT,y:TileIDT):Int { return x.priority - y.priority;});
+ }
+
+
+ function processQueue()
+ {
+
+ if ((enabled != 0) || (queue.length == 0) || (mapservice == null))
+ return;
+
+ if (queue.length == 0)
+ return;
+
+ var tid:TileIDT;
+ for (l in loaders)
+ {
+ if (l.used)
+ continue;
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "processQueue qlen:"+queue.length);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ if (queue.length == 0) return;
+
+ tid = queue.shift();
+
+ var url:String = mapservice.tile2url(tid);
+ if (url != "")
+ l.loadImage(tid, url);
+
+ if (!watchdog.running)
+ watchdog.start();
+
+ }
+
+ }
+
+ function loaderComplete(e:Event)
+ {
+
+ if ((e.target == null) || (e.target.loader == null))
+ return;
+
+ var loader:ImageLoader = e.target.loader;
+
+ if (!loader.ignore)
+ {
+ try {
+ var x:Int = loader.tid.x;
+ var y:Int = loader.tid.y;
+ var z:Int = loader.tid.z;
+ var t:Int = loader.tid.tidx;
+ var p:Int = loader.tid.priority;
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "tileLoaded ("+x+","+y+","+z+") priority:"+p);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ var bitmapc:Bitmap = new Bitmap(cast(loader.content, Bitmap).bitmapData.clone());
+ dispatchEvent(new TileLoadedEvent(x,y,z,t,p, bitmapc));
+
+ }
+ catch (unknown : Dynamic)
+ {
+
+ //chyba, znovu do fronty, pokud jiz neni vycerpan poc. pokusu
+ if (loader.tid.ttl > 0)
+ {
+ queue.push({x:loader.tid.x, y:loader.tid.y, z:loader.tid.z,
+ tidx:loader.tid.tidx,
+ ttl:loader.tid.ttl - 1,
+ priority:loader.tid.priority
+ });
+ if (enabled == 0)
+ sortQueue();
+ }
+
+ };
+ }
+ else
+ {
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "tileIgnored");
+ } catch (unknown : Dynamic) { };
+ #end
+ }
+
+ try {
+ loader.unload();
+ } catch (unknown : Dynamic) {};
+
+ loader.used = false;
+ loader.ignore = false;
+
+ processQueue();
+ }
+
+ function loaderFailed(l:ImageLoader)
+ {
+ l.used = false;
+ l.ignore = false;
+
+ #if TILE_EVT_DBG
+ try {
+ ExternalInterface.call("debugMessage", "tileError " + l.tid.x + ","+l.tid.y+","+l.tid.z);
+ } catch (unknown : Dynamic) { };
+ #end
+
+ if ((l.tid.ttl > 0) && (!l.ignore))
+ {
+ //loading failed, return request back to the queue
+ queue.push({x:l.tid.x,y:l.tid.y,z:l.tid.z,tidx:l.tid.tidx,ttl:l.tid.ttl - 1,priority:l.tid.priority});
+
+ if (enabled == 0)
+ sortQueue();
+ }
+
+ processQueue();
+ }
+
+
+ function loaderError(e:IOErrorEvent)
+ {
+
+ for (l in loaders)
+ if (l.contentLoaderInfo == e.target)
+ loaderFailed(l);
+ }
+
+ function getTile(x:Int, y:Int, z:Int) : TempTile
+ {
+ //looking for a tile in the sorted array
+
+ var min:Int = 0;
+ var max:Int = tempqueue.length-1;
+ var mid:Int;
+ var val:Int; var cmp:Int;
+ while (min <= max) {
+ mid = Math.floor((min + max) / 2);
+
+ cmp = (x - tempqueue[mid].x);
+ if (cmp == 0) cmp = (y - tempqueue[mid].y);
+ if (cmp == 0) cmp = (z - tempqueue[mid].z);
+
+ if (cmp == 0)
+ return tempqueue[mid]
+ else if (cmp > 0)
+ min = mid + 1;
+ else
+ max = mid - 1;
+
+ }
+
+ return null;
+ }
+
+ function insertTile(t:TempTile)
+ {
+ //insert TempTile into the sorted array
+
+ var min:Int = 0;
+ var max:Int = tempqueue.length-1;
+ var mid:Int;
+ var val:Int; var cmp:Int;
+
+ while (min <= max) {
+ mid = Math.floor((min + max) / 2);
+
+ cmp = (t.x - tempqueue[mid].x);
+ if (cmp == 0) cmp = (t.y - tempqueue[mid].y);
+ if (cmp == 0) cmp = (t.z - tempqueue[mid].z);
+
+ if (cmp > 0)
+ min = mid + 1;
+ else
+ max = mid - 1;
+
+ }
+
+ tempqueue.insert(min, t);
+ }
+
+}
+
diff --git a/src/map/Utils.hx b/src/map/Utils.hx
new file mode 100644
index 0000000..5f9b407
--- /dev/null
+++ b/src/map/Utils.hx
@@ -0,0 +1,74 @@
+/*******************************************************************************
+Copyright (c) 2010, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ Marek Vavrusa (marek AT vavrusa.com)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the organization nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+package map;
+
+import flash.geom.Point;
+import flash.filters.ColorMatrixFilter;
+
+class Utils
+{
+ public static function dec2hex(i:Int, digits:Int)
+ {
+ var c = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
+ var s:String = '';
+ var val = i;
+ for (j in 0...digits)
+ {
+ s = c[val % 16] + s;
+ val = val >> 4;
+ }
+ return s;
+ }
+
+ public static function desaturationFilter(sat:Float = 1.0) : ColorMatrixFilter
+ {
+ var r = 0.212671;
+ var g = 0.715160;
+ var b = 0.072169;
+ return new ColorMatrixFilter(
+ [/* R */ sat*r+1-sat, sat*g, sat*b, 0, 0,
+ /* G */ sat*r, sat*g+1-sat, sat*b, 0, 0,
+ /* B */ sat*r, sat*g, sat*b+1-sat, 0, 0,
+ /* A */ 0, 0, 0, 1, 0
+ ]
+ );
+ }
+
+}
+
+typedef LonLat = Point; /* for internal usage */
+
+typedef TileID = {
+ var x : Int;
+ var y : Int;
+ var z : Int;
+};
+