source: subversion/applications/editors/potlatch/potlatch.as @ 12005

Last change on this file since 12005 was 11943, checked in by richard, 11 years ago

changeset comments and a couple of other small fixes

File size: 39.2 KB
Line 
1
2        // =====================================================================================
3        // Initialise
4
5        // Resizable window, disable right-click
6        Stage.showMenu = false;
7        Stage.align="TL";
8        Stage.scaleMode="noScale";
9        resizeListener=new Object();
10        resizeListener.onResize=function() { resizeWindow(); };
11        Stage.addListener(resizeListener);
12        var panelheight=110;
13       
14        // Master movieclip for map
15        _root.createEmptyMovieClip("map",10);
16        _root.map.setMask(_root.masksquare);
17
18        // Master movieclip for panel
19        _root.createEmptyMovieClip("panel",15);
20        _root.panel._x=0; _root.panel._y=500;
21        _root.panel.beginFill(0xF3F3F3,100);
22        _root.panel.moveTo(0,0); _root.panel.lineTo(3000,0);
23        _root.panel.lineTo(3000,panelheight); _root.panel.lineTo(0,panelheight);
24        _root.panel.lineTo(0,0);
25        _root.panel.endFill();
26        _root.panel.createEmptyMovieClip("advice",0xFFFFFC);
27
28        _root.createEmptyMovieClip("windows",0xFFFFFD);
29        var windowdepth=1;
30        var windowsopen=0;
31
32        // Sound
33        beep=new Sound();
34        beep.loadSound("/potlatch/beep.mp3",false);
35
36        // Co-ordinates
37        // London 51.5,0; Weybridge 51.4,-0.5; Worcester 52.2,-2.25; Woodstock 51.85,-1.35
38        var minscale=13;                                // don't zoom out past this
39        var maxscale=19;                                // don't zoom in past this
40        if (scale) {} else {scale=14;}  // default scale if not provided (e.g. GPX)
41        var scale=Math.max(Math.min(Math.floor(scale),maxscale),minscale);
42        var masterscale=5825.4222222222;// master map scale - how many Flash pixels in 1 degree longitude
43                                                                        // (for Landsat, 5120)
44        updateCoords();                                 // get radius, scale
45       
46        // Preselected way/node (from query string)
47        var preway=Number(way);
48        var prenode=Number(node);
49
50        // Preferences
51        preferences=SharedObject.getLocal("preferences");
52        var usertoken=token;
53        if (winie=='true' || winie==true) { winie=true; } else { winie=false; }
54
55        // Key listener - needs to be initialised before Yahoo
56        keyListener=new Object();
57        keyListener.onKeyDown=function() { keyPressed(); };
58        Key.addListener(keyListener);
59
60        // Initialise Yahoo
61        var ywidth=0;           var yheight=0;                  // current Yahoo state
62        var yzoom=8;            var lastyzoom=yzoom;    //  |
63        var bgxoffset=0;        var bgyoffset=0;                // manually correct Yahoo imagery
64        var yahooloaded=false;                                          // is Yahoo component loaded?
65        var yahooinited=false;                                          // is Yahoo component inited?
66        var yahoorightsize=true;                                        // do we need to resize Yahoo?
67        _root.createEmptyMovieClip("yahoo",7);
68
69//      var layernames=new Array("None","Aerial - OpenAerialMap","Aerial - Yahoo!","OSM - Mapnik","OSM - Osmarender","OSM - Maplint (errors)","OSM - cycle map");
70//      var layernums=new Array();
71//      var j=layernames.length; for (i in layernames) { j--; layernums[layernames[i]]=j; }
72
73        // Main initialisation
74        _root.map.createEmptyMovieClip("areas"    ,8);  var areadepth=1;
75        _root.map.createEmptyMovieClip("gpx"      ,9);
76        _root.map.createEmptyMovieClip("relations",10); var reldepth=1;
77        _root.map.createEmptyMovieClip("ways"     ,11); var waydepth=1;
78        _root.map.createEmptyMovieClip("pois"     ,12); var poidepth=1;
79        _root.map.createEmptyMovieClip("elastic"  ,5003); // elastic line
80        initTiles();                                    // create tile clips on layer 7
81
82        _root.masksquare.useHandCursor=false;
83        _root.masksquare.onPress   =function() { mapClick(); };
84        _root.masksquare.onRollOver=function() { mapRollOver(); };
85        _root.masksquare.onRollOut =function() { mapRollOut(); };
86        _root.masksquare.onRelease =function() { mapClickEnd(); };
87        _root.onMouseDown=function() { _root.lastkeypressed=-1; };
88
89        selectWay(0);                                   // way selected?    0 no, otherwise way id
90        var poiselected=0;                              // POI selected?    0 no, otherwise way id
91        var pointselected=-2;                   // point selected? -2 no, otherwise point order
92        var waycount=0;                                 // number of ways currently loaded
93        var waysrequested=0;                    // total number of ways requested
94        var waysreceived=0;                             // total number of ways received
95        var writesrequested=0;                  // number of outstanding write operations
96        var relcount=0;                                 // number of relations currently loaded
97        var relsrequested=0;                    // total number of relations requested
98        var relsreceived=0;                             // total number of relations received
99        var poicount=0;                                 // number of POIs currently loaded
100        var whichrequested=0;                   // total number of whichways requested
101        var whichreceived=0;                    // total number of whichways received
102        var redrawlist=new Array();             // list of ways to redraw (after zooming)
103        var redrawskip=true;                    // skip redrawing ways, just do POIs?
104        var lastwhichways=new Date();   // last time whichways was requested
105        var lastresize=new Date();              // last time window was resized
106        var mapdragged=false;                   // map being dragged?
107        var drawpoint=-1;                               // point being drawn? -1 no, 0+ yes (point order)
108        var lastpoint=0;                                // last value of drawpoint (triple-click detection)
109        var lastpointtime=null;                 // time of last double-click (triple-click detection)
110        var newrelid=-1;                                // new relation ID  (for those not yet saved)
111        var newwayid=-1;                                // new way ID           (for those not yet saved)
112        var newnodeid=-2;                               // new node ID          (for those not yet saved)
113        var newpoiid=-1;                                // new POI ID           (for those not yet saved)
114        var nodes=new Object();                 // hash of nodes
115        var currentproptype='';                 // type of property currently being edited
116        var pointertype='';                             // current mouse pointer
117        var redopropertywindow=null;    // need to redraw property window after deletion?
118        var lastkeypressed=null;                // code of last key pressed
119        var keytarget='';                               // send keys where? ('','key','value')
120        var tilesetloaded=-1;                   // which tileset is loaded?
121        var tolerance=4/Math.pow(2,_root.scale-13);
122        var bigedge_l=999999; var bigedge_r=-999999; // area of largest whichways
123        var bigedge_b=999999; var bigedge_t=-999999; //  |
124        var saved=new Array();                  // no saved presets yet
125        var sandbox=false;                              // we're doing proper editing
126        var lang=System.capabilities.language; // language (e.g. 'en', 'fr')
127        var signature="Potlatch 0.10g"; // current version
128        var maximised=false;                    // minimised/maximised?
129        var sourcetags=new Array("","","Yahoo","","","","","NPE","OpenTopoMap");
130
131//      if (layernums[preferences.data.baselayer]==undefined) { preferences.data.baselayer="Aerial - Yahoo!"; }
132        if (preferences.data.baselayer    ==undefined) { preferences.data.baselayer    =2; }    // background layer
133        if (preferences.data.dimbackground==undefined) { preferences.data.dimbackground=true; } // dim background?
134        if (preferences.data.custompointer==undefined) { preferences.data.custompointer=true; } // use custom pointers?
135        if (preferences.data.thinlines    ==undefined) { preferences.data.thinlines    =false;} // always use thin lines?
136        if (preferences.data.advice       ==undefined) { preferences.data.advice       =true; } // show floating advice?
137        if (preferences.data.nosplash     ==undefined) { preferences.data.nosplash     =false; }// hide splash screen?
138        if (preferences.data.noname       ==undefined) { preferences.data.nosplash     =false; }// highlight unnamed ways?
139
140        // =====================================================================================
141        // Icons
142
143        _root.attachMovie("zoomin","i_zoomin",30);
144        with (_root.i_zoomin) { _x=5; _y=5; };
145        _root.i_zoomin.onPress=function() { zoomIn(); };
146
147        _root.attachMovie("zoomout","i_zoomout",31);
148        with (_root.i_zoomout) { _x=5; _y=27; };
149        _root.i_zoomout.onPress=function() { zoomOut(); };
150        changeScaleTo(_root.scale);
151
152        // Way-specific
153
154        _root.panel.attachMovie("scissors","i_scissors",32);
155        with (_root.panel.i_scissors) { _x=15; _y=63; };
156        _root.panel.i_scissors.onPress   =function() { _root.ws.splitWay(_root.pointselected); };
157        _root.panel.i_scissors.onRollOver=function() { setFloater(iText("Split way at selected point (X)",'tip_splitway')); };
158        _root.panel.i_scissors.onRollOut =function() { clearFloater(); };
159
160        _root.panel.attachMovie("rotation","i_direction",39);
161        with (_root.panel.i_direction) { _x=40; _y=63; _rotation=-45; _visible=true; _alpha=50; };
162        _root.panel.i_direction.onPress=function() { _root.ws.reverseWay(); };
163        _root.panel.i_direction.onRollOver=function() { setFloater(iText("Direction of way - click to reverse",'tip_direction')); };
164        _root.panel.i_direction.onRollOut =function() { clearFloater(); };
165
166        _root.panel.attachMovie("clockwise","i_clockwise",40);
167        with (_root.panel.i_clockwise) { _x=40; _y=63; _visible=false; };
168        _root.panel.i_clockwise.onPress=function() { _root.ws.reverseWay(); };
169        _root.panel.i_clockwise.onRollOver=function() { setFloater(iText("Clockwise circular way - click to reverse",'tip_clockwise')); };
170        _root.panel.i_clockwise.onRollOut =function() { clearFloater(); };
171
172        _root.panel.attachMovie("anticlockwise","i_anticlockwise",42);
173        with (_root.panel.i_anticlockwise) { _x=40; _y=63; _visible=false; };
174        _root.panel.i_anticlockwise.onPress=function() { _root.ws.reverseWay(); };
175        _root.panel.i_anticlockwise.onRollOver=function() { setFloater(iText("Anti-clockwise circular way - click to reverse",'tip_anticlockwise')); };
176        _root.panel.i_anticlockwise.onRollOut =function() { clearFloater(); };
177
178        // General tools
179
180        _root.panel.lineStyle(1,0xCCCCCC,100);
181        _root.panel.moveTo(5,78); _root.panel.lineTo(75,78);
182
183        _root.panel.attachMovie("undo","i_undo",38);
184        with (_root.panel.i_undo) { _x=15; _y=93; _alpha=50; };
185        _root.panel.i_undo.onPress   =function() { _root.undo.rollback(); };
186        _root.panel.i_undo.onRollOver=function() { setFloater(iText("Nothing to undo",'tip_noundo')); };
187        _root.panel.i_undo.onRollOut =function() { clearFloater(); };
188
189        _root.panel.attachMovie("gps","i_gps",36);
190        with (_root.panel.i_gps) { _x=40; _y=93; };
191        _root.panel.i_gps.onPress   =function() { loadGPS(); };
192        _root.panel.i_gps.onRollOver=function() { setFloater(iText("Show GPS tracks (G)",'tip_gps')); };
193        _root.panel.i_gps.onRollOut =function() { clearFloater(); };
194
195        _root.panel.attachMovie("prefs","i_prefs",37);
196        with (_root.panel.i_prefs) { _x=65; _y=93; };
197        _root.panel.i_prefs.onPress   =function() { openOptionsWindow(); };
198        _root.panel.i_prefs.onRollOver=function() { setFloater(iText("Set options (choose the map background)",'tip_options')); };
199        _root.panel.i_prefs.onRollOut =function() { clearFloater(); };
200
201        _root.panel.attachMovie("newattr","i_newattr",33);
202        with (_root.panel.i_newattr) { _x=690; _y=95; };
203        _root.panel.i_newattr.onRelease =function() { _root.panel.properties.enterNewAttribute(); };
204        _root.panel.i_newattr.onRollOver=function() { setFloater(iText("Add a new tag",'tip_addtag')); };
205        _root.panel.i_newattr.onRollOut =function() { clearFloater(); };
206
207        _root.panel.attachMovie("newrel","i_newrel",44);
208        with (_root.panel.i_newrel) { _x=690; _y=75; backgroundColor=0xDDBBBB; background=true;};
209        _root.panel.i_newrel.onRelease =function() { if (Key.isDown(Key.SHIFT)) { _root.panel.properties.repeatAttributes(false);
210                                                                                                } else { addToRelation(); } };
211        _root.panel.i_newrel.onRollOver=function() { setFloater(iText("Add to a relation",'tip_addrelation')); };
212        _root.panel.i_newrel.onRollOut =function() { clearFloater(); };
213
214        _root.panel.attachMovie("repeatattr","i_repeatattr",34);
215        with (_root.panel.i_repeatattr) { _x=690; _y=55; };
216        _root.panel.i_repeatattr.onPress   =function() { _root.panel.properties.repeatAttributes(true); };
217        _root.panel.i_repeatattr.onRollOver=function() { setFloater(iText("Repeat tags from the previously selected way (R)",'tip_repeattag')); };
218        _root.panel.i_repeatattr.onRollOut =function() { clearFloater(); };
219
220        _root.panel.attachMovie("exclamation","i_warning",35);
221        with (_root.panel.i_warning) { _x=58; _y=50; _visible=false; };
222        _root.panel.i_warning.onPress=function() { handleWarning(); };
223        _root.panel.i_warning.onRollOver=function() { setFloater(iText("An error occurred - click for details",'tip_alert')); };
224        _root.panel.i_warning.onRollOut =function() { clearFloater(); };
225        wflashid=setInterval(function() { _root.panel.i_warning._alpha=150-_root.panel.i_warning._alpha; }, 750);
226
227        _root.panel.attachMovie("padlock","padlock",41);
228        with (_root.panel.padlock) { _y=32; _visible=false; };
229        _root.panel.padlock.onPress=function() { keyLock(); };
230
231        _root.createEmptyMovieClip("pointer",0xFFFFFF);
232
233        // =====================================================================================
234        // Initialise text areas
235
236        // Debug text fields
237
238        _root.createTextField('chat',20,130,315,400,80); // 515
239        with (_root.chat) {
240                multiline=true; wordWrap=true;  border=true; selectable = true; type = 'input';
241                _visible=false;//#debug
242        };
243
244        _root.createTextField('coordmonitor',21,130,400,400,60); // 515
245        with (_root.coordmonitor) {
246                multiline=true; wordWrap=true; border=true; selectable = true; type = 'input';
247                _visible=false;//#debug
248        };
249
250        _root.createTextField('floater',0xFFFFFE,15,30,200,18);
251        with (floater) {
252                background=true; backgroundColor=0xFFEEEE;
253                border=true; borderColor=0xAAAAAA;
254                selectable=false; _visible=false;
255        }
256        var floaterID=null;
257
258        // Centre cross-hair
259       
260        if (_root.chat._visible) {
261                _root.createEmptyMovieClip("crosshair",0xFFFFF0);
262                with (_root.crosshair) {
263                        _x=Stage.width/2;
264                        _y=(Stage.height-panelheight)/2;
265                        lineStyle(1,0xFFFFFF,100);
266                        moveTo(-2,0); lineTo(-10,0);
267                        moveTo( 2,0); lineTo( 10,0);
268                        moveTo(0,-2); lineTo(0,-10);
269                        moveTo(0, 2); lineTo(0, 10);
270                }
271        }
272
273// for (i in layernames) { _root.chat.text+=i+"="+layernames[i]+","; }
274// for (i in layernums ) { _root.chat.text+=i+"="+layernums[i]+","; }
275
276        // Text formats
277       
278        plainText =new TextFormat(); plainText.color =0x000000; plainText.size =14; plainText.font ="_sans";
279        plainSmall=new TextFormat(); plainSmall.color=0x000000; plainSmall.size=12; plainSmall.font="_sans";
280        plainDim  =new TextFormat(); plainDim.color  =0x777777; plainDim.size  =12; plainDim.font  ="_sans";
281        plainRight=new TextFormat(); plainRight.color=0x000000; plainRight.size=12; plainRight.font="_sans"; plainRight.align="right";
282        plainTiny =new TextFormat(); plainTiny.color =0x000000; plainTiny.size =11; plainTiny.font ="_sans";
283        plainWhite=new TextFormat(); plainWhite.color=0xFFFFFF; plainWhite.size=12; plainWhite.font="_sans";
284        greySmall =new TextFormat(); greySmall.color =0x888888; greySmall.size =12; greySmall.font ="_sans";
285        boldText  =new TextFormat(); boldText.color  =0x000000; boldText.size  =14; boldText.font  ="_sans"; boldText.bold =true;
286        boldSmall =new TextFormat(); boldSmall.color =0x000000; boldSmall.size =12; boldSmall.font ="_sans"; boldSmall.bold=true;
287        boldWhite =new TextFormat(); boldWhite.color =0xFFFFFF; boldWhite.size =12; boldWhite.font ="_sans"; boldWhite.bold=true;
288        menu_on   =new TextFormat(); menu_on.color   =0x000000; menu_on.size   =12; menu_on.font   ="_sans"; menu_on.bold  =true;
289        menu_off  =new TextFormat(); menu_off.color  =0xFFFFFF; menu_off.size  =12; menu_off.font  ="_sans"; menu_off.bold =true;
290        auto_on   =new TextFormat(); auto_on.color   =0x0000FF; auto_on.size   =12; auto_on.font   ="_sans"; auto_on.bold  =true;
291        auto_off  =new TextFormat(); auto_off.color  =0xFFFFFF; auto_off.size  =12; auto_off.font  ="_sans"; auto_off.bold =true;
292
293        // Colour transform
294       
295        to_black  =new Object(); to_black.ra=to_black.ga=to_black.ba=-100;
296        to_red    =new Object(); to_red.rb=255; to_red.gb=0;
297        to_normal =new Object(); to_normal.ra=to_normal.ga=to_normal.ba=100;
298                                                         to_normal.rb=to_normal.gb=to_normal.bb=0;
299
300        // Text fields
301
302        _root.createEmptyMovieClip('waysloading',22);
303        _root.waysloading._visible=false;
304
305        _root.createTextField('tooltip',46,480,30,215,100);
306        with (_root.tooltip  ) { text=""; setTextFormat(plainRight); selectable=false; type='dynamic'; };
307
308        _root.panel.createTextField('t_type',23,5,5,220,20);
309        with (_root.panel.t_type         ) { text=signature; setTextFormat(boldText); selectable=false; };
310       
311        _root.panel.createTextField('t_details',24,5,23,220,20);
312        with (_root.panel.t_details) { text=""; setTextFormat(plainText); selectable=false; };
313       
314        // MovieClip loader
315        var tileLoader=new MovieClipLoader();
316        tileListener=new Object();
317        tileLoader.addListener(tileListener);
318
319        // Interaction with responder script
320        var loaderWaiting=false;
321
322        remote_read=new NetConnection();
323        remote_read.connect(apiurl+'/read');
324        remote_read.onStatus=function(info) { _root.panel.i_warning._visible=true; };
325
326        remote_write=new NetConnection();
327        remote_write.connect(apiurl+'/write');
328        remote_write.onStatus=function(info) { _root.panel.i_warning._visible=true; };
329
330        #include 'node.as'
331        #include 'anchorpoint.as'
332        #include 'poi.as'
333        #include 'relation.as'
334        #include 'way.as'
335        #include 'history.as'
336        #include 'ui.as'
337        #include 'properties.as'
338        #include 'world.as'
339        #include 'tiles.as'
340        #include 'gps.as'
341        #include 'undo.as'
342        #include 'advice.as'
343        #include 'changeset.as'
344        #include 'start.as'
345
346        // =====================================================================================
347        // Start
348
349        var undo=new UndoStack();
350
351        _root.panel.attachMovie("propwindow","properties",50);
352        with (_root.panel.properties) { _x=110; _y=25; _visible=false; };
353
354        _root.panel.attachMovie("presetmenu","presets",60);
355        with (_root.panel.presets) { _x=110; _y=1; _visible=false; };
356
357        updateButtons();
358        updateScissors();
359        resizeWindow();
360        startChangeset();
361        loadPresets();
362
363
364
365
366
367
368        // =====================================================================
369        // Map support functions
370        // mapRollOver/Out - user has rolled over/out the main map area
371       
372        function mapRollOver() {
373                removeMovieClip(_root.map.anchorhints);
374                if (_root.tooltip.text.substring(0,4)=='over') { clearTooltip(); }
375                if (_root.drawpoint>-1)     { setPointer('pen'); }
376                else if (_root.wayselected) { setPointer(''   ); }
377                                                       else { setPointer('pen'); }
378        }
379
380        function mapRollOut() {
381                if (_root.pointertype!='')  { setPointer(''   ); }
382        }
383       
384        // processMapDrag, moveMap - process map dragging
385
386        function processMapDrag() {
387                if (mapDragging() || Key.isDown(Key.SPACE)) {
388                        if (_root.pointertype!='hand') { setPointer('hand'); }
389
390                        if (_root.yahoo._visible) {
391                                var t=new Date();
392                                if ((t.getTime()-yahootime.getTime())<500) {
393                                        _root.yahoo._x+=Math.floor(_xmouse-lastxmouse); // less than 0.5s, so
394                                        _root.yahoo._y+=Math.floor(_ymouse-lastymouse); // just move offset
395                                } else {
396                                        redrawBackground();                                                             // 0.5s elapsed, so
397                                        _root.yahootime=new Date();                                             // request new tiles
398                                }
399                        } else if (preferences.data.baselayer) {
400                                redrawBackground();
401                        }
402                        moveMap(Math.floor(_xmouse-lastxmouse),Math.floor(_ymouse-lastymouse));
403                }
404        }
405
406        function endMapDrag() {
407                delete _root.onMouseMove;
408                delete _root.onMouseUp;
409                if (mapDragging()) {
410                        redrawBackground();
411                        updateLinks();
412                        whichWays();
413                }
414                restartElastic();
415                if (_root.wayselected) { setPointer(''); }
416                                                  else { setPointer('pen'); }
417        }
418       
419        function moveMap(xdiff,ydiff) {
420                _root.lastxmouse=_root._xmouse;
421                _root.lastymouse=_root._ymouse;
422                if (Key.isDown(Key.SPACE)) {
423                        _root.bgxoffset+=xdiff; _root.map.tiles._x+=xdiff;
424                        _root.bgyoffset+=ydiff; _root.map.tiles._y+=ydiff;
425                        updateCoords(_root.map._x,_root.map._y);
426                } else {
427                        _root.map._x+=xdiff;
428                        _root.map._y+=ydiff;
429                        updateCoords(_root.map._x,_root.map._y);
430                }
431        }
432
433        // mapClick - user has clicked within map area, so start drag
434       
435        function mapClick() {
436                setPointer('pen');
437                clearTooltip();
438                _root.onMouseMove=function() { processMapDrag(); };
439                _root.onMouseUp  =function() { endMapDrag(); };
440                _root.mapdragged=false;
441                _root.lastxmouse=_root._xmouse;
442                _root.lastymouse=_root._ymouse;
443                _root.firstxmouse=_root._xmouse;
444                _root.firstymouse=_root._ymouse;
445                _root.clicktime=new Date();
446                _root.yahootime=new Date();
447        }
448
449        // mapDragging - test whether map was dragged or just clicked
450       
451        function mapDragging() {
452                var t=new Date();
453                var tol=Math.max(_root.tolerance,2);
454                var longclick=(t.getTime()-_root.clicktime)>300;
455                var xdist=Math.abs(_root.firstxmouse-_root._xmouse);
456                var ydist=Math.abs(_root.firstymouse-_root._ymouse);
457                if ((xdist<tol*4  && ydist<tol*4 ) ||
458                   ((xdist<tol*10 && ydist<tol*10) && !longclick)) {
459                } else {
460                        _root.mapdragged=true;
461                }
462                return _root.mapdragged;
463        }
464
465        // mapClickEnd - end of click within map area
466
467        function mapClickEnd() {
468                removeWelcome(true);
469                var t=new Date();
470                if (!mapdragged) {
471                // Clicked on map without dragging
472                        // Adding a point to the way being drawn
473                        if (_root.drawpoint>-1) {
474                                _root.newnodeid--;
475                                _root.nodes[newnodeid]=new Node(newnodeid,_root.map._xmouse,_root.map._ymouse,new Array());
476                                if (_root.pointselected>-2) {
477                                        setTypeText(iText("Way",'way'),_root.wayselected);
478                                        _root.panel.properties.tidy();
479                                        _root.panel.properties.init('way',getPanelColumns(),4);
480                                        updateButtons();
481                                        updateScissors(false);
482                                }
483                                addEndPoint(_root.nodes[newnodeid]);
484                                restartElastic();
485
486                        // Deselecting a way
487                        } else if (_root.wayselected) {
488                                uploadSelected(); deselectAll();
489                                _root.lastpoint=-1;                             // Trap double-click to deselect
490                                _root.lastpointtime=new Date(); //  |
491
492                        // Deselecting a POI
493                        } else if (_root.poiselected) {
494                                uploadSelected(); deselectAll();
495
496                        // Starting a new way
497                        // ** double-click trap should probably also check distance moved
498                        } else if (_root.lastpoint!=-1 || (t.getTime()-_root.lastpointtime)>300) {
499                                _root.newnodeid--; 
500                                _root.nodes[newnodeid]=new Node(newnodeid,_root.map._xmouse,_root.map._ymouse,new Array());
501                                startNewWay(newnodeid);
502                        }
503                }
504                _root.mapdragged=false;
505        }
506
507
508
509        // =====================================================================
510        // Tooltip and pointer functions
511
512        function setTooltip(txt,delay) {
513                _root.tooltip.text=txt;
514                _root.tooltip.setTextFormat(plainRight);
515                _root.createEmptyMovieClip('ttbackground',45);
516                with (_root.ttbackground) {
517                        _x=Stage.width-5; _y=30;
518                        beginFill(0xFFFFFF,75);
519                        moveTo(0,0); lineTo(-_root.tooltip.textWidth-10,0);
520                        lineTo(-_root.tooltip.textWidth-10,_root.tooltip.textHeight+5);
521                        lineTo(0,_root.tooltip.textHeight+5); lineTo(0,0);
522                        endFill();
523                }
524        }
525
526        function clearTooltip() {
527                _root.tooltip.text='';
528                removeMovieClip(_root.ttbackground);
529        }
530       
531        function setFloater(txt) {
532                with (_root.floater) {
533                        text=txt;
534                        setTextFormat(plainSmall); 
535                        _width=textWidth+4;
536
537                        if (_root._ymouse+25<Stage.height      ) { _y=_root._ymouse+4;                   }
538                                                                                                else { _y=_root._ymouse-16;          }
539                        if (_root._xmouse+textWidth<Stage.width) { _x=_root._xmouse+4;                   }
540                                                                                                else { _x=_root._xmouse-textWidth-8; }
541                        _visible=false;
542                }
543                clearInterval(floaterID);
544                floaterID=setInterval(unveilFloater,1000);
545        }
546
547        function unveilFloater(txt) {
548                _root.floater._visible=true;
549                clearInterval(floaterID);
550        }
551       
552        function clearFloater(txt) {
553                clearInterval(floaterID);
554                _root.floater._visible=false;
555        }
556
557        function setPointer(ptype) {
558                if (_root.pointertype==ptype) { return; }
559                if ((ptype) && preferences.data.custompointer) {
560                        _root.attachMovie(ptype,"pointer",0xFFFFFF);
561                        _root.pointer.cacheAsBitmap=true;
562                        _root.pointer._x=_root._xmouse;
563                        _root.pointer._y=_root._ymouse;
564                        _root.pointer.startDrag(true);
565                        Mouse.hide();
566                } else {
567                        _root.pointer._visible=false;
568                        _root.pointer.stopDrag();
569                        Mouse.show();
570                        removeMovieClip(_root.pointer);
571                }
572                _root.pointertype=ptype;
573        }
574
575       
576
577
578
579        // =====================================================================================
580        // Keypress functions
581
582        // keyPressed                           - key listener
583
584        function keyPressed() {
585                clearAdvice();
586                var k=Key.getCode();
587                var c=Key.getAscii(); if (c>=97 && c<=122) { c=c-32; }
588                var s=String.fromCharCode(c);
589                _root.lastkeypressed=k;
590
591                if (keytarget=='keyname' || keytarget=='value') {
592                        if (_root.auto!=undefined) { _root.auto.keyRespond(k); }
593                                           else if (k==13) { autoEnter(); }
594                        return;
595                } else if (_root.windowsopen) {
596                        if (k==187 && _root.windows.relation.box.properties!=undefined) {
597                                _root.windows.relation.box.properties.enterNewAttribute();
598                        };
599                        return;
600                } else if (keytarget!='') { return; }
601
602                if (c>48 && c<58 && (wayselected!=0 || poiselected!=0)) {
603                        if (presetnames[_root.panel.properties.proptype][_root.panel.presets.group][c-48]!=null) {
604                                _root.panel.presets.setAttributes(c-48);
605                                _root.panel.presets.reflect();
606                                if (_root.panel.properties.proptype=='way') { _root.ws.redraw(); }
607                        }
608                        return;
609                } else if (k>=112 && k<=120) {
610                        preferences.data.dimbackground=Key.isDown(Key.SHIFT); 
611                        setBackground(k-112);
612                        return;
613                }
614
615                switch (k) {
616                        case 46:                ;                                                                                                       // DELETE/backspace - delete way/node
617                        case 8:                 if (Key.isDown(Key.SHIFT)) {                                            //  |
618                                                                if (_root.wayselected!=0) { _root.ws.removeWithConfirm(); }
619                                                        } else { keyDelete(1); }; break;                                        //  |
620                        case 13:                _root.junction=false; stopDrawing(); break;                     // ENTER - stop drawing line
621                        case 27:                keyRevert(); break;                                                                     // ESCAPE - revert current way
622                        case Key.PGUP:  zoomIn(); break;                                                                        // Page Up - zoom in
623                        case Key.PGDN:  zoomOut(); break;                                                                       // Page Down - zoom out
624                        case Key.LEFT:  moveMap( 140,0); updateLinks(); redrawBackground(); whichWays(); break; // cursor keys
625                        case Key.RIGHT: moveMap(-140,0); updateLinks(); redrawBackground(); whichWays(); break; //  |
626                        case Key.DOWN:  moveMap(0,-100); updateLinks(); redrawBackground(); whichWays(); break; //  |
627                        case Key.UP:    moveMap(0, 100); updateLinks(); redrawBackground(); whichWays(); break; //  |
628                        case Key.CAPSLOCK: dimMap(); break;                                                                     // CAPS LOCK - dim map
629                        case 167:               _root.panel.presets.cycleIcon(); break;                         // cycle presets
630                }
631               
632                switch (s) {
633                        case 'C':               closeChangeset(); break;                                                        // C - close current changeset
634                        case 'G':               loadGPS(); break;                                                                       // G - load GPS
635                        case 'H':               getHistory(); break;                                                            // H - history
636                        case 'L':               showPosition(); break;                                                          // L - show latitude/longitude
637                        case 'P':               askOffset(); break;                                                                     // O - parallel path
638                        case 'R':               _root.panel.properties.repeatAttributes(true);break;// R - repeat attributes
639                        case 'U':               getDeleted(); break;                                                            // U - undelete
640                        case 'X':               _root.ws.splitWay(_root.pointselected); break;          // X - split way
641                        case 'Z':               _root.undo.rollback(); break;                                           // Z - undo
642                        case '`':               _root.panel.presets.cycleIcon(); break;                         // '`' - cycle presets
643                        case '+':               _root.panel.properties.enterNewAttribute(); break;      // '+' - add new attribute (107/187)
644                        case '-':               keyDelete(0); break;                                                            // '-' - delete node from this way only (189)
645                        case '/':               cycleStacked(); break;                                                          // '/' - cycle between stacked ways (191)
646                        case 'M':               maximiseSWF(); break;                                                           // 'M' - maximise/minimise Potlatch
647                        case 'K':               keyLock(); break;                                                                       // 'K' - lock item
648                        case 'S':               _root.panel.properties.setTag("source",sourcetags[preferences.data.baselayer]); break;  // 'S' - set source tag
649//                      default:                _root.chat.text=Key.getCode()+" pressed";
650                };
651        }
652
653        function showPosition() { setTooltip("lat "+Math.floor(coord2lat (_root.map._ymouse)*10000)/10000
654                                                                          +"\nlon "+Math.floor(coord2long(_root.map._xmouse)*10000)/10000,0); }
655        function startCount()   { z=new Date(); _root.startTime=z.getTime(); }
656        function endCount(id)   { z=new Date(); zz=Math.floor((z.getTime()-_root.startTime)*100);
657                                                        if (zz>100) { _root.chat.text+=id+":"+zz+";"; } }
658
659        function showObjects(z,indnt) {
660                for (var i in z) {
661                        _root.chat.text+=indnt+i+" ("+typeof(z[i])+")\n";
662                        if (typeof(z[i])=='movieclip' || typeof(z[i])=='object') {
663                                showObjects(z[i],indnt+" ");
664                        }
665                }
666        }
667       
668        function showWaysForNode() {
669                var z=_root.ws.path[pointselected].ways;
670                _root.coordmonitor.text="";
671                for (i in z) { _root.coordmonitor.text+=i+","; }
672        }
673
674        function keyLock() {
675                _root.panel.padlock._x=_root.panel.t_details.textWidth+15;
676                if (_root.wayselected && _root.ws.locked && _root.ws.path.length>200 && !_root.ws.historic) {
677                        setAdvice(true,iText("Too long to unlock - please split into shorter ways",'advice_toolong'));
678                } else if (_root.wayselected) {
679                        _root.ws.locked=!_root.ws.locked;
680                        _root.ws.redraw();
681                        _root.panel.padlock._visible=_root.ws.locked;
682                } else if (_root.poiselected) {
683                        _root.map.pois[poiselected].locked=!_root.map.pois[poiselected].locked;
684                        _root.map.pois[poiselected].recolour();
685                        _root.panel.padlock._visible=_root.map.pois[poiselected].locked;
686                }
687        }
688
689        function keyDelete(doall) {
690                if (_root.poiselected) {
691                        // delete POI
692                        _root.map.pois[poiselected].saveUndo(iText("deleting",'deleting'));
693                        _root.map.pois[poiselected].remove();
694                } else if (_root.drawpoint>-1) {
695                        // 'backspace' most recently drawn point
696                        _root.undo.append(UndoStack.prototype.undo_deletepoint,
697                                                          new Array(deepCopy(_root.ws.path[drawpoint]),
698                                                                                [wayselected],[drawpoint]),
699                                                          iText("deleting a point",'action_deletepoint'));
700                        _root.ws.path[drawpoint].removeWay(_root.wayselected);
701                        if (_root.drawpoint==0) { _root.ws.path.shift(); }
702                                                           else { _root.ws.path.pop(); _root.drawpoint-=1; }
703                        if (_root.ws.path.length) {
704                                _root.ws.clean=false;
705                                markClean(false);
706                                _root.ws.redraw();
707                                _root.ws.highlightPoints(5000,"anchor");
708                                _root.ws.highlight();
709                                restartElastic();
710                        } else {
711                                _root.map.anchors[_root.drawpoint].endElastic();
712                                _root.ws.remove();
713                                _root.drawpoint=-1;
714                        }
715                } else if (_root.pointselected>-2) {
716                        // delete selected point
717                        if (doall==1) { _root.ws.path[_root.pointselected].removeFromAllWays(); }
718                                         else { _root.ws.removeAnchorPoint(pointselected); }
719                        _root.pointselected=-2;
720                        _root.drawpoint=-1;
721                        _root.map.elastic.clear();
722                        clearTooltip();
723                        markClean(false);
724                        if (_root.wayselected) { _root.ws.select(); }
725                }
726        };
727
728        function keyRevert() {
729                if              (_root.wayselected<0) { _root.ws.saveUndo(iText("deleting",'deleting'));
730                                                                                stopDrawing();
731                                                                                removeMovieClip(_root.map.areas[wayselected]);
732                                                                                removeMovieClip(_root.ws); }
733                else if (_root.wayselected>0) { _root.ws.saveUndo(iText("cancelling changes to",'action_cancelchanges'));
734                                                                                stopDrawing();
735                                                                                _root.ws.reload(); }
736                else if (_root.poiselected>0) { _root.map.pois[poiselected].saveUndo(iText("cancelling changes to",'action_cancelchanges'));
737                                                                                _root.map.pois[poiselected].reload(); }
738                else if (_root.poiselected<0) { _root.map.pois[poiselected].saveUndo(iText("deleting",'deleting'));
739                                                                                removeMovieClip(_root.map.pois[poiselected]); }
740                revertDirtyRelations();
741                deselectAll();
742        };
743
744
745
746        // =====================================================================
747        // Potlatch-specific UI functions
748       
749        function writeText(obj,t) {
750                with (obj) {
751                        text=t; wordWrap=true;
752                        setTextFormat(plainSmall);
753                        selectable=false; type='dynamic';
754                }
755        }
756
757        function handleError(code,result) {
758                var h=100;
759                if (code==-1) { error=result[0]; }
760                                 else { error=result[0]+iText("\n\nPlease e-mail richard\@systemeD.net with a bug report, saying what you were doing at the time.",'emailauthor'); h+=50; }
761                _root.windows.attachMovie("modal","error",++windowdepth);
762                _root.windows.error.init(275,h,new Array('Ok'),null);
763                _root.windows.error.box.createTextField("prompt",2,7,9,250,h-30);
764                writeText(_root.windows.error.box.prompt,error);
765        }
766
767        function handleWarning() {
768                _root.windows.attachMovie("modal","error",++windowdepth);
769                _root.windows.error.init(275,130,new Array('Retry','Cancel'),handleWarningAction);
770                _root.windows.error.box.createTextField("prompt",2,7,9,250,100);
771                writeText(_root.windows.error.box.prompt,iText("Sorry - the connection to the OpenStreetMap server failed. Any recent changes have not been saved.\n\nWould you like to try again?",'error_connectionfailed'));
772        };
773
774        function handleWarningAction(choice) {
775                if (choice=='Retry') {
776                        // loop through all ways which are uploading, and reupload
777                        _root.panel.i_warning._visible=false;
778                        for (var qway in _root.map.ways) {
779                                if (_root.map.ways[qway].uploading) {
780                                        _root.map.ways[qway].uploading=false;
781                                        _root.map.ways[qway].upload();
782                                }
783                        }
784                        for (var qrel in _root.map.relations) {
785                                if (_root.map.relations[qrel].uploading) {
786                                        _root.map.relations[qrel].uploading=false;
787                                        _root.map.relations[qrel].upload();
788                                }
789                        }
790                }
791        };
792
793
794        // =====================================================================
795        // Internationalisation functions
796       
797        function iText(en,id,key1,key2) {
798                var t=en;
799                if (l!='en' && _root.i18n[id][_root.lang]) {
800                        t=_root.i18n[id][_root.lang];
801                }
802                t=replaceStr(t,'$1',key1);
803                t=replaceStr(t,'$2',key2);
804                t=replaceStr(t,'\\n',"\n");
805                return t;
806        }
807
808        function replaceStr(s,a,b) {
809                while (s.indexOf(a)>-1) {
810                        var n=s.indexOf(a);
811                        s=s.substr(0,n)+b+s.substr(n+a.length);
812                }
813                return s;
814        }
815
816
817        // =====================================================================
818        // General support functions
819
820        // everyFrame() - called onEnterFrame
821
822        function everyFrame() {
823
824                // ---- Fix Yahoo! peculiarities
825                _root.yahoo.myMap.enableKeyboardShortcuts(false);
826
827                if (preferences.data.baselayer==2) {
828                        var t=0;
829                        for (i in _root.yahoo.myMap.map["map_"+(18-_root.scale)].mc) {
830                                t+=_root.yahoo.myMap.map["map_"+(18-_root.scale)].mc[i][i].getBytesTotal();
831                        }
832                        _root.yahoo._visible=(t>124000);        // 122850=all blank
833                }
834
835                if (_root.yahoo.myMap.config.isLoaded) {
836                        if (!_root.yahooinited) {
837                                _root.yahooinited=true;
838                                _root.yahooresizer=setInterval(resizeWindow,1000);
839                                setYahooSize();
840                                enableYahooZoom();
841                                _root.yahoo.myMap.map.updateCopyright();
842                        } else if (!_root.yahoorightsize) {
843                                _root.yahoorightsize=true;
844                                _root.yahooresizer=setInterval(resizeWindow,1000);
845                        }
846                }
847
848                // ---- Do we need to redraw the property window?
849                if (_root.redopropertywindow) {
850                        _root.redopropertywindow.tidy();
851                        _root.redopropertywindow.reinit();
852                        _root.redopropertywindow=null;
853                }
854
855                // ---- If resizing has stopped, issue new whichways
856                //              and resize panel
857                var t=new Date();
858                if ((t.getTime()-lastresize.getTime())>500) {
859                        if (lastresize.getTime()>lastwhichways.getTime()) {
860                                whichWays();
861                                redrawBackground();
862                        }
863                }
864
865                // ---- Control "loading ways" display
866                var loading=(_root.waysrequested!=_root.waysreceived) || (_root.whichrequested!=_root.whichreceived);
867                if (loading && _root.writesrequested) { setIOStatus(3); }
868                          else if (_root.writesrequested) { setIOStatus(2); }
869                                                        else if (loading) { setIOStatus(1); }
870                                                                                 else { _root.io=0; _root.waysloading._visible=false; }
871
872                // ---- Redraw lines if necessary (3 per frame)
873                if (_root.redrawlist.length) {
874                        for (var i=0; i<3; i++) {
875                                var w=_root.redrawlist.pop();
876                                _root.map.ways[w].redraw(_root.redrawskip);
877                        }
878                } else { _root.redrawskip=true; }
879
880                // ---- Service tile queue
881                if (preferences.data.baselayer!=0 &&
882                        preferences.data.baselayer!=2 ) { serviceTileQueue(); }
883
884                if (_root.map.ways._alpha<40) {
885                        if (!Key.isToggled(Key.CAPSLOCK)) { dimMap(); }
886                }
887                       
888                // ---- Reinstate focus if lost after click event
889                if (_root.reinstatefocus) {
890                        Selection.setFocus(_root.reinstatefocus); 
891                        _root.reinstatefocus=null;
892                }
893        }
894       
895        // Dim map on CAPS LOCK
896
897        function dimMap() {
898                _root.map.areas._alpha=
899                _root.map.highlight._alpha=
900                _root.map.relations._alpha=
901                _root.map.ways._alpha=
902                _root.map.pois._alpha=Key.isToggled(Key.CAPSLOCK)?30:100;
903        }
904
905        // Options window
906       
907        function openOptionsWindow() {
908                _root.windows.attachMovie("modal","options",++windowdepth);
909                _root.windows.options.init(290,170,new Array('Ok'),function() { preferences.flush(); } );
910                _root.windows.options.box.createTextField("prompt1",2,7,9,80,20);
911                writeText(_root.windows.options.box.prompt1,iText("Background:",'option_background'));
912
913                _root.windows.options.box.attachMovie("menu","background",30);
914                _root.windows.options.box.background.init(87,10,preferences.data.baselayer,
915                        new Array("None","-----------------------------------------","Aerial - Yahoo!","OSM - Mapnik","OSM - Osmarender","OSM - Maplint (errors)","OSM - cycle map","Other - out-of-copyright map","Other - OpenTopoMap"),
916                        'Choose the background to display',setBackground,null,0);
917
918                _root.windows.options.box.attachMovie("checkbox","fadepref",5);
919                _root.windows.options.box.fadepref.init(10,40,iText("Fade background",'option_fadebackground'),preferences.data.dimbackground,function(n) { preferences.data.dimbackground=n; redrawBackground(); });
920
921                _root.windows.options.box.attachMovie("checkbox","linepref",8);
922                _root.windows.options.box.linepref.init(10,60,iText("Use thin lines at all scales",'option_thinlines'),preferences.data.thinlines,function(n) { preferences.data.thinlines=n; changeScaleTo(_root.scale); redrawWays(); });
923
924                _root.windows.options.box.attachMovie("checkbox","noname",10);
925                _root.windows.options.box.noname.init(10,80,iText("Highlight unnamed roads",'option_noname'),preferences.data.noname,function(n) { preferences.data.noname=n; redrawWays(); });
926
927                _root.windows.options.box.attachMovie("checkbox","pointer",4);
928                _root.windows.options.box.pointer.init(10,100,iText("Use pen and hand pointers",'option_custompointers'),preferences.data.custompointer,function(n) { preferences.data.custompointer=n; });
929
930                _root.windows.options.box.attachMovie("checkbox","warnings",3);
931                _root.windows.options.box.warnings.init(10,120,iText("Show floating warnings",'option_warnings'),preferences.data.advice,function(n) { preferences.data.advice=n; });
932
933        }
934       
935        // markClean - set JavaScript variable for alert when leaving page
936
937        function markClean(a) {
938                if (!_root.sandbox) {
939                        if (winie) { // _root.chat._visible=true; fscommand("changesaved",a);
940                                           }
941                                  else { getURL("javascript:var changesaved="+a); }
942                }
943        }
944       
945        // deselectAll
946
947        function deselectAll() {
948                _root.map.createEmptyMovieClip("anchors",5000); 
949                removeMovieClip(_root.map.highlight);
950                _root.panel.i_clockwise._visible=false;
951                _root.panel.i_anticlockwise._visible=false;
952                _root.panel.i_direction._visible=true;
953                _root.panel.i_direction._alpha=50;
954                clearTooltip();
955                setTypeText("","");
956                _root.panel.padlock._visible=false;
957
958                _root.panel.properties.saveAttributes();
959                _root.panel.properties.tidy();
960                _root.panel.properties.init('');
961                _root.panel.presets.init();
962                updateButtons();
963                updateScissors(false);
964                poiselected=0;
965                pointselected=-2;
966                lastpoint=0;
967                selectWay(0);
968                markClean(true);
969        };
970       
971        // uploadSelected
972       
973        function uploadSelected() {
974                _root.panel.properties.tidy();
975                if (_root.wayselected!=0 && !_root.ws.clean) {
976                        uploadDirtyWays(true);
977                }
978                if (_root.poiselected!=0 && !_root.map.pois[poiselected].clean) {
979                        _root.map.pois[poiselected].upload();
980                }
981                uploadDirtyRelations();
982        };
983       
984        function uploadDirtyWays(allow_ws) {
985                var z=_root.map.ways;
986                for (i in z) {
987                        if (!_root.map.ways[i].clean && (i!=wayselected || allow_ws) && !_root.map.ways[i].hasDependentNodes()) { 
988                                _root.map.ways[i].upload();
989                        }
990                }
991        };
992
993        // highlightSquare
994       
995        function highlightSquare(sx,sy,ss) {
996                _root.map.createEmptyMovieClip("highlight",5);
997                _root.map.highlight._x=sx;
998                _root.map.highlight._y=sy;
999                _root.map.highlight.beginFill(0xFFFF00,80);
1000                _root.map.highlight.moveTo(-ss, ss);
1001                _root.map.highlight.lineTo( ss, ss);
1002                _root.map.highlight.lineTo( ss,-ss);
1003                _root.map.highlight.lineTo(-ss,-ss);
1004                _root.map.highlight.lineTo(-ss, ss);
1005                _root.map.highlight.endFill();
1006        };
1007
1008        // setIOStatus - update top-right message
1009
1010        function setIOStatus(msg) {
1011                if (_root.io==msg) { return; }
1012                _root.io=msg; var t;
1013                switch (msg) {
1014                        case 3: t=iText("loading/saving data",'hint_saving_loading'); break;
1015                        case 2: t=iText("saving data",'hint_saving'); break;
1016                        case 1: t=iText("loading data",'hint_loading'); break;
1017                }
1018                _root.waysloading.createTextField('prompt',2,0,0,195,20);
1019                with (_root.waysloading.prompt) { text=t; setTextFormat(plainRight); selectable=false; }
1020                _root.waysloading.createEmptyMovieClip('bg',1);
1021                with (_root.waysloading.bg) {
1022                        beginFill(0xFFFFFF,75);
1023                        moveTo(215,0); lineTo(210-_root.waysloading.prompt.textWidth-22,0);
1024                        lineTo(210-_root.waysloading.prompt.textWidth-22,_root.waysloading.prompt.textHeight+5);
1025                        lineTo(215,_root.waysloading.prompt.textHeight+5); lineTo(215,0);
1026                        endFill();
1027                }
1028                _root.waysloading._visible=true;
1029        }
1030
1031        // deepCopy (recursive) and shallowCopy (non-recursive)
1032
1033        function deepCopy(z) {
1034                var a;
1035                if (z.length==null) { a=new Object(); }
1036                                           else { a=new Array(); }
1037                for (var i in z) {
1038                        if (typeof(z[i])=='object') { a[i]=deepCopy(z[i]); }
1039                                                                   else { a[i]=z[i]; }
1040                }
1041                return a;
1042        };
1043
1044        function shallowCopy(z) {
1045                var a;
1046                if (z.length==null) { a=new Object(); }
1047                                           else { a=new Array(); }
1048                for (var i in z) { a[i]=z[i]; }
1049                return a;
1050        }
Note: See TracBrowser for help on using the repository browser.