diff --git a/draw.js b/draw.js index 2dbe213..ba9c738 100644 --- a/draw.js +++ b/draw.js @@ -52,7 +52,7 @@ var DrawingArea = new Lang.Class({ Name: 'DrawOnYourScreenDrawingArea', Extends: St.DrawingArea, - _init: function(params, monitor, helper) { + _init: function(params, monitor, helper, loadJson) { this.parent({ style_class: 'draw-on-your-screen', name: params && params.name ? params.name : ""}); // 'style-changed' is emitted when 'this' is added to an actor @@ -74,6 +74,9 @@ var DrawingArea = new Lang.Class({ this.textHasCursor = false; this.dashedLine = false; this.colors = [Clutter.Color.new(0, 0, 0, 255)]; + + if (loadJson) + this._loadJson(); }, _redisplay: function() { @@ -225,12 +228,12 @@ var DrawingArea = new Lang.Class({ this.smoothedStroke = this.settings.get_boolean('smoothed-stroke'); this.currentElement = new DrawingElement ({ - color: this.currentColor, + shape: this.currentShape == Shapes.TEXT ? Shapes.RECTANGLE : this.currentShape, + color: this.currentColor.to_string(), line: { lineWidth: this.currentLineWidth, lineJoin: this.currentLineJoin, lineCap: this.currentLineCap }, dash: { array: this.dashedLine ? this.dashArray : [0, 0] , offset: this.dashedLine ? this.dashOffset : 0 }, fill: fill, eraser: eraser, - shape: this.currentShape == Shapes.TEXT ? Shapes.RECTANGLE : this.currentShape, transform: { active: false, center: [0, 0], angle: 0, startAngle: 0, ratio: 1 }, text: '', font: { family: (this.currentFontFamilyId == 0 ? this.fontFamily : FontFamilyNames[this.currentFontFamilyId]), weight: this.currentFontWeight, style: this.currentFontStyle }, @@ -390,7 +393,7 @@ var DrawingArea = new Lang.Class({ selectColor: function(index) { this.currentColor = this.colors[index]; if (this.currentElement) { - this.currentElement.color = this.currentColor; + this.currentElement.color = this.currentColor.to_string(); this._redisplay(); } this.emitter.emit('show-osd', this.currentColor.to_string(), null); @@ -469,7 +472,7 @@ var DrawingArea = new Lang.Class({ this.get_parent().set_background_color(this.hasBackground ? this.activeBackgroundColor : null); }, - leaveDrawingMode: function() { + leaveDrawingMode: function(save) { if (this.keyPressedHandler) { this.disconnect(this.keyPressedHandler); this.keyPressedHandler = null; @@ -499,9 +502,11 @@ var DrawingArea = new Lang.Class({ this.dashedLine = false; this._redisplay(); this.get_parent().set_background_color(null); + if (save) + this._saveAsJson(); }, - save: function() { + saveAsSvg: function() { // stop drawing or writing if (this.currentElement && this.currentElement.shape == Shapes.TEXT) { this._stopWriting(); @@ -535,6 +540,41 @@ var DrawingArea = new Lang.Class({ } }, + _saveAsJson: function() { + let filename = `DrawOnYourScreen.json`; + let dir = GLib.get_user_data_dir(); + let path = GLib.build_filenamev([dir, filename]); + + let oldContents; + if (GLib.file_test(path, GLib.FileTest.EXISTS)) { + oldContents = GLib.file_get_contents(path)[1]; + if (oldContents instanceof Uint8Array) + oldContents = imports.byteArray.toString(oldContents); + } + + // do not use "content = JSON.stringify(this.elements, null, 2);", neither "content = JSON.stringify(this.elements);" + // because of compromise between disk usage and human readability + let contents = `[\n ` + new Array(...this.elements.map(element => JSON.stringify(element))).join(`,\n\n `) + `\n]`; + + if (contents != oldContents) + GLib.file_set_contents(path, contents); + }, + + _loadJson: function() { + let filename = `DrawOnYourScreen.json`; + let dir = GLib.get_user_data_dir(); + let path = GLib.build_filenamev([dir, filename]); + + if (!GLib.file_test(path, GLib.FileTest.EXISTS)) + return; + let [success, contents] = GLib.file_get_contents(path); + if (!success) + return; + if (contents instanceof Uint8Array) + contents = imports.byteArray.toString(contents); + this.elements.push(...JSON.parse(contents).map(object => new DrawingElement(object))); + }, + disable: function() { this.erase(); } @@ -560,6 +600,22 @@ var DrawingElement = new Lang.Class({ this[key] = params[key]; }, + // toJSON is called by JSON.stringify + toJSON: function() { + return { + shape: this.shape, + color: this.color, + line: this.line, + dash: this.dash, + fill: this.fill, + eraser: this.eraser, + transform: this.transform, + text: this.text, + font: this.font, + points: this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100]) + }; + }, + buildCairo: function(cr, showTextCursor) { cr.setLineCap(this.line.lineCap); cr.setLineJoin(this.line.lineJoin); @@ -575,7 +631,9 @@ var DrawingElement = new Lang.Class({ else cr.setOperator(Cairo.Operator.OVER); - Clutter.cairo_set_source_color(cr, this.color); + let [success, color] = Clutter.Color.from_string(this.color); + if (success) + Clutter.cairo_set_source_color(cr, color); let [points, shape, trans] = [this.points, this.shape, this.transform]; @@ -614,7 +672,7 @@ var DrawingElement = new Lang.Class({ buildSVG: function(bgColor) { let row = "\n "; let points = this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100]); - let color = this.eraser ? bgColor : this.color.to_string(); + let color = this.eraser ? bgColor : this.color; let isStraightLine = this.shape == Shapes.LINE && (points.length < 3 || points[2] == points[1] || points[2] == points[0]); let fill = this.fill && !isStraightLine; let attributes = `fill="${fill ? color : 'transparent'}" ` + diff --git a/extension.js b/extension.js index 813719b..4b35eff 100644 --- a/extension.js +++ b/extension.js @@ -98,7 +98,8 @@ var AreaManager = new Lang.Class({ let monitor = this.monitors[i]; let container = new St.Widget({ name: 'drawOnYourSreenContainer' + i }); let helper = new Draw.DrawingHelper({ name: 'drawOnYourSreenHelper' + i }, monitor); - let area = new Draw.DrawingArea({ name: 'drawOnYourSreenArea' + i }, monitor, helper); + let load = i == Main.layoutManager.primaryIndex && this.settings.get_boolean('persistent-drawing'); + let area = new Draw.DrawingArea({ name: 'drawOnYourSreenArea' + i }, monitor, helper, load); container.add_child(area); container.add_child(helper); @@ -122,7 +123,7 @@ var AreaManager = new Lang.Class({ 'redo': this.activeArea.redo.bind(this.activeArea), 'delete-last-element': this.activeArea.deleteLastElement.bind(this.activeArea), 'smooth-last-element': this.activeArea.smoothLastElement.bind(this.activeArea), - 'save-as-svg': this.activeArea.save.bind(this.activeArea), + 'save-as-svg': this.activeArea.saveAsSvg.bind(this.activeArea), 'toggle-background': this.activeArea.toggleBackground.bind(this.activeArea), 'toggle-square-area': this.activeArea.toggleSquareArea.bind(this.activeArea), 'increment-line-width': () => this.activeArea.incrementLineWidth(1), @@ -223,6 +224,7 @@ var AreaManager = new Lang.Class({ if (this.activeArea) { let activeIndex = this.areas.indexOf(this.activeArea); let activeContainer = this.activeArea.get_parent(); + let save = activeIndex == Main.layoutManager.primaryIndex && this.settings.get_boolean('persistent-drawing'); if (this.hiddenList) this.togglePanelAndDockOpacity(); @@ -230,7 +232,7 @@ var AreaManager = new Lang.Class({ Main.popModal(this.activeArea); this.removeInternalKeybindings(); this.activeArea.reactive = false; - this.activeArea.leaveDrawingMode(); + this.activeArea.leaveDrawingMode(save); this.activeArea = null; activeContainer.get_parent().remove_actor(activeContainer); diff --git a/locale/draw-on-your-screen.pot b/locale/draw-on-your-screen.pot index 94c8019..009c315 100644 --- a/locale/draw-on-your-screen.pot +++ b/locale/draw-on-your-screen.pot @@ -223,6 +223,12 @@ msgstr "" msgid "Draw On Your Screen becomes Draw On Your Desktop" msgstr "" +msgid "Persistent" +msgstr "" + +msgid "Persistent drawing through restart" +msgstr "" + msgid "Internal" msgstr "" diff --git a/prefs.js b/prefs.js index 772c85d..7089bba 100644 --- a/prefs.js +++ b/prefs.js @@ -139,6 +139,20 @@ const PrefsPage = new GObject.Class({ desktopBox.pack_start(desktopLabelBox, true, true, 4); desktopBox.pack_start(desktopSwitch, false, false, 4); listBox.add(desktopBox); + + let persistentBox = new Gtk.Box({ margin: MARGIN }); + let persistentLabelBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL }); + let persistentLabel1 = new Gtk.Label({label: _("Persistent")}); + let persistentLabel2 = new Gtk.Label({ use_markup: true, halign: 1, label: "" + _("Persistent drawing through restart") + "" }); + persistentLabel1.set_halign(1); + persistentLabel2.get_style_context().add_class("dim-label"); + persistentLabelBox.pack_start(persistentLabel1, true, true, 0); + persistentLabelBox.pack_start(persistentLabel2, true, true, 0); + let persistentSwitch = new Gtk.Switch({valign: 3}); + this.settings.bind("persistent-drawing", persistentSwitch, "active", 0); + persistentBox.pack_start(persistentLabelBox, true, true, 4); + persistentBox.pack_start(persistentSwitch, false, false, 4); + listBox.add(persistentBox); this.addSeparator(listBox); let internalTitleBox = new Gtk.Box({ margin: MARGIN }); diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled index dbb5659..a0f2bb1 100644 Binary files a/schemas/gschemas.compiled and b/schemas/gschemas.compiled differ diff --git a/schemas/org.gnome.shell.extensions.draw-on-your-screen.gschema.xml b/schemas/org.gnome.shell.extensions.draw-on-your-screen.gschema.xml index a41ba91..225c21d 100644 --- a/schemas/org.gnome.shell.extensions.draw-on-your-screen.gschema.xml +++ b/schemas/org.gnome.shell.extensions.draw-on-your-screen.gschema.xml @@ -11,6 +11,11 @@ move drawing on desktop move drawing on desktop + + false + persistent drawing + persistent drawing + ["<Alt><Super>d"] toggle drawing