[gnome-weather] CityView: use a proper GtkStack for showing forecasts



commit eb55f538d4b3c49096911e931c1ac1546d1a1745
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Fri Mar 6 19:48:36 2015 -0800

    CityView: use a proper GtkStack for showing forecasts
    
    Instead of a hack with destroying and readding widgets all the
    time. Simplifies the code at the expense of having more widgets
    live in the hierarchy.

 data/city.ui        |   95 +++++++++++++++++++++++------------------
 src/app/city.js     |  117 +++++++++++++++++++++++++++++++-------------------
 src/app/forecast.js |   20 ++++----
 3 files changed, 135 insertions(+), 97 deletions(-)
---
diff --git a/data/city.ui b/data/city.ui
index 562ab39..1ae124e 100644
--- a/data/city.ui
+++ b/data/city.ui
@@ -98,7 +98,7 @@
                     <child>
                       <object class="GtkStackSwitcher" id="day-stack-switcher">
                         <property name="visible">True</property>
-                        <property name="stack">day-stack</property>
+                        <property name="stack">forecast-stack</property>
                         <style>
                           <class name="osd"/>
                         </style>
@@ -108,34 +108,6 @@
                         <property name="top_attach">0</property>
                       </packing>
                     </child>
-                    <child>
-                      <object class="GtkStack" id="day-stack">
-                        <property name="visible">False</property>
-                        <property name="no_show_all">True</property>
-                        <child>
-                          <object class="GtkButton" id="today-Button">
-                            <property name="visible">True</property>
-                          </object>
-                          <packing>
-                            <property name="name">today-button</property>
-                            <property name="title" translatable="yes">Today</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkButton" id="tomorrow-button">
-                            <property name="visible">True</property>
-                          </object>
-                          <packing>
-                            <property name="name">tomorrow-button</property>
-                            <property name="title" translatable="yes">Tomorrow</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">0</property>
-                      </packing>
-                    </child>
                   </object>
                   <packing>
                     <property name="left_attach">0</property>
@@ -143,31 +115,70 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkGrid" id="parent-grid">
+                  <object class="GtkGrid" id="forecast-parent-grid">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <child>
-                      <object class="GtkScrolledWindow" id="forecast-scrolled-window">
+                      <object class="GtkStack" id="forecast-stack">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="vscrollbar_policy">never</property>
-                        <property name="min_content_width">332</property>
-                        <property name="margin-start">32</property>
-                        <property name="margin-end">32</property>
+                        <property name="can-focus">False</property>
                         <child>
-                          <object class="GtkViewport" id="forecast-viewport">
+                          <object class="GtkScrolledWindow" id="forecast-today">
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="hscroll_policy">natural</property>
-                            <property name="vscroll_policy">natural</property>
+                            <property name="can_focus">True</property>
+                            <property name="vscrollbar_policy">never</property>
+                            <property name="min_content_width">332</property>
+                            <property name="margin-start">32</property>
+                            <property name="margin-end">32</property>
                             <child>
-                              <object class="GtkGrid" id="forecast-grid">
+                              <object class="GtkViewport" id="forecast-today-viewport">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="halign">center</property>
+                                <property name="hscroll_policy">natural</property>
+                                <property name="vscroll_policy">natural</property>
+                                <child>
+                                  <object class="GtkGrid" id="forecast-today-grid">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">center</property>
+                                  </object>
+                                </child>
                               </object>
                             </child>
                           </object>
+                          <packing>
+                            <property name="name">today</property>
+                            <property name="title" translatable="yes">Today</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScrolledWindow" id="forecast-tomorrow">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="vscrollbar_policy">never</property>
+                            <property name="min_content_width">332</property>
+                            <property name="margin-start">32</property>
+                            <property name="margin-end">32</property>
+                            <child>
+                              <object class="GtkViewport" id="forecast-tomorrow-viewport">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="hscroll_policy">natural</property>
+                                <property name="vscroll_policy">natural</property>
+                                <child>
+                                  <object class="GtkGrid" id="forecast-tomorrow-grid">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="halign">center</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="name">tomorrow</property>
+                            <property name="title" translatable="yes">Tomorrow</property>
+                          </packing>
                         </child>
                       </object>
                       <packing>
