Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /SvgEditor.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (hide annotations) (download) (as text)
Tue Jul 20 06:13:09 2010 UTC (13 years, 8 months ago) by isao-hara
File MIME type: application/x-javascript
File size: 56342 byte(s)
iSlideManager updated
1 isao-hara 2 /*
2     * SvgEditor.js
3    
4     iSlideMaker
5     http://sourceforge.jp/projects/islidemaker/simple/
6    
7     Copyright(c) 2010, Isao Hara, isao-hara@users.sourceforge.jp
8    
9     All rights reserved. This program is made available under the terms of the
10     Eclipse Public License v1.0 which accompanies this distribution, and is
11     available at http://www.eclipse.org/legal/epl-v10.html
12    
13     Contributors: Isao Hara.
14    
15     */
16    
17     var systemDB;
18     var currentMode;
19     var editarea_w=80;
20     var editarea_h=10;
21     var MainTitle="Simple SVG Editor";
22    
23     var preview=null;
24     var targetItem=null;
25     var selectedItems=new Array();
26     var sx=0;
27     var sy=0;
28     var ex=0;
29     var ey=0;
30     var modeSVG=null;
31     var iSlideMgr='iSlideManager.php';
32     var MgrPath="";
33     var nextId=1;
34    
35     var lineEdit=null;
36     ////// SVG
37     var svg_ns = 'http://www.w3.org/2000/svg';
38     var svg_x=10;
39     var svg_y=10;
40     var svg_width = 100;
41     var svg_height = 50;
42     var svg_rx = 50;
43     var svg_ry = 30;
44     var svg_lw = 1;
45     var svg_wo = null;
46     var svg_ho = null;
47     var svg_ro = null;
48     var svg_rxo = null;
49     var svg_ryo = null;
50     var svg_fsize = null;
51     var svg_scale_dir = null;
52    
53     var svg_top = null;
54     var svg_select = null;
55     var svg_defs = null;
56    
57 isao-hara 14 ///// Color
58     var colors=new Array('none', '#ffffff',
59     '#000000', '#3f3f3f', '#7f7f7f', '#bfbfbf',
60     '#ff0000', '#ff7f00', '#ffff00', '#7fff00',
61     '#00ff00', '#00ff7f', '#00ffff', '#007fff',
62     '#0000ff', '#7f00ff', '#ff00ff', '#ff007f',
63     '#7f0000', '#7f3f00', '#7f7f00', '#3f7f00',
64     '#007f00', '#007f3f', '#007f7f', '#003f7f',
65     '#00007f', '#3f007f', '#7f007f', '#7f003f',
66     '#7f0000', '#7f3f00', '#7f7f00', '#3f7f00',
67     '#ffaaaa', '#ffd4aa', '#ffffaa', '#d4ffaa',
68     '#aaffaa', '#aaffd4', '#aaffff', '#aad4ff',
69     '#aaaaff', '#d4aaff', '#ffaaff', '#ffaad4'
70     );
71    
72 isao-hara 2 //// Initialize
73     function initEditor(name, dispname, size){
74     systemDB = initDB(name, dispname, size);
75     fileSelector();
76     preview=document.getElementById('preview');
77     if(preview){
78     preview.addEventListener("touchstart", onTouchStart,false);
79     preview.addEventListener("touchmove", onTouchMove, false);
80     preview.addEventListener("touchend", onTouchEnd, false);
81     preview.addEventListener("gesturestart", onGestureStart,false);
82     preview.addEventListener("gesturechange", onGestureChange, false);
83     preview.addEventListener("gestureend", onGestureEnd, false);
84     }
85     }
86    
87     function restoreValues(){
88     if(typeof(localStorage) == 'undefined'){
89     alert('local storage not suported');
90     }
91     MgrPath = localStorage.getItem('MgrPath') ? localStorage.getItem('MgrPath') : "";
92     window.onbeforeuload=function(){ return saveChanges(); }
93     }
94     function clearAll(){
95     localsStorage.clear();
96     restoreValudes();
97     }
98    
99     function saveChanges(){
100     localStorage.getItem('MgrPath') = MgrPath;
101     }
102    
103     // initialize a database
104     function initDB(name, dispname, size) {
105     try {
106     if (!window.openDatabase) {
107     alert('not supported');
108     } else {
109     var version = '1.0';
110     var myDB = openDatabase(name, version, dispname, size);
111     }
112     } catch(e) {
113     if (e == INVALID_STATE_ERR) {
114     alert("Invalid database version.");
115     } else {
116     alert("Unknown error "+e+".");
117     }
118     return null;
119     }
120    
121     createTables(myDB);
122     return myDB;
123     }
124    
125     function createTables(db) {
126     if (0) dropTables(db);
127    
128     db.transaction(
129     function (transaction) {
130     transaction.executeSql('CREATE TABLE IF NOT EXISTS files(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, filedata_id INTEGER NOT NULL, deleted INTEGER NOT NULL DEFAULT 0);', [], nullDataHandler, killTransaction);
131     transaction.executeSql('CREATE TABLE IF NOT EXISTS filedata(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, datablob BLOB NOT NULL DEFAULT "");', [], nullDataHandler, errorHandler);
132     }
133     );
134     }
135    
136     function dropTables(db) {
137     db.transaction(
138     function (transaction) {
139     transaction.executeSql('DROP TABLE files;');
140     transaction.executeSql('DROP TABLE filedata;');
141     }
142     );
143     }
144    
145     /// Create New File
146     function reallyCreateNewFileAction(name, db){
147     var myDB = db;
148     if(!db) myDB = systemDB;
149    
150     myDB.transaction(
151     function (transaction) {
152     var myfunc = new Function("transaction", "results", "transaction.executeSql('INSERT INTO files (name, filedata_id) VALUES (?, ?);', [ '"+name+"', results.insertId], nullDataHandler, killTransaction);");
153    
154     transaction.executeSql('INSERT INTO filedata (datablob) VALUES ("");', [], myfunc, errorHandler);
155     }
156     );
157    
158     fileSelector();
159     }
160    
161     function createNewFileAction(db){
162     var myDB = db;
163     if(!db) myDB = systemDB;
164    
165     var name = document.getElementById('createFilename').value
166     if(name == "") {
167     if (confirm('Filename is required, try agein?')) { createNewFile(); }else{ fileSelector(); }
168     return;
169     }
170    
171     myDB.transaction(
172     new Function("transaction", "transaction.executeSql('SELECT id,name from files where name=?;',['"+name+"'],"+
173     "function (transaction, results) {"+
174     "if(results.rows.length == 0){"+
175     "reallyCreateNewFileAction('"+name+"');"+
176     "}else{"+
177     "if (confirm(results.rows.item(0)['name']+' already exist, try agein?')) {"+
178     "createNewFile();"+
179     "}else{"+
180     "fileSelector();"+
181     "}"+
182     "}"+
183     "}, errorHandler);")
184     );
185    
186     }
187    
188     //// Delete File
189     function deleteUpdateResults(transaction, results)
190     {
191     if (results.rowsAffected) {
192     fileSelector();
193     }
194     }
195    
196     function reallyDelete(id, db){
197     var myDB = db;
198     if(!db) myDB = systemDB;
199    
200     myDB.transaction(
201     new Function("transaction",
202     "transaction.executeSql('DELETE FROM files where id=?;', [ "+id+" ], null, errorHandler);"
203     +"transaction.executeSql('DELETE FROM filedata where id=?;', [ "+id+" ], deleteUpdateResults, errorHandler);")
204     );
205     }
206    
207     function deleteFile(name, db){
208     var myDB = db;
209     if(!db) myDB = systemDB;
210    
211     myDB.transaction(
212     new Function("transaction", "transaction.executeSql('SELECT id,name from files where name=?;',['"+name+"'],"+
213     "function (transaction, results) {"+
214     "if (confirm('Really delete '+results.rows.item(0)['name']+'?')) {"+
215     "reallyDelete(results.rows.item(0)['id']);"+
216     "}"+
217     "}, errorHandler);")
218     );
219     }
220    
221     function reallyDeleteAll(db){
222     var myDB = db;
223     if(!db) myDB = systemDB;
224    
225     myDB.transaction(
226     new Function("transaction",
227     "transaction.executeSql('DELETE FROM files;',[],null, errorHandler);"
228     +"transaction.executeSql('DELETE FROM filedata;',[],deleteUpdateResults, errorHandler);")
229     );
230     }
231    
232     function deleteAllFile(db){
233     if (confirm('Really delete all file?')) {
234     reallyDeleteAll(db);
235     }
236     }
237    
238     ///// Rename
239     function reallyRenameFileAction(id, newname, db){
240     var myDB = db;
241     if(!db) myDB = systemDB;
242    
243     myDB.transaction(
244     function (transaction) {
245     transaction.executeSql('UPDATE files set name=? where id=?;', [newname,id ], null, errorHandler);
246     }
247     );
248     fileSelector();
249     }
250    
251     function renameFileAction(db){
252     var myDB = db;
253     if(!db) myDB = systemDB;
254    
255     var new_name = document.getElementById('newFilename').value
256     var id = document.getElementById('fileId').value
257    
258     if(new_name == "") {
259     alert('Filename is required.');
260     fileSelector();
261     return;
262     }
263    
264     myDB.transaction(
265     new Function("transaction", "transaction.executeSql('SELECT id,name from files where name=?;',['"+new_name+"'],"+
266     "function (transaction, results) {"+
267     "if(results.rows.length == 0){"+
268     "reallyRenameFileAction('"+id+"','"+new_name+"');"+
269     "}else{"+
270     "alert(results.rows.item(0)['name']+' already exist');"+
271     "fileSelector();"+
272     "}"+
273     "}, errorHandler);")
274     );
275    
276     }
277    
278    
279     /// Save File
280     function saveFile(db){
281     var myDB = db;
282     if(!db) myDB = systemDB;
283    
284     var editarea = document.getElementById('editarea');
285     var contents = "";
286     contents = editarea.value;
287    
288     myDB.transaction(
289     function (transaction) {
290     var datadiv = document.getElementById('tempdata');
291     var filedata_id = datadiv.getAttribute('lfdataid');
292    
293     transaction.executeSql("UPDATE filedata set datablob=? where id=?;",
294     [ contents, filedata_id ], nullDataHandler, errorHandler);
295    
296     alert('Saved.');
297     }
298     );
299     }
300    
301     function saveData(db){
302     var myDB = db;
303     if(!db) myDB = systemDB;
304    
305     var contents = "";
306     contents = getSVGContent();
307    
308     myDB.transaction(
309     function (transaction) {
310     var datadiv = document.getElementById('tempdata');
311     var filedata_id = datadiv.getAttribute('lfdataid');
312    
313     transaction.executeSql("UPDATE filedata set datablob=? where id=?;",
314     [ contents, filedata_id ], nullDataHandler, errorHandler);
315    
316     alert('Saved.');
317     }
318     );
319     }
320    
321 isao-hara 14 function saveContent(contents, db){
322     var myDB = db;
323     if(!db) myDB = systemDB;
324    
325     if(!contents) {
326     alert("Invalid content");
327     return;
328     }
329    
330     myDB.transaction(
331     function (transaction) {
332     var datadiv = document.getElementById('tempdata');
333     var filedata_id = datadiv.getAttribute('lfdataid');
334    
335     transaction.executeSql("UPDATE filedata set datablob=? where id=?;",
336     [ contents, filedata_id ], nullDataHandler, errorHandler);
337    
338     alert('Saved.');
339     }
340     );
341     }
342    
343 isao-hara 2 function showFileData(transaction, results){
344     var data = results.rows.item(0);
345     var filename = data['name'];
346     var filedata = data['datablob'];
347    
348     var datadiv = document.getElementById('tempdata');
349     datadiv.setAttribute('lfdataid', parseInt(data['filedata_id']));
350    
351     document.title=filename;
352    
353     previewFile(filedata);
354    
355     updateShowMenu();
356     setMode('Preview');
357     }
358    
359     function showFile(name){
360     getFile(name, 'showFileData');
361     }
362    
363     function getFile(name, func, db){
364     var myDB = db;
365     if(!db) myDB = systemDB;
366    
367     var datadiv = document.getElementById('tempdata');
368     if(datadiv) datadiv.setAttribute('lfname', name);
369    
370     myDB.transaction(
371     function (transaction) {
372     transaction.executeSql('SELECT * from files, filedata where files.name=? and files.filedata_id = filedata.id;', [name], eval(func), errorHandler);
373     }
374     );
375     }
376    
377     // Error Handlers
378     function killTransaction(transaction, error){
379     return true;
380     }
381    
382     function errorHandler(transaction, error){
383     alert('Oops. Error was '+error.message+' (Code '+error.code+')');
384    
385     var we_think_this_error_is_fatal = true;
386     if (we_think_this_error_is_fatal) return true;
387     return false;
388     }
389    
390     function nullDataHandler(transaction, results){
391     }
392    
393     ///////////////////////////
394    
395     function fileSelector(db) {
396     var myDB = db;
397     if(!db) myDB = systemDB;
398    
399     myDB.transaction(
400     function (transaction) {
401     transaction.executeSql("SELECT * from files where deleted=0;", [ ],
402     function (transaction, results) {
403     var filelist = '';
404     var menuDiv = document.getElementById('menuDiv');
405     if(menuDiv){
406     for(var i=0; i<results.rows.length; i++) {
407     var row = results.rows.item(i);
408     filelist = filelist + fileEntry(row);
409     }
410     if (filelist == "") {
411     filelist = "No files.<br />\n";
412     } else {
413     filelist = "<center><table class='filetable'>"+filelist+"</table></center>";
414     }
415     menuDiv.innerHTML="<H1 class='title'>"+MainTitle+"</H1>"+createMenuBar()+filelist;
416     }
417     }, errorHandler);
418     }
419     );
420     setMode('List');
421     }
422    
423     function fileSelectorOnServer(val) {
424     var filelist = '';
425     var menuDiv = document.getElementById('menuDiv');
426     var results = val.split(',');
427    
428     if(menuDiv){
429     for(var i=0; i<results.length; i++) {
430     var row = results[i];
431     filelist = filelist + fileEntryOnServer(row);
432     }
433     if (filelist == "") {
434     filelist = "No files.<br />\n";
435     } else {
436     filelist = "<center><table class='filetable'>"+filelist+"</table></center>";
437     }
438     var Menu = "<button onClick=\"fileSelector();\">Local Storage</button>";
439 isao-hara 16 Menu += "<button onClick=\"getRemoteFileList();\">List on Server</button>";
440 isao-hara 2 menuDiv.innerHTML="<H1 class='title'>"+MainTitle+"</H1>"+Menu+filelist;
441     }
442     setMode('List');
443     }
444    
445     function fileEntryOnServer(name){
446     name = name.split('.')[0];
447     var res = "<tr class='filerow'>";
448     res += "<td class='filenamecell' onClick=\"getRemoteFile('"+name+"');\">"+name+"</td>";
449     res += "<td class='filelinkcell'>";
450     res += "<button class='green' onClick=\"showRemoteFile('"+name+"');\">View</button>";
451 isao-hara 16 res += "<button onClick=\"downloadFile('"+name+"');\">Download to local storage</button>";
452     res += "<button onClick=\"downloadToFile('"+name+"');\">Download as SVG File</button>";
453 isao-hara 2 res += "</td></tr>\n";
454    
455     return res;
456     }
457    
458     function fileEntry(row){
459     var name = row['name'];
460     var files_id = row['id'];
461    
462     var res = "<tr class='filerow'>";
463     res += "<td class='filenamecell' onClick=\"showFile('"+name+"');\">"+name+"</td>";
464     res += "<td class='filelinkcell'>";
465     res += "<button class='blue' onClick=\"editFile('"+name+"');\">&nbsp;Edit&nbsp;</button> &nbsp;";
466     res += "<button class='green' onClick=\"renameFile('"+name+"',"+files_id+");\">&nbsp;Rename&nbsp;</button> &nbsp;";
467     res += "<button onClick=\"uploadFile('"+name+"');\">Upload</button>";
468     res += "<button class='red' onClick=\"deleteFile('"+name+"');\">Delete</button>";
469     res += "</td></tr>\n";
470    
471     return res;
472     }
473    
474     function createMenuBar(){
475     var menu = "<ul id='menubar'>";
476     menu += "<li><button onClick='createNewFile()'>Create New File</button></li>";
477     menu += "<li><button onClick='deleteAllFile()'>Delete All</button></li>";
478     menu += "<li><button onClick='getRemoteFileList()'>File List on a Server</button></li>";
479     menu += "</ul><p class='cls'>";
480     return menu;
481     }
482    
483     ////
484     function createNewFile(){
485     var popupDiv = document.getElementById('popup');
486     var string = "";
487    
488     string += "<H1 class='title'>Create New File</H1>\n";
489     string += "<div class=\"input_form\">\n";
490     string += "Filename:<input id='createFilename' name='name' value=\"\" />\n";
491     string += "<button onClick=\"createNewFileAction();hideItemById('popup'); \">Create</button>\n";
492     string += "<button onClick=\"hideItemById('popup'); \">Cancel</button>\n";
493     string += "</div>\n";
494    
495     popupDiv.innerHTML=string;
496     popupDiv.style.display='block';
497     }
498    
499    
500     /////
501     function renameFile(name, id){
502     var popupDiv = document.getElementById('popup');
503     var string = "";
504    
505     string += "<H1 class='title'>Rename File</H1>\n";
506     string += "<div class='input_form'>\n";
507     string += "Old Filename: "+name+"<br>";
508     string += "New Filename:<input id='newFilename' name='newname' value=\"\" />\n";
509     string += "<input type='hidden' id='fileId' value=\""+id+"\" /><br>\n";
510     string += "<button onClick=\"renameFileAction();hideItemById('popup');\">Rename</button>\n";
511     string += "<button onClick=\"hideItemById('popup'); \">Cancel</button>\n";
512     string += "</div>\n";
513    
514     popupDiv.innerHTML=string;
515     popupDiv.style.display='block';
516     }
517    
518     /// EditMenu
519     function insertStr(str, len){
520     var editarea = document.getElementById('editarea');
521     if(len < 0) len = str.length;
522    
523     if (editarea){
524     if(str=='DQ') str='"';
525     var strs = editarea.value;
526     var cPos = editarea.selectionStart;
527     var tmp = strs.substr(0,cPos);
528     editarea.value = tmp +str+strs.substr(cPos, strs.length);
529     cPos += len;
530     editarea.setSelectionRange(cPos, cPos);
531     editarea.focus();
532     }
533     }
534    
535     function insertTag(tag){
536     var str;
537     var len = -1;
538     if (tag == "p"){
539     str = "<p> </p>";
540     len = 4;
541     }else if (tag == "ul"){
542     str = "<ul class=\" \"> \n\n</ul>";
543     len = 17;
544     }else if (tag == "li"){
545     str = "<li> </li>";
546     len = 5;
547     }else if (tag == "href"){
548     str = "xlink:href=\"\"";
549     len = 12;
550     }else if (tag == "EQ"){
551     str = "=\"\"";
552     len = 2;
553     }else if (tag == "svg:text"){
554     str = "<svg:text x=\"100\" y=\"100\" fill=\"black\" font-size=\"12\"> </svg:text>";
555     len = 58;
556     }else if (tag == "svg:rect"){
557     str = "<svg:rect x=\"10\" y=\"10\" width=\"100\" height=\"100\" fill=\"white\" stroke=\"black\" />";
558     len = 13;
559     }else if (tag == "svg:circle"){
560     str = "<svg:circle cx=\"10\" cy=\"100\" r=\"100\" fill=\"white\" stroke=\"black\" strokc-width=\"1\"/>";
561     len = 17;
562     }
563     insertStr(str, len);
564     }
565    
566     function editMenuBar()
567     {
568     var str = "";
569     str += "<button onClick=\"insertStr('/',1);\">/</button>\n";
570     str += "<button onClick=\"insertStr('DQ',1);\">\"</button>\n";
571     str += "<button onClick=\"insertTag('EQ',1);\">=\"\"</button>\n";
572     str += "<button onClick=\"insertTag('p');\">p</button>\n";
573     str += "<button onClick=\"insertTag('href');\">href</button>\n";
574    
575     str += "<button onClick=\"insertTag('svg:text');\">TEXT</button>\n";
576     str += "<button onClick=\"insertTag('svg:rect');\">rect</button>\n";
577     str += "<button onClick=\"insertTag('svg:circle');\">circle</button>\n";
578    
579     str += "<button onClick=\"chEditareaHeight();\">...</button>\n";
580    
581     return str;
582     }
583    
584     function updateEditMenu(){
585     var menuDiv = document.getElementById('menuDiv');
586     menuDiv.innerHTML="<h1 class='title'>" +document.title+"</h1>\n";
587     menuDiv.innerHTML+= "<button onClick=\"saveFile();fileSelector();\"> Save </button>\n";
588     menuDiv.innerHTML+= "<button onClick=\"previewData();\"> Preview </button>\n";
589     menuDiv.innerHTML+= "<button onClick=\"fileSelector();\"> File List </button>\n";
590    
591     menuDiv.style.display='block';
592     }
593    
594     //// Editor
595     function editFileData(transaction, results){
596     var editDiv = document.getElementById('editDiv');
597     var datadiv = document.getElementById('tempdata');
598    
599     var data = results.rows.item(0);
600     var filename = data['name'];
601     var filedata = data['datablob'];
602     datadiv.setAttribute('lfdataid', parseInt(data['filedata_id']));
603    
604     var editcontent="<textarea id=\"editarea\" rows=\""+editarea_h+"\" cols=\""+editarea_w+"\">"+filedata+"</textarea>\n";
605    
606     document.title="EditFile: "+filename;
607     updateEditMenu();
608     editDiv.innerHTML = editMenuBar() +"<br>"+ editcontent;
609    
610     setMode('Edit');
611     }
612    
613     function editFile(name){
614     if(currentMode == 'Preview'){
615     var data = getSVGContent();
616     var editcontent="<textarea id=\"editarea\" rows=\""+editarea_h+"\" cols=\""+editarea_w+"\">"+data+"</textarea>\n";
617     updateEditMenu();
618     editDiv.innerHTML = editMenuBar() +"<br>"+ editcontent;
619    
620     setMode('Edit');
621     }else{
622     getFile(name, 'editFileData');
623     }
624     }
625    
626     function editCurrentFile(){
627     var datadiv = document.getElementById('tempdata');
628     var name = datadiv.getAttribute('lfname');
629    
630     editFile(name);
631     }
632    
633     // Show File
634     function updateShowMenu(){
635     var menuDiv = document.getElementById('menuDiv');
636     menuDiv.innerHTML="<h1 class='title'>" +document.title+"</h1>\n";
637     menuDiv.innerHTML+= "<button onClick=\"editCurrentFile();\"> Edit </button>\n";
638     menuDiv.innerHTML+= "<button onClick=\"saveData();\"> Save </button>\n";
639     menuDiv.innerHTML+= "<button onClick=\"fileSelector();\"> File List </button>\n";
640     menuDiv.innerHTML+= "<button onClick=\"showSVGSource();\"> &lt;SVG &gt; </button>\n";
641     menuDiv.innerHTML+= updateSVGObjMenu();
642     menuDiv.style.display='block';
643     updateToolBar();
644     }
645    
646    
647     function updateToolBar(){
648     var toolbar = document.getElementById('toolBar');
649 isao-hara 14 if(!toolbar.innerHTML){
650     toolbar.innerHTML= "<ul>";
651     toolbar.innerHTML+= "<li><button id=\"b_selector\" onClick=\"setSVGMode('selector');\"><img src=\"images/arrow.png\" /></button> </li>\n";
652     toolbar.innerHTML+= "<li><button id=\"b_newPath\" onClick=\"setSVGMode('newPath'); \"><img src=\"images/path.png\" /></button></li> \n";
653     toolbar.innerHTML+= "<li><button id=\"b_newLine\" onClick=\"setSVGMode('newLine'); \"><img src=\"images/line.png\" /> </button></li> \n";
654     toolbar.innerHTML+= "<li><button id=\"b_text\" onClick=\"setSVGMode('text'); \"><img src=\"images/text.png\" /></button> </li>\n";
655     toolbar.innerHTML+= "<li><button id=\"b_rect\" onClick=\"setSVGMode('rect'); \"> <img src=\"images/rect.png\" /> </button></li> \n";
656     toolbar.innerHTML+= "<li><button id=\"b_circle\" onClick=\"setSVGMode('circle'); \"> <img src=\"images/circle.png\" /> </button></li> \n";
657     toolbar.innerHTML+= "<li><button id=\"b_ellipse\" onClick=\"setSVGMode('ellipse'); \"> <img src=\"images/ellipse.png\" /> </button></li> \n";
658     toolbar.innerHTML+= "<li><button id=\"b_image\" onClick=\"setSVGMode('image'); \"> <img src=\"images/img.png\" /> </button></li> \n";
659     toolbar.innerHTML+= "</ul>";
660     }
661 isao-hara 2 toolbar.style.display='block';
662 isao-hara 4
663 isao-hara 2 }
664    
665     function setMode(m){
666     currentMode=m;
667     switch(m){
668     case 'List':
669     hideItemById('editDiv');
670     hideItemById('preview');
671     hideItemById('popup');
672     hideItemById('toolBar');
673 isao-hara 14 hideItemById('color-palette');
674 isao-hara 2 showItemById('menuDiv');
675     break;
676     case 'Edit':
677     hideItemById('preview');
678     hideItemById('popup');
679     hideItemById('toolBar');
680 isao-hara 14 hideItemById('color-palette');
681 isao-hara 2 showItemById('editDiv');
682     showItemById('menuDiv');
683     break;
684     case 'Preview':
685     showItemById('preview');
686     hideItemById('editDiv');
687     hideItemById('popup');
688 isao-hara 14 showItemById('color-palette');
689 isao-hara 2 showItemById('menuDiv');
690     showItemById('toolBar');
691     break;
692     default:
693     break;
694     }
695     }
696    
697     function hideItemById(id){
698     var itm = document.getElementById(id);
699     if(itm) itm.style.display='none';
700     }
701    
702     function showItemById(id){
703     var itm = document.getElementById(id);
704     if(itm) itm.style.display='block';
705     }
706    
707     function removeChildNodes(id){
708     var itm = document.getElementById(id);
709     if(!itm) return;
710    
711     var child = itm.firstChild;
712    
713     while(child){
714     itm.removeChild(child);
715     child = itm.firstChild;
716     }
717     }
718    
719     function chEditareaHeight(){
720     var itm = document.getElementById('editarea');
721     if(!itm) return;
722     var cv = itm.getAttribute('rows');
723     if(parseInt(cv) > editarea_h){
724     itm.setAttribute('rows', editarea_h);
725     }else{
726     itm.setAttribute('rows', editarea_h * 2);
727     }
728     }
729    
730     function format_file(str){
731     return "<pre>"+str+"</pre>";
732     }
733    
734     function previewData(data){
735     if(!data) data = document.getElementById('editarea').value;
736    
737     previewFile(data);
738    
739     updateShowMenu();
740     setMode('Preview');
741     }
742    
743     function previewFile(data){
744     removeChildNodes('preview');
745    
746     preview.style.display='block';
747     preview.style.position='absolute';
748     preview.style.top='180px';
749 isao-hara 14 preview.style.bottom='50px';
750     preview.style.left='0px';
751     preview.style.right='10px';
752     mkColorPalette();
753 isao-hara 2
754     var ele = toSVGElement(data, '100%','100%');
755    
756     preview.appendChild(ele);
757    
758     svg_top = document.getElementById('svg_top');
759     initSVGElementId(svg_top);
760     svg_select = createSVGObj('rect', 'x=1,y=1,width=1,height=1,visibility=hidden,stroke-dasharray=9 5', 'none', 'blue', 2);
761     svg_select.setAttribute("id","svg_select");
762     appendSVGObj(svg_select);
763 isao-hara 14 }
764 isao-hara 2
765 isao-hara 14
766    
767     function mkColorPalette(){
768     var palette = document.getElementById('color-palette');
769     if(!palette) return;
770     if(palette.innerHTML) return;
771    
772     palette.innerHTML="";
773     palette.addEventListener("touchstart", onTouchStartColor, false);
774    
775     palette.innerHTML="<select id=\"color_sel\"><option value=\"fill\">Fill</option><option value=\"stroke\">Color</option></select>";
776     for(var i=0; i<colors.length ;i++){
777     if(colors[i] == 'none')
778     palette.innerHTML +="<div class=\"item\" style=\"background-color:"+colors[i]+";\" color-val=\""+colors[i]+"\">X</div>";
779     else
780     palette.innerHTML +="<div class=\"item\" style=\"background-color:"+colors[i]+";\" color-val=\""+colors[i]+"\"> </div>";
781     }
782 isao-hara 2 }
783    
784     ////// for SVG object
785     ////////////////
786     function updateSVGObjMenu(){
787     var res = "";
788     var tag = modeSVG;
789     if(selectedItems.length > 1) return res;
790     if(selectedItems.length == 1) tag = getElementTag(selectedItems[0]);
791    
792     switch(tag){
793     case 'text':
794     if(selectedItems[0]){
795     res += setSVGObjectProp(selectedItems[0]);
796     }else{
797     res += propSVGText("", 24, '#000000');
798     }
799     break;
800     case 'rect':
801     case 'circle':
802     case 'ellipse':
803     case 'newPath':
804     case 'newLine':
805     case 'path':
806     case 'line':
807     case 'polyline':
808     case 'polygon':
809     if(selectedItems[0]){
810     res += setSVGObjectProp(selectedItems[0]);
811     }else{
812     res += propSVGObj(tag+":", 1, '#000000', '#ffffff');
813     }
814     break;
815 isao-hara 5 case 'image':
816     if(selectedItems[0]){
817     res += setSVGObjectProp(selectedItems[0]);
818     }else{
819 isao-hara 6 res += propSVGImage("", 100, 100);
820 isao-hara 5 }
821     break;
822 isao-hara 2 default:
823     break;
824     }
825     return res;
826     }
827    
828     function propSVGText(str, size, color){
829     if(!size) size = 24;
830     if(!color) color = '#000000';
831    
832     var res = "Text:";
833     res += "<input type=\"text\" id=\"svg_text\" value=\""+str+"\"/>";
834     res += "Color:<input type=\"text\" id=\"svg_color\" value=\""+color+"\" size=\"8\"/>";
835     res += "Size:<input type=\"text\" id=\"svg_size\" value=\""+size+"\" size=\"4\"/>";
836     return res;
837     }
838    
839     function propSVGObj(type, stroke, color, fill){
840     var res = type;
841     if(!stroke) stroke = 1;
842     if(!color) color = '#000000';
843     if(!fill) fill = '#ffffff';
844     res += "Fill:<input type=\"text\" id=\"svg_fill\" value=\""+fill+"\" size=\"8\"/>";
845     res += "Color:<input type=\"text\" id=\"svg_color\" value=\""+color+"\" size=\"8\"/>";
846     res += "L:<input type=\"text\" id=\"svg_stroke\" value=\""+stroke+"\" size=\"2\"/>";
847     return res;
848     }
849    
850     function propSVGLine(type, stroke, color, fill, style){
851     var res = propSVGObj(type, stroke, color, fill);
852 isao-hara 14 if(style==null) style="";
853 isao-hara 2 res += "Type:<input type=\"text\" id=\"svg_stroke_type\" value=\""+style+"\" size=\"8\"/>";
854     res += "Arrow:";
855     if(hasArrow('start')){
856 isao-hara 14 res += "<button class=\"tool\" onClick=\"removeLeftArrow();\"><img src=\"images/normal.png\" /></button>";
857 isao-hara 2 }else{
858 isao-hara 14 res += "<button class=\"tool\" onClick=\"setLeftArrow();\"><img src=\"images/larrow.png\" /></button>";
859 isao-hara 2 }
860     if(hasArrow('end')){
861 isao-hara 14 res += "<button class=\"tool\" onClick=\"removeRightArrow();\"><img src=\"images/normal.png\" /></button>";
862 isao-hara 2 }else{
863 isao-hara 14 res += "<button class=\"tool\" onClick=\"setRightArrow();\"><img src=\"images/rarrow.png\" /></button>";
864 isao-hara 2 }
865     return res;
866     }
867    
868 isao-hara 5 function propSVGImage(str, w, h){
869     var res = "image:";
870     res += "<input type=\"text\" id=\"svg_text\" value=\""+str+"\" />";
871     res += "Width:<input type=\"text\" id=\"svg_w\" value=\""+w+"\" size=\"4\"/>";
872     res += "Height:<input type=\"text\" id=\"svg_h\" value=\""+h+"\" size=\"4\"/>";
873     return res;
874     }
875    
876 isao-hara 2 function setSVGMode(m){
877 isao-hara 14 var btn = document.getElementById('b_'+modeSVG);
878     if(btn){ btn.style.border="1px solid black"; }
879    
880 isao-hara 2 modeSVG = m;
881     updateShowMenu();
882 isao-hara 4
883 isao-hara 2 if(m == 'selector'){
884     targetItem=null;
885     clearSelectedItems();
886     }
887 isao-hara 4
888     var btn = document.getElementById('b_'+modeSVG);
889 isao-hara 14 if(btn){ btn.style.border="3px solid red"; }
890 isao-hara 2 }
891    
892    
893     function toSVGElement(str, w, h){
894     var xmlsvg = "xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"";
895     var parser = new DOMParser();
896     var header = "<svg:svg width=\""+w+"\" height=\""+h+"\" "+xmlsvg+" id=\"svg_top\">";
897     var footer = "</svg:svg>";
898     var xmlDoc = parser.parseFromString(header+str+footer, "text/xml");
899     var xmlRoot = xmlDoc.documentElement;
900     var ele = document.importNode(xmlRoot,true);
901    
902     return ele;
903     }
904    
905     function createSVGElement(tag, id){
906     if(id=='new'){
907     id = 'svg_'+nextId;
908     nextId++;
909     }
910     var ele= document.createElementNS(svg_ns, tag);
911     ele.setAttribute("id", id);
912     return ele;
913     }
914    
915     function defSVGElement(node){
916     if(!svg_defs) svg_defs = document.getElementById('svg_defs');
917     if(!svg_defs){
918     svg_defs = createSVGElement('defs', 'svg_defs');
919     svg_top.insertBefore(svg_defs, svg_top.firstChild);
920     }
921     if(node) svg_defs.appendChild(node);
922     }
923    
924     function initSVGElementId(svg_top){
925     nextId = 1;
926     checkSVGElementId(svg_top);
927     appendSVGElementId(svg_top);
928     }
929    
930     function checkSVGElementId(top){
931     var objs = top.childNodes;
932    
933     for(var i=0; i<objs.length ;i++){
934     if(objs[i].tagName){
935     var id = objs[i].getAttribute("id");
936    
937     if(id && id.match(/svg_[0-9]+/i)){
938     var n = parseInt(RegExp.lastMatch.substr(4));
939     if(n >= nextId){
940     nextId = n+1;
941     }
942    
943     }
944     checkSVGElementId(objs[i]);
945     }
946     }
947     }
948    
949     function appendSVGElementId(top){
950     var objs = top.childNodes;
951    
952     for(var i=0; i<objs.length ;i++){
953     if(objs[i].tagName){
954     var id = objs[i].getAttribute("id");
955     if(!id){
956     objs[i].setAttribute("id", "svg_"+nextId);
957     nextId++;
958     }
959     }
960     appendSVGElementId(objs[i]);
961     }
962     }
963    
964     function selectedRectangle(x, y, ex, ey){
965     if(!svg_select) return null;
966    
967     svg_select.setAttribute("x",x);
968     svg_select.setAttribute("y",y);
969     svg_select.setAttribute("width", ex-x);
970     svg_select.setAttribute("height", ey-y);
971     svg_select.setAttribute("visibility", "visible");
972     return svg_select;
973     }
974    
975    
976     function setAttributes(obj, attrs){
977     var attr_array = attrs.split(',');
978    
979     for (var i=0; i<attr_array.length;i++){
980     var x = attr_array[i].split('=');
981     if(x.length == 2){
982     obj.setAttribute(x[0], x[1]);
983     }
984     }
985     }
986    
987     function createSVGObj(tag, attrs, fill, color, lw){
988     var ele = createSVGElement(tag, 'new');
989     setAttributes(ele, attrs);
990     if (fill) ele.setAttribute('fill', fill);
991     if (color) ele.setAttribute('stroke', color);
992     if(lw) ele.setAttribute('stroke-width', lw);
993    
994     return ele;
995     }
996    
997     function createSVGText(txt, x, y, size, color){
998     var ele = createSVGElement('text', 'new');
999    
1000     ele.setAttribute('x', x);
1001     ele.setAttribute('y', y);
1002     ele.setAttribute('font-size', size);
1003     ele.setAttribute('fill', color);
1004     ele.textContent=txt;
1005    
1006     return ele;
1007     }
1008    
1009     function createSVGImage(fname, width, height, attrs){
1010     var ele = createSVGElement('image', 'new');
1011 isao-hara 7 ele.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', fname);
1012 isao-hara 2 ele.setAttribute('width', width);
1013     ele.setAttribute('height', height);
1014     setAttributes(ele, attrs);
1015    
1016     return ele;
1017     }
1018    
1019     function createSVGMarker(pid, id, child){
1020     var parent = document.getElementById(pid);
1021     if(!parent) return;
1022     var ele = createSVGElement('marker', pid+'_'+id);
1023     ele.appendChild(child);
1024     return ele;
1025     }
1026    
1027     function setLeftArrow(){
1028     if( selectedItems.length == 1 ){
1029     setArrow(selectedItems[0], 'start', '');
1030     }
1031     }
1032    
1033     function setRightArrow(){
1034     if( selectedItems.length == 1 ){
1035     setArrow(selectedItems[0], 'end', '');
1036     }
1037     }
1038    
1039     function removeLeftArrow(){
1040     if( selectedItems.length == 1 ){
1041     if(!svg_defs) svg_defs = document.getElementById('svg_defs');
1042     var pid = selectedItems[0].getAttribute('id');
1043     var marker = document.getElementById(pid+'_startarrow');
1044     svg_defs.removeChild(marker);
1045     selectedItems[0].removeAttribute('marker-start');
1046     }
1047     }
1048    
1049     function removeRightArrow(){
1050     if( selectedItems.length == 1 ){
1051     if(!svg_defs) svg_defs = document.getElementById('svg_defs');
1052     var pid = selectedItems[0].getAttribute('id');
1053     var marker = document.getElementById(pid+'_endarrow');
1054     svg_defs.removeChild(marker);
1055     selectedItems[0].removeAttribute('marker-end');
1056     }
1057     }
1058    
1059     function hasArrow(pos){
1060     var pobj = selectedItems[0];
1061     if(!pobj) return false;
1062     var pid = pobj.getAttribute('id');
1063     var marker = document.getElementById(pid+'_'+pos+'arrow');
1064     if(marker) return true;
1065     return false;
1066     }
1067    
1068     function getArrowMarker(obj,pos){
1069     if(!obj) return false;
1070     var pid = obj.getAttribute('id');
1071     var marker = document.getElementById(pid+'_'+pos+'arrow');
1072     return false;
1073     }
1074    
1075     function setArrow(pobj, pos, type){
1076     if(!pobj) return;
1077     var pid = pobj.getAttribute('id');
1078     var marker = document.getElementById(pid+'_'+pos+'arrow');
1079     if(marker) return;
1080    
1081     var obj = createSVGElement('path', 'new');
1082    
1083     var refX = 0;
1084     var refY = 0;
1085    
1086     switch(pos){
1087     case 'start':
1088     refX=10;
1089     refY=10;
1090     setAttributes(obj,'d=M 20 0 L 0 10 20 20 Z');
1091     break;
1092     case 'end':
1093     setAttributes(obj,'d=M 0 0 L 20 10 0 20 Z');
1094     refX= 10;
1095     refY=10;
1096     break;
1097     default:
1098     return;
1099     }
1100    
1101     marker = createSVGMarker(pid, pos+'arrow' , obj);
1102     setAttributes(marker,'markerWidth=10,markerHeight=10,orient=auto,viewBox=0 0 20 20,markerUnits=strokeWidth,refX='+refX+',refY='+refY);
1103    
1104     marker.setAttribute("fill",pobj.getAttribute("stroke"));
1105    
1106     defSVGElement(marker);
1107     var mid = "url(#"+marker.getAttribute("id")+")";
1108     var mattr = "marker-"+pos;
1109     pobj.setAttribute(mattr, mid);
1110     }
1111    
1112     function appendSVGObj(obj){
1113     var svg_top = document.getElementById('svg_top');
1114     if(!svg_top) return;
1115    
1116     svg_top.appendChild(obj);
1117     }
1118    
1119     function isChildById(element, id) {
1120     if (element == null || element.parentNode == null || element.parentNode.nodeName=='BODY') return false;
1121     else if (element.parentNode.id == id) return true;
1122     else return isChildById(element.parentNode, id);
1123     }
1124    
1125     /////////////////////// Formatting SVG DOM
1126     function escapeHTML(text) {
1127     return text.replace( /[<>"&]/g,
1128     function (m) { return { '<': '&lt;', '>': '&gt;', '"': '&quot;', '&': '&amp;' }[m]; }
1129     );
1130     };
1131    
1132     function formatTag(ele){
1133     var str="";
1134     if(ele.nodeType == 1){
1135     var tag_a = ele.tagName.split(':');
1136     var tag;
1137     if(tag_a.length == 1){ tag = "svg:"+tag_a[0]; }else{ tag = ele.tagName; }
1138    
1139     str += "<"+tag;
1140     var attrs = ele.attributes;
1141     for(var i=0; i<attrs.length; i++){
1142     str += " "+attrs[i].nodeName+"=\""+attrs[i].nodeValue+"\"";
1143     }
1144     var cn = ele.childNodes;
1145     if(cn.length > 0){
1146     str +=">\n";
1147     for(var i=0; i<cn.length; i++){
1148 isao-hara 13 var tmp = trim(formatTag(cn[i]));
1149     if(tmp) str += " "+tmp+"\n";
1150 isao-hara 2 }
1151     str += "</"+tag+">";
1152     }else{
1153     str +=" />";
1154     }
1155     return str;
1156     }else if(ele.nodeType==3){
1157     return ele.textContent;
1158     }
1159     }
1160    
1161     function getSVGContent(){
1162     if(!svg_top) return "";
1163    
1164     var str = "";
1165     var elements = svg_top.childNodes;
1166     for(var i=0; i<elements.length; i++){
1167 isao-hara 12 if(elements[i] != svg_select){
1168     var tmp = trim(formatTag(elements[i]));
1169     if(tmp) str += tmp + '\n';
1170     }
1171 isao-hara 2 }
1172     return str;
1173     }
1174    
1175     function trim(str){
1176     return str.replace(/(^\s+)|(\s+$)/g, "");
1177     }
1178    
1179     /////// Access Server
1180     function newXMLRequest(){
1181     if(this.XMLHttpRequest){
1182     return new XMLHttpRequest();
1183     }else {
1184     return new ActiveXObject("Microsoft.XMLHTTP");
1185     }
1186     }
1187    
1188     function createRequestData(data){
1189     var str="filetype=svg";
1190     for (var i in data){
1191     str = str +"&"+ i +"="+encodeURIComponent(data[i]);
1192     }
1193     return str;
1194     }
1195    
1196     function postRequest(url, data, func){
1197     var postData=createRequestData(data);
1198     var obj=newXMLRequest();
1199    
1200     obj.onreadystatechange = function(){
1201     if (obj.readyState == 4 && obj.status == 200){
1202     func(obj.responseText);
1203     }
1204     }
1205     obj.open("POST", url, true);
1206     obj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
1207     obj.send(postData);
1208     }
1209    
1210     function commnadFinishAlert(s){
1211     alert(s);
1212     }
1213    
1214     function uploadFileData(transaction, results){
1215     var data = results.rows.item(0);
1216     var updata = new Array(0);
1217     updata['name']= data['name'];
1218     updata['datalob'] = data['datablob'];
1219     updata['cmd'] = 'upload'
1220    
1221     postRequest(MgrPath+iSlideMgr, updata, commnadFinishAlert);
1222     }
1223    
1224     function uploadFile(name){
1225     getFile(name, 'uploadFileData');
1226     }
1227    
1228     function getRemoteFileList(){
1229     var data=new Array();
1230     data['name'] = "SVG";
1231     data['cmd'] = "list";
1232     postRequest(MgrPath+iSlideMgr, data, fileSelectorOnServer);
1233     }
1234    
1235     function previewRemoteFile(content){
1236     previewFile(content);
1237     setMode('Preview');
1238     }
1239    
1240     function getRemoteFile(name){
1241     var data=new Array();
1242     data['name'] = name;
1243     data['cmd'] = "get";
1244     postRequest(MgrPath+iSlideMgr, data, previewRemoteFile);
1245     }
1246    
1247 isao-hara 16 function saveRemoteFile(content){
1248     // saveContenByFilename(content);
1249     alert("not implemented");
1250     }
1251    
1252     function downloadFile(name){
1253     var data=new Array();
1254     data['name'] = name;
1255     data['cmd'] = "get";
1256     var datadiv = document.getElementById('tempdata');
1257     datadiv.setAttribute('lfname', name);
1258     postRequest(MgrPath+iSlideMgr, data, saveRemoteFile);
1259     }
1260    
1261 isao-hara 2 function showRemoteFile(name){
1262     getRemoteFile(name);
1263     }
1264    
1265 isao-hara 16 function downloadToFile(name){
1266     var downloadForm = "";
1267     downloadForm += "<form action=\"iSlideManager.php\" method=\"post\">";
1268     downloadForm += "<input type=\"hidden\" name=\"cmd\" value=\"download\">";
1269     downloadForm += "<input type=\"hidden\" name=\"name\" value=\""+name+"\">";
1270     downloadForm += "<input type=\"hidden\" name=\"filetype\" value=\"svg\">";
1271     downloadForm += "<input type=\"submit\">";
1272     downloadForm += "</form>";
1273    
1274     var cmdForm = document.getElementById('cmdForm');
1275     cmdForm.innerHTML = downloadForm;
1276     cmdForm.firstChild.submit();
1277     }
1278    
1279 isao-hara 2 //////// Event Handler
1280     function setInnerHTML(id, val){
1281     var itm=document.getElementById(id);
1282     if(itm) itm.innerHTML=val;
1283     }
1284    
1285     function popupInfo(val){
1286     var str="<button onClick=\"hideItemById('popup');\">Close</button><hr> ";
1287     str += val;
1288     setInnerHTML('popup', str);
1289     showItemById('popup');
1290     }
1291    
1292     function addAttributeVal(obj, itm, dv){
1293     if(obj.hasAttribute(itm)){
1294     var x = parseInt(obj.getAttribute(itm));
1295     x = x + dv;
1296     obj.setAttribute(itm, x)
1297     }
1298     }
1299    
1300     function showSVGSource(){
1301     var str = getSVGContent();
1302 isao-hara 14 var escstr="<button onClick=\"hideItemById('popup');\">Close</button>";
1303     escstr+="<button onClick=\"saveContent(document.getElementById('ContentView').value); previewData(document.getElementById('ContentView').value);\">Save</button><hr> ";
1304     // escstr += "<pre>"+escapeHTML(str)+"</pre>";
1305     escstr += "<textarea cols=\"130\" rows=\"30\" id=\"ContentView\">"+str+"</textarea>";
1306 isao-hara 2 setInnerHTML('popup', escstr);
1307     showItemById('popup');
1308     }
1309    
1310    
1311     function getElementTag(obj){
1312 isao-hara 6 if (!obj) return null;
1313 isao-hara 2 var tag = obj.tagName.split(':');
1314     if(tag.length == 2 && tag[0]=='svg') return tag[1];
1315     return tag[0];
1316     }
1317    
1318     function setSVGObjectProp(obj){
1319     var tag = getElementTag(obj);
1320     var res ="";
1321     switch(tag){
1322     case 'text':
1323     res = propSVGText(obj.textContent, obj.getAttribute("font-size"), obj.getAttribute("fill"));
1324     break;
1325     case 'rect':
1326     case 'circle':
1327     case 'ellipse':
1328     res = propSVGObj(tag+":", obj.getAttribute("stroke-width"), obj.getAttribute("stroke"), obj.getAttribute("fill"));
1329     break;
1330     case 'path':
1331     case 'line':
1332     res = propSVGLine(tag+":",obj.getAttribute("stroke-width"),
1333     obj.getAttribute("stroke"),obj.getAttribute("fill"), obj.getAttribute("stroke-dasharray"));
1334     break;
1335 isao-hara 5 case 'image':
1336     res = propSVGImage(obj.getAttribute("xlink:href"),obj.getAttribute("width"),obj.getAttribute("height"));
1337     break;
1338 isao-hara 2 default:
1339     break;
1340     }
1341     if(res != ""){
1342     res += "<button onClick=\"updateSVGObj();\">OK</button>";
1343     res += "<button onClick=\"delSVGObj();\">Del</button>";
1344     }
1345    
1346     return res
1347     }
1348    
1349     function updateSVGObj(){
1350     if(selectedItems.length != 1) return;
1351     var obj = selectedItems[0];
1352     var tag = getElementTag(obj);
1353     var res ="";
1354     switch(tag){
1355     case 'text':
1356     var txt=document.getElementById('svg_text');
1357     var color=document.getElementById('svg_color');
1358     var size=document.getElementById('svg_size');
1359     obj.textContent = txt.value;
1360     obj.setAttribute("fill", color.value);
1361     obj.setAttribute("font-size", size.value);
1362     break;
1363     case 'rect':
1364     case 'circle':
1365     case 'ellipse':
1366     var fill=document.getElementById('svg_fill');
1367     var color=document.getElementById('svg_color');
1368     var L=document.getElementById('svg_stroke');
1369     obj.setAttribute("fill", fill.value);
1370     obj.setAttribute("stroke", color.value);
1371     obj.setAttribute("stroke-width", L.value);
1372     break;
1373     case 'path':
1374     case 'line':
1375     var fill=document.getElementById('svg_fill');
1376     var color=document.getElementById('svg_color');
1377     var L=document.getElementById('svg_stroke');
1378     var dash=document.getElementById('svg_stroke_type');
1379     obj.setAttribute("fill", fill.value);
1380     obj.setAttribute("stroke", color.value);
1381     obj.setAttribute("stroke-width", L.value);
1382     if(dash) obj.setAttribute("stroke-dasharray", dash.value);
1383     var id = obj.getAttribute("id");
1384     var marker = document.getElementById(id+'_startarrow');
1385     if(marker) marker.setAttribute("fill", color.value);
1386     var marker = document.getElementById(id+'_endarrow');
1387     if(marker) marker.setAttribute("fill", color.value);
1388     break;
1389 isao-hara 5 case 'image':
1390     var fname=document.getElementById('svg_text');
1391     var w=document.getElementById('svg_w');
1392     var h=document.getElementById('svg_h');
1393 isao-hara 6 obj.setAttribute("xlink:href", fname.value);
1394 isao-hara 5 obj.setAttribute("width", w.value);
1395     obj.setAttribute("height", h.value);
1396     break;
1397 isao-hara 2 default:
1398     break;
1399     }
1400    
1401     }
1402    
1403     function delSVGObj(){
1404     if(selectedItems.length != 1) return;
1405     var obj = selectedItems[0];
1406    
1407     if(!svg_top) return;
1408     svg_top.removeChild(obj);
1409     svg_select.setAttribute("visibility","hidden");
1410     }
1411    
1412     ///// For MobileSafari
1413     function getPreviewX(x){ return x - preview.offsetLeft; }
1414     function getPreviewY(y){ return y - preview.offsetTop; }
1415    
1416     function calcDit(x1, y1, x2, y2){
1417     return (x1-x2)*(x1-x2) +(y1-y2)*(y1-y2);
1418     }
1419    
1420     function isIncludeEllipse( x1, y1, cx, cy, rx, ry){
1421     return ((x1-cx)*(x1-cx)/rx/rx +(y1-cy)*(y1-cy)/ry/ry) < 1;
1422     }
1423    
1424     function getAttributeVal(obj, name){
1425     try{
1426     return parseInt(obj.getAttribute(name));
1427     }catch(e){ return 0; }
1428     }
1429    
1430     function checkIntersection(obj, x, y, ex, ey){
1431     var res = true;
1432     var bbox = obj.getBBox();
1433     var ox = bbox.x;
1434     var oy = bbox.y;
1435     var oex = bbox.x+bbox.width;
1436     var oey = bbox.y+bbox.height;
1437     if( ex < ox || oex < x || ey < oy || oey < y) res = false;
1438    
1439     var tag = getElementTag(obj);
1440     switch(tag){
1441     case 'circle':
1442     case 'ellipse':
1443     var cx = getAttributeVal(obj,"cx");
1444     var cy = getAttributeVal(obj,"cy");
1445     var rx = getAttributeVal(obj,"r");
1446     var ry = rx;
1447     if(!rx){
1448     var rx = getAttributeVal(obj,"rx");
1449     var ry = getAttributeVal(obj,"ry");
1450     }
1451    
1452     if(res){
1453     if(cx <x && cy < y && !isIncludeEllipse(x,y,cx,cy,rx,ry)) res=false;
1454     else if(cx < x && cy > ey && !isIncludeEllipse(x,ey,cx,cy,rx,ry)) res=false;
1455     else if(cx > ex && cy > ey && !isIncludeEllipse(ex,ey,cx,cy,rx,ry)) res=false;
1456     else if(cx > ex && cy < y && !isIncludeEllipse( ex,y,cx,cy,rx,ry)) res=false;
1457     }
1458     break;
1459     case 'path':
1460     var d = obj.getAttribute("d");
1461     var p = getPoints(d);
1462     for(var i=0;i<p.length;i++){
1463     var ox=p[i][0];
1464     var oy=p[i][1];
1465     if(x < ox && ox < ex && y < oy && oy < ey) {
1466     return true;
1467     }
1468     }
1469     return false;
1470     break;
1471     case 'line':
1472     var x1 = getAttributeVal(obj,"x1");
1473     var y1 = getAttributeVal(obj,"y1");
1474     var x2 = getAttributeVal(obj,"x2");
1475     var y2 = getAttributeVal(obj,"y2");
1476 isao-hara 3 var d = (y2-y1)/(x2-x1);
1477    
1478     if(res){
1479     var xx = Math.abs(x2-x1);
1480     var sign = 1;
1481     if(x2-x1 < 0){ sign = -1; }
1482     for(var i=0; i < xx; i++){
1483     var nx = i*sign + x1;
1484     var ny = d * i*sign + y1;
1485     if(x < nx && nx < ex && y < ny && ny < ey) return true;
1486     }
1487     }
1488 isao-hara 2 return false;
1489    
1490 isao-hara 3 return res;
1491 isao-hara 2 break;
1492     case 'text':
1493     case 'rect':
1494     case 'polygon':
1495     case 'polyline':
1496     case 'image':
1497     break;
1498     default:
1499     res=false;
1500     break;
1501     }
1502     return res;
1503     }
1504    
1505     function getBoundingBox(obj){
1506     var res = new Array(4);
1507     var bbox = obj.getBBox();
1508     res[0] = bbox.x-1;
1509     res[1] = bbox.y-1;
1510     res[2] = bbox.x+bbox.width+2;
1511     res[3] = bbox.y+bbox.height+2;
1512     return res;
1513     }
1514    
1515     function setSelectBox(){
1516     if(!svg_select) return;
1517    
1518     if(selectedItems.length == 0){
1519     svg_select.setAttribute("visibility","hidden");
1520     return;
1521     }
1522    
1523     var bbox = new Array(4);
1524     bbox[0] = 1000;
1525     bbox[1] = 1000;
1526     bbox[2] = 0;
1527     bbox[3] = 0;
1528    
1529     for(var i=0;i<selectedItems.length;i++){
1530     var bp = getBoundingBox(selectedItems[i]);
1531     if(bp[0] < bbox[0]) bbox[0]=bp[0];
1532     if(bp[1] < bbox[1]) bbox[1]=bp[1];
1533     if(bp[2] > bbox[2]) bbox[2]=bp[2];
1534     if(bp[3] > bbox[3]) bbox[3]=bp[3];
1535     }
1536     svg_select.setAttribute("x", bbox[0]);
1537     svg_select.setAttribute("y", bbox[1]);
1538     svg_select.setAttribute("width", bbox[2] - bbox[0]);
1539     svg_select.setAttribute("height", bbox[3] - bbox[1]);
1540     svg_select.setAttribute("visibility","visible;");
1541     }
1542    
1543     function getSelectedObjects(x1, y1, x2, y2){
1544     if(x1 > x2) { var tmp = x1; x1=x2; x2=tmp; }
1545     if(y1 > y2) { var tmp = y1; y1=y2; y2=tmp; }
1546    
1547 isao-hara 3 var val="";
1548 isao-hara 2 if(svg_top){
1549     var val ="";
1550     var objs = svg_top.childNodes;
1551     selectedItems = new Array();
1552     for(var i=0; i<objs.length;i++){
1553     if(objs[i].tagName){
1554 isao-hara 3
1555 isao-hara 2 if(objs[i] != svg_select && checkIntersection(objs[i], x1, y1, x2, y2)){
1556     selectedItems.push(objs[i]);
1557     }
1558 isao-hara 3 val += objs[i].tagName+" ";
1559 isao-hara 2 }
1560     }
1561     }
1562     setSelectBox();
1563     }
1564    
1565     function onTouchStart(e){
1566     //e.preventDefault();
1567     sx=e.touches[0].pageX;
1568     sy=e.touches[0].pageY;
1569     ex=e.touches[0].pageX;
1570     ey=e.touches[0].pageY;
1571    
1572     if (e.touches.length == 1){
1573     if((!modeSVG || modeSVG == 'selector') && selectedItems.length == 0){ // Selector Mode
1574     var x1=getPreviewX(sx-1);
1575     var y1=getPreviewY(sy-1);
1576     var x2=getPreviewX(sx+2);
1577     var y2=getPreviewY(sy+2);
1578     getSelectedObjects(x1, y1, x2, y2);
1579    
1580     if(selectedItems.length == 0){
1581     setSVGMode('selector');
1582     }else if(selectedItems.length == 1){
1583     targetItem=selectedItems[0];
1584     setSVGMode(getElementTag(targetItem));
1585     }else{
1586     setSVGMode('Group');
1587     }
1588     }else { // CreateMode
1589     if(selectedItems.length == 0){
1590    
1591     var fill=document.getElementById('svg_fill');
1592     var color=document.getElementById('svg_color');
1593     var L=document.getElementById('svg_stroke');
1594    
1595     var x = getPreviewX(sx);
1596     var y = getPreviewY(sy);
1597    
1598     switch(modeSVG){
1599     case 'text':
1600     var txt=document.getElementById('svg_text');
1601     var size=document.getElementById('svg_size');
1602     var y = y + parseInt(size.value)*0.8;
1603     if(txt.value) targetItem=createSVGText(txt.value, x, y, size.value, color.value);
1604     break;
1605     case 'rect':
1606     var attr = 'x='+x+',y='+y+',width='+svg_width+',height='+svg_height;
1607     targetItem=createSVGObj(modeSVG,attr, fill.value, color.value, L.value);
1608     break;
1609     case 'circle':
1610     var attr = 'cx='+x+',cy='+y+',r='+svg_rx;
1611     targetItem=createSVGObj(modeSVG,attr, fill.value, color.value, L.value);
1612     break;
1613     case 'ellipse':
1614     var attr = 'cx='+x+',cy='+y+',rx='+svg_rx+',ry='+svg_ry;
1615     targetItem=createSVGObj(modeSVG,attr, fill.value, color.value, L.value);
1616     break;
1617     case 'newPath':
1618     var attr = 'd=M '+x+' '+y+' L '+x+' '+y;
1619     targetItem=createSVGObj('path' ,attr, 'none', color.value, L.value);
1620     break;
1621     case 'newLine':
1622     var x2=x+1;
1623     var attr = 'x1='+x+',y1='+y+',x2='+x2+',y2='+y;
1624     targetItem=createSVGObj('line' ,attr, 'none', color.value, L.value);
1625 isao-hara 6 break;
1626 isao-hara 5 case 'image':
1627     var attr = 'x='+x+',y='+y;
1628     var txt=document.getElementById('svg_text');
1629     var w=document.getElementById('svg_w');
1630     var h=document.getElementById('svg_h');
1631     if(txt.value) targetItem=createSVGImage(txt.value ,w.value, h.value, attr);
1632 isao-hara 2 default:
1633     break;
1634     }
1635     if (targetItem){
1636     appendSVGObj(targetItem);
1637     selectedItems[0]=targetItem;
1638     }
1639     }else{
1640     var x1=getPreviewX(sx-1);
1641     var y1=getPreviewY(sy-1);
1642     var x2=getPreviewX(sx+2);
1643     var y2=getPreviewY(sy+2);
1644     if(!checkIntersection(svg_select, x1, y1, x2, y2)){
1645     setSVGMode('selector');
1646     }
1647     }
1648     }
1649     }
1650    
1651 isao-hara 6 updateSelectedRectangle();
1652 isao-hara 2 }
1653    
1654     function getPoints(d){
1655     var p = d.split(' ');
1656     var res = new Array();
1657     var isx=true;
1658     var x, y;
1659     for(var i=0; i<p.length;i++){
1660     if(p[i].match('[MLHVCSQTA]','i')){
1661     }else{
1662     if(isx){
1663     x = parseInt(p[i]);
1664     }else{
1665     y = parseInt(p[i]);
1666     res.push(new Array(x, y));
1667     }
1668     isx = !isx;
1669     }
1670     }
1671     return res;
1672     }
1673    
1674     function updatePath(d, x, y){
1675     var p = d.split(' ');
1676     var res = "";
1677     var isx=true;
1678     var val;
1679     for(var i=0; i<p.length;i++){
1680     if(p[i].match('[MLHVCSQTA]','i')){
1681     res += ' '+p[i];
1682     }else{
1683     if(isx){
1684     val = parseInt(p[i])+x;
1685     }else{
1686     val = parseInt(p[i])+y;
1687     }
1688    
1689     res += ' '+ val;
1690     isx = !isx;
1691     }
1692     }
1693     return trim(res);
1694     }
1695    
1696     function updateTransform(obj){
1697     try{
1698     var trans = obj.getAttribute("transform");
1699     if(!trans) return;
1700     if(trans.match(new RegExp("translate(.+,.+)","i"))){
1701     var str = RegExp.lastMatch;
1702     var vals = str.substr(10,str.length-11).split(',') ;
1703     var dx = parseInt(vals[0]);
1704     var dy = parseInt(vals[1]);
1705     switch(getElementTag(obj)){
1706     case 'text':
1707     case 'rect':
1708 isao-hara 6 case 'image':
1709 isao-hara 2 addAttributeVal(obj, "x", dx);
1710     addAttributeVal(obj, "y", dy);
1711     break;
1712     case 'circle':
1713     case 'ellipse':
1714     addAttributeVal(obj, "cx", dx);
1715     addAttributeVal(obj, "cy", dy);
1716     break;
1717    
1718     case 'path':
1719     var path = obj.getAttribute("d");
1720     obj.setAttribute("d", updatePath(path, dx, dy));
1721     break;
1722     case 'line':
1723     var x1 = getAttributeVal(obj,"x1");
1724     var y1 = getAttributeVal(obj,"y1");
1725     var x2 = getAttributeVal(obj,"x2");
1726     var y2 = getAttributeVal(obj,"y2");
1727     obj.setAttribute("x1", x1+dx);
1728     obj.setAttribute("y1", y1+dy);
1729     obj.setAttribute("x2", x2+dx);
1730     obj.setAttribute("y2", y2+dy);
1731    
1732     break;
1733     default:
1734     break;
1735     }
1736     obj.removeAttribute("transform");
1737     }
1738     }catch (e){
1739     }
1740     }
1741    
1742     function moveSelectedRectangle(dx, dy){
1743     if(!svg_select) return;
1744     svg_select.setAttribute("transform","translate("+dx+","+dy+")");
1745     }
1746    
1747     function updateSelectedRectangle(){
1748     if(!svg_select) return;
1749     if(selectedItems.length > 0){
1750     svg_select.setAttribute("visibility","visible;");
1751     }else{
1752     svg_select.setAttribute("visibility","hidden;");
1753     }
1754     }
1755    
1756     function clearSelectedItems(){
1757     for(i in selectedItems) delete selectedItems[i];
1758     }
1759    
1760     function onTouchMove(e){
1761 isao-hara 4 e.preventDefault();
1762     if (e.touches.length == 1){
1763     if(targetItem || selectedItems.length > 0){
1764     switch(modeSVG){
1765     case 'newPath':
1766     if(targetItem.tagName == 'path' ){
1767     var path = targetItem.getAttribute("d");
1768     path = path + ' '+ getPreviewX(e.touches[0].pageX) + ' '+ getPreviewY(e.touches[0].pageY) ;
1769     targetItem.setAttribute("d",path);
1770     }
1771     break;
1772     case 'newLine':
1773     if(targetItem.tagName == 'line' ){
1774     var x2 = getPreviewX(e.touches[0].pageX);
1775     var y2 = getPreviewY(e.touches[0].pageY);
1776     targetItem.setAttribute("x2",x2);
1777     targetItem.setAttribute("y2",y2);
1778     }
1779     break;
1780 isao-hara 2
1781 isao-hara 4 default:
1782     var dx = e.touches[0].pageX - sx;
1783     var dy = e.touches[0].pageY - sy;
1784 isao-hara 2
1785 isao-hara 4 if(selectedItems.length == 1 && getElementTag(selectedItems[0]) == 'line'){
1786     var lx = getPreviewX(e.touches[0].pageX);
1787     var ly = getPreviewY(e.touches[0].pageY);
1788 isao-hara 2
1789 isao-hara 4 if(!lineEdit){
1790     var x1 = getAttributeVal(selectedItems[0],"x1");
1791     var y1 = getAttributeVal(selectedItems[0],"y1");
1792     var x2 = getAttributeVal(selectedItems[0],"x2");
1793     var y2 = getAttributeVal(selectedItems[0],"y2");
1794     var xc = (x1+x2)/2;
1795     var yc = (y1+y2)/2;
1796     var eS = Math.min(Math.abs(x1-lx), Math.abs(y1-ly));
1797     var eC = Math.min(Math.abs(xc-lx), Math.abs(yc-ly));
1798     var eE = Math.min(Math.abs(x2-lx), Math.abs(y2-ly));
1799 isao-hara 2
1800 isao-hara 4 var minVal = Math.min(eS, Math.min(eC, eE));
1801     if(minVal == eS) lineEdit='start';
1802     else if(minVal == eE) lineEdit='end';
1803     else lineEdit='move';
1804     }
1805     if(lineEdit=='start'){
1806     selectedItems[0].setAttribute("x1",lx );
1807     selectedItems[0].setAttribute("y1",ly );
1808     setSelectBox();
1809     }else if(lineEdit == 'end'){
1810     selectedItems[0].setAttribute("x2",lx );
1811     selectedItems[0].setAttribute("y2",ly );
1812     setSelectBox();
1813     }else{
1814     selectedItems[0].setAttribute("transform","translate("+dx+","+dy+")");
1815     moveSelectedRectangle(dx, dy);
1816     }
1817     }else{
1818     for(var i=0; i<selectedItems.length;i++){
1819     selectedItems[i].setAttribute("transform","translate("+dx+","+dy+")");
1820     }
1821     moveSelectedRectangle(dx, dy);
1822     }
1823     break;
1824     }
1825     updateShowMenu();
1826     }else if(modeSVG == 'selector'){
1827     ex = e.touches[0].pageX;
1828     ey = e.touches[0].pageY;
1829     var x1=sx;
1830     var y1=sy;
1831     var x2=ex;
1832     var y2=ey;
1833 isao-hara 2
1834 isao-hara 4 if(sx > ex){ x1=ex; x2=sx; }
1835     if(sy > ey){ y1=ey; y2=sy; }
1836 isao-hara 2
1837 isao-hara 4 selectedRectangle(getPreviewX(x1), getPreviewY(y1), getPreviewX(x2), getPreviewY(y2));
1838     }
1839     }else if (e.touches.length == 2){
1840     var dx= e.touches[0].pageX-e.touches[1].pageX;
1841     var dy = e.touches[0].pageY-e.touches[1].pageY;
1842     var th = Math.abs(Math.atan2(dy , dx)/Math.PI *180);
1843 isao-hara 2
1844 isao-hara 4 if(th > 165 || th < 25) svg_scale_dir = 'x';
1845     else if(th > 65 && th < 115) svg_scale_dir = 'y';
1846     else svg_scale_dir = null;
1847     }
1848 isao-hara 2 }
1849    
1850     function onTouchEnd(e){
1851     e.preventDefault();
1852    
1853     for(var i=0; i<selectedItems.length;i++){
1854     updateTransform(selectedItems[i]);
1855     }
1856    
1857     if(modeSVG == 'selector'){
1858     var x1 = getPreviewX(sx);
1859     var y1 = getPreviewY(sy);
1860     var x2 = getPreviewX(ex);
1861     var y2 = getPreviewY(ey);
1862     getSelectedObjects(x1, y1, x2, y2);
1863     }
1864    
1865     updateSelectedRectangle();
1866     updateTransform(svg_select);
1867    
1868     setSelectBox();
1869     updateShowMenu();
1870 isao-hara 4 var btn = document.getElementById('b_'+modeSVG);
1871     if(btn){
1872     btn.style.border="3px solid red";
1873     }
1874 isao-hara 2 lineEdit=null;
1875     }
1876    
1877    
1878     function onGestureStart(e){
1879     targetItem = selectedItems[0];
1880     if(targetItem){
1881     svg_wo = targetItem.getAttribute("width");
1882     svg_ho = targetItem.getAttribute("height");
1883     svg_ro = targetItem.getAttribute("r");
1884     svg_rxo = targetItem.getAttribute("rx");
1885     svg_ryo = targetItem.getAttribute("ry");
1886     svg_fsize = targetItem.getAttribute("font-size");
1887     }else{
1888     svg_wo = null;
1889     svg_ho = null;
1890     svg_ro = null;
1891     svg_rxo = null;
1892     svg_ryo = null;
1893     svg_fsize = null;
1894     }
1895     }
1896    
1897     function onGestureChange(e){
1898 isao-hara 4 var scale = e.scale;
1899     var rotation = e.rotation;
1900 isao-hara 2
1901 isao-hara 4 if(targetItem){
1902 isao-hara 7 e.preventDefault();
1903 isao-hara 4 if (svg_wo && svg_scale_dir != 'y') targetItem.setAttribute("width", Math.round(svg_wo*scale ));
1904     if (svg_ho && svg_scale_dir != 'x') targetItem.setAttribute("height", Math.round(svg_ho*scale ));
1905     if (svg_ro) targetItem.setAttribute("r", Math.round(svg_ro*scale ));
1906     if (svg_rxo && svg_scale_dir != 'y') targetItem.setAttribute("rx", Math.round(svg_rxo*scale) );
1907     if (svg_ryo && svg_scale_dir != 'x') targetItem.setAttribute("ry", Math.round(svg_ryo*scale) );
1908     if (svg_fsize) targetItem.setAttribute("font-size", Math.round(svg_fsize*scale) );
1909 isao-hara 2
1910 isao-hara 4 updateShowMenu();
1911     }
1912 isao-hara 2 }
1913    
1914     function onGestureEnd(e){
1915 isao-hara 7 // e.preventDefault();
1916 isao-hara 4 svg_wo = null;
1917     svg_ho = null;
1918     svg_ro = null;
1919     svg_rxo = null;
1920     svg_ryo = null;
1921     svg_fsize = null;
1922 isao-hara 2 }
1923    
1924 isao-hara 14 function onTouchStartColor(e){
1925     if(e.touches.length == 1){
1926     var ele = e.touches[0].target;
1927     var color = ele.getAttribute("color-val");
1928     var color_sel = document.getElementById('color_sel');
1929     var fill_input = document.getElementById('svg_fill');
1930     var color_input = document.getElementById('svg_color');
1931     if(color) {
1932     for(var i=0;selectedItems.length; i++){
1933     selectedItems[i].setAttribute(color_sel.value, color);
1934     if(color_sel.value == 'fill'){
1935     fill_input.value=color;
1936     }else{
1937     color_input.value=color;
1938     }
1939     }
1940     }
1941     }
1942     }
1943 isao-hara 2 ///// For Safari
1944     function onMouseDown(e){
1945    
1946     if(targetItem){
1947     removeClass(targetItem, "selected");
1948     }
1949    
1950     if(isChildById(e.target, 'svg_top')) {
1951     targetItem=e.target;
1952     sx=e.pageX;
1953     sy=e.pageY;
1954     setInnerHTML('popup', e.pageX+","+e.pageY);
1955    
1956     }else{
1957     targetItem = null;
1958     }
1959    
1960     return true;
1961     }
1962    
1963     function onMouseMove(e){
1964     if(targetItem){
1965     addAttributeVal(targetItem, "x", e.pageX - sx );
1966     addAttributeVal(targetItem, "y", e.pageY - sy );
1967     addAttributeVal(targetItem, "cx", e.pageX - sx );
1968     addAttributeVal(targetItem, "cy", e.pageY - sy );
1969     }
1970     sx=e.pageX;
1971     sy=e.pageY;
1972     return true;
1973     }
1974    
1975     function onMouseUp(e){
1976     var str = getSVGContent();
1977     escstr = "<pre>"+escapeHTML(str)+"</pre>";
1978     setInnerHTML('popup', escstr);
1979    
1980     targetItem=null;
1981     return true;
1982     }
1983    
1984     if(!navigator.userAgent.match("iPad")){
1985     document.onmousedown=onMouseDown;
1986     document.onmousemove=onMouseMove;
1987     document.onmouseup=onMouseUp;
1988     }
1989    

Properties

Name Value
svn:executable *

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26