add gpl import
* Import palettes from a .gpl file (one palette for each column). * Add possibility to use more than 9 palettes. * Color display names support. * color.toJSON for svg and drawing saves, color.toString for display.
This commit is contained in:
parent
4cc0c9e028
commit
27e194905b
9
area.js
9
area.js
|
|
@ -64,14 +64,19 @@ var Tools = Object.assign({
|
|||
}, Shapes, Manipulations);
|
||||
Object.defineProperty(Tools, 'getNameOf', { enumerable: false });
|
||||
|
||||
// toJSON provides a string suitable for SVG color attribute whereas
|
||||
// toString provides a string suitable for displaying the color name to the user.
|
||||
const getColorFromString = function(string, fallback) {
|
||||
let [success, color] = Clutter.Color.from_string(string);
|
||||
color.toString = () => string;
|
||||
let [colorString, displayName] = string.split(':');
|
||||
let [success, color] = Clutter.Color.from_string(colorString);
|
||||
color.toJSON = () => colorString;
|
||||
color.toString = () => displayName || colorString;
|
||||
if (success)
|
||||
return color;
|
||||
|
||||
log(`${Me.metadata.uuid}: "${string}" color cannot be parsed.`);
|
||||
color = Clutter.Color.get_static(Clutter.StaticColor[fallback.toUpperCase()]);
|
||||
color.toJSON = () => fallback;
|
||||
color.toString = () => fallback;
|
||||
return color;
|
||||
};
|
||||
|
|
|
|||
10
elements.js
10
elements.js
|
|
@ -113,7 +113,7 @@ const _DrawingElement = new Lang.Class({
|
|||
toJSON: function() {
|
||||
return {
|
||||
shape: this.shape,
|
||||
color: this.color.toString(),
|
||||
color: this.color,
|
||||
line: this.line,
|
||||
dash: this.dash,
|
||||
fill: this.fill,
|
||||
|
|
@ -314,7 +314,7 @@ const _DrawingElement = new Lang.Class({
|
|||
_drawSvg: function(transAttribute, bgcolorString) {
|
||||
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 ? bgcolorString : this.color.toString();
|
||||
let color = this.eraser ? bgcolorString : this.color.toJSON();
|
||||
let fill = this.fill && !this.isStraightLine;
|
||||
let attributes = this.eraser ? `class="eraser" ` : '';
|
||||
|
||||
|
|
@ -633,7 +633,7 @@ const TextElement = new Lang.Class({
|
|||
|
||||
return {
|
||||
shape: this.shape,
|
||||
color: this.color.toString(),
|
||||
color: this.color,
|
||||
eraser: this.eraser,
|
||||
transformations: this.transformations,
|
||||
text: this.text,
|
||||
|
|
@ -703,7 +703,7 @@ const TextElement = new Lang.Class({
|
|||
_drawSvg: function(transAttribute, bgcolorString) {
|
||||
let row = "\n ";
|
||||
let [x, y, height] = [Math.round(this.x*100)/100, Math.round(this.y*100)/100, Math.round(this.height*100)/100];
|
||||
let color = this.eraser ? bgcolorString : this.color.toString();
|
||||
let color = this.eraser ? bgcolorString : this.color.toJSON();
|
||||
let attributes = this.eraser ? `class="eraser" ` : '';
|
||||
|
||||
if (this.points.length == 2) {
|
||||
|
|
@ -775,7 +775,7 @@ const ImageElement = new Lang.Class({
|
|||
toJSON: function() {
|
||||
return {
|
||||
shape: this.shape,
|
||||
color: this.color.toString(),
|
||||
color: this.color,
|
||||
fill: this.fill,
|
||||
eraser: this.eraser,
|
||||
transformations: this.transformations,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
/* jslint esversion: 6 */
|
||||
/* exported parseFile */
|
||||
|
||||
/*
|
||||
* Copyright 2019 Abakkk
|
||||
*
|
||||
* This file is part of DrawOnYourScreen, a drawing extension for GNOME Shell.
|
||||
* https://framagit.org/abakkk/DrawOnYourScreen
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const ByteArray = imports.byteArray;
|
||||
|
||||
/*
|
||||
* [
|
||||
* [
|
||||
* 'palette name 1', // a palette for each column
|
||||
* [
|
||||
* 'rgb(...)',
|
||||
* 'rgb(...):color display name', // the optional name separated with ':'
|
||||
* ...
|
||||
* ]
|
||||
* ],
|
||||
* [
|
||||
* 'palette name 2',
|
||||
* [...]
|
||||
* ],
|
||||
* ...
|
||||
* ]
|
||||
*/
|
||||
|
||||
function parse(contents) {
|
||||
let lines = contents.split('\n');
|
||||
let line, name, columnNumber;
|
||||
|
||||
line = lines.shift();
|
||||
if (!line || !line.startsWith('GIMP Palette'))
|
||||
log("Missing magic header");
|
||||
|
||||
line = lines.shift();
|
||||
if (line.startsWith('Name:')) {
|
||||
name = line.slice(5).trim() || file.get_basename();
|
||||
line = lines.shift();
|
||||
}
|
||||
if (line.startsWith('Columns:')) {
|
||||
columnNumber = Number(line.slice(8).trim()) || 1;
|
||||
line = lines.shift();
|
||||
}
|
||||
|
||||
let columns = (new Array(columnNumber)).fill(null).map(() => []);
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if (!line || line.startsWith('#'))
|
||||
return;
|
||||
|
||||
line = line.split('#')[0].trim();
|
||||
|
||||
let [, color, displayName] = line.split(/(^[\d\s]+)/);
|
||||
|
||||
let values = color.trim().split(/\D+/gi).filter(value => value >= 0 && value <= 255);
|
||||
if (values.length < 3)
|
||||
return;
|
||||
|
||||
let string = `rgb(${values[0]},${values[1]},${values[2]})`;
|
||||
if (displayName.trim())
|
||||
string += `:${displayName.trim()}`;
|
||||
|
||||
columns[index % columns.length].push(string);
|
||||
});
|
||||
|
||||
return columns.map((column, index) => [columnNumber > 1 ? `${name} ${index + 1}` : name, column]);
|
||||
}
|
||||
|
||||
function parseFile(file) {
|
||||
if (!file.query_exists(null))
|
||||
return [];
|
||||
|
||||
let [, contents] = file.load_contents(null);
|
||||
if (contents instanceof Uint8Array)
|
||||
contents = ByteArray.toString(contents);
|
||||
|
||||
return parse(contents);
|
||||
}
|
||||
53
prefs.js
53
prefs.js
|
|
@ -31,6 +31,7 @@ const Gtk = imports.gi.Gtk;
|
|||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
const Convenience = ExtensionUtils.getSettings && ExtensionUtils.initTranslations ? ExtensionUtils : Me.imports.convenience;
|
||||
const GimpPaletteParser = Me.imports.gimpPaletteParser;
|
||||
const Shortcuts = Me.imports.shortcuts;
|
||||
const gettext = imports.gettext.domain(Me.metadata['gettext-domain']).gettext;
|
||||
const _ = function(string) {
|
||||
|
|
@ -150,26 +151,32 @@ const DrawingPage = new GObject.Class({
|
|||
|
||||
let palettesFrame = new Frame({ label: _("Palettes") });
|
||||
box.add(palettesFrame);
|
||||
let palettesFrameBox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
|
||||
palettesFrame.add(palettesFrameBox);
|
||||
|
||||
let palettesScrolledWindow = new Gtk.ScrolledWindow({ vscrollbar_policy: Gtk.PolicyType.NEVER, margin_top: MARGIN / 2, margin_bottom: MARGIN / 2 });
|
||||
palettesFrame.add(palettesScrolledWindow);
|
||||
let palettesScrolledWindow = new Gtk.ScrolledWindow({ vscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
palettesFrameBox.add(palettesScrolledWindow);
|
||||
let palettesViewport = new Gtk.Viewport({ margin_top: MARGIN / 2, margin_bottom: MARGIN / 2 });
|
||||
palettesScrolledWindow.add(palettesViewport);
|
||||
this.palettesListBox = new Gtk.ListBox({ selection_mode: 0, hexpand: true });
|
||||
this.palettesListBox.get_style_context().add_class('background');
|
||||
this.palettesListBox.get_accessible().set_name(this.schema.get_key('palettes').get_summary());
|
||||
this.palettesListBox.get_accessible().set_description(this.schema.get_key('palettes').get_description());
|
||||
palettesScrolledWindow.add(this.palettesListBox);
|
||||
palettesViewport.add(this.palettesListBox);
|
||||
|
||||
this.settings.connect('changed::palettes', this._updatePalettes.bind(this));
|
||||
this._updatePalettes();
|
||||
|
||||
this.addBox = new Gtk.Box(ROWBOX_MARGIN_PARAMS);
|
||||
this.addBox.margin_bottom = MARGIN; // add space for the scrollbar
|
||||
let addBox = new Gtk.Box(ROWBOX_MARGIN_PARAMS);
|
||||
let addButton = Gtk.Button.new_from_icon_name('list-add-symbolic', Gtk.IconSize.BUTTON);
|
||||
addButton.set_tooltip_text(_("Add a new palette"));
|
||||
this.addBox.pack_start(addButton, true, true, 4);
|
||||
addBox.pack_start(addButton, true, true, 4);
|
||||
addButton.connect('clicked', this._addNewPalette.bind(this));
|
||||
this.palettesListBox.add(this.addBox);
|
||||
this.addBox.get_parent().set_activatable(false);
|
||||
let importButton = Gtk.Button.new_from_icon_name('document-open-symbolic', Gtk.IconSize.BUTTON);
|
||||
importButton.set_tooltip_text(_GTK("Select a File"));
|
||||
addBox.pack_start(importButton, true, true, 4);
|
||||
importButton.connect('clicked', this._importPalette.bind(this));
|
||||
palettesFrameBox.add(addBox);
|
||||
|
||||
let areaFrame = new Frame({ label: _("Area") });
|
||||
box.add(areaFrame);
|
||||
|
|
@ -285,10 +292,9 @@ const DrawingPage = new GObject.Class({
|
|||
|
||||
_updatePalettes: function() {
|
||||
this.palettes = this.settings.get_value('palettes').deep_unpack();
|
||||
this.palettesListBox.get_children().filter(row=> row.get_child() != this.addBox)
|
||||
.slice(this.palettes.length)
|
||||
this.palettesListBox.get_children().slice(this.palettes.length)
|
||||
.forEach(row => this.palettesListBox.remove(row));
|
||||
let paletteBoxes = this.palettesListBox.get_children().map(row => row.get_child()).filter(child => child != this.addBox);
|
||||
let paletteBoxes = this.palettesListBox.get_children().map(row => row.get_child());
|
||||
|
||||
this.palettes.forEach((palette, paletteIndex) => {
|
||||
let [name, colors] = palette;
|
||||
|
|
@ -316,17 +322,20 @@ const DrawingPage = new GObject.Class({
|
|||
paletteBox.get_parent().set_activatable(false);
|
||||
}
|
||||
|
||||
colors.splice(9);
|
||||
while (colors.length < 9)
|
||||
colors.push('transparent');
|
||||
|
||||
let colorsBox = paletteBox.get_children()[1];
|
||||
let colorButtons = colorsBox.get_children();
|
||||
colors.forEach((color, colorIndex) => {
|
||||
let [colorString, displayName] = color.split(':');
|
||||
if (colorButtons[colorIndex]) {
|
||||
colorButtons[colorIndex].color_string = color;
|
||||
colorButtons[colorIndex].color_string = colorString;
|
||||
colorButtons[colorIndex].tooltip_text = displayName || null;
|
||||
} else {
|
||||
let colorButton = new ColorStringButton({ color_string: color, use_alpha: true, show_editor: true, halign: Gtk.Align.START, hexpand: false });
|
||||
let colorButton = new ColorStringButton({ color_string: colorString, tooltip_text: displayName || null,
|
||||
use_alpha: true, show_editor: true,
|
||||
halign: Gtk.Align.START, hexpand: false });
|
||||
colorButton.connect('notify::color-string', this._onPaletteColorChanged.bind(this, paletteIndex, colorIndex));
|
||||
colorsBox.add(colorButton);
|
||||
}
|
||||
|
|
@ -347,6 +356,8 @@ const DrawingPage = new GObject.Class({
|
|||
|
||||
_onPaletteColorChanged: function(paletteIndex, colorIndex, colorButton) {
|
||||
this.palettes[paletteIndex][1][colorIndex] = colorButton.get_rgba().to_string();
|
||||
if (colorButton.tooltip_text)
|
||||
this.palettes[paletteIndex][1][colorIndex] += `:${colorButton.tooltip_text}`;
|
||||
this._savePalettes();
|
||||
},
|
||||
|
||||
|
|
@ -357,6 +368,20 @@ const DrawingPage = new GObject.Class({
|
|||
this._savePalettes();
|
||||
},
|
||||
|
||||
_importPalette: function() {
|
||||
let dialog = new Gtk.FileChooserNative({ action: Gtk.FileChooserAction.OPEN, title: _GTK("Select a File") });
|
||||
let filter = new Gtk.FileFilter();
|
||||
filter.set_name("GIMP Palette (*.gpl)");
|
||||
filter.add_pattern('*.gpl');
|
||||
dialog.add_filter(filter);
|
||||
if (dialog.run() == Gtk.ResponseType.ACCEPT) {
|
||||
let file = dialog.get_file();
|
||||
let palettes = GimpPaletteParser.parseFile(file);
|
||||
palettes.forEach(palette => this.palettes.push(palette));
|
||||
this._savePalettes();
|
||||
}
|
||||
},
|
||||
|
||||
_removePalette: function(paletteIndex) {
|
||||
this.palettes.splice(paletteIndex, 1);
|
||||
this._savePalettes();
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -100,12 +100,12 @@
|
|||
<key type="a(sas)" name="palettes">
|
||||
<default>
|
||||
[
|
||||
("Palette", ["HotPink","Cyan","yellow","Orangered","Chartreuse","DarkViolet","White","Gray","Black"]),
|
||||
("GNOME HIG lighter", ["rgb(153,193,241)","rgb(143,240,164)","rgb(249,240,107)","rgb(255,190,111)","rgb(246,97,81)","rgb(220,138,221)","rgb(205,171,143)","rgb(255,255,255)","rgb(119,118,123)"]),
|
||||
("GNOME HIG light", ["rgb(98,160,241)","rgb(87,227,137)","rgb(248,228,92)","rgb(255,163,72)","rgb(237,51,59)","rgb(192,97,203)","rgb(181,131,90)","rgb(246,245,244)","rgb(94,92,100)"]),
|
||||
("GNOME HIG normal", ["rgb(53,132,228)","rgb(51,209,122)","rgb(246,211,45)","rgb(255,120,0)","rgb(224,27,36)","rgb(145,65,172)","rgb(152,106,68)","rgb(222,221,218)","rgb(61,56,70)"]),
|
||||
("GNOME HIG dark", ["rgb(28,113,216)","rgb(46,194,126)","rgb(245,194,17)","rgb(230,97,0)","rgb(192,28,40)","rgb(129,61,156)","rgb(134,94,60)","rgb(192,191,188)","rgb(36,31,49)"]),
|
||||
("GNOME HIG darker", ["rgb(26,095,180)","rgb(38,162,105)","rgb(229,165,10)","rgb(198,70,0)","rgb(165,29,45)","rgb(97,53,131)","rgb(99,69,44)","rgb(154,153,150)","rgb(0,0,0)"])
|
||||
('Palette', ['HotPink', 'Cyan', 'yellow', 'Orangered', 'Chartreuse', 'DarkViolet', 'White', 'Gray', 'Black']),
|
||||
('GNOME HIG lighter', ['rgb(153,193,241):Blue 1', 'rgb(143,240,164):Green 1', 'rgb(249,240,107):Yellow 1', 'rgb(255,190,111):Orange 1', 'rgb(246,97,81):Red 1', 'rgb(220,138,221):Purple 1', 'rgb(205,171,143):Brown 1', 'rgb(255,255,255):Light 1', 'rgb(119,118,123):Dark 1']),
|
||||
('GNOME HIG light', ['rgb(98,160,234):Blue 2', 'rgb(87,227,137):Green 2', 'rgb(248,228,92):Yellow 2', 'rgb(255,163,72):Orange 2', 'rgb(237,51,59):Red 2', 'rgb(192,97,203):Purple 2', 'rgb(181,131,90):Brown 2', 'rgb(246,245,244):Light 2', 'rgb(94,92,100):Dark 2']),
|
||||
('GNOME HIG normal', ['rgb(53,132,228):Blue 3', 'rgb(51,209,122):Green 3', 'rgb(246,211,45):Yellow 3', 'rgb(255,120,0):Orange 3', 'rgb(224,27,36):Red 3', 'rgb(145,65,172):Purple 3', 'rgb(152,106,68):Brown 3', 'rgb(222,221,218):Light 3', 'rgb(61,56,70):Dark 3']),
|
||||
('GNOME HIG dark', ['rgb(28,113,216):Blue 4', 'rgb(46,194,126):Green 4', 'rgb(245,194,17):Yellow 4', 'rgb(230,97,0):Orange 4', 'rgb(192,28,40):Red 4', 'rgb(129,61,156):Purple 4', 'rgb(134,94,60):Brown 4', 'rgb(192,191,188):Light 4', 'rgb(36,31,49):Dark 4']),
|
||||
('GNOME HIG darker', ['rgb(26,95,180):Blue 5', 'rgb(38,162,105):Green 5', 'rgb(229,165,10):Yellow 5', 'rgb(198,70,0):Orange 5', 'rgb(165,29,45):Red 5', 'rgb(97,53,131):Purple 5', 'rgb(99,69,44):Brown 5', 'rgb(154,153,150):Light 5', 'rgb(0,0,0):Dark 5'])
|
||||
]
|
||||
</default>
|
||||
<summary>Color palettes</summary>
|
||||
|
|
|
|||
Loading…
Reference in New Issue