diff --git a/draw.js b/draw.js
index 087f504..b3853bb 100644
--- a/draw.js
+++ b/draw.js
@@ -2066,504 +2066,3 @@ var DrawingHelper = new Lang.Class({
}
});
-const getActor = function(object) {
- return GS_VERSION < '3.33.0' ? object.actor : object;
-};
-
-const DrawingMenu = new Lang.Class({
- Name: 'DrawOnYourScreenDrawingMenu',
-
- _init: function(area, monitor) {
- this.area = area;
- let side = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL ? St.Side.RIGHT : St.Side.LEFT;
- this.menu = new PopupMenu.PopupMenu(Main.layoutManager.dummyCursor, 0.25, side);
- this.menuManager = new PopupMenu.PopupMenuManager(GS_VERSION < '3.33.0' ? { actor: this.area } : this.area);
- this.menuManager.addMenu(this.menu);
-
- Main.layoutManager.uiGroup.add_actor(this.menu.actor);
- this.menu.actor.add_style_class_name('background-menu draw-on-your-screen-menu');
- this.menu.actor.set_style('max-height:' + monitor.height + 'px;');
- this.menu.actor.hide();
- this.hasSeparators = monitor.height >= 750;
-
- // do not close the menu on item activated
- this.menu.itemActivated = () => {};
- this.menu.connect('open-state-changed', this._onMenuOpenStateChanged.bind(this));
-
- // Case where the menu is closed (escape key) while the save entry clutter_text is active:
- // St.Entry clutter_text set the DEFAULT cursor on leave event with a delay and
- // overrides the cursor set by area.updatePointerCursor().
- // In order to update drawing cursor on menu closed, we need to leave the saveEntry before closing menu.
- // Since escape key press event can't be captured easily, the job is done in the menu close function.
- let menuCloseFunc = this.menu.close;
- this.menu.close = (animate) => {
- if (this.saveDrawingSubMenu && this.saveDrawingSubMenu.isOpen)
- this.saveDrawingSubMenu.close();
- menuCloseFunc.bind(this.menu)(animate);
- };
-
- this.colorIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(COLOR_ICON_PATH) });
- this.strokeIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(STROKE_ICON_PATH) });
- this.fillIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(FILL_ICON_PATH) });
- this.fillRuleNonzeroIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(FILLRULE_NONZERO_ICON_PATH) });
- this.fillRuleEvenoddIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(FILLRULE_EVENODD_ICON_PATH) });
- this.linejoinIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(LINEJOIN_ICON_PATH) });
- this.linecapIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(LINECAP_ICON_PATH) });
- this.fullLineIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(FULL_LINE_ICON_PATH) });
- this.dashedLineIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(DASHED_LINE_ICON_PATH) });
- },
-
- disable: function() {
- this.menuManager.removeMenu(this.menu);
- Main.layoutManager.uiGroup.remove_actor(this.menu.actor);
- this.menu.destroy();
- },
-
- _onMenuOpenStateChanged: function(menu, open) {
- if (open) {
- this.area.setPointerCursor('DEFAULT');
- } else {
- this.area.updatePointerCursor();
- // actionMode has changed, set previous actionMode in order to keep internal shortcuts working
- this.area.updateActionMode();
- this.area.grab_key_focus();
- }
- },
-
- popup: function() {
- if (this.menu.isOpen) {
- this.close();
- } else {
- this.open();
- this.menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
- }
- },
-
- open: function(x, y) {
- if (this.menu.isOpen)
- return;
- if (x === undefined || y === undefined)
- [x, y] = [this.area.monitor.x + this.area.monitor.width / 2, this.area.monitor.y + this.area.monitor.height / 2];
- this._redisplay();
- Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0);
- let monitor = this.area.monitor;
- this.menu._arrowAlignment = (y - monitor.y) / monitor.height;
- this.menu.open(BoxPointer.PopupAnimation.NONE);
- this.menuManager.ignoreRelease();
- },
-
- close: function() {
- if (this.menu.isOpen)
- this.menu.close();
- },
-
- _redisplay: function() {
- this.menu.removeAll();
-
- this.menu.addAction(_("Undo"), this.area.undo.bind(this.area), 'edit-undo-symbolic');
- this.menu.addAction(_("Redo"), this.area.redo.bind(this.area), 'edit-redo-symbolic');
- this.menu.addAction(_("Erase"), this.area.deleteLastElement.bind(this.area), 'edit-clear-all-symbolic');
- this.menu.addAction(_("Smooth"), this.area.smoothLastElement.bind(this.area), 'format-text-strikethrough-symbolic');
- this._addSeparator(this.menu);
-
- this._addSubMenuItem(this.menu, 'document-edit-symbolic', ToolNames, this.area, 'currentTool', this._updateSectionVisibility.bind(this));
- this._addColorSubMenuItem(this.menu);
- this.fillItem = this._addSwitchItem(this.menu, _("Fill"), this.strokeIcon, this.fillIcon, this.area, 'fill', this._updateSectionVisibility.bind(this));
- this.fillSection = new PopupMenu.PopupMenuSection();
- this.fillSection.itemActivated = () => {};
- this.fillRuleItem = this._addSwitchItem(this.fillSection, _("Evenodd"), this.fillRuleNonzeroIcon, this.fillRuleEvenoddIcon, this.area, 'currentEvenodd');
- this.menu.addMenuItem(this.fillSection);
- this._addSeparator(this.menu);
-
- let lineSection = new PopupMenu.PopupMenuSection();
- this._addSliderItem(lineSection, this.area, 'currentLineWidth');
- this._addSubMenuItem(lineSection, this.linejoinIcon, LineJoinNames, this.area, 'currentLineJoin');
- this._addSubMenuItem(lineSection, this.linecapIcon, LineCapNames, this.area, 'currentLineCap');
- this._addSwitchItem(lineSection, _("Dashed"), this.fullLineIcon, this.dashedLineIcon, this.area, 'dashedLine');
- this._addSeparator(lineSection);
- this.menu.addMenuItem(lineSection);
- lineSection.itemActivated = () => {};
- this.lineSection = lineSection;
-
- let fontSection = new PopupMenu.PopupMenuSection();
- let FontGenericNamesCopy = Object.create(FontGenericNames);
- FontGenericNamesCopy[0] = this.area.currentThemeFontFamily;
- this._addSubMenuItem(fontSection, 'font-x-generic-symbolic', FontGenericNamesCopy, this.area, 'currentFontGeneric');
- this._addSubMenuItem(fontSection, 'format-text-bold-symbolic', FontWeightNames, this.area, 'currentFontWeight');
- this._addSubMenuItem(fontSection, 'format-text-italic-symbolic', FontStyleNames, this.area, 'currentFontStyle');
- this._addSwitchItem(fontSection, _("Right aligned"), 'format-justify-left-symbolic', 'format-justify-right-symbolic', this.area, 'currentTextRightAligned');
- this._addSeparator(fontSection);
- this.menu.addMenuItem(fontSection);
- fontSection.itemActivated = () => {};
- this.fontSection = fontSection;
-
- let manager = Extension.manager;
- this._addSimpleSwitchItem(this.menu, _("Hide panel and dock"), manager.hiddenList ? true : false, manager.togglePanelAndDockOpacity.bind(manager));
- this._addSimpleSwitchItem(this.menu, _("Add a drawing background"), this.area.hasBackground, this.area.toggleBackground.bind(this.area));
- this._addSimpleSwitchItem(this.menu, _("Add a grid overlay"), this.area.hasGrid, this.area.toggleGrid.bind(this.area));
- this._addSimpleSwitchItem(this.menu, _("Square drawing area"), this.area.isSquareArea, this.area.toggleSquareArea.bind(this.area));
- this._addSeparator(this.menu);
-
- this._addDrawingNameItem(this.menu);
- this._addOpenDrawingSubMenuItem(this.menu);
- this._addSaveDrawingSubMenuItem(this.menu);
-
- this.menu.addAction(_("Save drawing as a SVG file"), this.area.saveAsSvg.bind(this.area), 'image-x-generic-symbolic');
- this.menu.addAction(_("Edit style"), manager.openUserStyleFile.bind(manager), 'document-page-setup-symbolic');
- this.menu.addAction(_("Show help"), () => { this.close(); this.area.toggleHelp(); }, 'preferences-desktop-keyboard-shortcuts-symbolic');
-
- this._updateSectionVisibility();
- },
-
- _updateSectionVisibility: function() {
- if (this.area.currentTool != Shapes.TEXT) {
- this.lineSection.actor.show();
- this.fontSection.actor.hide();
- this.fillItem.setSensitive(true);
- this.fillSection.setSensitive(true);
- } else {
- this.lineSection.actor.hide();
- this.fontSection.actor.show();
- this.fillItem.setSensitive(false);
- this.fillSection.setSensitive(false);
- }
-
- if (this.area.fill)
- this.fillSection.actor.show();
- else
- this.fillSection.actor.hide();
- },
-
- _addSwitchItem: function(menu, label, iconFalse, iconTrue, target, targetProperty, onToggled) {
- let item = new PopupMenu.PopupSwitchMenuItem(label, target[targetProperty]);
-
- item.icon = new St.Icon({ style_class: 'popup-menu-icon' });
- getActor(item).insert_child_at_index(item.icon, 1);
- let icon = target[targetProperty] ? iconTrue : iconFalse;
- if (icon && icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon))
- item.icon.set_gicon(icon);
- else if (icon)
- item.icon.set_icon_name(icon);
-
- item.connect('toggled', (item, state) => {
- target[targetProperty] = state;
- let icon = target[targetProperty] ? iconTrue : iconFalse;
- if (icon && icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon))
- item.icon.set_gicon(icon);
- else if (icon)
- item.icon.set_icon_name(icon);
- if (onToggled)
- onToggled();
- });
- menu.addMenuItem(item);
- return item;
- },
-
- _addSimpleSwitchItem: function(menu, label, active, onToggled) {
- let item = new PopupMenu.PopupSwitchMenuItem(label, active);
- item.connect('toggled', onToggled);
- menu.addMenuItem(item);
- },
-
- _addSliderItem: function(menu, target, targetProperty) {
- let item = new PopupMenu.PopupBaseMenuItem({ activate: false });
- let label = new St.Label({ text: _("%d px").format(target[targetProperty]), style_class: 'draw-on-your-screen-menu-slider-label' });
- let slider = new Slider.Slider(target[targetProperty] / 50);
-
- if (GS_VERSION < '3.33.0') {
- slider.connect('value-changed', (slider, value, property) => {
- target[targetProperty] = Math.max(Math.round(value * 50), 0);
- label.set_text(target[targetProperty] + " px");
- if (target[targetProperty] === 0)
- label.add_style_class_name(Extension.WARNING_COLOR_STYLE_CLASS_NAME);
- else
- label.remove_style_class_name(Extension.WARNING_COLOR_STYLE_CLASS_NAME);
- });
- } else {
- slider.connect('notify::value', () => {
- target[targetProperty] = Math.max(Math.round(slider.value * 50), 0);
- label.set_text(target[targetProperty] + " px");
- if (target[targetProperty] === 0)
- label.add_style_class_name(Extension.WARNING_COLOR_STYLE_CLASS_NAME);
- else
- label.remove_style_class_name(Extension.WARNING_COLOR_STYLE_CLASS_NAME);
- });
- }
-
- getActor(slider).x_expand = true;
- getActor(item).add_child(getActor(slider));
- getActor(item).add_child(label);
- if (slider.onKeyPressEvent)
- getActor(item).connect('key-press-event', slider.onKeyPressEvent.bind(slider));
- menu.addMenuItem(item);
- },
-
- _addSubMenuItem: function(menu, icon, obj, target, targetProperty, callback) {
- let item = new PopupMenu.PopupSubMenuMenuItem(_(obj[target[targetProperty]]), icon ? true : false);
- if (icon && icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon))
- item.icon.set_gicon(icon);
- else if (icon)
- item.icon.set_icon_name(icon);
-
- item.menu.itemActivated = () => {
- item.menu.close();
- };
-
- GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
- for (let i in obj) {
- let text;
- if (targetProperty == 'currentFontGeneric')
- text = `${_(obj[i])}`;
- else if (targetProperty == 'currentFontWeight')
- text = `${_(obj[i])}`;
- else if (targetProperty == 'currentFontStyle')
- text = `${_(obj[i])}`;
- else
- text = _(obj[i]);
-
- let iCaptured = Number(i);
- let subItem = item.menu.addAction(text, () => {
- item.label.set_text(_(obj[iCaptured]));
- target[targetProperty] = iCaptured;
- if (callback)
- callback();
- });
-
- subItem.label.get_clutter_text().set_use_markup(true);
-
- // change the display order of tools
- if (obj == ToolNames && i == Shapes.POLYGON)
- item.menu.moveMenuItem(subItem, 4);
- else if (obj == ToolNames && i == Shapes.POLYLINE)
- item.menu.moveMenuItem(subItem, 5);
- }
- return GLib.SOURCE_REMOVE;
- });
- menu.addMenuItem(item);
- },
-
- _addColorSubMenuItem: function(menu) {
- let item = new PopupMenu.PopupSubMenuMenuItem(_("Color"), true);
- item.icon.set_gicon(this.colorIcon);
- item.icon.set_style(`color:${this.area.currentColor.to_string().slice(0, 7)};`);
-
- item.menu.itemActivated = () => {
- item.menu.close();
- };
-
- GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
- for (let i = 1; i < this.area.colors.length; i++) {
- let text = this.area.colors[i].to_string();
- let iCaptured = i;
- let colorItem = item.menu.addAction(text, () => {
- this.area.currentColor = this.area.colors[iCaptured];
- item.icon.set_style(`color:${this.area.currentColor.to_string().slice(0, 7)};`);
- });
- colorItem.label.get_clutter_text().set_use_markup(true);
- // Foreground color markup is not displayed since 3.36, use style instead but the transparency is lost.
- colorItem.label.set_style(`color:${this.area.colors[i].to_string().slice(0, 7)};`);
- }
- return GLib.SOURCE_REMOVE;
- });
- menu.addMenuItem(item);
- },
-
- _addDrawingNameItem: function(menu) {
- this.drawingNameMenuItem = new PopupMenu.PopupMenuItem('', { reactive: false, activate: false });
- this.drawingNameMenuItem.setSensitive(false);
- menu.addMenuItem(this.drawingNameMenuItem);
- this._updateDrawingNameMenuItem();
- },
-
- _updateDrawingNameMenuItem: function() {
- getActor(this.drawingNameMenuItem).visible = this.area.jsonName ? true : false;
- if (this.area.jsonName) {
- let prefix = this.area.drawingContentsHasChanged ? "* " : "";
- this.drawingNameMenuItem.label.set_text(`${prefix}${this.area.jsonName}`);
- this.drawingNameMenuItem.label.get_clutter_text().set_use_markup(true);
- }
- },
-
- _addOpenDrawingSubMenuItem: function(menu) {
- let item = new PopupMenu.PopupSubMenuMenuItem(_("Open drawing"), true);
- this.openDrawingSubMenuItem = item;
- this.openDrawingSubMenu = item.menu;
- item.icon.set_icon_name('document-open-symbolic');
-
- item.menu.itemActivated = () => {
- item.menu.close();
- };
-
- item.menu.openOld = item.menu.open;
- item.menu.open = (animate) => {
- if (!item.menu.isOpen)
- this._populateOpenDrawingSubMenu();
- item.menu.openOld();
- };
-
- menu.addMenuItem(item);
- },
-
- _populateOpenDrawingSubMenu: function() {
- this.openDrawingSubMenu.removeAll();
- let jsonFiles = getJsonFiles();
- jsonFiles.forEach(file => {
- let item = this.openDrawingSubMenu.addAction(`${file.displayName}`, () => {
- this.area.loadJson(file.name);
- this._updateDrawingNameMenuItem();
- this._updateSaveDrawingSubMenuItemSensitivity();
- });
- item.label.get_clutter_text().set_use_markup(true);
-
- let expander = new St.Bin({
- style_class: 'popup-menu-item-expander',
- x_expand: true,
- });
- getActor(item).add_child(expander);
-
- let deleteButton = new St.Button({ style_class: 'draw-on-your-screen-menu-delete-button',
- child: new St.Icon({ icon_name: 'edit-delete-symbolic',
- style_class: 'popup-menu-icon',
- x_align: Clutter.ActorAlign.END }) });
- getActor(item).add_child(deleteButton);
-
- deleteButton.connect('clicked', () => {
- file.delete();
- item.destroy();
- });
- });
-
- this.openDrawingSubMenuItem.setSensitive(!this.openDrawingSubMenu.isEmpty());
- },
-
- _addSaveDrawingSubMenuItem: function(menu) {
- let item = new PopupMenu.PopupSubMenuMenuItem(_("Save drawing"), true);
- this.saveDrawingSubMenuItem = item;
- this._updateSaveDrawingSubMenuItemSensitivity();
- this.saveDrawingSubMenu = item.menu;
- item.icon.set_icon_name('document-save-symbolic');
-
- item.menu.itemActivated = () => {
- item.menu.close();
- };
-
- item.menu.openOld = item.menu.open;
- item.menu.open = (animate) => {
- if (!item.menu.isOpen)
- this._populateSaveDrawingSubMenu();
- item.menu.openOld();
- };
- menu.addMenuItem(item);
- },
-
- _updateSaveDrawingSubMenuItemSensitivity: function() {
- this.saveDrawingSubMenuItem.setSensitive(this.area.elements.length > 0);
- },
-
- _populateSaveDrawingSubMenu: function() {
- this.saveDrawingSubMenu.removeAll();
- let saveEntry = new DrawingMenuEntry({ initialTextGetter: getDateString,
- entryActivateCallback: (text) => {
- this.area.saveAsJsonWithName(text);
- this.saveDrawingSubMenu.toggle();
- this._updateDrawingNameMenuItem();
- },
- invalidStrings: [Me.metadata['persistent-file-name'], '/'],
- primaryIconName: 'insert-text' });
- this.saveDrawingSubMenu.addMenuItem(saveEntry.item);
- },
-
- _addSeparator: function(menu) {
- if (this.hasSeparators) {
- let separatorItem = new PopupMenu.PopupSeparatorMenuItem(' ');
- getActor(separatorItem).add_style_class_name('draw-on-your-screen-menu-separator-item');
- menu.addMenuItem(separatorItem);
- }
- }
-});
-
-// based on searchItem.js, https://github.com/leonardo-bartoli/gnome-shell-extension-Recents
-const DrawingMenuEntry = new Lang.Class({
- Name: 'DrawOnYourScreenDrawingMenuEntry',
-
- _init: function(params) {
- this.params = params;
- this.item = new PopupMenu.PopupBaseMenuItem({ style_class: 'draw-on-your-screen-menu-entry-item',
- activate: false,
- reactive: true,
- can_focus: false });
-
- this.itemActor = GS_VERSION < '3.33.0' ? this.item.actor : this.item;
-
- this.entry = new St.Entry({
- style_class: 'search-entry draw-on-your-screen-menu-entry',
- track_hover: true,
- reactive: true,
- can_focus: true,
- x_expand: true
- });
-
- this.entry.set_primary_icon(new St.Icon({ style_class: 'search-entry-icon',
- icon_name: this.params.primaryIconName }));
-
- this.entry.clutter_text.connect('text-changed', this._onTextChanged.bind(this));
- this.entry.clutter_text.connect('activate', this._onTextActivated.bind(this));
-
- this.clearIcon = new St.Icon({
- style_class: 'search-entry-icon',
- icon_name: 'edit-clear-symbolic'
- });
- this.entry.connect('secondary-icon-clicked', this._reset.bind(this));
-
- getActor(this.item).add_child(this.entry);
- getActor(this.item).connect('notify::mapped', (actor) => {
- if (actor.mapped) {
- this.entry.set_text(this.params.initialTextGetter());
- this.entry.clutter_text.grab_key_focus();
- }
- });
- },
-
- _setError: function(hasError) {
- if (hasError)
- this.entry.add_style_class_name('draw-on-your-screen-menu-entry-error');
- else
- this.entry.remove_style_class_name('draw-on-your-screen-menu-entry-error');
- },
-
- _reset: function() {
- this.entry.text = '';
- this.entry.clutter_text.set_cursor_visible(true);
- this.entry.clutter_text.set_selection(0, 0);
- this._setError(false);
- },
-
- _onTextActivated: function(clutterText) {
- let text = clutterText.get_text();
- if (text.length == 0)
- return;
- if (this._getIsInvalid())
- return;
- this._reset();
- this.params.entryActivateCallback(text);
- },
-
- _onTextChanged: function(clutterText) {
- let text = clutterText.get_text();
- this.entry.set_secondary_icon(text.length ? this.clearIcon : null);
-
- if (text.length)
- this._setError(this._getIsInvalid());
- },
-
- _getIsInvalid: function() {
- for (let i = 0; i < this.params.invalidStrings.length; i++) {
- if (this.entry.text.indexOf(this.params.invalidStrings[i]) != -1)
- return true;
- }
-
- return false;
- }
-});
-
-