[gnome-weather/wip/ewlsh/gtk4] Start work on popover, fix chart layouts



commit 600299642070322999173816b61876c08b8fd7a8
Author: Evan Welsh <contact evanwelsh com>
Date:   Sun Jan 2 14:49:28 2022 -0600

    Start work on popover, fix chart layouts

 data/places-popover.ui    |  86 ++++-----------------
 src/app/entry.js          |  20 ++---
 src/app/hourlyForecast.js |  65 ++++++++--------
 src/app/world.js          | 191 ++++++++++++++++++++++++++++------------------
 4 files changed, 172 insertions(+), 190 deletions(-)
---
diff --git a/data/places-popover.ui b/data/places-popover.ui
index ea1e846..f1fffaa 100644
--- a/data/places-popover.ui
+++ b/data/places-popover.ui
@@ -18,66 +18,6 @@
         </layout>
       </object>
     </child>
-    <child>
-      <object class="GtkStack" id="auto-location-stack">
-        <property name="vhomogeneous">0</property>
-        <property name="hhomogeneous">0</property>
-        <property name="transition_type">crossfade</property>
-        <child>
-          <object class="GtkStackPage">
-            <property name="name">auto-location-switch-grid</property>
-            <property name="child">
-              <object class="GtkGrid" id="auto-location-grid">
-                <property name="column_homogeneous">1</property>
-                <property name="margin_top">6</property>
-                <property name="margin_bottom">6</property>
-                <child>
-                  <object class="GtkLabel" id="auto-location-label">
-                    <property name="label" translatable="yes">Automatic Location</property>
-                    <property name="halign">start</property>
-                    <attributes>
-                      <attribute name="weight" value="PANGO_WEIGHT_BOLD"></attribute>
-                    </attributes>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                    <layout>
-                      <property name="column">0</property>
-                      <property name="row">0</property>
-                    </layout>
-                  </object>
-                </child>
-                <child>
-                  <object class="GtkSwitch" id="auto-location-switch">
-                    <property name="halign">end</property>
-                    <layout>
-                      <property name="column">1</property>
-                      <property name="row">0</property>
-                    </layout>
-                  </object>
-                </child>
-              </object>
-            </property>
-          </object>
-        </child>
-        <child>
-          <object class="GtkStackPage">
-            <property name="name">locating-label</property>
-            <property name="child">
-              <object class="GtkLabel" id="locating-label">
-                <property name="label" translatable="yes">Locating…</property>
-                <property name="halign">center</property>
-                <property name="valign">center</property>
-              </object>
-            </property>
-          </object>
-        </child>
-        <layout>
-          <property name="column">0</property>
-          <property name="row">1</property>
-        </layout>
-      </object>
-    </child>
     <child>
       <object class="GtkStack" id="popover-stack">
         <property name="vhomogeneous">0</property>
@@ -130,18 +70,22 @@
             <property name="orientation">vertical</property>
             <property name="row_spacing">10</property>
             <child>
-              <object class="GtkScrolledWindow" id="city-search-scroll">
-                <child>
-                  <object class="GtkListView" id="city-search-results">
-                    <property name="halign">center</property>
-                    <property name="valign">center</property>
-                    <property name="hexpand">True</property>
-                    <layout>
-                      <property name="column">0</property>
-                      <property name="row">0</property>
-                    </layout>
+              <object class="GtkFrame">
+                <property name="name">search-frame</property>
+                <property name="child">
+                  <object class="GtkScrolledWindow" id="search-list-scroll-window">
+                    <child>
+                      <object class="GtkListView" id="search-list-view">
+                        <property name="name">search-list-view</property>
+                        <property name="hexpand">1</property>
+                      </object>
+                    </child>
                   </object>
-                </child>
+                </property>
+                <layout>
+                  <property name="column">0</property>
+                  <property name="row">1</property>
+                </layout>
               </object>
             </child>
           </object>
