source: subversion/applications/editors/potlatch/relation.as @ 8926

Last change on this file since 8926 was 8894, checked in by richard, 11 years ago

Potlatch 0.10

  • Property svn:executable set to *
File size: 12.1 KB
Line 
1
2        // =====================================================================================
3        // relations.as
4        // Potlatch relation-handling code
5        // =====================================================================================
6
7        // ** highlight isn't yellow if it's part of a relation (should be)
8        // ** default tags: type, name
9        // ** verboseText isn't very good
10
11        // =====================================================================================
12        // Classes - OSMRelation
13
14        function OSMRelation() {
15                this.members = new Array();
16                this.attr=new Array();
17                this.isHighlighting = false;
18                this.clean=true;                                        // altered since last upload?
19                this.uploading=false;                           // currently uploading?
20                this.locked=false;                                      // locked against upload?
21        };
22        OSMRelation.prototype=new MovieClip();
23
24
25        // OSMRelation.verboseText - create long description of relation
26
27        OSMRelation.prototype.verboseText = function() {
28                var text = this._name+": ";
29                var type = undefined;
30                if ( this.attr['type'] ) {
31                        type = this.attr['type'];
32                        text += type + " ";
33                }
34
35                if ( type == 'route' ) {
36                        if ( this.attr['route'] )       text += this.attr['route'] + " ";
37                        if ( this.attr['network'] )     text += this.attr['network'] + " ";
38                        if ( this.attr['ref'] )         text += this.attr['ref']+" ";
39                        if ( this.attr['name'] )        text += this.attr['name']+" ";
40                        if ( this.attr['state'] )       text += "("+this.attr['state']+") ";
41                } else if ( this.attr['name'] ) text += this.attr['name'];
42
43                return text;
44        };
45
46        // OSMRelation.getType/getName - summary info used in property window
47
48        OSMRelation.prototype.getType=function() {
49                if (!this.attr['type']) { return "relation"; }
50                if (this.attr['type']=='route') {
51                        if (this.attr['network']) { return this.attr['network']; }
52                        if (this.attr['route']) { return this.attr['route']; }
53                }
54                return this.attr['type'];
55        };
56       
57        OSMRelation.prototype.getName=function() {
58                if (this.attr['ref' ]) { return this.attr['ref' ]; }
59                if (this.attr['name']) { return this.attr['name']; }
60                return '';
61        };
62
63        // OSMRelation.load - load from remote server
64
65        OSMRelation.prototype.load=function() {
66                responder = function() { };
67                responder.onResult = function(result) {
68                        _root.relsreceived+=1;
69                        var w=result[0];
70                        var i,id;
71                        _root.map.relations[w].clean=true;
72                        _root.map.relations[w].locked=false;
73                        _root.map.relations[w].oldversion=0;
74                        _root.map.relations[w].attr=result[1];
75                        _root.map.relations[w].members=result[2];
76                        _root.map.relations[w].redraw();
77                };
78                remote.call('getrelation',responder,Math.floor(this._name));
79        };
80
81        OSMRelation.prototype.reload=function() {
82                if ( this._name < 0 )
83                        this.removeMovieClip();
84                else {
85                        _root.relsrequested++;
86                        this.load();
87                }
88        };
89
90        // OSMRelation.upload - save to remote server
91
92        OSMRelation.prototype.upload=function() {
93                putresponder=function() { };
94                putresponder.onResult=function(result) {
95                        var code=result.shift(); if (code) { handleError(code,result); return; }
96                        var nw=result[1];       // new relation ID
97                        if (result[0]!=nw) {
98                                _root.map.relations[result[0]]._name=nw;
99                        }
100                        _root.map.relations[nw].uploading=false;
101                };
102
103                // ways/nodes for negative IDs should have been previously put
104                // so the server should know about them
105                if (!this.uploading && !this.locked && !_root.sandbox ) {
106                        this.attr['created_by']=_root.signature;
107                        this.uploading=true;
108                        remote.call('putrelation', putresponder, _root.usertoken,
109                                Math.floor(this._name),
110                                this.attr, this.members, 1);
111                        this.clean=true;
112                }
113        };
114
115
116        // OSMRelation.redraw           - show on map
117        // OSMRelation.drawPoint
118        // OSMRelation.setHighlight
119
120        OSMRelation.prototype.redraw=function() {
121                this.createEmptyMovieClip("line",1);                                    // clear line
122                var linewidth=10;
123                var linealpha= this.isHighlighting ? 75 : 50;
124                var c = this.isHighlighting ? 0xff8800 : 0x8888ff;
125
126                var type = this.getType();
127                if ( !this.isHighlighting ) {
128                        if ( relcolours[type] != undefined ) {
129                                c = relcolours[type]; linewidth = relwidths[type]; linealpha = relalphas[type];
130                        }
131                }
132                this.line.lineStyle(linewidth,c,linealpha,false,"none");
133
134                var ms = this.members;
135                for ( var m = 0; m < ms.length; m++ ) {
136                        if ( ms[m][0] == 'way' && _root.map.ways[ms[m][1]] ) {
137                                var way = _root.map.ways[ms[m][1]];
138               
139                                this.line.moveTo(nodes[way.path[0]].x,nodes[way.path[0]].y);
140                                for (var i=1; i<way.path.length; i+=1) {
141                                        this.line.lineTo(nodes[way.path[i]].x,nodes[way.path[i]].y);
142                                }
143                        } else if ( ms[m][0] == 'node' && _root.map.pois[ms[m][1]] ) {
144                                var poi = _root.map.pois[ms[m][1]];
145                                this.drawPoint(poi._x, poi._y);
146                        } else if ( ms[m][0] == 'node' ) {
147                                this.drawPoint(nodes[ms[m][1]].x,nodes[ms[m][1]].y);
148                        }
149                }
150        };
151
152        OSMRelation.prototype.drawPoint = function(x, y) {
153                var z = Math.max(100/Math.pow(2,_root.scale-13),6.25)/30;
154                this.line.moveTo(x-z,y-z);
155                this.line.lineTo(x-z,y+z);
156                this.line.lineTo(x+z,y+z);
157                this.line.lineTo(x+z,y-z);
158                this.line.lineTo(x-z,y-z);
159        };
160
161        OSMRelation.prototype.setHighlight = function(highlight) {
162                if ( this.isHighlighting == highlight )
163                        return;
164
165                this.isHighlighting = highlight;
166                this.redraw();
167        };
168
169        // ---- Editing and information functions
170
171        OSMRelation.prototype.getWayRole=function(way_id) {
172                return this.getRole('way', way_id);
173        };
174
175        OSMRelation.prototype.getRole=function(type, id) {
176                var ws = this.members;
177                var role;
178                for ( var m = 0; m < ws.length && role == undefined; m++ ) {
179                        if ( ws[m][0] == type && ws[m][1] == id ) {
180                                role = ws[m][2];
181                        }
182                }
183                return role;
184        };
185
186        OSMRelation.prototype.renumberMember=function(type, id, new_id) {
187                var ws = this.members;
188                var set = false;
189                for ( var m = 0; m < ws.length && !set; m++ ) {
190                        if ( ws[m][0] == type && ws[m][1] == id ) {
191                                ws[m][1] = new_id;
192                                set = true;
193                        }
194                }
195        };
196
197        OSMRelation.prototype.setRole=function(type, id, role) {
198                var ws = this.members;
199                var set = false;
200                var diff = true;
201                for ( var m = 0; m < ws.length && !set; m++ ) {
202                        if ( ws[m][0] == type && ws[m][1] == id ) {
203                                diff = (ws[m][2] != role);
204                                ws[m][2] = role;
205                                set = true;
206                        }
207                }
208                if ( !set )
209                        this.members.push([type, id, role]);
210                if ( diff ) {
211                        this.clean = false;
212                        this.redraw();
213                }
214        };
215
216        OSMRelation.prototype.setWayRole=function(way_id, role) {
217                this.setRole('way', way_id, role);
218        };
219
220        OSMRelation.prototype.hasWay=function(way_id) {
221                var role = this.getWayRole(way_id);
222                return role == undefined ? false : true;
223        };
224
225        OSMRelation.prototype.getNodeRole=function(node_id) {
226                return this.getRole('node', node_id);
227        };
228
229        OSMRelation.prototype.setNodeRole=function(node_id, role) {
230                this.setRole('node', node_id, role);
231        };
232
233        OSMRelation.prototype.hasNode=function(node_id) {
234                var role = this.getNodeRole(node_id);
235                return role == undefined ? false : true;
236        };
237
238        OSMRelation.prototype.removeMember=function(type, id) {
239                this.removeMemberDirty(type, id, true);
240        };
241
242        OSMRelation.prototype.removeMemberDirty=function(type, id, markDirty) {
243                var ws = this.members;
244                for (var m in ws) {
245                        if ( ws[m][0] == type && ws[m][1] == id ) {
246                                ws.splice(m, 1);
247                                if ( markDirty )
248                                        this.clean = false;
249                                this.redraw();
250                        }
251                }
252        };
253
254        OSMRelation.prototype.removeWay=function(way_id) {
255                this.removeMember('way', way_id);
256        };
257
258        OSMRelation.prototype.removeNode=function(node_id) {
259                this.removeMember('node', node_id);
260        };
261
262        // ----- UI
263
264        OSMRelation.prototype.editRelation = function() {
265                var rel = this;
266                var completeEdit = function() {
267                        rel.setHighlight(false);
268                        _root.panel.properties.reinit();
269                };
270
271                rel.setHighlight(true);
272                _root.panel.properties.enableTabs(false);
273               
274                _root.windows.attachMovie("modal","relation",++windowdepth);
275                _root.windows.relation.init(402, 255, ["OK"], completeEdit);
276                var z=5;
277                var box=_root.windows.relation.box;
278               
279                box.createTextField("title",z++,7,7,400-14,20);
280                with (box.title) {
281                        type='dynamic';
282                        text=this._name; setTextFormat(plainText);
283                        setNewTextFormat(boldText); replaceSel("Relation ");
284                }
285
286                // Light grey background
287                box.createEmptyMovieClip('lightgrey',z++);
288                with (box.lightgrey) {
289                        beginFill(0xF3F3F3,100);
290                        moveTo(10,30); lineTo(392,30);
291                        lineTo(392,213); lineTo(10,213);
292                        lineTo(10,30); endFill();
293                };
294
295                box.attachMovie("propwindow","properties",z++);
296                with (box.properties) { _x=14; _y=34; };
297                _root.editingrelation = this;
298                box.properties.ynumber = 9;
299                box.properties.init("relation",2,9);
300
301                box.attachMovie("newattr", "newattr", z++);
302                with ( box.newattr ) {
303                        _x = 400-16; _y = 18;
304                }
305                box.newattr.onRelease =function() { box.properties.enterNewAttribute(); };
306                box.newattr.onRollOver=function() { setFloater(iText("Add a new tag",'tip_addtag')); };
307                box.newattr.onRollOut =function() { clearFloater(); };
308        };
309
310        Object.registerClass("relation",OSMRelation);
311
312
313        // ===============================
314        // Support functions for relations
315
316        function redrawRelationsForMember(type, id) {
317                var rels = type == 'way' ? getRelationsForWay(id) : getRelationsForNode(id);
318                for ( r in rels )
319                        _root.map.relations[rels[r]].redraw();
320        }
321
322        // the server-side handles removing a deleted object from a relation
323        // but we need to keep the client side in sync
324        function memberDeleted(type, id) {
325                var rels = _root.map.relations;
326                for ( r in rels )
327                        rels[r].removeMemberDirty(type, id, false);
328        }
329
330        function renumberMemberOfRelation(type, id, new_id) {
331                var rels = _root.map.relations;
332                for ( r in rels )
333                        rels[r].renumberMember(type, id, new_id);
334        }
335
336        function getRelationsForWay(way) {
337                var rels = [];
338                var z = _root.map.relations;
339                for ( var i in z ) {
340                        if ( z[i].hasWay(way) )
341                                rels.push(i);
342                }
343                return rels;
344        }
345
346        function getRelationsForNode(node) {
347                var rels = [];
348                var z = _root.map.relations;
349                for ( var i in z ) {
350                        if ( z[i].hasNode(node) )
351                                rels.push(i);
352                }
353                return rels;
354        }
355
356        function uploadDirtyRelations() {
357                var rs = _root.map.relations;
358                for ( var i in rs ) {
359                        if ( !rs[i].clean ) {
360                                rs[i].upload();
361                        }
362                }
363        }
364
365        function revertDirtyRelations() {
366                var rs = _root.map.relations;
367                for ( var i in rs ) {
368                        if ( !rs[i].clean ) {
369                                rs[i].reload();
370                        }
371                }
372        }
373
374        // addToRelation - add a way/point to a relation
375        //                                 called when user clicks '+' relation button
376
377        function addToRelation() {
378                var proptype = _root.panel.properties.proptype;
379                var type, id;
380                switch (proptype) {
381                        case 'way':             type='way' ; id=wayselected; break;
382                        case 'point':   type='node'; id=_root.ws.path[_root.pointselected]; break;
383                        case 'POI':             type='node'; id=poiselected; break;
384                }
385                if ( type == undefined || id == undefined ) return;
386
387                var completeAdd = function(button) {
388                        if ( button != 'Add' ) return false;
389
390                        var box = _root.windows.relation.box;
391
392                        var selected = box.addroute_menu.selected;
393                        var keepDialog = false;
394                        if ( selected > 0 ) {
395                                var rs = _root.map.relations;
396                                for ( var r in rs ) {
397                                        selected -= 1;
398                                        if ( selected == 0 )
399                                                rs[r].setRole(type, id, '');
400                                }
401                        } else if ( selected == 0 ) {
402                                var nid = newrelid--;
403                                _root.map.relations.attachMovie("relation",nid,++reldepth);
404                                _root.map.relations[nid].setRole(type, id, '');
405                                _root.map.relations[nid].attr['type'] = undefined;
406                                _root.windows.relation.remove(); keepDialog = true;
407                                _root.map.relations[nid].editRelation();
408                        }
409                        _root.panel.properties.reinit();
410                        if (keepDialog) { _root.panel.properties.enableTabs(false); }
411                        return keepDialog;
412                };
413
414                _root.windows.attachMovie("modal","relation",++windowdepth);
415                _root.windows.relation.init(300, 140, [iText("Cancel",'cancel'), iText("Add",'add')], completeAdd);
416                var z = 5;
417                var box = _root.windows.relation.box;
418               
419                box.createTextField("title",z++,7,7,300-14,20);
420                box.title.text = iText("Add $1 to a relation",'prompt_addtorelation',proptype);
421                with (box.title) {
422                        wordWrap=true;
423                        setTextFormat(boldText);
424                        selectable=false; type='dynamic';
425                }
426               
427                box.createTextField("instr",z++,7,30,300-14,40);
428                writeText(box.instr, iText("Select an existing relation to add to, or create a new relation.",'prompt_selectrelation'));
429
430                var relations = new Array(iText("Create a new relation",'createrelation'));
431                var rs = _root.map.relations;
432                for ( var r in rs ) {
433                        relations.push(rs[r].verboseText());
434                }
435                // a normal, scrollable list may be better than a menu
436                box.attachMovie("menu", "addroute_menu", z++);
437                box.addroute_menu.init(7, 75, 0, relations,
438                                        iText('Add to the chosen route','tip_selectrelation'),null, null, 300-14);
439        }
Note: See TracBrowser for help on using the repository browser.