popup-menu: Allow adjusting where in the source the arrow points to

Currently BoxPointer/Menus always point to the center of the
associated source actor. This is generally what we want, but
add some API to adjust that behavior for the cases where it
isn't.

https://bugzilla.gnome.org/show_bug.cgi?id=659274
This commit is contained in:
Florian Müllner 2011-09-15 00:14:03 +02:00
parent d0edd970e1
commit 85520e34ab
2 changed files with 25 additions and 7 deletions

View File

@ -46,6 +46,7 @@ BoxPointer.prototype = {
this._yOffset = 0; this._yOffset = 0;
this._xPosition = 0; this._xPosition = 0;
this._yPosition = 0; this._yPosition = 0;
this._sourceAlignment = 0.5;
}, },
show: function(animate, onComplete) { show: function(animate, onComplete) {
@ -180,7 +181,7 @@ BoxPointer.prototype = {
this.bin.allocate(childBox, flags); this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) if (this._sourceActor && this._sourceActor.mapped)
this._reposition(this._sourceActor, this._alignment); this._reposition(this._sourceActor, this._arrowAlignment);
}, },
_drawBorder: function(area) { _drawBorder: function(area) {
@ -312,18 +313,31 @@ BoxPointer.prototype = {
this.actor.show(); this.actor.show();
this._sourceActor = sourceActor; this._sourceActor = sourceActor;
this._alignment = alignment; this._arrowAlignment = alignment;
this._reposition(sourceActor, alignment); this._reposition(sourceActor, alignment);
}, },
setSourceAlignment: function(alignment) {
this._sourceAlignment = alignment;
if (!this._sourceActor)
return;
// We need to show it now to force an allocation,
// so that we can query the correct size.
this.actor.show();
this._reposition(this._sourceActor, this._arrowAlignment);
},
_reposition: function(sourceActor, alignment) { _reposition: function(sourceActor, alignment) {
// Position correctly relative to the sourceActor // Position correctly relative to the sourceActor
let sourceNode = sourceActor.get_theme_node(); let sourceNode = sourceActor.get_theme_node();
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box()); let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor); let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) / 2; let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) / 2; let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
// We also want to keep it onscreen, and separated from the // We also want to keep it onscreen, and separated from the

View File

@ -1142,10 +1142,10 @@ function PopupMenu() {
PopupMenu.prototype = { PopupMenu.prototype = {
__proto__: PopupMenuBase.prototype, __proto__: PopupMenuBase.prototype,
_init: function(sourceActor, alignment, arrowSide) { _init: function(sourceActor, arrowAlignment, arrowSide) {
PopupMenuBase.prototype._init.call (this, sourceActor, 'popup-menu-content'); PopupMenuBase.prototype._init.call (this, sourceActor, 'popup-menu-content');
this._alignment = alignment; this._arrowAlignment = arrowAlignment;
this._arrowSide = arrowSide; this._arrowSide = arrowSide;
this._boxPointer = new BoxPointer.BoxPointer(arrowSide, this._boxPointer = new BoxPointer.BoxPointer(arrowSide,
@ -1198,13 +1198,17 @@ PopupMenu.prototype = {
this._boxPointer.setArrowOrigin(origin); this._boxPointer.setArrowOrigin(origin);
}, },
setSourceAlignment: function(alignment) {
this._boxPointer.setSourceAlignment(alignment);
},
open: function(animate) { open: function(animate) {
if (this.isOpen) if (this.isOpen)
return; return;
this.isOpen = true; this.isOpen = true;
this._boxPointer.setPosition(this.sourceActor, this._alignment); this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
this._boxPointer.show(animate); this._boxPointer.show(animate);
this.actor.raise_top(); this.actor.raise_top();