group menu items at the bottom

In addition, 'Save as a SVG file' -> "Export to a SVG file'.
This commit is contained in:
abakkk 2020-09-16 22:12:54 +02:00
parent f9e25fa8f6
commit 072adde856
8 changed files with 124 additions and 81 deletions

View File

@ -1139,7 +1139,7 @@ var DrawingArea = new Lang.Class({
return [getGiconSvgContent, getImageSvgContent];
},
saveAsSvg: function() {
exportToSvg: function() {
// stop drawing or writing
if (this.currentElement && this.currentElement.shape == Shapes.TEXT && this.isWriting) {
this._stopWriting();
@ -1204,8 +1204,8 @@ var DrawingArea = new Lang.Class({
this._saveAsJson(Files.Jsons.getNamed(name), false, callback);
},
saveAsJson: function() {
this._saveAsJson(Files.Jsons.getDated(), true);
saveAsJson: function(notify, callback) {
this._saveAsJson(Files.Jsons.getDated(), notify, callback);
},
savePersistent: function() {

View File

@ -200,8 +200,8 @@ const AreaManager = new Lang.Class({
// available when writing
this.internalKeybindings2 = {
'save-as-svg': this.activeArea.saveAsSvg.bind(this.activeArea),
'save-as-json': this.activeArea.saveAsJson.bind(this.activeArea),
'export-to-svg': this.activeArea.exportToSvg.bind(this.activeArea),
'save-as-json': this.activeArea.saveAsJson.bind(this.activeArea, true, null),
'open-previous-json': this.activeArea.loadPreviousJson.bind(this.activeArea),
'open-next-json': this.activeArea.loadNextJson.bind(this.activeArea),
'toggle-background': this.activeArea.toggleBackground.bind(this.activeArea),

View File

@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Draw On Your Screen\n"
"Report-Msgid-Bugs-To: https://framagit.org/abakkk/DrawOnYourScreen/issues\n"
"POT-Creation-Date: 2020-09-11 03:43+0200\n"
"POT-Creation-Date: 2020-09-16 21:11+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -272,13 +272,19 @@ msgstr ""
msgid "Smooth"
msgstr ""
msgid "Open drawing"
msgstr ""
msgid "Save drawing as…"
msgstr ""
msgid "Palette"
msgstr ""
msgid "Color"
msgstr ""
msgid "Open drawing"
msgid "Type a name"
msgstr ""
#. Translators: "Preferences" page in preferences
@ -535,6 +541,9 @@ msgstr ""
msgid "Erase last brushstroke"
msgstr ""
msgid "Export drawing to a SVG file"
msgstr ""
msgid "Increment line width"
msgstr ""
@ -559,9 +568,6 @@ msgstr ""
msgid "Save drawing"
msgstr ""
msgid "Save drawing as a SVG file"
msgstr ""
msgid "Select color 1"
msgstr ""

139
menu.js
View File

@ -30,6 +30,7 @@ const St = imports.gi.St;
const BoxPointer = imports.ui.boxpointer;
const Config = imports.misc.config;
const Dash = imports.ui.dash;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const Slider = imports.ui.slider;
@ -221,12 +222,17 @@ var DrawingMenu = new Lang.Class({
_redisplay: function() {
this.menu.removeAll();
this.actionButtons = [];
let groupItem = new PopupMenu.PopupBaseMenuItem({ reactive: false, can_focus: false, style_class: 'draw-on-your-screen-menu-group-item' });
getActor(groupItem).add_child(this._createActionButton(_("Undo"), this.area.undo.bind(this.area), 'edit-undo-symbolic'));
getActor(groupItem).add_child(this._createActionButton(_("Redo"), this.area.redo.bind(this.area), 'edit-redo-symbolic'));
getActor(groupItem).add_child(this._createActionButton(_("Erase"), this.area.deleteLastElement.bind(this.area), 'edit-clear-all-symbolic'));
getActor(groupItem).add_child(this._createActionButton(_("Smooth"), this.area.smoothLastElement.bind(this.area), Files.Icons.SMOOTH));
this.undoButton = new ActionButton(_("Undo"), 'edit-undo-symbolic', this.area.undo.bind(this.area), this._updateActionSensitivity.bind(this));
this.redoButton = new ActionButton(_("Redo"), 'edit-redo-symbolic', this.area.redo.bind(this.area), this._updateActionSensitivity.bind(this));
this.eraseButton = new ActionButton(_("Erase"), 'edit-clear-all-symbolic', this.area.deleteLastElement.bind(this.area), this._updateActionSensitivity.bind(this));
this.smoothButton = new ActionButton(_("Smooth"), Files.Icons.SMOOTH, this.area.smoothLastElement.bind(this.area), this._updateActionSensitivity.bind(this));
this.eraseButton.child.add_style_class_name('draw-on-your-screen-menu-destructive-button');
this.smoothButton.child.add_style_class_name('draw-on-your-screen-menu-destructive-button');
getActor(groupItem).add_child(this.undoButton);
getActor(groupItem).add_child(this.redoButton);
getActor(groupItem).add_child(this.eraseButton);
getActor(groupItem).add_child(this.smoothButton);
this.menu.addMenuItem(groupItem);
this._addSeparator(this.menu, true);
@ -275,40 +281,33 @@ var DrawingMenu = new Lang.Class({
this._addSeparator(this.menu);
this._addDrawingNameItem(this.menu);
this._addOpenDrawingSubMenuItem(this.menu, 'document-open-symbolic');
this._addSaveDrawingSubMenuItem(this.menu, 'document-save-as-symbolic');
this._addOpenDrawingSubMenuItem(this.menu, _("Open drawing"), 'document-open-symbolic');
this._addSaveDrawingSubMenuItem(this.menu, _("Save drawing as…"), 'document-save-as-symbolic');
this._addSeparator(this.menu);
this.menu.addAction(getSummary('save-as-svg'), this.area.saveAsSvg.bind(this.area), Files.Icons.DOCUMENT_EXPORT);
this.menu.addAction(getSummary('open-preferences'), areaManager.openPreferences.bind(areaManager), 'document-page-setup-symbolic');
this.menu.addAction(getSummary('toggle-help'), () => { this.close(); this.area.toggleHelp(); }, 'preferences-desktop-keyboard-shortcuts-symbolic');
groupItem = new PopupMenu.PopupBaseMenuItem({ reactive: false, can_focus: false, style_class: 'draw-on-your-screen-menu-group-item' });
this.saveButton = new ActionButton(getSummary('save-as-json'), 'document-save-symbolic', this.area.saveAsJson.bind(this.area, false, this._onDrawingSaved.bind(this)), null);
this.svgButton = new ActionButton(getSummary('export-to-svg'), Files.Icons.DOCUMENT_EXPORT, this.area.exportToSvg.bind(this.area), null);
this.prefsButton = new ActionButton(getSummary('open-preferences'), 'document-page-setup-symbolic', areaManager.openPreferences.bind(areaManager), null);
this.helpButton = new ActionButton(getSummary('toggle-help'), 'preferences-desktop-keyboard-shortcuts-symbolic', () => { this.close(); this.area.toggleHelp(); }, null);
getActor(groupItem).add_child(this.saveButton);
getActor(groupItem).add_child(this.svgButton);
getActor(groupItem).add_child(this.prefsButton);
getActor(groupItem).add_child(this.helpButton);
this.menu.addMenuItem(groupItem);
this._updateActionSensitivity();
this._updateSectionVisibility();
},
// from system.js (GS 3.34-)
_createActionButton: function(accessibleName, callback, icon) {
let button = new St.Button({ track_hover: true,
x_align: Clutter.ActorAlign.CENTER,
accessible_name: accessibleName,
// use 'popup-menu' and 'popup-menu-item' style classes to provide theme colors
style_class: 'system-menu-action popup-menu-item popup-menu' });
button.child = new St.Icon(typeof icon == 'string' ? { icon_name: icon } : { gicon: icon });
button.connect('clicked', () => {
callback();
this._updateActionSensitivity();
});
button.bind_property('reactive', button, 'can_focus', GObject.BindingFlags.DEFAULT);
this.actionButtons.push(button);
return new St.Bin({ child: button, x_expand: true });
},
_updateActionSensitivity: function() {
let [undoButton, redoButton, eraseButton, smoothButton] = this.actionButtons;
undoButton.reactive = this.area.elements.length > 0;
redoButton.reactive = this.area.undoneElements.length > 0;
eraseButton.reactive = this.area.elements.length > 0;
smoothButton.reactive = this.area.elements.length > 0 && this.area.elements[this.area.elements.length - 1].shape == this.drawingTools.NONE;
this.undoButton.child.reactive = this.area.elements.length > 0;
this.redoButton.child.reactive = this.area.undoneElements.length > 0;
this.eraseButton.child.reactive = this.area.elements.length > 0;
this.smoothButton.child.reactive = this.area.elements.length > 0 && this.area.elements[this.area.elements.length - 1].shape == this.drawingTools.NONE;
this.saveButton.child.reactive = this.area.elements.length > 0;
this.svgButton.child.reactive = this.area.elements.length > 0;
this.saveDrawingSubMenuItem.setSensitive(this.area.elements.length > 0);
},
_updateSectionVisibility: function() {
@ -577,8 +576,8 @@ var DrawingMenu = new Lang.Class({
}
},
_addOpenDrawingSubMenuItem: function(menu, icon) {
let item = new PopupMenu.PopupSubMenuMenuItem(_("Open drawing"), true);
_addOpenDrawingSubMenuItem: function(menu, label, icon) {
let item = new PopupMenu.PopupSubMenuMenuItem(label, true);
this.openDrawingSubMenuItem = item;
this.openDrawingSubMenu = item.menu;
item.setSensitive(Boolean(Files.Jsons.getSorted().length));
@ -605,7 +604,7 @@ var DrawingMenu = new Lang.Class({
let subItem = this.openDrawingSubMenu.addAction(`<i>${String(json)}</i>`, () => {
this.area.loadJson(json);
this._updateDrawingNameMenuItem();
this._updateSaveDrawingSubMenuItemSensitivity();
this._updateActionSensitivity();
}, json.gicon);
subItem.label.get_clutter_text().set_use_markup(true);
@ -617,7 +616,7 @@ var DrawingMenu = new Lang.Class({
});
getActor(subItem).add_child(expander);
let insertButton = new St.Button({ style_class: 'button draw-on-your-screen-menu-insert-button',
let insertButton = new St.Button({ style_class: 'button draw-on-your-screen-menu-inline-button',
child: new St.Icon({ icon_name: 'insert-image-symbolic',
style_class: 'popup-menu-icon' }) });
getActor(subItem).add_child(insertButton);
@ -630,7 +629,7 @@ var DrawingMenu = new Lang.Class({
this._updateSectionVisibility();
});
let deleteButton = new St.Button({ style_class: 'button draw-on-your-screen-menu-delete-button',
let deleteButton = new St.Button({ style_class: 'button draw-on-your-screen-menu-inline-button draw-on-your-screen-menu-destructive-button',
child: new St.Icon({ icon_name: 'edit-delete-symbolic',
style_class: 'popup-menu-icon' }) });
getActor(subItem).add_child(deleteButton);
@ -645,10 +644,9 @@ var DrawingMenu = new Lang.Class({
this.openDrawingSubMenuItem.setSensitive(!this.openDrawingSubMenu.isEmpty());
},
_addSaveDrawingSubMenuItem: function(menu, icon) {
let item = new PopupMenu.PopupSubMenuMenuItem(getSummary('save-as-json'), true);
_addSaveDrawingSubMenuItem: function(menu, label, icon) {
let item = new PopupMenu.PopupSubMenuMenuItem(label, true);
this.saveDrawingSubMenuItem = item;
this._updateSaveDrawingSubMenuItemSensitivity();
this.saveDrawingSubMenu = item.menu;
item.icon.set_icon_name(icon);
@ -674,13 +672,14 @@ var DrawingMenu = new Lang.Class({
_populateSaveDrawingSubMenu: function() {
this.saveDrawingSubMenu.removeAll();
let saveEntry = new DrawingMenuEntry({ initialTextGetter: Files.getDateString,
entryActivateCallback: (text) => {
this.area.saveAsJsonWithName(text, this._onDrawingSaved.bind(this));
this.saveDrawingSubMenu.toggle();
},
invalidStrings: [Me.metadata['persistent-file-name'], '/'],
primaryIconName: 'insert-text' });
let saveEntry = new Entry({ initialTextGetter: () => this.area.currentJson ? this.area.currentJson.name : "",
hint_text: _("Type a name"),
entryActivateCallback: (text) => {
this.area.saveAsJsonWithName(text, this._onDrawingSaved.bind(this));
this.saveDrawingSubMenu.toggle();
},
invalidStrings: [Me.metadata['persistent-file-name'], '/'],
primaryIconName: 'insert-text' });
this.saveDrawingSubMenu.addMenuItem(saveEntry.item);
},
@ -712,8 +711,51 @@ const updateSubMenuAdjustment = function(itemActor) {
adjustment.set_value(newScrollValue);
};
// An action button that uses upstream dash item tooltips.
const ActionButton = new Lang.Class({
Name: 'DrawOnYourScreenDrawingMenuActionButton',
Extends: St.Bin,
_labelShowing: false,
_resetHoverTimeoutId: 0,
_showLabelTimeoutId: 0,
showLabel: Dash.DashItemContainer.prototype.showLabel,
hideLabel: Dash.DashItemContainer.prototype.hideLabel,
_syncLabel: Dash.Dash.prototype._syncLabel,
_init: function(name, icon, callback, callbackAfter) {
this._labelText = name;
let button = new St.Button({ track_hover: true,
x_align: Clutter.ActorAlign.CENTER,
accessible_name: name,
// use 'popup-menu' and 'popup-menu-item' style classes to provide theme colors
//style_class: 'system-menu-action popup-menu-item popup-menu' });
style_class: 'button draw-on-your-screen-menu-action-button' });
button.child = new St.Icon(typeof icon == 'string' ? { icon_name: icon } : { gicon: icon });
button.connect('clicked', () => {
callback();
if (callbackAfter)
callbackAfter();
});
button.bind_property('reactive', button, 'can_focus', GObject.BindingFlags.DEFAULT);
button.connect('notify::hover', () => this._syncLabel(this));
this.parent({ child: button, x_expand: true });
},
get label() {
if (!this._label) {
this._label = new St.Label({ style_class: 'dash-label' });
Main.layoutManager.uiGroup.add_actor(this._label);
this.connect('destroy', () => this._label.destroy());
}
return this._label;
}
});
// based on searchItem.js, https://github.com/leonardo-bartoli/gnome-shell-extension-Recents
const DrawingMenuEntry = new Lang.Class({
const Entry = new Lang.Class({
Name: 'DrawOnYourScreenDrawingMenuEntry',
_init: function(params) {
@ -726,6 +768,7 @@ const DrawingMenuEntry = new Lang.Class({
this.itemActor = GS_VERSION < '3.33.0' ? this.item.actor : this.item;
this.entry = new St.Entry({
hint_text: params.hint_text || "",
style_class: 'search-entry draw-on-your-screen-menu-entry',
track_hover: true,
reactive: true,

Binary file not shown.

View File

@ -131,6 +131,10 @@
<default>["Delete"]</default>
<summary>Erase last brushstroke</summary>
</key>
<key type="as" name="export-to-svg">
<default>["&lt;Primary&gt;&lt;Alt&gt;s"]</default>
<summary>Export drawing to a SVG file</summary>
</key>
<key type="as" name="increment-line-width">
<default><![CDATA[['<Primary>KP_Add','<Primary><Shift>plus']]]></default>
<summary>Increment line width</summary>
@ -163,10 +167,6 @@
<default>["&lt;Primary&gt;s"]</default>
<summary>Save drawing</summary>
</key>
<key type="as" name="save-as-svg">
<default>["&lt;Primary&gt;&lt;Alt&gt;s"]</default>
<summary>Save drawing as a SVG file</summary>
</key>
<key type="as" name="select-color1">
<default><![CDATA[['<Primary>KP_1','<Primary>1']]]></default>
<summary>Select color 1</summary>

View File

@ -52,7 +52,7 @@ var INTERNAL_KEYBINDINGS = [
['switch-font-family', 'switch-font-family-reverse', 'switch-font-weight', 'switch-font-style', 'switch-text-alignment'],
['switch-image-file', 'switch-image-file-reverse', 'paste-image-files'],
['toggle-panel-and-dock-visibility', 'toggle-background', 'toggle-grid', 'toggle-square-area'],
['open-next-json', 'open-previous-json', 'save-as-json', 'save-as-svg', 'open-preferences', 'toggle-help'],
['open-next-json', 'open-previous-json', 'save-as-json', 'export-to-svg', 'open-preferences', 'toggle-help'],
];
if (GS_VERSION < '3.36') {

View File

@ -76,23 +76,20 @@
margin-top: 0;
}
/* system-menu-action: from GS 3.34- */
.draw-on-your-screen-menu .system-menu-action {
min-width: 0;
border: none;
border-radius: 32px;
padding: 12px;
margin: 0;
.draw-on-your-screen-menu-destructive-button:hover {
color: #e01b24; /* upstream destructive color, light: #e01b24, dark: #b2161d */
}
.draw-on-your-screen-menu .system-menu-action:hover,
.draw-on-your-screen-menu .system-menu-action:focus {
border: none;
/* override .button upstream style class */
.draw-on-your-screen-menu-action-button {
min-height: 0;
min-width: 0;
border-radius: 32px;
padding: 12px;
}
.draw-on-your-screen-menu .system-menu-action > StIcon {
icon-size: 16px;
.draw-on-your-screen-menu-action-button > StIcon {
icon-size: 1em;
}
.draw-on-your-screen-menu-slider-label {
@ -120,16 +117,13 @@
padding: 0.35em 0.57em;
}
.draw-on-your-screen-menu-delete-button, .draw-on-your-screen-menu-insert-button {
/* override .button upstream style class */
.draw-on-your-screen-menu-inline-button {
min-height: 1px;
padding: 2px 4px; /* default 3px 24px */
}
.draw-on-your-screen-menu-delete-button:hover {
color: #e01b24; /* upstream destructive color, light: #e01b24, dark: #b2161d */
}
.draw-on-your-screen-menu-delete-button .popup-menu-icon, .draw-on-your-screen-menu-insert-button .popup-menu-icon {
.draw-on-your-screen-menu-inline-button .popup-menu-icon {
icon-size: 0.85em; /* default 1.09 */
}