add persistence feature
This commit is contained in:
parent
0c17e2cfbe
commit
2b25958d8c
74
draw.js
74
draw.js
|
|
@ -52,7 +52,7 @@ var DrawingArea = new Lang.Class({
|
||||||
Name: 'DrawOnYourScreenDrawingArea',
|
Name: 'DrawOnYourScreenDrawingArea',
|
||||||
Extends: St.DrawingArea,
|
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 : ""});
|
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
|
// 'style-changed' is emitted when 'this' is added to an actor
|
||||||
|
|
@ -74,6 +74,9 @@ var DrawingArea = new Lang.Class({
|
||||||
this.textHasCursor = false;
|
this.textHasCursor = false;
|
||||||
this.dashedLine = false;
|
this.dashedLine = false;
|
||||||
this.colors = [Clutter.Color.new(0, 0, 0, 255)];
|
this.colors = [Clutter.Color.new(0, 0, 0, 255)];
|
||||||
|
|
||||||
|
if (loadJson)
|
||||||
|
this._loadJson();
|
||||||
},
|
},
|
||||||
|
|
||||||
_redisplay: function() {
|
_redisplay: function() {
|
||||||
|
|
@ -225,12 +228,12 @@ var DrawingArea = new Lang.Class({
|
||||||
this.smoothedStroke = this.settings.get_boolean('smoothed-stroke');
|
this.smoothedStroke = this.settings.get_boolean('smoothed-stroke');
|
||||||
|
|
||||||
this.currentElement = new DrawingElement ({
|
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 },
|
line: { lineWidth: this.currentLineWidth, lineJoin: this.currentLineJoin, lineCap: this.currentLineCap },
|
||||||
dash: { array: this.dashedLine ? this.dashArray : [0, 0] , offset: this.dashedLine ? this.dashOffset : 0 },
|
dash: { array: this.dashedLine ? this.dashArray : [0, 0] , offset: this.dashedLine ? this.dashOffset : 0 },
|
||||||
fill: fill,
|
fill: fill,
|
||||||
eraser: eraser,
|
eraser: eraser,
|
||||||
shape: this.currentShape == Shapes.TEXT ? Shapes.RECTANGLE : this.currentShape,
|
|
||||||
transform: { active: false, center: [0, 0], angle: 0, startAngle: 0, ratio: 1 },
|
transform: { active: false, center: [0, 0], angle: 0, startAngle: 0, ratio: 1 },
|
||||||
text: '',
|
text: '',
|
||||||
font: { family: (this.currentFontFamilyId == 0 ? this.fontFamily : FontFamilyNames[this.currentFontFamilyId]), weight: this.currentFontWeight, style: this.currentFontStyle },
|
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) {
|
selectColor: function(index) {
|
||||||
this.currentColor = this.colors[index];
|
this.currentColor = this.colors[index];
|
||||||
if (this.currentElement) {
|
if (this.currentElement) {
|
||||||
this.currentElement.color = this.currentColor;
|
this.currentElement.color = this.currentColor.to_string();
|
||||||
this._redisplay();
|
this._redisplay();
|
||||||
}
|
}
|
||||||
this.emitter.emit('show-osd', this.currentColor.to_string(), null);
|
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);
|
this.get_parent().set_background_color(this.hasBackground ? this.activeBackgroundColor : null);
|
||||||
},
|
},
|
||||||
|
|
||||||
leaveDrawingMode: function() {
|
leaveDrawingMode: function(save) {
|
||||||
if (this.keyPressedHandler) {
|
if (this.keyPressedHandler) {
|
||||||
this.disconnect(this.keyPressedHandler);
|
this.disconnect(this.keyPressedHandler);
|
||||||
this.keyPressedHandler = null;
|
this.keyPressedHandler = null;
|
||||||
|
|
@ -499,9 +502,11 @@ var DrawingArea = new Lang.Class({
|
||||||
this.dashedLine = false;
|
this.dashedLine = false;
|
||||||
this._redisplay();
|
this._redisplay();
|
||||||
this.get_parent().set_background_color(null);
|
this.get_parent().set_background_color(null);
|
||||||
|
if (save)
|
||||||
|
this._saveAsJson();
|
||||||
},
|
},
|
||||||
|
|
||||||
save: function() {
|
saveAsSvg: function() {
|
||||||
// stop drawing or writing
|
// stop drawing or writing
|
||||||
if (this.currentElement && this.currentElement.shape == Shapes.TEXT) {
|
if (this.currentElement && this.currentElement.shape == Shapes.TEXT) {
|
||||||
this._stopWriting();
|
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() {
|
disable: function() {
|
||||||
this.erase();
|
this.erase();
|
||||||
}
|
}
|
||||||
|
|
@ -560,6 +600,22 @@ var DrawingElement = new Lang.Class({
|
||||||
this[key] = params[key];
|
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) {
|
buildCairo: function(cr, showTextCursor) {
|
||||||
cr.setLineCap(this.line.lineCap);
|
cr.setLineCap(this.line.lineCap);
|
||||||
cr.setLineJoin(this.line.lineJoin);
|
cr.setLineJoin(this.line.lineJoin);
|
||||||
|
|
@ -575,7 +631,9 @@ var DrawingElement = new Lang.Class({
|
||||||
else
|
else
|
||||||
cr.setOperator(Cairo.Operator.OVER);
|
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];
|
let [points, shape, trans] = [this.points, this.shape, this.transform];
|
||||||
|
|
||||||
|
|
@ -614,7 +672,7 @@ var DrawingElement = new Lang.Class({
|
||||||
buildSVG: function(bgColor) {
|
buildSVG: function(bgColor) {
|
||||||
let row = "\n ";
|
let row = "\n ";
|
||||||
let points = this.points.map((point) => [Math.round(point[0]*100)/100, Math.round(point[1]*100)/100]);
|
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 isStraightLine = this.shape == Shapes.LINE && (points.length < 3 || points[2] == points[1] || points[2] == points[0]);
|
||||||
let fill = this.fill && !isStraightLine;
|
let fill = this.fill && !isStraightLine;
|
||||||
let attributes = `fill="${fill ? color : 'transparent'}" ` +
|
let attributes = `fill="${fill ? color : 'transparent'}" ` +
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,8 @@ var AreaManager = new Lang.Class({
|
||||||
let monitor = this.monitors[i];
|
let monitor = this.monitors[i];
|
||||||
let container = new St.Widget({ name: 'drawOnYourSreenContainer' + i });
|
let container = new St.Widget({ name: 'drawOnYourSreenContainer' + i });
|
||||||
let helper = new Draw.DrawingHelper({ name: 'drawOnYourSreenHelper' + i }, monitor);
|
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(area);
|
||||||
container.add_child(helper);
|
container.add_child(helper);
|
||||||
|
|
||||||
|
|
@ -122,7 +123,7 @@ var AreaManager = new Lang.Class({
|
||||||
'redo': this.activeArea.redo.bind(this.activeArea),
|
'redo': this.activeArea.redo.bind(this.activeArea),
|
||||||
'delete-last-element': this.activeArea.deleteLastElement.bind(this.activeArea),
|
'delete-last-element': this.activeArea.deleteLastElement.bind(this.activeArea),
|
||||||
'smooth-last-element': this.activeArea.smoothLastElement.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-background': this.activeArea.toggleBackground.bind(this.activeArea),
|
||||||
'toggle-square-area': this.activeArea.toggleSquareArea.bind(this.activeArea),
|
'toggle-square-area': this.activeArea.toggleSquareArea.bind(this.activeArea),
|
||||||
'increment-line-width': () => this.activeArea.incrementLineWidth(1),
|
'increment-line-width': () => this.activeArea.incrementLineWidth(1),
|
||||||
|
|
@ -223,6 +224,7 @@ var AreaManager = new Lang.Class({
|
||||||
if (this.activeArea) {
|
if (this.activeArea) {
|
||||||
let activeIndex = this.areas.indexOf(this.activeArea);
|
let activeIndex = this.areas.indexOf(this.activeArea);
|
||||||
let activeContainer = this.activeArea.get_parent();
|
let activeContainer = this.activeArea.get_parent();
|
||||||
|
let save = activeIndex == Main.layoutManager.primaryIndex && this.settings.get_boolean('persistent-drawing');
|
||||||
|
|
||||||
if (this.hiddenList)
|
if (this.hiddenList)
|
||||||
this.togglePanelAndDockOpacity();
|
this.togglePanelAndDockOpacity();
|
||||||
|
|
@ -230,7 +232,7 @@ var AreaManager = new Lang.Class({
|
||||||
Main.popModal(this.activeArea);
|
Main.popModal(this.activeArea);
|
||||||
this.removeInternalKeybindings();
|
this.removeInternalKeybindings();
|
||||||
this.activeArea.reactive = false;
|
this.activeArea.reactive = false;
|
||||||
this.activeArea.leaveDrawingMode();
|
this.activeArea.leaveDrawingMode(save);
|
||||||
this.activeArea = null;
|
this.activeArea = null;
|
||||||
|
|
||||||
activeContainer.get_parent().remove_actor(activeContainer);
|
activeContainer.get_parent().remove_actor(activeContainer);
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,12 @@ msgstr ""
|
||||||
msgid "Draw On Your Screen becomes Draw On Your Desktop"
|
msgid "Draw On Your Screen becomes Draw On Your Desktop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Persistent"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Persistent drawing through restart"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Internal"
|
msgid "Internal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
||||||
14
prefs.js
14
prefs.js
|
|
@ -139,6 +139,20 @@ const PrefsPage = new GObject.Class({
|
||||||
desktopBox.pack_start(desktopLabelBox, true, true, 4);
|
desktopBox.pack_start(desktopLabelBox, true, true, 4);
|
||||||
desktopBox.pack_start(desktopSwitch, false, false, 4);
|
desktopBox.pack_start(desktopSwitch, false, false, 4);
|
||||||
listBox.add(desktopBox);
|
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: "<small>" + _("Persistent drawing through restart") + "</small>" });
|
||||||
|
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);
|
this.addSeparator(listBox);
|
||||||
|
|
||||||
let internalTitleBox = new Gtk.Box({ margin: MARGIN });
|
let internalTitleBox = new Gtk.Box({ margin: MARGIN });
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -11,6 +11,11 @@
|
||||||
<summary>move drawing on desktop</summary>
|
<summary>move drawing on desktop</summary>
|
||||||
<description>move drawing on desktop</description>
|
<description>move drawing on desktop</description>
|
||||||
</key>
|
</key>
|
||||||
|
<key type="b" name="persistent-drawing">
|
||||||
|
<default>false</default>
|
||||||
|
<summary>persistent drawing</summary>
|
||||||
|
<description>persistent drawing</description>
|
||||||
|
</key>
|
||||||
<key type="as" name="toggle-drawing">
|
<key type="as" name="toggle-drawing">
|
||||||
<default>["<Alt><Super>d"]</default>
|
<default>["<Alt><Super>d"]</default>
|
||||||
<summary>toggle drawing</summary>
|
<summary>toggle drawing</summary>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue