Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion data/theme/cinnamon-sass/widgets/_menus.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ $menuitem_border_radius: $base_border_radius * 1;
background: none;
}

.check-box {
.check-box,
.radiobutton {
StBoxLayout { spacing: 0; }
}
}
Expand Down
2 changes: 1 addition & 1 deletion data/theme/cinnamon-sass/widgets/_switch-check.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ $check_width: 20px;
// radio

.radiobutton {
CinnamonGenericContainer { spacing: 0.8em; }
StBoxLayout { spacing: 0.8em; }

StBin {
width: $check_width;
Expand Down
18 changes: 10 additions & 8 deletions js/ui/popupMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,15 +513,16 @@ var PopupMenuItem = class PopupMenuItem extends PopupBaseMenuItem {
this._icon = null;
break;
case OrnamentType.DOT:
if ((this._ornament.child)&&(!(this._ornament.child._delegate instanceof RadioButton.RadioBox))) {
if ((this._ornament.child) && (!(this._ornament.child._delegate instanceof RadioButton.RadioButton))) {
this._ornament.child.destroy();
this._ornament.child = null;
}
if (!this._ornament.child) {
let radioOrn = new RadioButton.RadioBox(state);
this._ornament.child = radioOrn.actor;
let radioOrn = new RadioButton.RadioButton();
switchOrn.set_checked(state);
this._ornament.child = radioOrn;
} else {
this._ornament.child._delegate.setToggleState(state);
this._ornament.child.set_checked(state);
}
this._icon = null;
break;
Expand Down Expand Up @@ -1158,15 +1159,16 @@ var PopupIndicatorMenuItem = class PopupIndicatorMenuItem extends PopupBaseMenuI
this._icon = null;
break;
case OrnamentType.DOT:
if ((this._ornament.child)&&(!(this._ornament.child._delegate instanceof RadioButton.RadioBox))) {
if ((this._ornament.child) && (!(this._ornament.child._delegate instanceof RadioButton.RadioButton))) {
this._ornament.child.destroy();
this._ornament.child = null;
}
if (!this._ornament.child) {
let radioOrn = new RadioButton.RadioBox(state);
this._ornament.child = radioOrn.actor;
let radioOrn = new RadioButton.RadioButton();
radioOrn.set_checked(state);
this._ornament.child = radioOrn;
} else {
this._ornament.child._delegate.setToggleState(state);
this._ornament.child.set_checked(state);
}
this._icon = null;
break;
Expand Down
211 changes: 28 additions & 183 deletions js/ui/radioButton.js
Original file line number Diff line number Diff line change
@@ -1,196 +1,41 @@
const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Pango = imports.gi.Pango;
const Cinnamon = imports.gi.Cinnamon;
const St = imports.gi.St;
const Signals = imports.signals;

const Lang = imports.lang;

function RadioButtonContainer() {
this._init();
}
RadioButtonContainer.prototype = {
_init: function() {
this.actor = new Cinnamon.GenericContainer({ y_align: St.Align.MIDDLE });
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('style-changed', Lang.bind(this,
function() {
let node = this.actor.get_theme_node();
this._spacing = node.get_length('spacing');
}));
this.actor.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
var RadioButton = GObject.registerClass(
class RadioButton extends St.Button {
_init(label) {
let container = new St.BoxLayout();
super._init({
style_class: 'radiobutton',
important: true,
child: container,
button_mask: St.ButtonMask.ONE,
toggle_mode: true,
can_focus: true,
x_fill: true,
y_fill: true,
});

this._box = new St.Bin();
this.actor.add_actor(this._box);

this.label = new St.Label();
this.label.clutter_text.set_line_wrap(false);
this.label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
this.actor.add_actor(this.label);

this._spacing = 0;
},

_getPreferredWidth: function(actor, forHeight, alloc) {
let [minWidth, natWidth] = this._box.get_preferred_width(forHeight);

alloc.min_size = minWidth + this._spacing;
alloc.natural_size = natWidth + this._spacing;
},

_getPreferredHeight: function(actor, forWidth, alloc) {
let [minBoxHeight, natBoxHeight] =
this._box.get_preferred_height(-1);
let [minLabelHeight, natLabelHeight] =
this.label.get_preferred_height(-1);

alloc.min_size = Math.max(minBoxHeight, 2 * minLabelHeight);
alloc.natural_size = Math.max(natBoxHeight, 2 * natLabelHeight);
},

_allocate: function(actor, box, flags) {
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;

let childBox = new Clutter.ActorBox();
let [minBoxWidth, natBoxWidth] =
this._box.get_preferred_width(-1);
let [minBoxHeight, natBoxHeight] =
this._box.get_preferred_height(-1);
childBox.x1 = box.x1;
childBox.x2 = box.x1 + natBoxWidth;
childBox.y1 = box.y1;
childBox.y2 = box.y1 + natBoxHeight;
this._box.allocate(childBox, flags);

childBox.x1 = box.x1 + natBoxWidth + this._spacing;
childBox.x2 = availWidth - childBox.x1;
childBox.y1 = box.y1;
childBox.y2 = box.y2;
this.label.allocate(childBox, flags);
}
};

function RadioBox(state) {
this._init(state);
}

RadioBox.prototype = {
_init: function(state) {
this.actor = new St.Button({ style_class: 'radiobutton',
button_mask: St.ButtonMask.ONE,
toggle_mode: true,
can_focus: true,
x_fill: true,
y_fill: true,
y_align: St.Align.MIDDLE });

this.actor._delegate = this;
this.actor.checked = state;
this._container = new St.Bin();
this.actor.set_child(this._container);
},

setToggleState: function(state) {
this.actor.checked = state;
},

toggle: function() {
this.setToggleState(!this.actor.checked);
},
this._box.set_y_align(Clutter.ActorAlign.START);
container.add_child(this._box);

destroy: function() {
this.actor.destroy();
}
};

function RadioButton(label) {
this._init(label);
}

RadioButton.prototype = {
__proto__: RadioBox.prototype,

_init: function(label) {
RadioBox.prototype._init.call(this, false);
this._container.destroy();
this._container = new RadioButtonContainer();
this.actor.set_child(this._container.actor);
this._label = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
this._label.clutter_text.set_line_wrap(true);
this._label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
container.add_child(this._label);

if (label)
this.setLabel(label);
},

setLabel: function(label) {
this._container.label.set_text(label);
},

getLabelActor: function() {
return this._container.label;
}
};

function RadioButtonGroup() {
this._init();
}

RadioButtonGroup.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ vertical: true, width: 250 });
this._buttons = [];
this._activeId = null;
},

addButton: function(buttonId, label) {
this.radioButton = new RadioButton(label);
this.radioButton.actor.connect("clicked",
Lang.bind(this, function(actor) {
this.buttonClicked(actor, buttonId);
}));

this._buttons.push({ id: buttonId, button: this.radioButton });
this.actor.add(this.radioButton.actor, { x_fill: true, y_fill: false, y_align: St.Align.MIDDLE });
},

radioChanged: function(actor) {

},

buttonClicked: function(actor, buttonId) {
for (const button of this._buttons) {
if (buttonId !== button['id'] && button['button'].actor.checked) {
button['button'].actor.checked = false;
}
else if (buttonId === button['id'] && !button['button'].actor.checked) {
button['button'].actor.checked = true;
}
}

// Only trigger real changes to radio selection.
if (buttonId !== this._activeId) {
this._activeId = buttonId;
this.emit('radio-changed', this._activeId);
}
},

setActive: function(buttonId) {
for (const button of this._buttons) {
button['button'].actor.checked = buttonId === button['id'];
}

if (this._activeId != buttonId) {
this._activeId = buttonId;
this.emit('radio-changed', this._activeId);
}
},
setLabel(label) {
this._label.set_text(label);
}

getActive: function() {
return this._activeId;
}
}
Signals.addSignalMethods(RadioButtonGroup.prototype);
getLabelActor() {
return this._label;
}
});
11 changes: 6 additions & 5 deletions js/ui/windowMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,17 @@ var MnemonicLeftOrnamentedMenuItem = class MnemonicLeftOrnamentedMenuItem extend
this._icon = null;
break;
case PopupMenu.OrnamentType.DOT:
if ((this._ornament.child)&&(!(this._ornament.child._delegate instanceof RadioButton.RadioBox))) {
if ((this._ornament.child) && (!(this._ornament.child._delegate instanceof RadioButton.RadioButton))) {
this._ornament.child.destroy();
this._ornament.child = null;
}
if (!this._ornament.child) {
let radioOrn = new RadioButton.RadioBox(state);
this._ornament.child = radioOrn.actor;
radioOrn.actor.reactive = false;
let radioOrn = new RadioButton.RadioButton();
radioOrn.set_checked(state);
this._ornament.child = radioOrn;
radioOrn.reactive = false;
} else {
this._ornament.child._delegate.setToggleState(state);
this._ornament.child.set_checked(state);
}
this._icon = null;
break;
Expand Down
Loading