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

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

Potlatch 0.10c... part two

  • Property svn:executable set to *
File size: 28.2 KB
Line 
1 
2        // =====================================================================================
3        // properties.as
4        // Potlatch property window functions
5        // =====================================================================================
6
7        // to do later:
8        // -- relations:
9        //              sort colouring/highlighting
10        //              better presentation for drop-down "choose a relation" menu
11        //              search for relations
12        //              link icon?
13        //              repeat relations
14        //              preset menu
15        //              autocomplete
16        //                      will need to be a higher stacking level than modal
17        // -- scrollbar background/clicking?
18
19        // properties is cleared/inited on:
20        // - anchorpoint.select
21        // - POI.reload and POI.select
22        // - potlatch.as: mapClickEnd, deselectAll
23        // - (relations, not a problem as yet)
24        // - Way.select
25       
26        // =====================================================================================
27        // Preset menu
28       
29        PresetMenu=function() {};
30        PresetMenu.prototype=new MovieClip();
31
32        PresetMenu.prototype.init=function(pw) {
33                if (pw) {
34                        this.pw=pw;                     // reference to property window
35                        pw.presetmenu=this;     // and back again!
36                        this.group='road';      // what group of tags? (e.g. 'road')
37                        this.setIcon(this.group);
38                        this.reflect();
39                } else {
40                        removeMovieClip(this.dropdown);
41                        removeMovieClip(this.icon);
42                }
43        };
44        PresetMenu.prototype.initMenu=function(value) {
45                this.attachMovie("menu","dropdown",1);
46                this.dropdown.init(30,5,value,
47                                                   presetnames[this.pw.proptype][this.group],
48                                                   'Choose from a menu of preset tags describing the '+pw.proptype,
49                                                   this.setAttributes,this,151);
50        };
51        PresetMenu.prototype.reflect=function() {
52                var i,t;
53                var pt=this.pw.proptype;
54                var found=this.pw.findInPresetMenu(this.group);
55                if (found) { this.initMenu(found); return; }
56                for (i=0; i<presetmenus[pt].length; i+=1) {
57                        t=this.pw.findInPresetMenu(presetmenus[pt][i]); if (t) { found=t; this.group=presetmenus[pt][i]; }
58                }
59                if (found) { this.initMenu(found);
60                                         this.setIcon(); }
61                          else { this.initMenu(0); }
62        };
63        PresetMenu.prototype.setIcon=function() {
64                this.attachMovie("preset_"+this.group,"icon",2);
65                with (this.icon) { _x=10; _y=15; }
66                this.icon.onPress   =function() { this._parent.cycleIcon(); };
67                this.icon.onRollOver=function() { setFloater(iText("Choose what type of presets are offered in the menu.",'tip_presettype')); };
68                this.icon.onRollOut =function() { clearFloater(); };
69        };
70        PresetMenu.prototype.cycleIcon=function() {
71                var j=0;
72                var pt=this.pw.proptype;
73                for (var i=0; i<presetmenus[pt].length; i+=1) {
74                        if (presetmenus[pt][i]==this.group) { j=i+1; }
75                }
76                this.group=presetmenus[pt][j%i];
77                this.setIcon();
78                this.initMenu(this.pw.findInPresetMenu(this.group));
79        };
80        PresetMenu.prototype.setAttributes=function(pre) {
81                var pname=presetnames[this.pw.proptype][this.group][pre];
82                var pkeys=presets[pname];
83                var pkey;
84                this.pw.saveUndo();
85                for (pkey in pkeys) {
86                        if (this.pw.proparr[pkey].length>0 && presets[pname][pkey].substr(0,6)=='(type ') {}
87                        else { setValueInObject(this.pw.proptype, pkey, presets[pname][pkey]); }
88                }
89                this.pw.reinit();
90                this.pw.saveAttributes();
91                if (this.pw.proptype!='POI') { _root.ws.redraw(); }
92        };
93
94        Object.registerClass("presetmenu",PresetMenu);
95
96
97        // =====================================================================================
98        // Autocomplete
99
100        // Still to do
101        // - some way of stopping keys being added twice with same name
102        //   (probably rename to highway_2?)
103        // - wipe preset menu when POI reverted
104        // - some way of invoking full autocomplete menu when value deleted
105        //   (probably using up cursor/down cursor)
106
107        AutoMenu=function() {};
108        AutoMenu.prototype=new MovieClip();
109        AutoMenu.prototype.redraw=function(tf) {
110
111                this.tf=tf;                                                     // textfield instance
112                this.pw=tf._parent._parent._parent;     // PropertyWindow instance
113                this.field=tf._name;                            // keyname|value
114                this.key=tf._parent.keyname.text;
115                var curval=tf.text;
116
117                if (this.field=='value' && curval=='' &&
118                   (_root.lastkeypressed==8 || _root.lastkeypressed==46)) {
119                        // if user has just deleted value, don't show autocomplete!
120                        this.remove(); return;
121                }
122
123                // Find possible values for autocomplete
124                if (curval=='key') { curval=''; }                                       // full menu on 'key'
125                var possible=new Array();
126                if (this.field=='keyname') {
127                        z=_root.autotags[this.pw.proptype];                             // key
128                        for (i in z) {
129                                if (i.slice(0,curval.length)==curval) { possible.push(i); }
130                                // ** shouldn't add if there's already a key of that name
131                        }
132                        possible.sort();
133                } else {
134                        z=_root.autotags[this.pw.proptype][this.key];   // value
135                        for (i in z) {
136                                if (z[i].slice(0,curval.length)==curval) { possible.push(z[i]); }
137                        }
138                }
139
140                // Draw autocomplete window
141                var p=getGlobalCoord(tf); var wx=p[0]; var wy=p[1];
142                this.autonumkeys=Math.min(possible.length,Math.floor(wy/16));
143                if (this.autonumkeys==0) { this.remove(); return; }
144                if (this.autonumkeys==1 && possible[0]==curval) { this.remove(); return; }
145
146                this.createEmptyMovieClip("autolist",1);
147               
148                with (this.autolist) {
149                        _x=wx; _y=wy-16*this.autonumkeys-3;
150                        clear();
151                        beginFill(0x0000FF,100);
152                        moveTo(0,0); lineTo(100,0);
153                        lineTo(100,16*this.autonumkeys+3);
154                        lineTo(0,16*this.autonumkeys+3); lineTo(0,0);
155                        endFill();
156                };
157
158                this.useHandCursor=true;
159                this.onPress=function() {
160                        this.select(Math.floor(this.autolist._ymouse/16));
161                        this.paste();
162                        var f=this.field;
163                        var k=this.key;
164                        if (f=='keyname') {
165                                renameKey(this.tf);
166                                _root.reinstatefocus=this.tf._parent.value;
167                        } else {
168                                this.remove();
169                                Selection.setFocus(null);
170                                _root.keytarget='';
171                        }
172                };
173
174                this.createEmptyMovieClip("triangle",2);
175                with (this.triangle) {
176                        clear();
177                        beginFill(0x0000FF,100);
178                        moveTo(5,0);  lineTo(15,0);
179                        lineTo(10,5); lineTo(5,0);
180                        endFill();
181                        _x=wx; _y=wy;
182                };
183               
184                for (i=0; i<this.autonumkeys; i++) {
185                        this.autolist.createTextField("o"+i,i,0,i*16,100,20);
186                        with (this.autolist["o"+i]) {
187                                text=possible[i]; setTextFormat(boldWhite); type='dynamic'; 
188                                background=true; backgroundColor=0x0000FF; selectable=false;
189                        };
190                }
191                this.select(0);
192        };
193        AutoMenu.prototype.remove=function() {
194                removeMovieClip(this);
195        };
196
197        // AutoMenu.select              - set and highlight autocomplete value
198
199        AutoMenu.prototype.select=function(n) {
200                this.autolist["o"+this.selected].backgroundColor=0x0000FF;
201                this.autolist["o"+this.selected].setTextFormat(auto_off);
202                this.selected=n;
203                this.autolist["o"+n].backgroundColor=0x00FFFF;
204                this.autolist["o"+n].setTextFormat(auto_on);
205        };
206       
207        // AutoMenu.paste               - write currently selected value into textfield
208
209        AutoMenu.prototype.paste=function() {
210                var newval=this.autolist["o"+this.selected].text;
211                var tf=this.tf;
212                tf.text=newval;
213                if (this.field=='keyname') { renameKey(tf); }
214                                                          else { setValueFromTextfield(tf); }
215                Selection.setSelection(newval.length,newval.length);
216        };
217       
218
219        // keyRespond                   - respond to up/down/enter keypresses
220       
221        AutoMenu.prototype.keyRespond=function(k) {
222                switch (k) {
223                        case Key.UP:    if (this.selected>0  ) { this.select(this.selected-1); }
224                                                        this.paste(); break;
225                        case Key.DOWN:  if (this.selected+1<this.autonumkeys) { this.select(this.selected+1); }
226                                                        this.paste(); break;
227                        case 13:                this.paste();
228                                                        this.remove();
229                                                        autoEnter(); break;
230                        case 27:                this.remove(); break;
231                };
232        };
233       
234        // autoEnter                    - Enter pressed, move to next field
235
236        function autoEnter() {
237                if (Selection.getFocus().split('.').pop()=='keyname') {
238                        Selection.setFocus(eval(Selection.getFocus())._parent.value);
239                } else {
240                        Selection.setFocus(null);
241                }
242        }
243
244        Object.registerClass("auto",AutoMenu);
245
246
247        // =====================================================================================
248        // PropertyWindow object
249
250        PropertyWindow=function() {
251                this.proptype='';
252        };
253        PropertyWindow.prototype=new MovieClip();
254       
255        PropertyWindow.prototype.reinit=function() {
256                var n=this.savedundo;
257                this.init(this.proptype,this.xnumber,this.ynumber);
258                this.savedundo=n;
259        };
260
261        PropertyWindow.prototype.init=function(proptype,w,h) {
262                this.createEmptyMovieClip("attributes",1);
263                this.createEmptyMovieClip("attrmask",2);
264                this.createEmptyMovieClip("scrollbar",3);
265//              if (proptype=='') { this.saveAttributes(); }
266                this.proptype=proptype;
267                this.tab=0;
268                this.xnumber=w;
269                this.ynumber=h;
270                this.tagcount=0;
271                this.savedundo=false;
272                if (proptype=='') { return; }
273
274                this.relarr = [];
275                switch (proptype) {
276                        case 'point':
277                                this.proparr=_root.ws.path[_root.pointselected].attr;
278                                this.relarr=getRelationsForNode(_root.ws.path[_root.pointselected].id);
279                                break;
280                        case 'POI':
281                                this.proparr=_root.map.pois[poiselected].attr;
282                                this.relarr=getRelationsForNode(poiselected);
283                                break;
284                        case 'way':
285                                this.proparr=_root.ws.attr;
286                                this.relarr=getRelationsForWay(wayselected);
287                                break;
288                        case 'relation':
289                                this.proparr=_root.editingrelation.attr;
290                                break;
291                }
292
293                this.xpos=0; this.ypos=0;
294
295                // Attach relations
296                relarr=this.relarr;
297                for (var rel in relarr) {
298                        if (_root.map.relations[relarr[rel]]) {
299                                this.attributes.attachMovie("relmember",this.tagcount, this.tagcount);
300                                var pos = this.getXY(this.tagcount);
301                                this.attributes[this.tagcount]._x=pos[0];
302                                this.attributes[this.tagcount]._y=pos[1];
303                                this.attributes[this.tagcount].init(relarr[rel]);
304                                this.attributes[this.tagcount].value.tabIndex=++this.tab;
305                                this.attributes[this.tagcount].value.tabEnabled=true;
306                                this.tagcount+=1;
307                        }
308                }
309
310                // Attach keys/values
311                // sorted alphabetically, but with namespaced tags at the end
312
313                proparr=this.proparr;   // annoying scope issues
314                proplist=new Array();
315                for (el in proparr) { proplist.push(el); }
316                proplist.sort(function(a,b) {
317                        if      (a.indexOf(':')<b.indexOf(':')) { return -1; }
318                        else if (a.indexOf(':')>b.indexOf(':')) { return  1; }
319                        else if (a<b) { return -1; }
320                        else if (a>b) { return  1; }
321                        else              { return  0; }
322                });
323                for (i=0; i<proplist.length; i++) {
324                        el=proplist[i];
325                        if (proparr[el]!='' && el!='created_by' && el!='edited_by') {
326                                this.attributes.attachMovie("keyvalue",this.tagcount,this.tagcount);
327                                var pos = this.getXY(this.tagcount);
328                                this.attributes[this.tagcount]._x=pos[0];
329                                this.attributes[this.tagcount]._y=pos[1];
330                                this.attributes[this.tagcount].init(el);
331                                this.attributes[this.tagcount].keyname.tabIndex=++this.tab;
332                                this.attributes[this.tagcount].value.tabIndex=++this.tab;
333                                this.tagcount+=1;
334                        }
335                }
336
337
338                this.scrollbar._x=0; this.scrollbar._y=this.ynumber*19;
339                this.updateMask();                                      // Draw scrollbar
340        };
341
342        PropertyWindow.prototype.saveUndo=function() {
343                // don't have more than two consecutive undos for the same way
344                if (this.savedundo) { return; }
345                this.savedundo=true;
346                var task  =_root.undo[_root.undo.length-1][0];
347                var params=_root.undo[_root.undo.length-1][1];
348
349                switch (this.proptype) {
350                        case 'way':             _root.undo.append(UndoStack.prototype.undo_waytags,
351                                                                                          new Array(_root.ws,deepCopy(this.proparr)),
352                                                                                          iText("setting tags on a way",'action_waytags')); break;
353                        case 'point':   _root.undo.append(UndoStack.prototype.undo_pointtags,
354                                                                                          new Array(_root.ws,_root.pointselected,deepCopy(this.proparr)),
355                                                                                          iText("setting tags on a point",'action_pointtags')); break;
356                        case 'POI':             _root.undo.append(UndoStack.prototype.undo_poitags,
357                                                                                          new Array(_root.map.pois[poiselected],deepCopy(this.proparr)),
358                                                                                          iText("setting tags on a POI",'action_poitags')); break;
359                };
360        };
361
362        PropertyWindow.prototype.getXY=function(i) {
363                var x = Math.floor(i / this.ynumber);
364                var y = i % this.ynumber;
365                return [x*190, y*19];
366        };
367
368        PropertyWindow.prototype.enableTabs=function(a) {
369                for (var i in this.attributes) {
370                        this.attributes[i].keyname.tabEnabled=a;
371                        this.attributes[i].value.tabEnabled  =a;
372                }
373        };
374
375        // PropertyWindow.enterNewAttribute
376
377        PropertyWindow.prototype.enterNewAttribute=function() {
378                // ** check nothing already exists called "key"
379                this.saveUndo();
380                this.attributes.attachMovie("keyvalue",this.tagcount,this.tagcount);
381                var pos = this.getXY(this.tagcount);
382                this.attributes[this.tagcount]._x=pos[0];
383                this.attributes[this.tagcount]._y=pos[1];
384                this.attributes[this.tagcount].init('key');
385                this.attributes[this.tagcount].keyname.tabIndex=++this.tab;
386                this.attributes[this.tagcount].value.tabIndex=++this.tab;
387                Selection.setFocus(this.attributes[this.tagcount].keyname);
388                Selection.setSelection(0,3);
389                this.tagcount+=1;
390                this.updateMask();
391                this.attributes[this.tagcount-1].scrollToField();
392        };
393
394        // PropertyWindow.updateMask
395        // create mask given size of window, create scrollbar
396
397        PropertyWindow.prototype.updateMask=function() {
398                this.cols=Math.floor((this.tagcount+(this.ynumber-1))/this.ynumber);// number of columns used
399                var pxwidth=this.xnumber*190-5;
400
401                // Create and apply mask
402                with (this.attrmask) {
403                        clear();
404                        beginFill(0,100);
405                        moveTo(0,0); lineTo(pxwidth,0);
406                        lineTo(pxwidth,this.ynumber*19); lineTo(0,this.ynumber*19);
407                        lineTo(0,0); endFill();
408                }
409                this.attributes.setMask(this.attrmask);
410
411                // Draw scrollbar
412                var percent=(Math.min(this.xnumber/this.cols,1));       // what percentage of scrollbar to show?
413                var swidth=pxwidth*percent;                                                     // how wide is the scrollbar?
414                this.mwidth=pxwidth-swidth;                                                     // furthest right scrollbar can go
415                this.sscope=(this.cols-this.xnumber)*190;                       // how many unshown pixels in attributes
416                if (percent==1) { var c=0xE0E0E0; }                                     // colour to show scrollbar
417                                   else { var c=0xCCCCCC; }                                     //  |
418                with (this.scrollbar) {
419                        clear();
420                        beginFill(c,100);
421                        moveTo(0,0); lineTo(swidth,0);
422                        lineTo(swidth,4); lineTo(0,4);
423                        lineTo(0,0); endFill();
424                };
425
426                // Scrollbar move events
427                if (percent<1) {
428                        this.scrollbar.onPress=function() {
429                                this.onMouseMove=function() {
430                                        this._parent.attributes._x=-(this._x/this._parent.mwidth)*this._parent.sscope;
431                                };
432                                this.startDrag(false,0,this._y,this._parent.mwidth,this._y);
433                        };
434                        this.scrollbar.onRelease=function() {
435                                delete this.onMouseMove;
436                                this.stopDrag();
437                        };
438                }
439        };
440       
441        PropertyWindow.prototype.repeatAttributes=function(dotags) {
442                var i,proparr,relarr;
443                this.saveUndo();
444                switch (this.proptype) {
445                        case 'point':   proparr=_root.savedpointway.path[_root.saved['point']].attr; 
446                                                        relarr=getRelationsForNode(_root.savedpointway.path[_root.saved['point']].id);
447                                                        break;
448                        case 'POI':             proparr=_root.saved['POI'].attr;
449                                                        relarr=getRelationsForNode(_root.saved['POI']._name);
450                                                        break; // ** formerly had _root.map.pois[poiselected].attr=new Array(); in here, no obvious reason why
451                        case 'way':             proparr=_root.saved['way'].attr;
452                                                        relarr=getRelationsForWay(_root.saved['way']._name);
453                                                        break;
454                }
455
456                // repeat tags
457                if (dotags) {
458                        for (i in proparr) {
459                                if (Key.isDown(Key.SHIFT) && (i=='name' || i=='ref') || i=='created_by') {
460                                        // ignore name and ref if SHIFT pressed
461                                } else {
462                                        switch (this.proptype) {
463                                                case 'point':   j=_root.savedpointway.path[_root.saved['point']].attr[i]; break;
464                                                case 'POI':             j=_root.saved['POI'].attr[i]; break;
465                                                case 'way':             j=_root.saved['way'].attr[i]; break;
466                                        }
467                                        setValueInObject(this.proptype,i,j);
468                                }
469                        }
470                }
471
472                // repeat relations
473                for (i in relarr) {
474                        var r=_root.map.relations[relarr[i]];   // reference to this relation
475                        switch (this.proptype) {
476                                case 'point':   r.setNodeRole(_root.ws.path[_root.pointselected].id,r.getNodeRole(_root.savedpointway.path[_root.saved['point']].id)); break;
477                                case 'POI':             r.setNodeRole(poiselected,r.getNodeRole(_root.saved['POI']._name)); break;
478                                case 'way':             r.setWayRole (wayselected,r.getWayRole (_root.saved['way']._name)); break;
479                        }
480                }
481                if (this.proptype!='POI') { _root.ws.redraw(); }
482                this.reflect();
483                this.reinit();
484        };
485
486        PropertyWindow.prototype.saveAttributes=function() {
487                if (this.tagcount==0) { return; }
488                switch (this.proptype) {
489                        case 'point':   _root.saved[this.proptype]=_root.pointselected; _root.savedpointway=_root.ws; break;
490                        case 'POI':             _root.saved[this.proptype]=_root.map.pois[poiselected]; break;
491                        case 'way':             _root.saved[this.proptype]=_root.ws; break;
492                };
493        };
494
495        PropertyWindow.prototype.findInPresetMenu=function(group) {
496                var pname,pkeys,pre,ok,cvalue;
497                var f=0;
498                for (pre=presetnames[this.proptype][group].length-1; pre>-1; pre-=1) {
499                        pname=presetnames[this.proptype][group][pre];
500                        pkeys=_root.presets[pname];
501                        if (pkeys) {
502                                ok=1;
503                                for (pkey in pkeys) {
504                                        cvalue=this.proparr[pkey];
505                                        if (cvalue==null) { cvalue=''; }
506                                        if (cvalue!=presets[pname][pkey] && presets[pname][pkey].substr(0,6)!='(type ') { ok=0; }
507                                }
508                                if (ok==1) { f=pre; }
509                        }
510                }
511                return f;
512        };
513
514        PropertyWindow.prototype.reflect=function() {
515                if (this.presetmenu) { this.presetmenu.reflect(); }
516        };
517
518        PropertyWindow.prototype.setTag=function(k,v) {
519                this.saveUndo();
520                setValueInObject(this.proptype,k,v);
521                this.reinit();
522                this.saveAttributes();
523        };
524       
525
526       
527        // Remove any '(type...' or blank keys before uploading
528
529        PropertyWindow.prototype.tidy=function() {
530                var proparr=this.proparr;
531                for (var el in proparr) {
532                        if (proparr[el]=='' || proparr[el].substr(0,6)=='(type ') { delete this.proparr[el]; }
533                }
534        };
535
536        Object.registerClass("propwindow",PropertyWindow);
537
538
539
540
541
542        // =====================================================================================
543        // KeyValue object
544
545        function KeyValue() {};
546        KeyValue.prototype=new MovieClip();
547
548        KeyValue.prototype.init=function(key,value) {
549
550                // Initialise key
551
552                this.createTextField('keyname',1,0,-1,70,18);
553                with (this.keyname) {
554                        backgroundColor=0xBBBBBB;
555                        background=true;
556                        text=key;
557                        type='input';
558                        setTextFormat(boldSmall);
559                        setNewTextFormat(boldSmall);
560                        restrict="^"+chr(0)+"-"+chr(31);
561                };
562                this.keyname.onSetFocus =function() {
563                        this._parent.scrollToField();
564                        _root.keytarget='keyname';
565                };
566                this.keyname.onKillFocus=function() {
567                        renameKey(this);
568                        if (_root.lastkeypressed==-1 && _root.auto.autolist.hitTest(_root._xmouse,_root._ymouse)) { return; }
569                        if (this.text=='') { _root.redopropertywindow=this._parent._parent._parent; }
570                        _root.keytarget='';
571                        _root.auto.remove();
572                        this._parent._parent._parent.reflect();
573                };
574                this.keyname.onChanged=function(tf) {
575                        if (tf.text=='+' || tf.text=='=') {
576                                // if FP has picked up the "+" keypress, ignore it and set back to 'key'
577                                tf.text='key';
578                                tf.setTextFormat(boldSmall);
579                                tf.setNewTextFormat(boldSmall);
580                                Selection.setFocus(tf); Selection.setSelection(0,3);
581                        }
582                        if (!_root.auto) { _root.attachMovie("auto","auto",75); }
583                        _root.auto.redraw(tf);
584                        this._parent._parent._parent.saveAttributes();
585                };
586
587                // Initialise value
588
589                this.createTextField('value',2,72,-1,100,18);
590                this.value.onSetFocus =function() {
591                        this._parent.scrollToField();
592                        if (this.textColor==0x888888) { this.text=''; this.textColor=0; }
593                        if (!_root.auto) { _root.attachMovie("auto","auto",75); }
594                        _root.auto.redraw(this);
595                        _root.keytarget='value'; 
596                };
597                this.value.onKillFocus=function() {
598                        if (_root.reinstatefocus) { return; }
599                        if (_root.lastkeypressed==-1 && _root.auto.autolist.hitTest(_root._xmouse,_root._ymouse)) { return; }
600                        _root.keytarget='';
601                        if (this.text=='') {
602                                if (this._parent.lastvalue.substr(0,6)=='(type ') {
603                                        this.text=this._parent.lastvalue; this.textColor=0x888888;
604                                } else {
605                                        _root.redopropertywindow=this._parent._parent._parent; 
606                                }
607                        }
608                        if (this._parent._parent._parent.proptype!='POI') { _root.ws.redraw(); }
609                        _root.auto.remove();
610                        this._parent._parent._parent.reflect();
611                        this._parent.lastvalue=this.text;
612                };
613                this.value.onChanged=function(tf) {
614                        setValueFromTextfield(tf);
615                        if (!_root.auto) { _root.attachMovie("auto","auto",75); }
616                        _root.auto.redraw(tf);
617                        this._parent._parent._parent.saveAttributes();
618                };
619                with (this.value) {
620                        backgroundColor=0xDDDDDD;
621                        background=true;
622                        type='input';
623                        setTextFormat(plainSmall);
624                        setNewTextFormat(plainSmall);
625                        restrict="^"+chr(0)+"-"+chr(31);
626                };
627                this.value.text=this.getValueFromObject(key);
628                if (this.value.text.substr(0,6)=='(type ') { this.value.textColor=0x888888; }
629                this.lastkey=key;
630                this.lastvalue=this.value.text;
631               
632                // Initialise close box
633               
634                this.createEmptyMovieClip('grey',3);
635                with (this.grey) {
636                        beginFill(0xDDDDDD,100);
637                        moveTo(172,-1); lineTo(182,-1);
638                        lineTo(182,17); lineTo(172,17);
639                        endFill();
640                };
641
642                this.attachMovie("closecross", "i_remove", 4);
643                with (this.i_remove) { _x=174; _y=8; };
644                this.i_remove.onPress=function() {
645                        this._parent.value.text='';
646                        setValueFromTextfield(this._parent.value);
647                        _root.auto.remove();
648                        this._parent._parent._parent.reflect();
649                        if (this._parent._parent._parent.proptype!='POI') { _root.ws.redraw(); }
650                        _root.redopropertywindow=this._parent._parent._parent;
651                };
652        };
653
654        // KeyValue.getValueFromObject(key)
655        // for a given key, returns the value from the way, point or POI
656
657        KeyValue.prototype.getValueFromObject=function(k) {
658                var v;
659                switch (this._parent._parent.proptype) {
660                        case 'point':   v=_root.ws.path[_root.pointselected].attr[k]; break;
661                        case 'POI':             v=_root.map.pois[poiselected].attr[k]; break;
662                        case 'way':             v=_root.ws.attr[k]; break;
663                        case 'relation':v=_root.editingrelation.attr[k]; break;
664                }
665                if (v==undefined) { v='(type value here)'; }
666                return v;
667        };
668
669        // KeyValue.scrollToField()
670        // make sure this field is visible
671       
672        KeyValue.prototype.scrollToField=function() {
673                var pw=this._parent._parent;
674                if (this._x>=-(pw.attributes._x) &&
675                        this._x< -(pw.attributes._x)+190*(pw.xnumber-1)+5) {
676                        return;                 // In view
677                                                        // -(pw.attributes._x) is left x of the panel
678                }
679
680                // To get in view, we need our column on the right of the panel
681                var newcol=Math.floor(this._x/190);             // column we're in
682                newcol=Math.min(newcol,pw.cols-pw.xnumber);
683                newcol=Math.max(newcol,0);
684                pw.attributes._x=-newcol*190;
685                pw.scrollbar._x=newcol*190/pw.sscope*pw.mwidth;
686                // (inverse of calculation in pw.scrollbar.onPress)
687        };
688
689        Object.registerClass("keyvalue",KeyValue);
690
691        // =====================================================================================
692        // KeyValue support functions
693
694        // setValueFromTextfield(value textfield)
695        // setValueInObject(property type,key,value)
696        // - update the way, point or POI with the new value
697        //   (opposite of getValueFromObject)
698       
699        function setValueFromTextfield(tf) {
700                tf._parent._parent._parent.saveUndo();
701                setValueInObject(tf._parent._parent._parent.proptype,
702                                                 tf._parent.keyname.text,
703                                                 tf.text);
704        };
705       
706        function setValueInObject(proptype,k,v) {
707                switch (proptype) {
708                        case 'point':   var id=_root.ws.path[_root.pointselected].id;
709                                                        nodes[id].attr[k]=v;
710                                                        nodes[id].tagged=hasTags(nodes[id].attr);
711                                                        _root.ws.clean=false; break;
712                        case 'POI':             _root.map.pois[poiselected].attr[k]=v;
713                                                        _root.map.pois[poiselected].clean=false; break;
714                        case 'way':             _root.ws.attr[k]=v;
715                                                        _root.ws.clean=false; break;
716                        case 'relation':_root.editingrelation.attr[k]=v;
717                                                        _root.editingrelation.clean=false; break;
718                }
719        };
720
721        // renameKey(key textfield)
722
723        function renameKey(tf) {
724                var k=tf.text;
725                tf._parent._parent._parent.saveUndo();
726                if (k!=tf._parent.lastkey) {
727                        // field has been renamed, so delete old one and set new one
728                        // (temporary references used to get around Ming delete bug)
729                        switch (tf._parent._parent._parent.proptype) {
730                                case 'point':   var noderef=_root.ws.path[_root.pointselected];
731                                                                delete noderef.attr[tf._parent.lastkey];
732                                                                _root.ws.clean=false; break;
733                                case 'POI':             var poiref=_root.map.pois[poiselected];
734                                                                delete poiref.attr[tf._parent.lastkey];
735                                                                _root.map.pois[poiselected].clean=false; break;
736                                case 'way':             delete _root.ws.attr[tf._parent.lastkey];
737                                                                _root.ws.clean=false; break;
738                                case 'relation':delete _root.editingrelation.attr[tf._parent.lastkey];
739                                                                _root.editingrelation.clean=false; break;
740                        }
741                        setValueFromTextfield(tf._parent.value);
742                        tf._parent.lastkey=k;
743                }
744        };
745
746        // =====================================================================================
747        // RelMember object
748
749        function RelMember() {};
750        RelMember.prototype=new MovieClip();
751
752        RelMember.prototype.init=function(rel_id) {
753                this.rel = _root.map.relations[rel_id];
754
755                // Grey background
756                this.createEmptyMovieClip('grey',1);
757                with (this.grey) {
758                        beginFill(0x909090,100);
759                        moveTo(0,0); lineTo(182,0);
760                        lineTo(182,17); lineTo(0,17);
761                        endFill();
762                        lineStyle(1,0xDDDDDD,100);
763                        moveTo(115,2); lineTo(115,15);
764                        moveTo(166,2); lineTo(166,15);
765                };
766
767                // Initialise key
768                this.createEmptyMovieClip('keynameclick', 2);
769                this.keynameclick.createTextField('keyname',1,0,-1,118,18);
770                var t=this.rel.getType(); var n=this.rel.getName();
771                with (this.keynameclick.keyname) {
772                        type='dynamic'; selectable=false;
773                        text=n; setTextFormat(plainWhite);
774                        setNewTextFormat(boldWhite); replaceSel(t+" ");
775                };
776                this.keynameclick.onPress=function() {
777                        this._parent.rel.editRelation();
778                };
779                this.keynameclick.onRollOver=function() { this._parent.rel.setHighlight(true); };
780                this.keynameclick.onRollOut=function() { this._parent.rel.setHighlight(false); };
781
782                // Remove icon
783                this.attachMovie("closecross", "i_remove", 4);
784                with (this.i_remove) { _x=174; _y=8; };
785                this.i_remove.onPress=function() { this._parent.removeRelation(); };
786
787                // Role (value)
788                this.createTextField('value',3,116,1,50,15);    // 3,92,-1,70,18
789                with (this.value) {
790                        backgroundColor=0xDDDDDD;
791                        background=true;
792                        type='input';
793                        setTextFormat(plainTiny);
794                        setNewTextFormat(plainTiny);
795                        restrict="^"+chr(0)+"-"+chr(31);
796                };
797                this.value.text=this.getRole();
798                this.value.onSetFocus =function() { this._parent.scrollToField();
799                                                                                        _root.keytarget='value'; };
800                this.value.onKillFocus=function() { _root.keytarget=''; };
801                this.value.onChanged  =function(tf) { this._parent.setRole(tf); };
802        };
803
804        RelMember.prototype.getRole=function() {
805                var v;
806                switch (this._parent._parent.proptype) {
807                        case 'point':   v=this.rel.getNodeRole(_root.ws.path[_root.pointselected].id); break;
808                        case 'POI':             v=this.rel.getNodeRole(poiselected); break;
809                        case 'way':             v=this.rel.getWayRole(wayselected); break;
810                }
811                if (v==undefined) { v='(type value here)'; }
812                return v;               
813        };
814
815        RelMember.prototype.setRole=function(tf) {
816                var role = tf.text;
817                switch (this._parent._parent.proptype) {
818                        case 'point':   v=this.rel.setNodeRole(_root.ws.path[_root.pointselected].id, role); break;
819                        case 'POI':             v=this.rel.setNodeRole(poiselected, role); break;
820                        case 'way':             v=this.rel.setWayRole(wayselected, role); break;
821                }
822        };
823
824        RelMember.prototype.removeRelation=function() {
825                switch (this._parent._parent.proptype) {
826                        case 'point': this.rel.removeNode(_root.ws.path[_root.pointselected].id); break;
827                        case 'POI': this.rel.removeNode(poiselected); break;
828                        case 'way': this.rel.removeWay(wayselected); break;
829                }
830                _root.panel.properties.reinit();
831        };
832
833        RelMember.prototype.scrollToField=KeyValue.prototype.scrollToField;
834
835        Object.registerClass("relmember",RelMember);
836
837
838
839
840        // =====================================================================================
841        // General support functions
842
843        // setTypeText - set contents of type window
844       
845        function setTypeText(a,b) {
846                _root.panel.t_type.text=a;    _root.panel.t_type.setTextFormat(boldText);
847                _root.panel.t_details.text=b; _root.panel.t_details.setTextFormat(plainText);
848                if (_root.ws.locked ||
849                        _root.map.pois[_root.poiselected].locked) {
850                        _root.panel.padlock._visible=true;
851                        _root.panel.padlock._x=_root.panel.t_details.textWidth+15;
852                } else {
853                        _root.panel.padlock._visible=false;
854                }
855                _root.panel.createEmptyMovieClip('historylink',25);
856                with (_root.panel.historylink) {
857                        beginFill(0,0); moveTo(5,23);
858                        lineTo(7+_root.panel.t_details.textWidth,23);
859                        lineTo(7+_root.panel.t_details.textWidth,23+_root.panel.t_details.textHeight);
860                        lineTo(5,23+_root.panel.t_details.textHeight); lineTo(5,23);
861                };
862                _root.panel.historylink.onPress=getHistory;
863                _root.panel.historylink.useHandCursor=true;
864        }
865
866        // getPanelColumns - how many columns can fit into the panel?
867
868        function getPanelColumns() {
869                return Math.max(Math.floor((Stage.width-110-15)/190),1);
870        }
871
872        // getGlobalCoord - where on the screen is the textfield?
873
874        function getGlobalCoord(tf) {
875                var pt=new Object();
876                pt.x=tf._parent._x+72*(tf._name=='value');
877                pt.y=tf._parent._y-2;
878                tf._parent.localToGlobal(pt);
879                return new Array(pt.x-tf._parent._x,pt.y-tf._parent._y);
880        }
881
882        // updateButtons - set alpha for buttons
883       
884        function updateButtons() {
885                var pt=_root.panel.properties.proptype;
886                _root.panel.i_repeatattr._alpha=100-50*(pt=='' || _root.saved[pt]=='');
887                _root.panel.i_newattr._alpha   =100-50*(pt=='');
888                _root.panel.i_newrel._alpha    =100-50*(pt=='');
889        }
890
891        function updateScissors(v) {
892                _root.panel.i_scissors._alpha=50+50*v;
893        }
894
895        // hashLength
896       
897        function hashLength (a) {
898                var l=0;
899                for (var i in a) { l++; }
900                return l;
901        }
902
Note: See TracBrowser for help on using the repository browser.