Fix behavior of More... links by adding a Link class
We had problems because the More links were reacting on press but other elements were reacting on release. (Often the link would trigger *and* an item.) Just connecting to ::button-release-event on ClutterText gives a stuck grab (since ClutterText gets the press but not the release), so we need more complicated code that we encapsulate into a new class. link.js: new "pseudo-widget" that implements a clickable link. overlay.js: Use Link.Link for the More.. links http://bugzilla.gnome.org/show_bug.cgi?id=573323
This commit is contained in:
parent
6676260308
commit
cb4ad9a963
81
js/ui/link.js
Normal file
81
js/ui/link.js
Normal file
@ -0,0 +1,81 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
// Link is a clickable link. Right now it just handles properly capturing
|
||||
// press and release events and short-circuiting the button handling in
|
||||
// ClutterText, but more features like different colors for hover/pressed states
|
||||
// or a different mouse cursor could be implemented.
|
||||
//
|
||||
// The properties passed in are forwarded to the Clutter.Text() constructor,
|
||||
// so can include, 'text', 'font_name', etc.
|
||||
function Link(props) {
|
||||
this._init(props);
|
||||
}
|
||||
|
||||
Link.prototype = {
|
||||
_init : function(props) {
|
||||
let realProps = { reactive: true };
|
||||
// The user can pass in reactive: false to override the above and get
|
||||
// a non-reactive link (a link to the current page, perhaps)
|
||||
Lang.copyProperties(props, realProps);
|
||||
|
||||
this.actor = new Clutter.Text(realProps);
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
|
||||
this.actor.connect('enter-event', Lang.bind(this, this._onEnter));
|
||||
this.actor.connect('leave-event', Lang.bind(this, this._onLeave));
|
||||
|
||||
this._buttonDown = false;
|
||||
this._havePointer = false;
|
||||
},
|
||||
|
||||
// Update the text of the link
|
||||
setText : function(text) {
|
||||
this.actor.text = text;
|
||||
},
|
||||
|
||||
// We want to react on buttonDown, but if we override button-release-event for
|
||||
// ClutterText, but not button-press-event, we get a stuck grab. Tracking
|
||||
// buttonDown and doing the grab isn't really necessary, but doing it makes
|
||||
// the behavior perfectly correct if the user clicks on one actor, drags
|
||||
// to another and releases - that should not trigger either actor.
|
||||
_onButtonPress : function(actor, event) {
|
||||
this._buttonDown = true;
|
||||
this._havePointer = true; // Hack to work around poor enter/leave tracking in Clutter
|
||||
Clutter.grab_pointer(actor);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_onButtonRelease : function(actor, event) {
|
||||
if (this._buttonDown) {
|
||||
this._buttonDown = false;
|
||||
Clutter.ungrab_pointer(actor);
|
||||
|
||||
if (this._havePointer)
|
||||
this.emit('clicked');
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_onEnter : function(actor, event) {
|
||||
if (event.get_source() == actor)
|
||||
this._havePointer = true;
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_onLeave : function(actor, event) {
|
||||
if (event.get_source() == actor)
|
||||
this._havePointer = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(Link.prototype);
|
@ -11,6 +11,7 @@ const Signals = imports.signals;
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const DocDisplay = imports.ui.docDisplay;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Link = imports.ui.link;
|
||||
const Main = imports.ui.main;
|
||||
const Panel = imports.ui.panel;
|
||||
const Tweener = imports.ui.tweener;
|
||||
@ -198,12 +199,11 @@ Sideshow.prototype = {
|
||||
this._appsSection.append(this._appDisplay.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
let moreAppsBox = new Big.Box({x_align: Big.BoxAlignment.END});
|
||||
this._moreAppsText = new Clutter.Text({ color: SIDESHOW_TEXT_COLOR,
|
||||
font_name: "Sans Bold 14px",
|
||||
text: "More...",
|
||||
height: LABEL_HEIGHT,
|
||||
reactive: true});
|
||||
moreAppsBox.append(this._moreAppsText, Big.BoxPackFlags.EXPAND);
|
||||
this._moreAppsLink = new Link.Link({ color: SIDESHOW_TEXT_COLOR,
|
||||
font_name: "Sans Bold 14px",
|
||||
text: "More...",
|
||||
height: LABEL_HEIGHT });
|
||||
moreAppsBox.append(this._moreAppsLink.actor, Big.BoxPackFlags.EXPAND);
|
||||
this._appsSection.append(moreAppsBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this.actor.add_actor(this._appsSection);
|
||||
@ -226,12 +226,11 @@ Sideshow.prototype = {
|
||||
this._docsSection.append(this._docDisplay.actor, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
let moreDocsBox = new Big.Box({x_align: Big.BoxAlignment.END});
|
||||
this._moreDocsText = new Clutter.Text({ color: SIDESHOW_TEXT_COLOR,
|
||||
font_name: "Sans Bold 14px",
|
||||
text: "More...",
|
||||
height: LABEL_HEIGHT,
|
||||
reactive: true});
|
||||
moreDocsBox.append(this._moreDocsText, Big.BoxPackFlags.EXPAND);
|
||||
this._moreDocsLink = new Link.Link({ color: SIDESHOW_TEXT_COLOR,
|
||||
font_name: "Sans Bold 14px",
|
||||
text: "More...",
|
||||
height: LABEL_HEIGHT });
|
||||
moreDocsBox.append(this._moreDocsLink.actor, Big.BoxPackFlags.EXPAND);
|
||||
this._docsSection.append(moreDocsBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this.actor.add_actor(this._docsSection);
|
||||
@ -267,24 +266,22 @@ Sideshow.prototype = {
|
||||
me._appDisplay.selectFirstItem();
|
||||
});
|
||||
|
||||
this._moreAppsText.connect('button-press-event',
|
||||
this._moreAppsLink.connect('clicked',
|
||||
function(o, event) {
|
||||
if (me._moreAppsMode) {
|
||||
me._unsetMoreAppsMode();
|
||||
} else {
|
||||
me._setMoreAppsMode();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
this._moreDocsText.connect('button-press-event',
|
||||
this._moreDocsLink.connect('clicked',
|
||||
function(o, event) {
|
||||
if (me._moreDocsMode) {
|
||||
me._unsetMoreDocsMode();
|
||||
} else {
|
||||
me._setMoreDocsMode();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
},
|
||||
|
||||
@ -319,7 +316,7 @@ Sideshow.prototype = {
|
||||
|
||||
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
|
||||
|
||||
this._moreAppsText.hide();
|
||||
this._moreAppsLink.actor.hide();
|
||||
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
|
||||
|
||||
// Move the selection to the applications section if it was in the docs section.
|
||||
@ -356,7 +353,7 @@ Sideshow.prototype = {
|
||||
|
||||
this._moreAppsMode = false;
|
||||
|
||||
this._moreAppsText.hide();
|
||||
this._moreAppsLink.actor.hide();
|
||||
|
||||
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
|
||||
|
||||
@ -410,12 +407,12 @@ Sideshow.prototype = {
|
||||
this._appDisplay.updateDimensions(this._width + this._additionalWidth,
|
||||
this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT,
|
||||
EXPANDED_SIDESHOW_COLUMNS);
|
||||
this._moreAppsText.text = "Less...";
|
||||
this._moreAppsLink.setText("Less...");
|
||||
} else {
|
||||
this._appDisplay.updateDimensions(this._width, this._appsSectionDefaultHeight - SIDESHOW_SECTION_MISC_HEIGHT, SIDESHOW_COLUMNS);
|
||||
this._moreAppsText.text = "More...";
|
||||
this._moreAppsLink.setText("More...");
|
||||
}
|
||||
this._moreAppsText.show();
|
||||
this._moreAppsLink.actor.show();
|
||||
},
|
||||
|
||||
// Sets the 'More' mode for browsing documents. Updates the documents section to have more items.
|
||||
@ -430,7 +427,7 @@ Sideshow.prototype = {
|
||||
if (!this._appsSection.has_clip)
|
||||
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
|
||||
|
||||
this._moreDocsText.hide();
|
||||
this._moreDocsLink.actor.hide();
|
||||
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
|
||||
|
||||
// Move the selection to the docs section if it was in the apps section.
|
||||
@ -469,7 +466,7 @@ Sideshow.prototype = {
|
||||
|
||||
this._moreDocsMode = false;
|
||||
|
||||
this._moreDocsText.hide();
|
||||
this._moreDocsLink.actor.hide();
|
||||
|
||||
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
|
||||
|
||||
@ -520,12 +517,12 @@ Sideshow.prototype = {
|
||||
this._docDisplay.updateDimensions(this._width + this._additionalWidth,
|
||||
this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT,
|
||||
EXPANDED_SIDESHOW_COLUMNS);
|
||||
this._moreDocsText.text = "Less...";
|
||||
this._moreDocsLink.setText("Less...");
|
||||
} else {
|
||||
this._docDisplay.updateDimensions(this._width, this._docsSectionDefaultHeight - SIDESHOW_SECTION_MISC_HEIGHT, SIDESHOW_COLUMNS);
|
||||
this._moreDocsText.text = "More...";
|
||||
this._moreDocsLink.setText("More...");
|
||||
}
|
||||
this._moreDocsText.show();
|
||||
this._moreDocsLink.actor.show();
|
||||
}
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user