diff --git a/src/app/city.js b/src/app/city.js
index ec931a7..e5ace08 100644
--- a/src/app/city.js
+++ b/src/app/city.js
@@ -46,58 +46,59 @@ const WeatherWidget = new Lang.Class({
         let outerBox = builder.get_object('outer-box');
         this._contentFrame = builder.get_object('content-frame');
         this._outerGrid = builder.get_object('outer-grid');
-        this._forecastGrid = builder.get_object('forecast-grid');
         this._wForecastFrame = builder.get_object('weekly-forecast-frame');
-        let forecastScrollingWindow = builder.get_object('forecast-scrolled-window');
         this._icon = builder.get_object('conditions-image');
         this._temperature = builder.get_object('temperature-label');
         this._conditions = builder.get_object('conditions-label');
         this.timeLabel = builder.get_object('time-label');
         this.timeGrid = builder.get_object('time-grid');
-        this._dayStack = builder.get_object('day-stack');
-        this._leftButton = builder.get_object('left-button');
-        this._rightButton = builder.get_object('right-button');
-
-        this._forecasts = new Forecast.ForecastBox({ hexpand: false });
-        this._forecastGrid.attach(this._forecasts, 0, 0, 1, 1);
 
         this._weeklyForecasts = new WForecast.WeeklyForecastFrame();
         this._outerGrid.attach(this._weeklyForecasts, 1, 0, 1, 2);
 
-        this._hscrollbar = forecastScrollingWindow.get_hscrollbar();
-        this._hscrollbar.set_opacity(0.0);
+        this._forecasts = { };
+        this._hadjustments = { };
 
-        this._hadjustment = forecastScrollingWindow.get_hadjustment();
+        for (let t of ['today', 'tomorrow']) {
+            let box = new Forecast.ForecastBox({ hexpand: false });
 
-        this._hadjustment.connect('changed', Lang.bind(this, function() {
-            if ((this._hadjustment.get_upper() - this._hadjustment.get_lower()) == 
this._hadjustment.page_size) {
-                this._leftButton.set_sensitive(false);
-                this._rightButton.set_sensitive(false);
-            } else if (this._hadjustment.value == this._hadjustment.get_lower()){
-                this._leftButton.set_sensitive(false);
-                this._rightButton.set_sensitive(true);
-            } else if (this._hadjustment.value >= (this._hadjustment.get_upper() - 
this._hadjustment.page_size)){
-                this._leftButton.set_sensitive(true);
-                this._rightButton.set_sensitive(false);
-            } else {
-                this._leftButton.set_sensitive(true);
-                this._rightButton.set_sensitive(true);
-            }
-        }));
+            this._forecasts[t] = box;
+            builder.get_object('forecast-' + t + '-grid').add(box);
+
+            let fsw = builder.get_object('forecast-' + t);
+            let hscrollbar = fsw.get_hscrollbar();
+            hscrollbar.set_opacity(0.0);
+            hscrollbar.hide();
+            let hadjustment = fsw.get_hadjustment();
+            hadjustment.connect('changed', Lang.bind(this, this._syncLeftRightButtons));
+            hadjustment.connect('value-changed', Lang.bind(this, this._syncLeftRightButtons));
+
+            this._hadjustments[t] = hadjustment;
+        }
+
+        this._dayStack = builder.get_object('forecast-stack');
+        this._leftButton = builder.get_object('left-button');
+        this._rightButton = builder.get_object('right-button');
 
         this._dayStack.connect('notify::visible-child', Lang.bind(this, function() {
-            this.clear();
-            if (this._info) {
-                let forecasts = this._info.get_forecast_list();
-                this._forecasts.update(forecasts, this._dayStack.get_visible_child_name());
-                this._hadjustment.value = this._hadjustment.get_lower();
-                this._forecasts.show();
+            let visible_child = this._dayStack.visible_child;
+            if (visible_child == null)
+                return; // can happen at destruction
+
+            let hadjustment = visible_child.get_hadjustment();
+            hadjustment.value = hadjustment.get_lower();
+            this._syncLeftRightButtons();
+
+            if (this._tickId) {
+                this.remove_tick_callback(this._tickId);
+                this._tickId = 0;
             }
         }));
 
         this._leftButton.connect('clicked', Lang.bind(this, function() {
-            this._target = this._hadjustment.value - this._hadjustment.page_size;
-            if (this._target <= this._hadjustment.get_lower()) {
+            let hadjustment = this._dayStack.visible_child.get_hadjustment();
+            this._target = hadjustment.value - hadjustment.page_size;
+            if (this._target <= hadjustment.get_lower()) {
                 this._leftButton.set_sensitive(false);
                 this._rightButton.set_sensitive(true);
             } else
@@ -105,12 +106,13 @@ const WeatherWidget = new Lang.Class({
 
             this._start = new Date().getTime();
             this._end = this._start + 328;
-            this._tickId = this._forecastGrid.add_tick_callback(Lang.bind(this, this._animate));
+            this._tickId = this.add_tick_callback(Lang.bind(this, this._animate));
         }));
 
         this._rightButton.connect('clicked', Lang.bind(this, function() {
-            this._target = this._hadjustment.value + this._hadjustment.page_size;
-            if (this._target >= this._hadjustment.get_upper() - this._hadjustment.page_size) {
+            let hadjustment = this._dayStack.visible_child.get_hadjustment();
+            this._target = hadjustment.value + hadjustment.page_size;
+            if (this._target >= hadjustment.get_upper() - hadjustment.page_size) {
                 this._rightButton.set_sensitive(false);
                 this._leftButton.set_sensitive(true);
             } else
@@ -118,24 +120,43 @@ const WeatherWidget = new Lang.Class({
 
             this._start = new Date().getTime();
             this._end = this._start + 328;
-            this._tickId = this._forecastGrid.add_tick_callback(Lang.bind(this, this._animate));
+            this._tickId = this.add_tick_callback(Lang.bind(this, this._animate));
         }));
 
         this.add(outerBox);
     },
 
+    _syncLeftRightButtons: function() {
+        let hadjustment = this._dayStack.visible_child.get_hadjustment();
+        if ((hadjustment.get_upper() - hadjustment.get_lower()) == hadjustment.page_size) {
+            this._leftButton.set_sensitive(false);
+            this._rightButton.set_sensitive(false);
+        } else if (hadjustment.value == hadjustment.get_lower()){
+            this._leftButton.set_sensitive(false);
+            this._rightButton.set_sensitive(true);
+        } else if (hadjustment.value >= (hadjustment.get_upper() - hadjustment.page_size)){
+            this._leftButton.set_sensitive(true);
+            this._rightButton.set_sensitive(false);
+        } else {
+            this._leftButton.set_sensitive(true);
+            this._rightButton.set_sensitive(true);
+        }
+    },
+
     _animate: function() {
-        let value = this._hadjustment.value;
+        let hadjustment = this._dayStack.visible_child.get_hadjustment();
+        let value = hadjustment.value;
         let t = 1.0;
         let now = new Date().getTime();
         if (now < this._end) {
             t = (now - this._start) / 700;
             t = this._easeOutCubic (t);
-            this._hadjustment.value = value + t * (this._target - value);
+            hadjustment.value = value + t * (this._target - value);
             return true;
         } else {
-            this._hadjustment.value = value + t * (this._target - value);
-            this._forecastGrid.remove_tick_callback(this._tickId);
+            hadjustment.value = value + t * (this._target - value);
+            this.remove_tick_callback(this._tickId);
+            this._tickId = 0;
             return false;
         }
     },
@@ -146,7 +167,13 @@ const WeatherWidget = new Lang.Class({
     },
 
     clear: function() {
-        this._forecasts.clear();
+        for (let t of ['today', 'tomorrow'])
+            this._forecasts[t].clear();
+
+        if (this._tickId) {
+            this.remove_tick_callback(this._tickId);
+            this._tickId = 0;
+        }
     },
 
     _get_style_class: function(info) {
@@ -169,8 +196,8 @@ const WeatherWidget = new Lang.Class({
         context.add_class(this._currentStyle);
 
         let forecasts = info.get_forecast_list();
-        this._forecasts.update(forecasts, this._dayStack.get_visible_child_name());
-        this._forecasts.show();
+        for (let t of ['today', 'tomorrow'])
+            this._forecasts[t].update(forecasts, t);
 
         if (forecasts.length == 0) {
             this._weeklyForecasts.hide();
diff --git a/src/app/forecast.js b/src/app/forecast.js
index 1b3b566..6f479f9 100644
--- a/src/app/forecast.js
+++ b/src/app/forecast.js
@@ -91,17 +91,17 @@ const ForecastBox = new Lang.Class({
     },
 
     update: function(infos, day) {
-        if (infos.length > 0) {
-            let now = GLib.DateTime.new_now_local();
-            if (day == "tomorrow-button")
-                now = now.add_days(1);
-            let dayInfo = this._preprocess(now, infos);
-
-            if (dayInfo.length == 0) {
-                now = now.add_hours(-2);
-                dayInfo = this._preprocess(now, infos);
-            }
+        let now = GLib.DateTime.new_now_local();
+        if (day == 'tomorrow')
+            now = now.add_days(1);
+        let dayInfo = this._preprocess(now, infos);
+
+        if (dayInfo.length == 0) {
+            now = now.add_hours(-2);
+            dayInfo = this._preprocess(now, infos);
+        }
 
+        if (dayInfo.length > 0) {
             for (let i = 0; i < dayInfo.length; i++) {
                 let info = dayInfo[i];
                 this._addOneInfo(info, i);


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