panel: Abstract the centered panel logic out into a ClutterLayoutManager
Since we want to use this in the overview as well, put it into centerLayout.js
This commit is contained in:
parent
2ee8b0e427
commit
c0f9c52ba6
@ -41,6 +41,7 @@ nobase_dist_js_DATA = \
|
|||||||
ui/boxpointer.js \
|
ui/boxpointer.js \
|
||||||
ui/calendar.js \
|
ui/calendar.js \
|
||||||
ui/checkBox.js \
|
ui/checkBox.js \
|
||||||
|
ui/centerLayout.js \
|
||||||
ui/ctrlAltTab.js \
|
ui/ctrlAltTab.js \
|
||||||
ui/dash.js \
|
ui/dash.js \
|
||||||
ui/dateMenu.js \
|
ui/dateMenu.js \
|
||||||
|
60
js/ui/centerLayout.js
Normal file
60
js/ui/centerLayout.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
|
||||||
|
const CenterLayout = new Lang.Class({
|
||||||
|
Name: 'CenterLayout',
|
||||||
|
Extends: Clutter.BoxLayout,
|
||||||
|
|
||||||
|
vfunc_allocate: function(container, box, flags) {
|
||||||
|
let rtl = container.get_text_direction() == Clutter.TextDirection.RTL;
|
||||||
|
|
||||||
|
let availWidth = box.x2 - box.x1;
|
||||||
|
let availHeight = box.y2 - box.y1;
|
||||||
|
|
||||||
|
// Assume that these are the first three widgets and they are all visible.
|
||||||
|
let [left, center, right] = container.get_children();
|
||||||
|
|
||||||
|
// Only support horizontal layouts for now.
|
||||||
|
let [leftMinWidth, leftNaturalWidth] = left.get_preferred_width(availHeight);
|
||||||
|
let [centerMinWidth, centerNaturalWidth] = center.get_preferred_width(availHeight);
|
||||||
|
let [rightMinWidth, rightNaturalWidth] = right.get_preferred_width(availHeight);
|
||||||
|
|
||||||
|
let sideWidth = (availWidth - centerMinWidth) / 2;
|
||||||
|
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
childBox.y1 = box.y1;
|
||||||
|
childBox.y2 = box.y1 + availHeight;
|
||||||
|
|
||||||
|
let leftSide = Math.min(Math.floor(sideWidth), leftNaturalWidth);
|
||||||
|
let rightSide = Math.min(Math.floor(sideWidth), rightNaturalWidth);
|
||||||
|
|
||||||
|
if (rtl) {
|
||||||
|
childBox.x1 = availWidth - leftSide;
|
||||||
|
childBox.x2 = availWidth;
|
||||||
|
} else {
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = leftSide;
|
||||||
|
}
|
||||||
|
childBox.x1 += box.x1;
|
||||||
|
left.allocate(childBox, flags);
|
||||||
|
|
||||||
|
let maxSide = Math.max(leftSide, rightSide);
|
||||||
|
let sideWidth = Math.max((availWidth - centerNaturalWidth) / 2, maxSide);
|
||||||
|
|
||||||
|
childBox.x1 = box.x1 + Math.ceil(sideWidth);
|
||||||
|
childBox.x2 = box.x2 - Math.ceil(sideWidth);
|
||||||
|
center.allocate(childBox, flags);
|
||||||
|
|
||||||
|
if (rtl) {
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = rightSide;
|
||||||
|
} else {
|
||||||
|
childBox.x1 = availWidth - rightSide;
|
||||||
|
childBox.x2 = availWidth;
|
||||||
|
}
|
||||||
|
childBox.x1 += box.x1;
|
||||||
|
right.allocate(childBox, flags);
|
||||||
|
}
|
||||||
|
});
|
121
js/ui/panel.js
121
js/ui/panel.js
@ -15,6 +15,7 @@ const Signals = imports.signals;
|
|||||||
const Atk = imports.gi.Atk;
|
const Atk = imports.gi.Atk;
|
||||||
|
|
||||||
|
|
||||||
|
const CenterLayout = imports.ui.centerLayout;
|
||||||
const Config = imports.misc.config;
|
const Config = imports.misc.config;
|
||||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
@ -937,12 +938,47 @@ try {
|
|||||||
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
|
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PanelLayout = new Lang.Class({
|
||||||
|
Name: 'PanelLayout',
|
||||||
|
Extends: CenterLayout.CenterLayout,
|
||||||
|
|
||||||
|
vfunc_allocate: function(container, box, flags) {
|
||||||
|
this.parent(container, box, flags);
|
||||||
|
|
||||||
|
let availWidth = box.x2 - box.x1;
|
||||||
|
let availHeight = box.y2 - box.y1;
|
||||||
|
|
||||||
|
let [left, center, right, leftCorner, rightCorner] = container.get_children();
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
|
||||||
|
let cornerMinWidth, cornerMinHeight;
|
||||||
|
let cornerWidth, cornerHeight;
|
||||||
|
|
||||||
|
[cornerMinWidth, cornerWidth] = leftCorner.get_preferred_width(-1);
|
||||||
|
[cornerMinHeight, cornerHeight] = leftCorner.get_preferred_height(-1);
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = cornerWidth;
|
||||||
|
childBox.y1 = availHeight;
|
||||||
|
childBox.y2 = availHeight + cornerHeight;
|
||||||
|
leftCorner.allocate(childBox, flags);
|
||||||
|
|
||||||
|
[cornerMinWidth, cornerWidth] = rightCorner.get_preferred_width(-1);
|
||||||
|
[cornerMinHeight, cornerHeight] = rightCorner.get_preferred_height(-1);
|
||||||
|
childBox.x1 = availWidth - cornerWidth;
|
||||||
|
childBox.x2 = availWidth;
|
||||||
|
childBox.y1 = availHeight;
|
||||||
|
childBox.y2 = availHeight + cornerHeight;
|
||||||
|
rightCorner.allocate(childBox, flags);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const Panel = new Lang.Class({
|
const Panel = new Lang.Class({
|
||||||
Name: 'Panel',
|
Name: 'Panel',
|
||||||
|
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this.actor = new Shell.GenericContainer({ name: 'panel',
|
this.actor = new St.Widget({ name: 'panel',
|
||||||
reactive: true });
|
reactive: true,
|
||||||
|
layoutManager: new PanelLayout() });
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
|
|
||||||
this._sessionStyle = null;
|
this._sessionStyle = null;
|
||||||
@ -962,7 +998,6 @@ const Panel = new Lang.Class({
|
|||||||
this._leftCorner = new PanelCorner(this._rightBox, St.Side.LEFT);
|
this._leftCorner = new PanelCorner(this._rightBox, St.Side.LEFT);
|
||||||
else
|
else
|
||||||
this._leftCorner = new PanelCorner(this._leftBox, St.Side.LEFT);
|
this._leftCorner = new PanelCorner(this._leftBox, St.Side.LEFT);
|
||||||
|
|
||||||
this.actor.add_actor(this._leftCorner.actor);
|
this.actor.add_actor(this._leftCorner.actor);
|
||||||
|
|
||||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
|
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
|
||||||
@ -971,9 +1006,6 @@ const Panel = new Lang.Class({
|
|||||||
this._rightCorner = new PanelCorner(this._rightBox, St.Side.RIGHT);
|
this._rightCorner = new PanelCorner(this._rightBox, St.Side.RIGHT);
|
||||||
this.actor.add_actor(this._rightCorner.actor);
|
this.actor.add_actor(this._rightCorner.actor);
|
||||||
|
|
||||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
|
||||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
|
||||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
|
||||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||||
|
|
||||||
Main.layoutManager.panelBox.add(this.actor);
|
Main.layoutManager.panelBox.add(this.actor);
|
||||||
@ -984,83 +1016,6 @@ const Panel = new Lang.Class({
|
|||||||
this._updatePanel();
|
this._updatePanel();
|
||||||
},
|
},
|
||||||
|
|
||||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
|
||||||
alloc.min_size = -1;
|
|
||||||
alloc.natural_size = Main.layoutManager.primaryMonitor.width;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
|
||||||
// We don't need to implement this; it's forced by the CSS
|
|
||||||
alloc.min_size = -1;
|
|
||||||
alloc.natural_size = -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
_allocate: function(actor, box, flags) {
|
|
||||||
let allocWidth = box.x2 - box.x1;
|
|
||||||
let allocHeight = box.y2 - box.y1;
|
|
||||||
|
|
||||||
let [leftMinWidth, leftNaturalWidth] = this._leftBox.get_preferred_width(-1);
|
|
||||||
let [centerMinWidth, centerNaturalWidth] = this._centerBox.get_preferred_width(-1);
|
|
||||||
let [rightMinWidth, rightNaturalWidth] = this._rightBox.get_preferred_width(-1);
|
|
||||||
|
|
||||||
let sideWidth, centerWidth;
|
|
||||||
centerWidth = centerNaturalWidth;
|
|
||||||
sideWidth = (allocWidth - centerWidth) / 2;
|
|
||||||
|
|
||||||
let childBox = new Clutter.ActorBox();
|
|
||||||
|
|
||||||
childBox.y1 = 0;
|
|
||||||
childBox.y2 = allocHeight;
|
|
||||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
|
|
||||||
childBox.x1 = allocWidth - Math.min(Math.floor(sideWidth),
|
|
||||||
leftNaturalWidth);
|
|
||||||
childBox.x2 = allocWidth;
|
|
||||||
} else {
|
|
||||||
childBox.x1 = 0;
|
|
||||||
childBox.x2 = Math.min(Math.floor(sideWidth),
|
|
||||||
leftNaturalWidth);
|
|
||||||
}
|
|
||||||
this._leftBox.allocate(childBox, flags);
|
|
||||||
|
|
||||||
childBox.x1 = Math.ceil(sideWidth);
|
|
||||||
childBox.y1 = 0;
|
|
||||||
childBox.x2 = childBox.x1 + centerWidth;
|
|
||||||
childBox.y2 = allocHeight;
|
|
||||||
this._centerBox.allocate(childBox, flags);
|
|
||||||
|
|
||||||
childBox.y1 = 0;
|
|
||||||
childBox.y2 = allocHeight;
|
|
||||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
|
|
||||||
childBox.x1 = 0;
|
|
||||||
childBox.x2 = Math.min(Math.floor(sideWidth),
|
|
||||||
rightNaturalWidth);
|
|
||||||
} else {
|
|
||||||
childBox.x1 = allocWidth - Math.min(Math.floor(sideWidth),
|
|
||||||
rightNaturalWidth);
|
|
||||||
childBox.x2 = allocWidth;
|
|
||||||
}
|
|
||||||
this._rightBox.allocate(childBox, flags);
|
|
||||||
|
|
||||||
let cornerMinWidth, cornerMinHeight;
|
|
||||||
let cornerWidth, cornerHeight;
|
|
||||||
|
|
||||||
[cornerMinWidth, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1);
|
|
||||||
[cornerMinHeight, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1);
|
|
||||||
childBox.x1 = 0;
|
|
||||||
childBox.x2 = cornerWidth;
|
|
||||||
childBox.y1 = allocHeight;
|
|
||||||
childBox.y2 = allocHeight + cornerHeight;
|
|
||||||
this._leftCorner.actor.allocate(childBox, flags);
|
|
||||||
|
|
||||||
[cornerMinWidth, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1);
|
|
||||||
[cornerMinHeight, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1);
|
|
||||||
childBox.x1 = allocWidth - cornerWidth;
|
|
||||||
childBox.x2 = allocWidth;
|
|
||||||
childBox.y1 = allocHeight;
|
|
||||||
childBox.y2 = allocHeight + cornerHeight;
|
|
||||||
this._rightCorner.actor.allocate(childBox, flags);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onButtonPress: function(actor, event) {
|
_onButtonPress: function(actor, event) {
|
||||||
if (event.get_source() != actor)
|
if (event.get_source() != actor)
|
||||||
return false;
|
return false;
|
||||||
|
30
tests/interactive/center-layout.js
Normal file
30
tests/interactive/center-layout.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
|
||||||
|
const CenterLayout = imports.ui.centerLayout;
|
||||||
|
const UI = imports.testcommon.ui;
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
let stage = new Clutter.Stage({ user_resizable: true });
|
||||||
|
UI.init(stage);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
let container = new St.Widget({ style: 'border: 2px solid black;',
|
||||||
|
layout_manager: new CenterLayout.CenterLayout() });
|
||||||
|
container.add_constraint(new Clutter.BindConstraint({ coordinate: Clutter.BindCoordinate.SIZE, source: stage }));
|
||||||
|
stage.add_actor(container);
|
||||||
|
|
||||||
|
let left = new Clutter.Actor({ background_color: Clutter.Color.get_static(Clutter.StaticColor.RED), width: 300 });
|
||||||
|
let center = new Clutter.Actor({ background_color: Clutter.Color.get_static(Clutter.StaticColor.BLUE), width: 100 });
|
||||||
|
let right = new Clutter.Actor({ background_color: Clutter.Color.get_static(Clutter.StaticColor.YELLOW), width: 200 });
|
||||||
|
|
||||||
|
container.add_actor(left);
|
||||||
|
container.add_actor(center);
|
||||||
|
container.add_actor(right);
|
||||||
|
|
||||||
|
UI.main(stage);
|
||||||
|
}
|
||||||
|
test();
|
Loading…
Reference in New Issue
Block a user