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

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

remove debug statement

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