From 1abdb528a20b2ddcc59c687c72c5fb13930a87d8 Mon Sep 17 00:00:00 2001 From: abakkk Date: Tue, 30 Jun 2020 23:43:52 +0200 Subject: [PATCH] draw-to-menu 3 --- draw.js | 501 -------------------------------------------------------- 1 file changed, 501 deletions(-) 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; - } -}); - -