diff --git a/src/app/entry.js b/src/app/entry.js
index 5380ab1..fff170c 100644
--- a/src/app/entry.js
+++ b/src/app/entry.js
@@ -1,5 +1,7 @@
 const { Gio, GLib, GWeather, GObject, Gtk, Gdk } = imports.gi;
 
+const World = imports.app.world;
+
 const LocationItem = GObject.registerClass(
     {
         Properties: {
@@ -261,6 +263,8 @@ var LocationSearchEntry = GObject.registerClass(
          * @param {number} baseline
          */
         vfunc_size_allocate(width, height, baseline) {
+            super.vfunc_size_allocate(width, height, baseline);
+
             this._entry.size_allocate(new Gdk.Rectangle({
                 x: 0,
                 y: 0,
@@ -268,11 +272,7 @@ var LocationSearchEntry = GObject.registerClass(
                 height
             }), baseline);
 
-            if (this._popup) {
-                this._popup.set_size_request(this.get_allocation().width, -1);
-                this._popup.queue_resize();
-                this._popup.present();
-            }
+
         }
 
         vfunc_grab_focus() {
@@ -332,16 +332,16 @@ var LocationSearchEntry = GObject.registerClass(
         _buildFactory() {
             let factory = new Gtk.SignalListItemFactory();
             this._setupId = factory.connect("setup", (source, item) => {
-                const label = new Gtk.Label();
-                item.set_child(label);
+
+                item.set_child(new World.LocationRow('--', false));
             });
             this._bindId = factory.connect("bind", (source, listitem) => {
-                const label = listitem.get_child();
+                const row = listitem.get_child();
                 /** @type {typeof LocationItem.prototype} */
                 const item = listitem.get_item();
 
-                if (label instanceof Gtk.Label) {
-                    label.set_label(item.display_name);
+                if (row instanceof World.LocationRow) {
+                    row.locationName = item.display_name;
                 }
             });
 
diff --git a/src/app/hourlyForecast.js b/src/app/hourlyForecast.js
index a360840..81d52e6 100644
--- a/src/app/hourlyForecast.js
+++ b/src/app/hourlyForecast.js
@@ -36,7 +36,7 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
             spacing: 0,
             name: 'hourly-forecast-box',
         });
-        
+
         this.update_property([Gtk.AccessibleProperty.LABEL], [_('Hourly Forecast')]);
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
 
@@ -90,9 +90,11 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
                     this._addSeparator();
             }
         } else {
-            let label = new Gtk.Label({ label: _('Forecast not available'),
-                                        use_markup: true,
-                                        visible: true });
+            let label = new Gtk.Label({
+                label: _('Forecast not available'),
+                use_markup: true,
+                visible: true
+            });
             this.prepend(label);
         }
 
@@ -100,7 +102,6 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
     }
 
     _addHourEntry(info, tz, timeLabel) {
-        let hourEntry = new HourEntry();
 
         if (!timeLabel) {
             let [ok, date] = info.get_value_update();
@@ -117,15 +118,8 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
 
             timeLabel = datetime.format(timeFormat);
         }
-        hourEntry.timeLabel.label = timeLabel;
-        hourEntry.image.iconName = info.get_icon_name() + '-small';
-        hourEntry.temperatureLabel.label = Util.getTempString(info);
 
-        if (Util.isDarkTheme()) {
-            const color = "#f6d32d";
-            const label = "<span color=\""+ color + "\">" + hourEntry.temperatureLabel.label + "</span>";
-            hourEntry.temperatureLabel.set_markup(label);
-        };
+        let hourEntry = new HourEntry({ info, timeLabel });
 
         this.append(hourEntry);
 
@@ -133,15 +127,17 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
     }
 
     _addSeparator() {
-        let separator = new Gtk.Separator({ orientation: Gtk.Orientation.VERTICAL,
-                                            visible: true});
+        let separator = new Gtk.Separator({
+            orientation: Gtk.Orientation.VERTICAL,
+            visible: true
+        });
         this.prepend(separator);
     }
 
     clear() {
-      for (const w of Array.from(this)) {
-          this.remove(w);
-      }
+        for (const w of Array.from(this)) {
+            this.remove(w);
+        }
     }
 
     hasForecastInfo() {
@@ -150,10 +146,10 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
 
     vfunc_snapshot(snapshot) {
         const allocation = this.get_allocation();
-        
+
         const rect = new Graphene.Rect();
         rect.init(0, 0, allocation.width, allocation.height);
-        
+
         let cr = snapshot.append_cairo(rect);
         const temps = this._hourlyInfo.map(info => Util.getTemp(info));
 
@@ -170,7 +166,7 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
         const width = this.get_allocated_width();
         const height = this.get_allocated_height();
 
-        const entryWidth = 75 ;
+        const entryWidth = 75;
         const separatorWidth = 1;
 
         const lineWidth = 2;
@@ -188,7 +184,7 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
         Gdk.cairo_set_source_rgba(cr, strokeColor);
 
         let x = 0;
-        cr.moveTo (x, graphMinY + ((1 - values[0]) * graphHeight));
+        cr.moveTo(x, graphMinY + ((1 - values[0]) * graphHeight));
 
         x += entryWidth / 2;
         cr.lineTo(x, graphMinY + ((1 - values[0]) * graphHeight));
@@ -227,20 +223,23 @@ var HourEntry = GObject.registerClass({
     InternalChildren: ['timeLabel', 'image', 'temperatureLabel'],
 }, class HourEntry extends Gtk.Widget {
 
-    _init(params) {
-        super._init({...params});
-    }
+    _init({ timeLabel, info, ...params }) {
+        super._init({ ...params });
 
-    get timeLabel() {
-        return this._timeLabel;
-    }
+        Object.assign(this.layoutManager, {
+           orientation: Gtk.Orientation.VERTICAL, 
+        });
 
-    get image() {
-        return this._image;
-    }
+        this._timeLabel.label = timeLabel;
+        this._image.iconName = info.get_icon_name() + '-small';
+        this._temperatureLabel.label = Util.getTempString(info);
 
-    get temperatureLabel() {
-        return this._temperatureLabel;
+        // TODO:
+        if (Util.isDarkTheme()) {
+            const color = "#f6d32d";
+            const label = "<span color=\"" + color + "\">" + this.temperatureLabel.label + "</span>";
+            this.temperatureLabel.set_markup(label);
+        };
     }
 });
 HourEntry.set_layout_manager_type(Gtk.BoxLayout);
\ No newline at end of file
diff --git a/src/app/world.js b/src/app/world.js
index 36797fd..ecf72e2 100644
--- a/src/app/world.js
+++ b/src/app/world.js
@@ -25,6 +25,112 @@ const GWeather = imports.gi.GWeather;
 const CurrentLocationController = imports.app.currentLocationController;
 const Util = imports.misc.util;
 
+// TODO: Finish converting into a proper GObject w/ properties
+const LocationRow = GObject.registerClass(class LocationRow extends Gtk.Widget {
+
+    _init(locationName, isCurrentLocation) {
+        super._init({});
+
+        this._locationName = locationName;
+        this._isCurrentLocation = isCurrentLocation;
+
+        this._build();
+    }
+
+    get locationName() { return this._locationName };
+
+    get isCurrentLocation() { return this._isCurrentLocation; }
+
+    set locationName(value) {
+        this._locationName = value;
+        this._build();
+    }
+
+    set isCurrentLocation(value) {
+        this._isCurrentLocation = value;
+        this._build();
+    }
+
+    _build() {
+
+        if (!this.grid) {
+            this.grid = new Gtk.Grid({
+                orientation: Gtk.Orientation.HORIZONTAL,
+                column_spacing: 12,
+                margin_start: 12,
+                margin_end: 12,
+                margin_top: 12,
+                margin_bottom: 12,
+                visible: true
+            });
+
+            let grid = this.grid;
+            let locationGrid = new Gtk.Grid({
+                orientation: Gtk.Orientation.HORIZONTAL,
+                column_spacing: 12,
+                halign: Gtk.Align.START,
+                hexpand: true,
+                visible: true
+            });
+            this.locationLabel = new Gtk.Label({
+                label: this.locationName,
+                use_markup: true,
+                halign: Gtk.Align.START,
+                visible: true
+            });
+
+            locationGrid.attach(this.locationLabel, 0, 0, 1, 1);
+            grid.attach(locationGrid, 0, 0, 1, 1);
+
+            let tempLabel = new Gtk.Label({
+                use_markup: true,
+                halign: Gtk.Align.END,
+                margin_start: 12,
+                visible: true
+            });
+            this.tempLabel = tempLabel;
+            grid.attach(tempLabel, 1, 0, 1, 1);
+
+            this.image = new Gtk.Image({
+                icon_size: Gtk.IconSize.LARGE,
+                use_fallback: true,
+                halign: Gtk.Align.END
+            });
+            grid.attach(this.image, 2, 0, 1, 1);
+        }
+
+        if (this.isCurrentLocation && !this.currentImage) {
+            this.currentImage = new Gtk.Image({
+                icon_size: Gtk.IconSize.LARGE,
+                icon_name: 'mark-location-symbolic',
+                use_fallback: true,
+                halign: Gtk.Align.START
+            });
+            this.grid.attach(this.currentImage, 1, 0, 1, 1);
+        } else if (!this.isCurrentLocation && this.currentImage) {
+            this.currentImage.unparent();
+            this.currentImage = null;
+        }
+
+        this.locationLabel.label = this.locationName;
+
+    }
+
+    vfunc_root() {
+        super.vfunc_root();
+
+        this.grid.set_parent(this);
+    }
+
+    vfunc_unroot() {
+        this.grid.unparent();
+        this.grid = null;
+
+        super.vfunc_unroot();
+    }
+});
+LocationRow.set_layout_manager_type(Gtk.BoxLayout);
+
 class _WorldContentView extends Gtk.Popover {
     static [GObject.TypeName] = 'WorldContentView';
 
@@ -42,11 +148,12 @@ class _WorldContentView extends Gtk.Popover {
         let grid = builder.get_object('popover-grid');
         this.set_child(grid);
 
-        this._searchResults = builder.get_object('city-search-results');
         this._searchGrid = builder.get_object('empty-search-grid');
         this._searchResultsGrid = builder.get_object('search-grid');
         this._locationsGrid = builder.get_object('locations-grid');
-
+        this._searchListView = builder.get_object('search-list-view');
+        this._searchListScrollWindow = builder.get_object('search-list-scroll-window');
+        this._searchListScrollWindow.set_size_request(-1, 400);
         this.model = application.model;
         this._window = window;
 
@@ -63,7 +170,8 @@ class _WorldContentView extends Gtk.Popover {
         });
 
         this._locationEntry = builder.get_object('location-entry');
-        this._locationEntry.setListView(this._searchResults);
+       
+        this._locationEntry.setListView(this._searchListView);
         this._locationEntry.connect('search-updated', (_, term) => {
             if (term) {
                 this._stackPopover.set_visible_child(this._searchResultsGrid);
@@ -77,26 +185,11 @@ class _WorldContentView extends Gtk.Popover {
             this._locationEntry.grab_focus();
         });
 
-        let autoLocStack = builder.get_object('auto-location-stack');
-        let autoLocSwitch = builder.get_object('auto-location-switch');
-        this._currentLocationController = application.currentLocationController;
 
-        if (this._currentLocationController.autoLocation == CurrentLocationController.AutoLocation.ENABLED) {
-            autoLocStack.visible_child_name = 'locating-label';
-        } else {
-            autoLocStack.visible_child_name = 'auto-location-switch-grid';
-            autoLocSwitch.active = false;
-            autoLocSwitch.sensitive = (this._currentLocationController.autoLocation != 
CurrentLocationController.AutoLocation.NOT_AVAILABLE);
-        }
 
-        let handlerId = autoLocSwitch.connect('notify::active', () => {
-            this._currentLocationController.setAutoLocation(autoLocSwitch.active);
+        this._currentLocationController = application.currentLocationController;
 
-            if (autoLocSwitch.active && !this.model.addedCurrentLocation)
-                autoLocStack.visible_child_name = 'locating-label';
 
-            this.hide();
-        });
 
         this._listbox.connect('row-activated', (listbox, row) => {
             this._window.showInfo(row._info, false);
@@ -105,12 +198,6 @@ class _WorldContentView extends Gtk.Popover {
         });
 
         this.model.connect('current-location-changed', (model, info) => {
-            autoLocStack.visible_child_name = 'auto-location-switch-grid';
-            GObject.signal_handler_block(autoLocSwitch, handlerId);
-            autoLocSwitch.active = (this._currentLocationController.autoLocation == 
CurrentLocationController.AutoLocation.ENABLED);
-            autoLocSwitch.sensitive = (this._currentLocationController.autoLocation != 
CurrentLocationController.AutoLocation.NOT_AVAILABLE);
-            GObject.signal_handler_unblock(autoLocSwitch, handlerId);
-
             this._window.showInfo(info, true);
         });
 
@@ -165,57 +252,9 @@ class _WorldContentView extends Gtk.Popover {
     _onLocationAdded(model, info, isCurrentLocation) {
         let location = info.location;
 
-        let grid = new Gtk.Grid({
-            orientation: Gtk.Orientation.HORIZONTAL,
-            column_spacing: 12,
-            margin_start: 12,
-            margin_end: 12,
-            margin_top: 12,
-            margin_bottom: 12,
-            visible: true
-        });
 
         let name = location.get_city_name();
-        let locationGrid = new Gtk.Grid({
-            orientation: Gtk.Orientation.HORIZONTAL,
-            column_spacing: 12,
-            halign: Gtk.Align.START,
-            hexpand: true,
-            visible: true
-        });
-        let locationLabel = new Gtk.Label({
-            label: name,
-            use_markup: true,
-            halign: Gtk.Align.START,
-            visible: true
-        });
-        locationGrid.attach(locationLabel, 0, 0, 1, 1);
-        grid.attach(locationGrid, 0, 0, 1, 1);
-
-        let tempLabel = new Gtk.Label({
-            use_markup: true,
-            halign: Gtk.Align.END,
-            margin_start: 12,
-            visible: true
-        });
-        grid.attach(tempLabel, 1, 0, 1, 1);
-
-        if (isCurrentLocation) {
-            let image = new Gtk.Image({
-                icon_size: Gtk.IconSize.LARGE,
-                icon_name: 'mark-location-symbolic',
-                use_fallback: true,
-                halign: Gtk.Align.START
-            });
-            locationGrid.attach(image, 1, 0, 1, 1);
-        }
-
-        let image = new Gtk.Image({
-            icon_size: Gtk.IconSize.LARGE,
-            use_fallback: true,
-            halign: Gtk.Align.END
-        });
-        grid.attach(image, 2, 0, 1, 1);
+        const grid = new LocationRow(name, isCurrentLocation);
 
         let row = new Gtk.ListBoxRow({ visible: true });
         row.set_child(grid);
@@ -245,8 +284,8 @@ class _WorldContentView extends Gtk.Popover {
             return;
 
         info._updatedId = info.connect('updated', (info) => {
-            tempLabel.label = info.get_temp_summary();
-            image.icon_name = info.get_symbolic_icon_name();
+            grid.tempLabel.label = info.get_temp_summary();
+            grid.image.icon_name = info.get_symbolic_icon_name();
         });
 
         this._syncStackPopover();


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