[gnome-weather/wip/ewlsh/gtk4: 2/2] Initial thermometer port




commit 9217560bdab53c6f7d8eb5d4bad2662138dfc0e0
Author: Evan Welsh <contact evanwelsh com>
Date:   Fri Dec 31 13:36:47 2021 -0800

    Initial thermometer port

 data/application.css     |   4 +-
 src/app/dailyForecast.js |   7 +-
 src/app/thermometer.js   | 189 +++++++++++++++++++++++------------------------
 3 files changed, 97 insertions(+), 103 deletions(-)
---
diff --git a/data/application.css b/data/application.css
index 12dde99..6aaf9a3 100644
--- a/data/application.css
+++ b/data/application.css
@@ -51,12 +51,12 @@
     color: #c89009;
 }
 
-thermometer > high {
+WeatherThermometer > label.high {
     font-weight: bold;
     color: #c89009;
 }
 
-thermometer > low {
+WeatherThermometer > label.low {
     font-weight: bold;
     color: #2174d9;
 }
diff --git a/src/app/dailyForecast.js b/src/app/dailyForecast.js
index 3ac5ad9..a0e3280 100644
--- a/src/app/dailyForecast.js
+++ b/src/app/dailyForecast.js
@@ -194,12 +194,8 @@ var DailyForecastBox = GObject.registerClass(class DailyForecastBox extends Gtk.
 
         dayEntry.image.iconName = `${dayInfo.get_icon_name()}-small`;
 
-        const adjustment = Gtk.Adjustment.new(minTemp,
-            weekLowestTemp, weekHighestTemp,
-            0, 0,
-            maxTemp - minTemp);
-        dayEntry.thermometer.adjustment = adjustment;
 
+        dayEntry.thermometer.setTemperatureRange(weekLowestTemp, weekHighestTemp, minTemp, maxTemp);
         dayEntry.nightTemperatureLabel.label = Util.getTempString(nightInfo);
         dayEntry.nightImage.iconName = nightInfo.get_icon_name() + '-small';
         dayEntry.nightHumidity.label = nightInfo.get_humidity();
@@ -350,4 +346,3 @@ var DayEntry = GObject.registerClass({
 });
 
 DayEntry.set_layout_manager_type(Gtk.BoxLayout);
-      
\ No newline at end of file
diff --git a/src/app/thermometer.js b/src/app/thermometer.js
index 8356ea4..59a531c 100644
--- a/src/app/thermometer.js
+++ b/src/app/thermometer.js
@@ -21,10 +21,13 @@
 const GObject = imports.gi.GObject;
 const Gdk = imports.gi.Gdk;
 const Gtk = imports.gi.Gtk;
+const Gsk = imports.gi.Gsk;
 const Pango = imports.gi.Pango;
 const Cairo = imports.cairo;
+const Graphene = imports.gi.Graphene;
 
-const Thermometer = GObject.registerClass({
+const ThermometerScale = GObject.registerClass({
+  CssName: 'WeatherThermometerScale',
   Properties: {
     'adjustment': GObject.ParamSpec.object(
       'adjustment',
@@ -34,91 +37,42 @@ const Thermometer = GObject.registerClass({
       Gtk.Adjustment,
     ),
   },
-  CssName: 'thermometer',
-},class Thermometer extends Gtk.DrawingArea {
+}, class ThermometerScale extends Gtk.Widget {
 
-  _init(params) {
+  _init({ adjustment, radius = 12, margin = 12, ...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._highStyleContext = createStyleContext('high');
-    this._lowStyleContext = createStyleContext('low');
-
-    this._radius = 12;
-    this._margin = 12;
-  }
-
-  get adjustment() {
-    return this._adjustment;
-  }
-
-  set adjustment(adjustment) {
     this._adjustment = adjustment;
+    this._adjustment.connect('changed', () => {
+      this.queue_draw();
+    });
 
-    this._updatePangoLayouts(adjustment);
-  }
-
-  vfunc_get_preferred_width() {
-    const [highWidth] = this._highLayout.get_pixel_size();
-    const [lowWidth] = this._lowLayout.get_pixel_size();
+    this.vexpand = true;
 
-    const width = Math.max(this._radius, highWidth, lowWidth);
-    return [width, width];
+    this._radius = radius;
+    this._margin = margin;
   }
 
-  vfunc_get_preferred_height() {
-    const [, highHeight] = this._highLayout.get_pixel_size();
-    const [, lowHeight] = this._lowLayout.get_pixel_size();
+  vfunc_measure(orientation /*, for_size */) {
+    let minimum = this._radius + this._margin, minimum_baseline = -1, natural_baseline = - 1;
 
-    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._highStyleContext, highLabel);
-
-    const lowLabel = Math.round(value) + "°";
-    this._lowLayout = this._createPangoLayout(this._lowStyleContext, lowLabel);
-  }
-
-  _createPangoLayout(styleContext, text) {
-    const context = this._createPangoContext(styleContext);
-    const layout = Pango.Layout.new(context);
-
-    layout.set_text(text, -1);
-
-    return layout;
+    if (orientation === Gtk.Orientation.HORIZONTAL) {
+      return [minimum, minimum, minimum_baseline, natural_baseline];
+    } else {
+      return [minimum, minimum, minimum_baseline, natural_baseline];
+    }
   }
 
-  _createPangoContext(styleContext) {
-    const display = this.get_display();
-    const context = Gdk.pango_context_get_for_display(display);
+  vfunc_snapshot(snapshot) {
+    if (!this._adjustment)
+      return super.vfunc_snapshot(snapshot);
 
-    const font = styleContext.get_property('font', styleContext.get_state());
-    context.set_font_description (font);
+    const allocation = this.get_allocation();
 
-    return context;
-  }
+    const rect = new Graphene.Rect();
+    rect.init(0, 0, allocation.width, allocation.height);
 
-  vfunc_draw(cr) {
+    let cr = snapshot.append_cairo(rect);
     const lower = this._adjustment.get_lower();
     const upper = this._adjustment.get_upper();
     const value = this._adjustment.get_value();
@@ -127,41 +81,22 @@ const Thermometer = GObject.registerClass({
     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 maxScaleHeight = height - 2 * radius - 2 * margin;
 
     const factor = maxScaleHeight / (upper - lower);
-    const scaleY = highHeight + radius + margin + (upper - value - pageSize) * factor;
+    const scaleY = 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._highStyleContext, cr,
-                      width / 2 - highWidth / 2, highY,
-                      this._highLayout);
-
-    Gtk.render_layout(this._lowStyleContext, cr,
-                      width / 2 - lowWidth / 2, lowY,
-                      this._lowLayout);
+    super.vfunc_snapshot(snapshot);
 
-    cr.restore();
-
-    return false;
+    cr.$dispose();
   }
 
   _renderScale(cr, x, y, radius, height) {
@@ -188,5 +123,69 @@ const Thermometer = GObject.registerClass({
 
     return pattern;
   }
+})
+
+var Thermometer = GObject.registerClass({
+
+  CssName: 'WeatherThermometer',
+}, class Thermometer extends Gtk.Widget {
+
+  _init({ ...params }) {
+    super._init(params);
+
+    this._adjustment = Gtk.Adjustment.new(
+      0,
+      0,
+      0,
+      0,
+      0,
+      0
+    );
+
+    this.layoutManager.orientation = Gtk.Orientation.VERTICAL;
+
+    this._scale = new ThermometerScale({ adjustment: this._adjustment });
+    this._highLabel = new Gtk.Label();
+    this._highLabel.add_css_class('high');
+    this._lowLabel = new Gtk.Label();
+    this._lowLabel.add_css_class('low');
+
+    this._highLabel.set_parent(this);
+    this._scale.set_parent(this);
+    this._lowLabel.set_parent(this);
+
+    this._updateLabels();
+
+    this._radius = 12;
+    this._margin = 12;
+
+  }
+
+  setTemperatureRange(weekLowestTemp, weekHighestTemp, minTemp, maxTemp) {
+    this._adjustment.configure(
+      minTemp,
+      weekLowestTemp,
+      weekHighestTemp,
+      0, 0,
+      maxTemp - minTemp
+    );
+
+    this._updateLabels();
+
+  }
 
+  _updateLabels() {
+    if (!this._adjustment) return;
+
+    const value = this._adjustment.get_value();
+    const pageSize = this._adjustment.get_page_size();
+
+    const highLabel = Math.round(value + pageSize) + "°";
+    this._highLabel.label = highLabel;
+
+    const lowLabel = Math.round(value) + "°";
+    this._lowLabel.label = lowLabel;
+  }
 });
+
+Thermometer.set_layout_manager_type(Gtk.BoxLayout);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]