[gnome-weather] Add a new Thermometer widget
- From: Vitaly Dyachkov <vitalydyachkov src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-weather] Add a new Thermometer widget
- Date: Thu, 28 Oct 2021 15:11:08 +0000 (UTC)
commit 091f298c262dd59645feec5a25f03d81dab75f6e
Author: Vitaly Dyachkov <obyknovenius me com>
Date: Wed Oct 27 17:07:58 2021 +0200
Add a new Thermometer widget
src/app/thermometer.js | 190 +++++++++++++++++++++++++++++
src/org.gnome.Weather.src.gresource.xml.in | 1 +
2 files changed, 191 insertions(+)
---
diff --git a/src/app/thermometer.js b/src/app/thermometer.js
new file mode 100644
index 0000000..725c528
--- /dev/null
+++ b/src/app/thermometer.js
@@ -0,0 +1,190 @@
+/* thermometer.js
+ *
+ * Copyright 2021 Vitaly Dyachkov <obyknovenius me com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+const GObject = imports.gi.GObject;
+const Gdk = imports.gi.Gdk;
+const Gtk = imports.gi.Gtk;
+const Pango = imports.gi.Pango;
+const Cairo = imports.cairo;
+
+const Thermometer = GObject.registerClass({
+ Properties: {
+ 'adjustment': GObject.ParamSpec.object(
+ 'adjustment',
+ 'Adjustment',
+ 'The GtkAdjustment that contains the current value of this thermometer object',
+ GObject.ParamFlags.READWRITE,
+ Gtk.Adjustment,
+ ),
+ },
+ CssName: 'thermometer',
+},class Thermometer extends Gtk.DrawingArea {
+
+ _init(params) {
+ super._init(params);
+
+ const styleContext = this.get_style_context();
+
+ const createStyleContext = (selector) => {
+ const path = styleContext.get_path().copy();
+
+ const pos = path.append_type(GObject.TYPE_NONE);
+ path.iter_set_object_name(pos, selector);
+
+ const context = Gtk.StyleContext.new();
+ context.set_parent(styleContext);
+ context.set_path(path);
+
+ return context;
+ }
+
+ this._highContext = createStyleContext('high');
+ this._lowContext = createStyleContext('low');
+
+ this._radius = 12;
+ this._margin = 12;
+ }
+
+ get adjustment() {
+ return this._adjustment;
+ }
+
+ set adjustment(adjustment) {
+ this._adjustment = adjustment;
+
+ this._updatePangoLayouts(adjustment);
+ }
+
+ vfunc_get_preferred_width() {
+ const [ highWidth ] = this._highLayout.get_pixel_size();
+ const [ lowWidth ] = this._lowLayout.get_pixel_size();
+
+ const width = Math.max(this._radius, highWidth, lowWidth);
+ return [ width, width ];
+ }
+
+ vfunc_get_preferred_height() {
+ const [ , highHeight ] = this._highLayout.get_pixel_size();
+ const [ , lowHeight ] = this._lowLayout.get_pixel_size();
+
+ const height = highHeight + this._maring + lowHeight;
+ return [ height, height ];
+ }
+
+ _updatePangoLayouts(adjustment) {
+ const value = adjustment.get_value();
+ const pageSize = adjustment.get_page_size();
+
+ const highLabel = Math.round(value + pageSize) + "°";
+ this._highLayout = this._createPangoLayout(this._highContext, highLabel);
+
+ const lowLabel = Math.round(value) + "°";
+ this._lowLayout = this._createPangoLayout(this._lowContext, lowLabel);
+ }
+
+ _createPangoLayout(styleContext, text) {
+ const context = this._createPangoContext(styleContext);
+ const layout = Pango.Layout.new(context);
+
+ layout.set_text(text, -1);
+
+ return layout;
+ }
+
+ _createPangoContext(styleContext) {
+ const display = this.get_display();
+ const context = Gdk.pango_context_get_for_display(display);
+
+ const font = styleContext.get_property('font', styleContext.get_state());
+ context.set_font_description (font);
+
+ return context;
+ }
+
+ vfunc_draw(cr) {
+ const lower = this._adjustment.get_lower();
+ const upper = this._adjustment.get_upper();
+ const value = this._adjustment.get_value();
+ const pageSize = this._adjustment.get_page_size();
+
+ const width = this.get_allocated_width();
+ const height = this.get_allocated_height();
+
+ const [ highWidth, highHeight ] = this._highLayout.get_pixel_size();
+ const [ lowWidth, lowHeight ] = this._lowLayout.get_pixel_size();
+
+ const radius = this._radius;
+ const margin = this._margin;
+
+ const maxScaleHeight = height - highHeight - lowHeight - 2 * radius - 2 * margin;
+
+ const factor = maxScaleHeight / (upper - lower);
+ const scaleY = highHeight + radius + margin + (upper - value - pageSize) * factor;
+ const scaleHeight = pageSize * factor;
+
+ let highY = 0;
+ let lowY = height - lowHeight;
+
+ cr.save();
+
+ if (maxScaleHeight > 0) {
+ this._renderScale(cr, width / 2 - radius, scaleY, radius, scaleHeight);
+
+ highY = scaleY - radius - margin - highHeight;
+ lowY = scaleY + scaleHeight + radius + margin;
+ }
+
+ Gtk.render_layout(this._highContext, cr,
+ width / 2 - highWidth / 2, highY,
+ this._highLayout);
+
+ Gtk.render_layout(this._lowContext, cr,
+ width / 2 - lowWidth / 2, lowY,
+ this._lowLayout);
+
+ cr.restore();
+
+ return false;
+ }
+
+ _renderScale(cr, x, y, radius, height) {
+ const gradient = this._createGradient(y - radius, y + height + radius);
+ cr.setSource(gradient);
+
+ cr.newSubPath();
+ cr.arc(x + radius, y, radius, Math.PI, 0);
+ cr.arc(x + radius, y + height, radius, 0, Math.PI);
+ cr.closePath();
+ cr.fill();
+ }
+
+ _createGradient(start, end) {
+ const pattern = new Cairo.LinearGradient(0, start, 0, end);
+
+ const highColor = this._highContext.get_color(this._highContext.get_state());
+ pattern.addColorStopRGB(0.0, 246/255, 211/255, 45/255);
+
+ const lowColor = this._lowContext.get_color(this._lowContext.get_state());
+ pattern.addColorStopRGB(1.0, 28/255, 113/255, 216/255);
+
+ return pattern;
+ }
+
+});
diff --git a/src/org.gnome.Weather.src.gresource.xml.in b/src/org.gnome.Weather.src.gresource.xml.in
index 17b7432..9613401 100644
--- a/src/org.gnome.Weather.src.gresource.xml.in
+++ b/src/org.gnome.Weather.src.gresource.xml.in
@@ -4,6 +4,7 @@
<file>app/city.js</file>
<file>app/currentLocationController.js</file>
<file>app/hourlyForecast.js</file>
+ <file>app/thermometer.js</file>
<file>app/dailyForecast.js</file>
<file>app/main.js</file>
<file>app/window.js</file>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]