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

Last change on this file since 14979 was 14979, checked in by richard, 10 years ago

a few small fixes

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