From e2726f3e3862b233a0cb47e22423bf000e540abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 14 Feb 2012 00:13:57 +0100 Subject: [PATCH] Add a checkbox widget gnome-keyring dialogs need checkboxes, and while it is possible to get pretty close using CSS tricks, a dedicated widgets yields better results. https://bugzilla.gnome.org/show_bug.cgi?id=669811 --- data/Makefile.am | 1 + data/theme/check-box.svg | 67 ++++++++++++++++++++++++++ data/theme/gnome-shell.css | 19 ++++++++ js/Makefile.am | 1 + js/ui/checkBox.js | 97 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 data/theme/check-box.svg create mode 100644 js/ui/checkBox.js diff --git a/data/Makefile.am b/data/Makefile.am index 8456c805a..e7dccf398 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -22,6 +22,7 @@ dist_theme_DATA = \ theme/calendar-arrow-left.svg \ theme/calendar-arrow-right.svg \ theme/calendar-today.svg \ + theme/check-box.svg \ theme/close-window.svg \ theme/close.svg \ theme/corner-ripple-ltr.png \ diff --git a/data/theme/check-box.svg b/data/theme/check-box.svg new file mode 100644 index 000000000..30e858ebe --- /dev/null +++ b/data/theme/check-box.svg @@ -0,0 +1,67 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index cc63843d4..ece3b5bbe 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -90,6 +90,25 @@ StTooltip StLabel { text-align: center; } +.check-box ShellGenericContainer { + spacing: .8em; +} + +.check-box StBin { + width: 1.2em; + height: 1.2em; + border: 1px solid white; + border-radius: 4px; +} + +.check-box:checked StBin { + background-image: url("check-box.svg"); +} + +.check-box:focus StBin { + border: 1px solid #3465a4; +} + /* PopupMenu */ .popup-menu-boxpointer { diff --git a/js/Makefile.am b/js/Makefile.am index f3413ba1b..98f7a4858 100644 --- a/js/Makefile.am +++ b/js/Makefile.am @@ -43,6 +43,7 @@ nobase_dist_js_DATA = \ ui/autorunManager.js \ ui/boxpointer.js \ ui/calendar.js \ + ui/checkBox.js \ ui/contactDisplay.js \ ui/ctrlAltTab.js \ ui/dash.js \ diff --git a/js/ui/checkBox.js b/js/ui/checkBox.js new file mode 100644 index 000000000..e66fc7952 --- /dev/null +++ b/js/ui/checkBox.js @@ -0,0 +1,97 @@ +const Clutter = imports.gi.Clutter; +const Pango = imports.gi.Pango; +const Shell = imports.gi.Shell; +const St = imports.gi.St; + +const Lang = imports.lang; + +const CheckBoxContainer = new Lang.Class({ + Name: 'CheckBoxContainer', + + _init: function() { + this.actor = new Shell.GenericContainer(); + 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; + + this._box = new St.Bin(); + this.actor.add_actor(this._box); + + this.label = new St.Label(); + this.label.clutter_text.set_line_wrap(true); + 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(forWidth); + let [minLabelHeight, natLabelHeight] = + this.label.get_preferred_height(forWidth); + + alloc.min_size = Math.max(minBoxHeight, minLabelHeight); + alloc.natural_size = Math.max(natBoxHeight, 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); + } +}); + +const CheckBox = new Lang.Class({ + Name: 'CheckBox', + + _init: function(label) { + this.actor = new St.Button({ style_class: 'check-box', + button_mask: St.ButtonMask.ONE, + toggle_mode: true, + can_focus: true, + x_fill: true, + y_fill: true }); + this._container = new CheckBoxContainer(); + this.actor.set_child(this._container.actor); + + if (label) + this.setLabel(label); + }, + + setLabel: function(label) { + this._container.label.set_text(label); + } +});