gnome-shell/js/ui/shellEntry.js
Florian Müllner 3b1330880f cleanup: Use Function.prototype.bind()
When not using arrow notation with anonymous functions, we use Lang.bind()
to bind `this` to named callbacks. However since ES5, this functionality
is already provided by Function.prototype.bind() - in fact, Lang.bind()
itself uses it when no extra arguments are specified. Just use the built-in
function directly where possible, and use arrow notation in the few places
where we pass additional arguments.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/23
2018-02-21 13:55:02 +00:00

178 lines
5.5 KiB
JavaScript

// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const St = imports.gi.St;
const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
var EntryMenu = new Lang.Class({
Name: 'ShellEntryMenu',
Extends: PopupMenu.PopupMenu,
_init(entry) {
this.parent(entry, 0, St.Side.TOP);
this._entry = entry;
this._clipboard = St.Clipboard.get_default();
// Populate menu
let item;
item = new PopupMenu.PopupMenuItem(_("Copy"));
item.connect('activate', this._onCopyActivated.bind(this));
this.addMenuItem(item);
this._copyItem = item;
item = new PopupMenu.PopupMenuItem(_("Paste"));
item.connect('activate', this._onPasteActivated.bind(this));
this.addMenuItem(item);
this._pasteItem = item;
this._passwordItem = null;
Main.uiGroup.add_actor(this.actor);
this.actor.hide();
},
_makePasswordItem() {
let item = new PopupMenu.PopupMenuItem('');
item.connect('activate', this._onPasswordActivated.bind(this));
this.addMenuItem(item);
this._passwordItem = item;
},
get isPassword() {
return this._passwordItem != null;
},
set isPassword(v) {
if (v == this.isPassword)
return;
if (v) {
this._makePasswordItem();
this._entry.input_purpose = Gtk.InputPurpose.PASSWORD;
} else {
this._passwordItem.destroy();
this._passwordItem = null;
this._entry.input_purpose = Gtk.InputPurpose.FREE_FORM;
}
},
open(animate) {
this._updatePasteItem();
this._updateCopyItem();
if (this._passwordItem)
this._updatePasswordItem();
this.parent(animate);
this._entry.add_style_pseudo_class('focus');
let direction = Gtk.DirectionType.TAB_FORWARD;
if (!this.actor.navigate_focus(null, direction, false))
this.actor.grab_key_focus();
},
_updateCopyItem() {
let selection = this._entry.clutter_text.get_selection();
this._copyItem.setSensitive(!this._entry.clutter_text.password_char &&
selection && selection != '');
},
_updatePasteItem() {
this._clipboard.get_text(St.ClipboardType.CLIPBOARD,
(clipboard, text) => {
this._pasteItem.setSensitive(text && text != '');
});
},
_updatePasswordItem() {
let textHidden = (this._entry.clutter_text.password_char);
if (textHidden)
this._passwordItem.label.set_text(_("Show Text"));
else
this._passwordItem.label.set_text(_("Hide Text"));
},
_onCopyActivated() {
let selection = this._entry.clutter_text.get_selection();
this._clipboard.set_text(St.ClipboardType.CLIPBOARD, selection);
},
_onPasteActivated() {
this._clipboard.get_text(St.ClipboardType.CLIPBOARD,
(clipboard, text) => {
if (!text)
return;
this._entry.clutter_text.delete_selection();
let pos = this._entry.clutter_text.get_cursor_position();
this._entry.clutter_text.insert_text(text, pos);
});
},
_onPasswordActivated() {
let visible = !!(this._entry.clutter_text.password_char);
this._entry.clutter_text.set_password_char(visible ? '' : '\u25cf');
}
});
function _setMenuAlignment(entry, stageX) {
let [success, entryX, entryY] = entry.transform_stage_point(stageX, 0);
if (success)
entry.menu.setSourceAlignment(entryX / entry.width);
};
function _onButtonPressEvent(actor, event, entry) {
if (entry.menu.isOpen) {
entry.menu.close(BoxPointer.PopupAnimation.FULL);
return Clutter.EVENT_STOP;
} else if (event.get_button() == 3) {
let [stageX, stageY] = event.get_coords();
_setMenuAlignment(entry, stageX);
entry.menu.open(BoxPointer.PopupAnimation.FULL);
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
};
function _onPopup(actor, entry) {
let [success, textX, textY, lineHeight] = entry.clutter_text.position_to_coords(-1);
if (success)
entry.menu.setSourceAlignment(textX / entry.width);
entry.menu.open(BoxPointer.PopupAnimation.FULL);
};
function addContextMenu(entry, params) {
if (entry.menu)
return;
params = Params.parse (params, { isPassword: false });
entry.menu = new EntryMenu(entry);
entry.menu.isPassword = params.isPassword;
entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry });
entry._menuManager.addMenu(entry.menu);
// Add an event handler to both the entry and its clutter_text; the former
// so padding is included in the clickable area, the latter because the
// event processing of ClutterText prevents event-bubbling.
entry.clutter_text.connect('button-press-event', (actor, event) => {
_onButtonPressEvent(actor, event, entry);
});
entry.connect('button-press-event', (actor, event) => {
_onButtonPressEvent(actor, event, entry);
});
entry.connect('popup-menu', actor => { _onPopup(actor, entry); });
entry.connect('destroy', () => {
entry.menu.destroy();
entry.menu = null;
entry._menuManager = null;
});
}