[gnome-shell] shell-entry: Add API to support entry context menus
- From: Florian MÃllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] shell-entry: Add API to support entry context menus
- Date: Mon, 17 Oct 2011 13:30:34 +0000 (UTC)
commit 6257e64d03745abcbd312bf3cd9460c3b46f148e
Author: Florian MÃllner <fmuellner gnome org>
Date: Wed Sep 14 18:47:09 2011 +0200
shell-entry: Add API to support entry context menus
Add addContextMenu() to support context menus on right-click/long-press.
Depending on the parameters passed, the context menu only contains
"Copy"/"Paste" actions or an additional "Show/Hide Text" toggle action
for password entries.
https://bugzilla.gnome.org/show_bug.cgi?id=659275
js/Makefile.am | 1 +
js/ui/shellEntry.js | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 174 insertions(+), 0 deletions(-)
---
diff --git a/js/Makefile.am b/js/Makefile.am
index 7c72637..58e0489 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -46,6 +46,7 @@ nobase_dist_js_DATA = \
ui/messageTray.js \
ui/modalDialog.js \
ui/networkAgent.js \
+ ui/shellEntry.js \
ui/shellMountOperation.js \
ui/notificationDaemon.js \
ui/overview.js \
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
new file mode 100644
index 0000000..1dc0088
--- /dev/null
+++ b/js/ui/shellEntry.js
@@ -0,0 +1,173 @@
+const Clutter = imports.gi.Clutter;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+const St = imports.gi.St;
+
+const Main = imports.ui.main;
+const Params = imports.misc.params;
+const PopupMenu = imports.ui.popupMenu;
+
+
+function _EntryMenu(entry, params) {
+ this._init(entry, params);
+};
+
+_EntryMenu.prototype = {
+ __proto__: PopupMenu.PopupMenu.prototype,
+
+ _init: function(entry, params) {
+ params = Params.parse (params, { isPassword: false });
+
+ PopupMenu.PopupMenu.prototype._init.call(this, entry, 0, St.Side.TOP);
+
+ this.actor.add_style_class_name('entry-context-menu');
+
+ this._entry = entry;
+ this._clipboard = St.Clipboard.get_default();
+
+ // Populate menu
+ let item;
+ item = new PopupMenu.PopupMenuItem(_("Copy"));
+ item.connect('activate', Lang.bind(this, this._onCopyActivated));
+ this.addMenuItem(item);
+ this._copyItem = item;
+
+ item = new PopupMenu.PopupMenuItem(_("Paste"));
+ item.connect('activate', Lang.bind(this, this._onPasteActivated));
+ this.addMenuItem(item);
+ this._pasteItem = item;
+
+ this._passwordItem = null;
+ if (params.isPassword) {
+ item = new PopupMenu.PopupMenuItem('');
+ item.connect('activate', Lang.bind(this,
+ this._onPasswordActivated));
+ this.addMenuItem(item);
+ this._passwordItem = item;
+ }
+
+ Main.uiGroup.add_actor(this.actor);
+ this.actor.hide();
+ },
+
+ open: function() {
+ this._updatePasteItem();
+ this._updateCopyItem();
+ if (this._passwordItem)
+ this._updatePasswordItem();
+
+ let direction = Gtk.DirectionType.TAB_FORWARD;
+ if (!this.actor.navigate_focus(null, direction, false))
+ this.actor.grab_key_focus();
+
+ PopupMenu.PopupMenu.prototype.open.call(this);
+ },
+
+ _updateCopyItem: function() {
+ let selection = this._entry.clutter_text.get_selection();
+ this._copyItem.setSensitive(selection && selection != '');
+ },
+
+ _updatePasteItem: function() {
+ this._clipboard.get_text(Lang.bind(this,
+ function(clipboard, text) {
+ this._pasteItem.setSensitive(text && text != '');
+ }));
+ },
+
+ _updatePasswordItem: function() {
+ 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: function() {
+ let selection = this._entry.clutter_text.get_selection();
+ this._clipboard.set_text(selection);
+ },
+
+ _onPasteActivated: function() {
+ this._clipboard.get_text(Lang.bind(this,
+ function(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: function() {
+ 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 _onClicked(action, actor) {
+ let entry = actor._menu ? actor : actor.get_parent();
+
+ if (entry._menu.isOpen) {
+ entry._menu.close();
+ } else if (action.get_button() == 3) {
+ let [stageX, stageY] = action.get_coords();
+ _setMenuAlignment(entry, stageX);
+ entry._menu.open();
+ }
+};
+
+function _onLongPress(action, actor, state) {
+ let entry = actor._menu ? actor : actor.get_parent();
+
+ if (state == Clutter.LongPressState.QUERY)
+ return action.get_button() == 1 && !entry._menu.isOpen;
+
+ if (state == Clutter.LongPressState.ACTIVATE) {
+ let [stageX, stageY] = action.get_coords();
+ _setMenuAlignment(entry, stageX);
+ entry._menu.open();
+ }
+ return false;
+};
+
+function _onPopup(actor) {
+ let entry = actor._menu ? actor : actor.get_parent();
+ let [success, textX, textY, lineHeight] = entry.clutter_text.position_to_coords(-1);
+ if (success)
+ entry._menu.setSourceAlignment(textX / entry.width);
+ entry._menu.open();
+};
+
+function addContextMenu(entry, params) {
+ if (entry._menu)
+ return;
+
+ entry._menu = new _EntryMenu(entry, params);
+ entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry });
+ entry._menuManager.addMenu(entry._menu);
+
+ let clickAction;
+
+ // Add a click action 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.
+ clickAction = new Clutter.ClickAction();
+ clickAction.connect('clicked', _onClicked);
+ clickAction.connect('long-press', _onLongPress);
+ entry.clutter_text.add_action(clickAction);
+
+ clickAction = new Clutter.ClickAction();
+ clickAction.connect('clicked', _onClicked);
+ clickAction.connect('long-press', _onLongPress);
+ entry.add_action(clickAction);
+
+ entry.connect('popup-menu', _onPopup);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]