diff --git a/editor/svg-editor.css b/editor/svg-editor.css index 683c7804..7639f931 100644 --- a/editor/svg-editor.css +++ b/editor/svg-editor.css @@ -31,6 +31,7 @@ body { vertical-align: middle; width: 640px; height: 480px; + -apple-dashboard-region:dashboard-region(control rectangle 0px 0px 0px 0px); /* for widget regions that shouldn't react to dragging */ } #svg_editor div#palette_holder { diff --git a/editor/svg-editor.html b/editor/svg-editor.html index 3a8d5781..72a7906e 100644 --- a/editor/svg-editor.html +++ b/editor/svg-editor.html @@ -42,6 +42,7 @@
| Clear + Save Source
diff --git a/editor/svg-editor.js b/editor/svg-editor.js index b5d91d08..0898cb0f 100644 --- a/editor/svg-editor.js +++ b/editor/svg-editor.js @@ -33,7 +33,35 @@ function svg_edit_setup() { // with a gradient will appear black in Firefox, etc. See bug 308590 // https://bugzilla.mozilla.org/show_bug.cgi?id=308590 var saveHandler = function(window,svg) { - window.open("data:image/svg+xml;base64," + Utils.encode64(svg)); + if(window.opera && window.opera.io && window.opera.io.filesystem) + { + try { + window.opera.io.filesystem.browseForSave( + new Date().getTime(), /* mountpoint name */ + "", /* default location */ + function(file) { + try { + if (file) { + var fstream = file.open(file, "w"); + fstream.write(svg, "UTF-8"); + fstream.close(); + } + } + catch(e) { + console.log("Write to file failed."); + } + }, + false /* not persistent */ + ); + } + catch(e) { + console.log("Save file failed."); + } + } + else + { + window.open("data:image/svg+xml;base64," + Utils.encode64(svg)); + } }; // called when we've selected a different element @@ -469,6 +497,10 @@ function svg_edit_setup() { var clickSave = function(){ svgCanvas.save(); }; + + var clickOpen = function(){ + svgCanvas.open(); + }; var clickUndo = function(){ if (svgCanvas.getUndoStackSize() > 0) @@ -568,6 +600,7 @@ function svg_edit_setup() { $('#tool_poly').click(clickPoly); $('#tool_clear').click(clickClear); $('#tool_save').click(clickSave); + $('#tool_open').click(clickOpen); $('#tool_source').click(showSourceEditor); $('#tool_source_cancel,#svg_source_overlay').click(cancelSourceEditor); $('#tool_source_save').click(saveSourceEditor); @@ -594,7 +627,7 @@ function svg_edit_setup() { // added these event handlers for all the push buttons so they // behave more like buttons being pressed-in and not images function setPushButtons() { - var toolnames = ['clear','save','source','delete','delete_multi','paste','clone','clone_multi','move_top','move_bottom']; + var toolnames = ['clear','open','save','source','delete','delete_multi','paste','clone','clone_multi','move_top','move_bottom']; var all_tools = ''; var cur_class = 'tool_button_current'; @@ -646,6 +679,7 @@ function svg_edit_setup() { ['7', clickPoly], [modKey+'N', function(evt){clickClear();evt.preventDefault();}], [modKey+'S', function(evt){editingsource?saveSourceEditor():clickSave();evt.preventDefault();}], + [modKey+'O', function(evt){clickOpen();evt.preventDefault();}], ['del', function(evt){deleteSelected();evt.preventDefault();}], ['backspace', function(evt){deleteSelected();evt.preventDefault();}], ['shift+up', moveToTopSelected], @@ -829,5 +863,13 @@ function svg_edit_setup() { $('#stroke_width').SpinButton({ min: 1, max: 99, step: 1, callback: changeStrokeWidth }); $('#angle').SpinButton({ min: -359, max: 359, step: 5, callback: changeRotationAngle }); + // if Opera and in widget form, enable the Open button + if (window.opera) { + opera.postError('opera.io=' + opera.io); + if(opera && opera.io && opera.io.filesystem) { + $('#tool_open').show(); + } + } + return svgCanvas; }; diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js index 689ca44c..29b7d62a 100644 --- a/editor/svgcanvas.js +++ b/editor/svgcanvas.js @@ -1360,8 +1360,6 @@ function SvgCanvas(c) freehand_max_y = Math.max(y, freehand_max_y); // break; missing on purpose case "path": -// var dx = x - start_x; -// var dy = y - start_y; start_x = x; start_y = y; d_attr += + x + "," + y + " "; @@ -1379,8 +1377,29 @@ function SvgCanvas(c) // if we are dragging a point, let's move it if (current_poly_pt_drag != -1 && current_poly) { var i = current_poly_pt_drag * 2; - var dx = x - current_poly_pts[i], - dy = y - current_poly_pts[i+1]; + + // if the image is rotated, then we must modify the x,y mouse coordinates + // and rotate them into the shape's rotated coordinate system + + // FIXME: the problem is that the element's rotation is controlled by + // two things: an angle and a rotation point (the center of the element). + // If the element's bbox is changed, its center changes. In this case, + // we keep the rotation center where it is (parse it out from the transform + // attribute), and move the poly point appropriately). This looks good while + // dragging, but looks funny when you subsequently rotate the element again. + if (angle) { + // extract the shape's (potentially) old 'center' from the transform attribute + var matched_numbers = current_poly.getAttribute('transform').match(/([\d\.\-\+]+)/g); + var cx = parseFloat(matched_numbers[1]), + cy = parseFloat(matched_numbers[2]); + var bbox = canvas.getBBox(current_poly); + var dx = x - cx, dy = y - cy; + var r = Math.sqrt( dx*dx + dy*dy ); + var theta = Math.atan2(dy,dx) - angle; + x = cx + r * Math.cos(theta); + y = cy + r * Math.sin(theta); + } + current_poly_pts[i] = x; current_poly_pts[i+1] = y; @@ -1394,7 +1413,7 @@ function SvgCanvas(c) arr[0] = ["M", curx, ",", cury].join(''); for (var j = 1; j < len; ++j) { var px = current_poly_pts[j*2], py = current_poly_pts[j*2+1]; - arr[j] = ["l", (px-curx), ",", (py-cury)].join(''); + arr[j] = ["l", parseInt(px-curx), ",", parseInt(py-cury)].join(''); curx = px; cury = py; } @@ -1785,6 +1804,40 @@ function SvgCanvas(c) // public functions + this.open = function() { + if(window.opera && window.opera.io && window.opera.io.filesystem) + { + try { + window.opera.io.filesystem.browseForFile( + new Date().getTime(), /* mountpoint name */ + "", /* default location */ + function(file) { + try { + if (file) { + fstream = file.open(file, "r"); + var output = ""; + while (!fstream.eof) { + output += fstream.readLine("UTF-16"); + } + + canvas.setSvgString(output); /* 'this' is bound to the filestream object here */ + } + } + catch(e) { + console.log("Reading file failed."); + } + }, + false, /* not persistent */ + false, /* no multiple selections */ + "*.svg" /* file extension filter */ + ); + } + catch(e) { + console.log("Open file failed."); + } + } + }; + this.save = function() { // remove the selected outline before serializing this.clearSelection(); diff --git a/widget/Makefile b/widget/Makefile new file mode 100644 index 00000000..84deba88 --- /dev/null +++ b/widget/Makefile @@ -0,0 +1,12 @@ +ZIP = zip +PACKAGE = svgedit-2.3 +FILEMASK = \*.html \*.css \*.js \*.txt \*.png \*.jpg \*.gif \*.svg \*.xml + +clean: + rm -f *.*~ + rm -rf ./editor/ + +widget: clean + rm -f $(PACKAGE).wgt + cp -r ../editor . + $(ZIP) $(PACKAGE).wgt -r . -i $(FILEMASK) diff --git a/widget/config.xml b/widget/config.xml new file mode 100644 index 00000000..81af90aa --- /dev/null +++ b/widget/config.xml @@ -0,0 +1,16 @@ + + + SVG Edit + + A simple SVG Editor. + + 800 + 600 + + SVG Edit + 2009-08 + + + + + \ No newline at end of file diff --git a/widget/index.html b/widget/index.html new file mode 100644 index 00000000..28d30cc0 --- /dev/null +++ b/widget/index.html @@ -0,0 +1,11 @@ + + + SVG Edit + + + + + Failed to load for some reason. + + + \ No newline at end of file diff --git a/widget/style.css b/widget/style.css new file mode 100644 index 00000000..b3b268ea --- /dev/null +++ b/widget/style.css @@ -0,0 +1,2 @@ +body { margin: 0px; padding: 0px; } +#container { width: 100%; height: 100%; border: none; } \ No newline at end of file