[gnome-weather] Redesign the main layout
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-weather] Redesign the main layout
- Date: Fri, 12 Jun 2020 19:13:43 +0000 (UTC)
commit 45d42f487eb0433e555f741eccdbc8508d371a63
Author: Vitaly Dyachkov <obyknovenius me com>
Date: Fri Jun 12 19:13:38 2020 +0000
Redesign the main layout
data/application.css | 94 ++-----
data/day-entry.ui | 413 +++++++++++++++++++++++++++++
data/hour-entry.ui | 60 +++++
data/org.gnome.Weather.data.gresource.xml | 11 +-
data/weather-clear-night.jpg | Bin 1310871 -> 0 bytes
data/weather-clear.jpg | Bin 100291 -> 0 bytes
data/weather-few-clouds-night.jpg | Bin 147364 -> 0 bytes
data/weather-few-clouds.jpg | Bin 401504 -> 0 bytes
data/weather-fog.jpg | Bin 619902 -> 0 bytes
data/weather-overcast.jpg | Bin 419325 -> 0 bytes
data/weather-showers.jpg | Bin 721902 -> 0 bytes
data/weather-snow.jpg | Bin 1205617 -> 0 bytes
data/weather-storm.jpg | Bin 274077 -> 0 bytes
data/weather-widget.ui | 377 ++++++++++----------------
data/window.ui | 101 +++----
src/app/city.js | 143 ++++------
src/app/dailyForecast.js | 319 ++++++++++++++++++++++
src/app/forecast.js | 164 ------------
src/app/hourlyForecast.js | 198 ++++++++++++++
src/app/main.js | 3 -
src/app/weeklyForecast.js | 152 -----------
src/app/window.js | 58 ++--
src/misc/util.js | 45 ++++
src/org.gnome.Weather.src.gresource.xml.in | 4 +-
24 files changed, 1311 insertions(+), 831 deletions(-)
---
diff --git a/data/application.css b/data/application.css
index 32979d3..98236cc 100644
--- a/data/application.css
+++ b/data/application.css
@@ -1,74 +1,23 @@
+#conditions-grid {
+ margin: 20px;
+}
+
+#places-label {
+ font-weight: bold;
+}
+
#weather-page-placeholder-title {
font-weight: bold;
font-size: 1.2em;
}
#weather-page-content-view {
- background-color: black;
background-size: cover;
background-position: center;
background-origin: border-box;
background-clip: border-box;
}
-#weather-page-content-view.weather-clear,
-#weather-page-content-view.weather-clear:backdrop {
- background-image: url("weather-clear.jpg");
- color: rgba(0,0,0,0.8);
-}
-
-#weather-page-content-view.weather-clear-night,
-#weather-page-content-view.weather-clear-night:backdrop {
- background-image: url("weather-clear-night.jpg");
- color: rgba(255,255,255,0.8);
-}
-
-#weather-page-content-view.weather-few-clouds,
-#weather-page-content-view.weather-few-clouds:backdrop {
- background-image: url("weather-few-clouds.jpg");
- color: rgba(0,0,0,0.6);
-}
-
-#weather-page-content-view.weather-few-clouds-night,
-#weather-page-content-view.weather-few-clouds-night:backdrop {
- background-image: url("weather-few-clouds-night.jpg");
- color: rgba(255,255,255,0.8);
-}
-
-#weather-page-content-view.weather-fog,
-#weather-page-content-view.weather-fog:backdrop {
- background-image: url("weather-fog.jpg");
- background-position: center 20%;
- color: rgba(255,255,255,0.8);
-}
-
-#weather-page-content-view.weather-overcast,
-#weather-page-content-view.weather-overcast:backdrop {
- background-image: url("weather-overcast.jpg");
- color: rgba(255,255,255,0.8);
-}
-
-#weather-page-content-view.weather-showers,
-#weather-page-content-view.weather-showers:backdrop,
-#weather-page-content-view.weather-showers-scattered,
-#weather-page-content-view.weather-showers-scattered:backdrop {
- background-image: url("weather-showers.jpg");
- color: rgba(255,255,255,1.0);
-}
-
-#weather-page-content-view.weather-snow,
-#weather-page-content-view.weather-snow:backdrop {
- background-image: url("weather-snow.jpg");
- color: rgba(255,255,255,0.8);
-}
-
-#weather-page-content-view.weather-storm,
-#weather-page-content-view.weather-storm:backdrop {
- background-image: url("weather-storm.jpg");
- background-position: center 80%;
- color: rgba(255,255,255,0.8);
-}
-
#loading-label {
padding-top: 24px;
font-size: 1.5em;
@@ -76,15 +25,7 @@
#temperature-label {
font-size: 4em;
-}
-
-#conditions-label {
- font-size: 2.5em;
-}
-
-#wind-label {
- font-size: 1.5em;
- padding-bottom: 12px; /* keep in sync with conditions-image */
+ margin-left: 16px;
}
#attribution-label {
@@ -95,15 +36,6 @@
color: @theme_fg_color;
}
-#conditions-image {
- padding: 12px;
-}
-
-#weekly-forecast-frame {
- background-color: rgba(0, 0, 0, 0.5);
- color: white;
-}
-
.content-view.cell {
font-weight: bold;
}
@@ -111,3 +43,11 @@
#locations-list-box {
border: 1px solid @borders;
}
+
+.forecast-temperature-label {
+ font-weight: bold;
+ color: #c89009;
+}
+
+@define-color temp_graph_border_color rgba(246, 211, 45, 1.0);
+@define-color temp_graph_background_color rgba(248, 228, 92, 0.5);
diff --git a/data/day-entry.ui b/data/day-entry.ui
new file mode 100644
index 0000000..8eb2b58
--- /dev/null
+++ b/data/day-entry.ui
@@ -0,0 +1,413 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkPopoverMenu" id="more_menu">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkAlignment">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="top_padding">16</property>
+ <property name="bottom_padding">16</property>
+ <property name="left_padding">16</property>
+ <property name="right_padding">16</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">16</property>
+ <property name="row_homogeneous">True</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Night</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Morning</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Afternoon</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Evening</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="nightImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">weather-showers-symbolic</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="morningImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">weather-showers-symbolic</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="afternoonImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">weather-showers-symbolic</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="eveningImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">weather-showers-symbolic</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">8</property>
+ <property name="row_homogeneous">True</property>
+ <property name="column_homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="nightTemperatureLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">16°</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="morningTemperatureLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">16°</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="afternoonTemperatureLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">16°</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eveningTemperatureLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">16°</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">weather-windy</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">weather-windy</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">weather-windy</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="nightHumidity">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">2.1 mm</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="morningHumidity">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">2.1 mm</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="afternoonHumidity">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">2.1 mm</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eveningHumidity">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">2.1 mm</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="nightWind">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">5 m/s</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="morningWind">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">5 m/s</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="afternoonWind">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">5 m/s</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eveningWind">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">5 m/s</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="height">5</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="submenu">main</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <template class="Gjs_DayEntry" parent="GtkBox">
+ <property name="width_request">75</property>
+ <property name="height_request">200</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="nameLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="label" translatable="yes">Tues</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dateLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="label" translatable="yes">7 June</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="vexpand">True</property>
+ <property name="pixel_size">32</property>
+ <property name="icon_name">weather-showers-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="maxTemperatureLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="label" translatable="yes">18°</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="minTemperatureLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="label" translatable="yes">9°</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="popover">more_menu</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">view-more-symbolic</property>
+ </object>
+ </child>
+ <style>
+ <class name="image-button"/>
+ <class name="circular"/>
+ <class name="flat"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/data/hour-entry.ui b/data/hour-entry.ui
new file mode 100644
index 0000000..df5d94e
--- /dev/null
+++ b/data/hour-entry.ui
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="Gjs_HourEntry" parent="GtkBox">
+ <property name="width_request">75</property>
+ <property name="height_request">200</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="timeLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="label" translatable="yes">Now</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="vexpand">True</property>
+ <property name="pixel_size">32</property>
+ <property name="icon_name">weather-showers-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="temperatureLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">end</property>
+ <property name="margin_bottom">16</property>
+ <property name="label" translatable="yes">13°</property>
+ <style>
+ <class name="forecast-temperature-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/data/org.gnome.Weather.data.gresource.xml b/data/org.gnome.Weather.data.gresource.xml
index 9913ed5..eb357d3 100644
--- a/data/org.gnome.Weather.data.gresource.xml
+++ b/data/org.gnome.Weather.data.gresource.xml
@@ -6,16 +6,9 @@
<file preprocess="xml-stripblanks">primary-menu.ui</file>
<file preprocess="xml-stripblanks">weather-widget.ui</file>
<file preprocess="xml-stripblanks">window.ui</file>
+ <file preprocess="xml-stripblanks">hour-entry.ui</file>
+ <file preprocess="xml-stripblanks">day-entry.ui</file>
<file>application.css</file>
- <file>weather-clear.jpg</file>
- <file>weather-clear-night.jpg</file>
- <file>weather-few-clouds.jpg</file>
- <file>weather-few-clouds-night.jpg</file>
- <file>weather-fog.jpg</file>
- <file>weather-overcast.jpg</file>
- <file>weather-showers.jpg</file>
- <file>weather-snow.jpg</file>
- <file>weather-storm.jpg</file>
</gresource>
<gresource prefix="/org/gnome/shell">
<file>ShellWeatherIntegration.xml</file>
diff --git a/data/weather-widget.ui b/data/weather-widget.ui
index 6e6940a..9bfb198 100644
--- a/data/weather-widget.ui
+++ b/data/weather-widget.ui
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.1 -->
+<!-- Generated with glade 3.22.0 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<template class="Gjs_WeatherWidget" parent="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
<child>
<object class="GtkFrame" id="contentFrame">
<property name="name">weather-page-content-view</property>
@@ -16,314 +17,230 @@
<object class="GtkGrid" id="outerGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="vexpand">True</property>
<child>
- <object class="GtkGrid" id="alignment">
+ <object class="GtkOverlay" id="forecast-overlay">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">center</property>
- <property name="valign">start</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="margin-top">50</property>
- <property name="margin-start">50</property>
- <property name="margin-end">20</property>
- <property name="row_spacing">32</property>
+ <property name="margin_bottom">50</property>
<child>
- <object class="GtkGrid" id="inner-grid">
- <property name="name">conditions-grid</property>
+ <object class="GtkStack" id="forecastStack">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="column_spacing">20</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="conditions-grid-a11y">
- <property name="accessible-name" translatable="yes">Current conditions</property>
- </object>
- </child>
- <child>
- <object class="GtkImage" id="conditionsImage">
- <property name="name">conditions-image</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="pixel_size">172</property>
- <property name="icon-size">2</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="temperatureLabel">
- <property name="name">temperature-label</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="valign">start</property>
- <property name="halign">start</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="conditionsLabel">
- <property name="name">conditions-label</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="valign">start</property>
- <property name="vexpand">True</property>
- <property name="halign">start</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
<child>
- <object class="GtkBox" id="windBox">
- <property name="name">wind-box</property>
+ <object class="GtkScrolledWindow" id="forecast-hourly">
<property name="visible">True</property>
- <property name="orientation">horizontal</property>
- <property name="halign">start</property>
- <property name="valign">start</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkImage" id="windIcon">
- <property name="name">wind-icon</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="icon-name">weather-windy-symbolic</property>
- </object>
- </child>
+ <property name="can_focus">True</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="min_content_width">332</property>
<child>
- <object class="GtkLabel" id="windLabel">
- <property name="name">wind-label</property>
+ <object class="GtkViewport" id="forecast-hourly-viewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="vexpand">True</property>
- <property name="halign">start</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="stack-grid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkStackSwitcher" id="day-stack-switcher">
- <property name="visible">True</property>
- <property name="stack">forecastStack</property>
- <style>
- <class name="osd"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="forecast-parent-grid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkStack" id="forecastStack">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <child>
- <object class="GtkScrolledWindow" id="forecast-today">
- <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="hscroll_policy">natural</property>
+ <property name="vscroll_policy">natural</property>
<child>
- <object class="GtkViewport" id="forecast-today-viewport">
+ <object class="GtkAlignment" id="forecast-hourly-alignment">
<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="halign">center</property>
+ <property name="left_padding">20</property>
+ <property name="right_padding">20</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>
+ <placeholder/>
</child>
</object>
</child>
</object>
- <packing>
- <property name="name">today</property>
- <property name="title" translatable="yes">Today</property>
- </packing>
</child>
+ </object>
+ <packing>
+ <property name="name">hourly</property>
+ <property name="title" translatable="yes">Hourly</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="forecast-daily">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="min_content_width">332</property>
<child>
- <object class="GtkScrolledWindow" id="forecast-tomorrow">
+ <object class="GtkViewport" id="forecast-daily-viewport">
<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>
+ <property name="hscroll_policy">natural</property>
+ <property name="vscroll_policy">natural</property>
<child>
- <object class="GtkViewport" id="forecast-tomorrow-viewport">
+ <object class="GtkAlignment" id="forecast-daily-alignment">
<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="halign">center</property>
+ <property name="left_padding">20</property>
+ <property name="right_padding">20</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>
+ <placeholder/>
</child>
</object>
</child>
</object>
- <packing>
- <property name="name">tomorrow</property>
- <property name="title" translatable="yes">Tomorrow</property>
- </packing>
</child>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
+ <property name="name">daily</property>
+ <property name="title" translatable="yes">Daily</property>
+ <property name="position">1</property>
</packing>
</child>
+ </object>
+ <packing>
+ <property name="index">-1</property>
+ </packing>
+ </child>
+ <child type="overlay">
+ <object class="GtkButton" id="rightButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="margin_right">28</property>
<child>
- <object class="GtkButton" id="leftButton">
+ <object class="GtkImage" id="right-image">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="valign">center</property>
- <style>
- <class name="osd"/>
- </style>
- <child>
- <object class="GtkImage" id="left-image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon-name">go-previous-symbolic</property>
- <property name="icon_size">1</property>
- </object>
- </child>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-next-symbolic</property>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
</child>
+ <style>
+ <class name="osd"/>
+ </style>
+ </object>
+ </child>
+ <child type="overlay">
+ <object class="GtkButton" id="leftButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="margin_left">28</property>
<child>
- <object class="GtkButton" id="rightButton">
+ <object class="GtkImage" id="left-image">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="valign">center</property>
- <style>
- <class name="osd"/>
- </style>
- <child>
- <object class="GtkImage" id="right-image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon-name">go-next-symbolic</property>
- </object>
- </child>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ <property name="icon_size">1</property>
</object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- </packing>
</child>
+ <style>
+ <class name="osd"/>
+ </style>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
+ <property name="index">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
- <object class="GtkGrid" id="timeGrid">
+ <object class="GtkGrid" id="inner-grid">
+ <property name="name">conditions-grid</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="margin-end">20</property>
+ <property name="column_spacing">10</property>
<child>
- <object class="GtkImage" id="clock-image">
+ <object class="GtkImage" id="conditionsImage">
+ <property name="name">conditions-image</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="margin-start">10</property>
- <property name="margin-end">10</property>
- <property name="margin-top">15</property>
- <property name="margin-bottom">15</property>
- <property name="icon_name">document-open-recent-symbolic</property>
+ <property name="valign">start</property>
+ <property name="pixel_size">96</property>
+ <property name="icon_size">2</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="height">2</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="timeLabel">
+ <object class="GtkLabel" id="temperatureLabel">
+ <property name="name">temperature-label</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin-top">15</property>
- <property name="margin-bottom">15</property>
- <property name="label">label</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="placesButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <child>
+ <object class="GtkBox" id="placesBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="placesLabel">
+ <property name="name">places-label</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Places</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="placesImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">pan-down-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="text-button"/>
+ <class name="flat"/>
+ </style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="inner-grid-atkobject">
+ <property name="AtkObject::accessible-name" translatable="yes">Current
conditions</property>
+ </object>
+ </child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
</object>
diff --git a/data/window.ui b/data/window.ui
index ff650d9..14307a0 100644
--- a/data/window.ui
+++ b/data/window.ui
@@ -1,71 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.0 -->
<interface>
- <!-- interface-requires gtk+ 3.10 -->
+ <requires lib="gtk+" version="3.10"/>
<object class="GtkHeaderBar" id="header-bar">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="vexpand">False</property>
- <property name="show-close-button">True</property>
+ <property name="show_close_button">True</property>
<child>
<object class="GtkMenuButton" id="primary-menu-button">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="use-popover">True</property>
+ <property name="receives_default">False</property>
<property name="valign">center</property>
- <style>
- <class name="image-button"/>
- </style>
<child>
<object class="GtkImage" id="primary-menu-img">
<property name="visible">True</property>
- <property name="icon-name">open-menu-symbolic</property>
- <property name="icon-size">1</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ <property name="icon_size">1</property>
</object>
</child>
- </object>
- <packing>
- <property name="pack_type">end</property>
- </packing>
- </child>
- <child>
- <object class="GtkMenuButton" id="places-button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Places</property>
- <property name="use-popover">True</property>
- <property name="valign">center</property>
<style>
- <class name="text-button"/>
+ <class name="image-button"/>
</style>
</object>
<packing>
- <property name="pack_type">start</property>
+ <property name="pack_type">end</property>
</packing>
</child>
<child>
<object class="GtkButton" id="refresh-button">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="action-name">win.refresh</property>
+ <property name="receives_default">False</property>
<property name="valign">center</property>
- <style>
- <class name="image-button"/>
- </style>
- <child internal-child="accessible">
- <object class="AtkObject" id="refresh-button-a11y">
- <property name="accessible-name" translatable="yes">Refresh</property>
- </object>
- </child>
+ <property name="action_name">win.refresh</property>
<child>
<object class="GtkImage" id="refresh-button-image">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="icon-name">view-refresh-symbolic</property>
- <property name="icon-size">1</property>
+ <property name="icon_name">view-refresh-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="refresh-button-atkobject">
+ <property name="AtkObject::accessible-name" translatable="yes">Refresh</property>
</object>
</child>
+ <style>
+ <class name="image-button"/>
+ </style>
</object>
<packing>
<property name="pack_type">end</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
@@ -75,67 +65,62 @@
<property name="orientation">vertical</property>
<child>
<object class="GtkStack" id="main-stack">
- <property name="transition-type">crossfade</property>
+ <property name="can_focus">False</property>
+ <property name="transition_type">crossfade</property>
<child>
<object class="GtkGrid" id="initial-grid">
- <property name="visible">True</property>
<property name="name">initial-grid</property>
+ <property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="margin_top">25</property>
- <property name="margin_bottom">25</property>
<property name="halign">center</property>
<property name="valign">center</property>
- <property name="row_homogeneous">True</property>
+ <property name="margin_top">25</property>
+ <property name="margin_bottom">25</property>
<property name="vexpand">False</property>
+ <property name="orientation">vertical</property>
+ <property name="row_homogeneous">True</property>
<child>
<object class="GtkImage" id="mark-location-image">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="icon_name">mark-location-symbolic</property>
- <property name="icon_size">6</property>
- <property name="use_fallback">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="vexpand">False</property>
+ <property name="icon_name">mark-location-symbolic</property>
+ <property name="use_fallback">True</property>
+ <property name="icon_size">6</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="search-location-label">
<property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="label" translatable="yes">Search for a location</property>
+ <property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="vexpand">False</property>
+ <property name="label" translatable="yes">Search for a location</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="search-nereby-location-label">
<property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="label" translatable="yes">To see weather information, enter the name of a
city.</property>
+ <property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="vexpand">False</property>
+ <property name="label" translatable="yes">To see weather information, enter the name of a
city.</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -147,23 +132,15 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
</object>
</child>
- <child>
- <placeholder/> <!-- city view -->
- </child>
</object>
<packing>
- <property name="left-attach">0</property>
- <property name="top-attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
</object>
</interface>
-
diff --git a/src/app/city.js b/src/app/city.js
index 86726ee..c187561 100644
--- a/src/app/city.js
+++ b/src/app/city.js
@@ -21,9 +21,11 @@ const GLib = imports.gi.GLib;
const Gnome = imports.gi.GnomeDesktop;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
+const GWeather = imports.gi.GWeather;
-const Forecast = imports.app.forecast;
-const WForecast = imports.app.weeklyForecast;
+const WorldView = imports.app.world;
+const HourlyForecast = imports.app.hourlyForecast;
+const DailyForecast = imports.app.dailyForecast;
const Util = imports.misc.util;
const SPINNER_SIZE = 128;
@@ -33,32 +35,37 @@ const SCROLLING_ANIMATION_TIME = 400000; //us
var WeatherWidget = GObject.registerClass({
Template: 'resource:///org/gnome/Weather/weather-widget.ui',
InternalChildren: ['contentFrame', 'outerGrid', 'conditionsImage',
- 'temperatureLabel', 'conditionsLabel', 'windLabel',
- 'timeLabel', 'timeGrid', 'forecastStack',
- 'leftButton', 'rightButton',
- 'forecast-today-grid', 'forecast-tomorrow-grid',
- 'forecast-today', 'forecast-tomorrow'],
+ 'placesButton', 'placesLabel','temperatureLabel',
+ 'forecastStack','leftButton', 'rightButton',
+ 'forecast-hourly', 'forecast-hourly-alignment',
+ 'forecast-daily', 'forecast-daily-alignment'],
}, class WeatherWidget extends Gtk.Frame {
- _init(params) {
+ _init(application, window, params) {
super._init(Object.assign({
shadow_type: Gtk.ShadowType.NONE,
name: 'weather-page'
}, params));
- this._currentStyle = null;
this._info = null;
- this._weeklyForecasts = new WForecast.WeeklyForecastFrame();
- this._outerGrid.attach(this._weeklyForecasts, 1, 0, 1, 2);
+ this._worldView = new WorldView.WorldContentView(application, window);
+ this._placesButton.set_popover(this._worldView);
+
+ this._dailyForecasts = new DailyForecast.DailyForecastFrame();
this._forecasts = { };
- for (let t of ['today', 'tomorrow']) {
- let box = new Forecast.ForecastBox({ hexpand: false });
+ for (let t of ['hourly', 'daily']) {
+ let box;
+ if (t == 'hourly') {
+ box = new HourlyForecast.HourlyForecastFrame();
+ } else {
+ box = new DailyForecast.DailyForecastFrame();
+ }
this._forecasts[t] = box;
- this['_forecast_' + t + '_grid'].add(box);
+ this['_forecast_' + t + '_alignment'].add(box);
let fsw = this['_forecast_' + t];
let hscrollbar = fsw.get_hscrollbar();
@@ -104,17 +111,17 @@ var WeatherWidget = GObject.registerClass({
_syncLeftRightButtons() {
let hadjustment = this._forecastStack.visible_child.get_hadjustment();
if ((hadjustment.get_upper() - hadjustment.get_lower()) == hadjustment.page_size) {
- this._leftButton.set_sensitive(false);
- this._rightButton.set_sensitive(false);
+ this._leftButton.hide();
+ this._rightButton.hide();
} else if (hadjustment.value == hadjustment.get_lower()){
- this._leftButton.set_sensitive(false);
- this._rightButton.set_sensitive(true);
+ this._leftButton.hide();
+ this._rightButton.show();
} else if (hadjustment.value >= (hadjustment.get_upper() - hadjustment.page_size)){
- this._leftButton.set_sensitive(true);
- this._rightButton.set_sensitive(false);
+ this._leftButton.show();
+ this._rightButton.hide();
} else {
- this._leftButton.set_sensitive(true);
- this._rightButton.set_sensitive(true);
+ this._leftButton.show();
+ this._rightButton.show();
}
}
@@ -147,7 +154,7 @@ var WeatherWidget = GObject.registerClass({
}
clear() {
- for (let t of ['today', 'tomorrow'])
+ for (let t of ['hourly', 'daily'])
this._forecasts[t].clear();
if (this._tickId) {
@@ -156,49 +163,36 @@ var WeatherWidget = GObject.registerClass({
}
}
- _getStyleClass(info) {
- let icon = info.get_icon_name();
- let name = icon.replace(/(-\d{3})/, "");
- return name;
- }
-
- setTimeVisible(visible) {
- this._timeGrid.visible = visible;
- }
-
- setTime(time) {
- this._timeLabel.label = time;
+ getForecastStack() {
+ return this._forecastStack;
}
update(info) {
this._info = info;
- this._conditionsLabel.label = Util.getWeatherConditions(info);
- this._temperatureLabel.label = info.get_temp_summary();
- this._windLabel.label = info.get_wind();
+ let location = info.location;
+ let city = location;
+ if (location.get_level() == GWeather.LocationLevel.WEATHER_STATION)
+ city = location.get_parent();
+
+ let country = city.get_parent();
+ while (country && country.get_level() > GWeather.LocationLevel.COUNTRY)
+ country = country.get_parent();
+
+ if (country)
+ this._placesLabel.set_text(city.get_name() + ', ' + country.get_name());
+ else
+ this._placesLabel.set_text(city.get_name());
+
+ this._worldView.refilter();
this._conditionsImage.icon_name = info.get_symbolic_icon_name();
- let context = this._contentFrame.get_style_context();
- if (this._currentStyle)
- context.remove_class(this._currentStyle);
- this._currentStyle = this._getStyleClass(info);
- context.add_class(this._currentStyle);
+ this._temperatureLabel.label = info.get_temp_summary();
let forecasts = info.get_forecast_list();
let tz = GLib.TimeZone.new(info.location.get_timezone().get_tzid());
- for (let t of ['today', 'tomorrow'])
- this._forecasts[t].update(forecasts, tz, t);
-
- if (!this._forecasts['today'].hasForecastInfo() && this._forecasts['tomorrow'].hasForecastInfo())
- this._forecastStack.set_visible_child_name('tomorrow');
-
- // FIXME: This doesn't make sense, since the above code assumes forecasts.length != 0.
- if (forecasts.length == 0) {
- this._weeklyForecasts.hide();
- } else {
- this._weeklyForecasts.show();
- this._weeklyForecasts.update(forecasts);
- }
+ for (let t of ['hourly', 'daily'])
+ this._forecasts[t].update(forecasts, tz);
}
});
@@ -207,10 +201,10 @@ var WeatherView = GObject.registerClass({
InternalChildren: ['spinner']
}, class WeatherView extends Gtk.Stack {
- _init(params) {
+ _init(application, window, params) {
super._init(params);
- this._infoPage = new WeatherWidget();
+ this._infoPage = new WeatherWidget(application, window);
this.add_named(this._infoPage, 'info');
this._info = null;
@@ -265,40 +259,11 @@ var WeatherView = GObject.registerClass({
_onUpdate(info) {
this._infoPage.clear();
this._infoPage.update(info);
- this._updateTime();
this._spinner.stop();
this.visible_child_name = 'info';
}
- setTimeVisible(visible) {
- if (this._clockHandlerId && !visible) {
- this._wallClock.disconnect(this._clockHandlerId);
- this._clockHandlerId = 0;
- }
-
- if (!this._clockHandlerId && visible) {
- this._clockHandlerId = this._wallClock.connect('notify::clock', () => {
- this._updateTime();
- });
- }
-
- this._infoPage.setTimeVisible(visible);
- }
-
- _updateTime() {
- this._infoPage.setTime(this._getTime());
- }
-
- _getTime() {
- if (this._info != null) {
- let location = this._info.location;
- let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
- let dt = GLib.DateTime.new_now(tz);
-
- return this._wallClock.string_for_datetime (dt,
- this._desktopSettings.get_enum('clock-format'),
- false, false, false);
- }
- return null;
+ getInfoPage() {
+ return this._infoPage;
}
});
diff --git a/src/app/dailyForecast.js b/src/app/dailyForecast.js
new file mode 100644
index 0000000..5819c7e
--- /dev/null
+++ b/src/app/dailyForecast.js
@@ -0,0 +1,319 @@
+// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
+//
+// Copyright (c) 2014 Saurabh Patel <srp201201051 gmail com>
+//
+// Gnome Weather 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 2 of the License, or (at your
+// option) any later version.
+//
+// Gnome Weather 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 Gnome Weather; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+
+const Util = imports.misc.util;
+
+var DailyForecastFrame = GObject.registerClass(class DailyForecastFrame extends Gtk.Frame {
+
+ _init(params) {
+ super._init(Object.assign({
+ shadow_type: Gtk.ShadowType.IN,
+ name: 'daily-forecast-frame',
+ }, params));
+ this.get_accessible().accessible_name = _('Daily Forecast');
+
+ this._box = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
+ spacing: 0});
+ this.add(this._box);
+ }
+
+ // get infos for the correct day
+ _preprocess(infos) {
+ let i;
+
+ let day = GLib.DateTime.new_now_local();
+ day = day.add_days(1);
+
+ // First ignore all infos that are on a different
+ // older than day.
+ // infos are ordered by time, and it's assumed at some point
+ // there is an info for the day (otherwise, nothing
+ // is shown)
+ for (i = 0; i < infos.length; i++) {
+ let info = infos[i];
+
+ let datetime = Util.getDateTime(info);
+ if (Util.arrayEqual(day.get_ymd(), datetime.get_ymd()))
+ break;
+ }
+
+ let weekInfos = [];
+ while (i < infos.length) {
+ let dayInfos = {day: day, infos: []};
+ for ( ; i < infos.length; i++) {
+ let info = infos[i];
+
+ let datetime = Util.getDateTime(info);
+ if (!Util.arrayEqual(day.get_ymd(), datetime.get_ymd()))
+ break;
+
+ dayInfos.infos.push(info);
+ }
+ weekInfos.push(dayInfos);
+ day = day.add_days(1);
+ }
+ return weekInfos;
+ }
+
+ update(infos) {
+ let weekInfos = this._preprocess(infos);
+
+ if (weekInfos.length > 0) {
+ for (let i = 0; i < weekInfos.length; i++) {
+ let dayInfos = weekInfos[i];
+ this._addDayEntry(dayInfos);
+
+ if (i < weekInfos.length - 1)
+ this._addSeparator();
+ }
+ } else {
+ let label = new Gtk.Label({ label: _('Forecast not available'),
+ use_markup: true,
+ visible: true });
+ this._box.pack_start(label, true, false, 0);
+ }
+ }
+
+ _addDayEntry({day, infos}) {
+ let maxInfo;
+ let maxTemp = -Infinity;
+
+ let minInfo;
+ let minTemp = Infinity;
+
+ day = Util.getDay(day);
+ let dayInfo;
+ let dayDiff = Infinity;
+
+ let night = Util.getNight(day);
+ let nightInfo;
+ let nightDiff = Infinity;
+
+ let morning = Util.getMorning(day);
+ let morningInfo;
+ let morningDiff = Infinity;
+
+ let afternoon = Util.getAfternoon(day);
+ let afternoonInfo;
+ let afternoonDiff = Infinity;
+
+ let evening = Util.getEvening(day);
+ let eveningInfo;
+ let eveningDiff = Infinity;
+
+ for (let i = 0; i < infos.length; i++) {
+ let info = infos[i];
+
+ let temp = Util.getTemp(info);
+ if (temp > maxTemp) {
+ maxInfo = info;
+ maxTemp = temp;
+ }
+ if (temp < minTemp) {
+ minInfo = info;
+ minTemp = minTemp;
+ }
+
+ let datetime = Util.getDateTime(info);
+
+ let diff = Math.abs(datetime.difference(day));
+ if (diff < dayDiff) {
+ dayInfo = info;
+ dayDiff = diff;
+ }
+
+ diff = Math.abs(datetime.difference(night));
+ if (diff < nightDiff) {
+ nightInfo = info;
+ nightDiff = diff;
+ }
+
+ diff = Math.abs(datetime.difference(morning));
+ if (diff < morningDiff) {
+ morningInfo = info;
+ morningDiff = diff;
+ }
+
+ diff = Math.abs(datetime.difference(afternoon));
+ if (diff < afternoonDiff) {
+ afternoonInfo = info;
+ afternoonDiff = diff;
+ }
+
+ diff = Math.abs(datetime.difference(evening));
+ if (diff < eveningDiff) {
+ eveningInfo = info;
+ eveningDiff = diff;
+ }
+ }
+
+ let dayEntry = new DayEntry();
+
+ let nameFormat = '%a';
+ dayEntry.nameLabel.label = day.format(nameFormat);
+
+ /* Translators: this is the time format for day and month name according to the current locale */
+ let dateFormat = _('%e %b');
+ dayEntry.dateLabel.label = day.format(dateFormat);
+
+ dayEntry.image.iconName = dayInfo.get_symbolic_icon_name();
+
+ dayEntry.maxTemperatureLabel.label = maxInfo.get_temp_summary();
+ dayEntry.minTemperatureLabel.label = minInfo.get_temp_summary();
+
+ dayEntry.nightTemperatureLabel.label = nightInfo.get_temp_summary();
+ dayEntry.nightImage.iconName = nightInfo.get_symbolic_icon_name();
+ dayEntry.nightHumidity.label = nightInfo.get_humidity();
+ dayEntry.nightWind.label = nightInfo.get_wind();
+
+ dayEntry.morningTemperatureLabel.label = morningInfo.get_temp_summary();
+ dayEntry.morningImage.iconName = morningInfo.get_symbolic_icon_name();
+ dayEntry.morningHumidity.label = morningInfo.get_humidity();
+ dayEntry.morningWind.label = morningInfo.get_wind();
+
+ dayEntry.afternoonTemperatureLabel.label = afternoonInfo.get_temp_summary();
+ dayEntry.afternoonImage.iconName = afternoonInfo.get_symbolic_icon_name();
+ dayEntry.afternoonHumidity.label = afternoonInfo.get_humidity();
+ dayEntry.afternoonWind.label = afternoonInfo.get_wind();
+
+ dayEntry.eveningTemperatureLabel.label = eveningInfo.get_temp_summary();
+ dayEntry.eveningImage.iconName = eveningInfo.get_symbolic_icon_name();
+ dayEntry.eveningHumidity.label = eveningInfo.get_humidity();
+ dayEntry.eveningWind.label = eveningInfo.get_wind();
+
+ this._box.pack_start(dayEntry, false, false, 0);
+ }
+
+ _addSeparator() {
+ let separator = new Gtk.Separator({ orientation: Gtk.Orientation.VERTICAL,
+ visible: true});
+ this._box.pack_start(separator, false, false, 0);
+ }
+
+ clear() {
+ this._box.foreach(function(w) { w.destroy(); });
+ }
+});
+
+var DayEntry = GObject.registerClass({
+ Template: 'resource:///org/gnome/Weather/day-entry.ui',
+ InternalChildren: ['nameLabel', 'dateLabel', 'image',
+ 'maxTemperatureLabel', 'minTemperatureLabel',
+ 'nightTemperatureLabel', 'nightImage',
+ 'nightHumidity', 'nightWind',
+ 'morningTemperatureLabel', 'morningImage',
+ 'morningHumidity', 'morningWind',
+ 'afternoonTemperatureLabel', 'afternoonImage',
+ 'afternoonHumidity', 'afternoonWind',
+ 'eveningTemperatureLabel', 'eveningImage',
+ 'eveningHumidity', 'eveningWind'],
+}, class DayEntry extends Gtk.Box {
+
+ _init(params) {
+ super._init(params);
+ }
+
+ get nameLabel() {
+ return this._nameLabel;
+ }
+
+ get dateLabel() {
+ return this._dateLabel;
+ }
+
+ get image() {
+ return this._image;
+ }
+
+ get maxTemperatureLabel() {
+ return this._maxTemperatureLabel;
+ }
+
+ get minTemperatureLabel() {
+ return this._minTemperatureLabel;
+ }
+
+ get nightTemperatureLabel() {
+ return this._nightTemperatureLabel;
+ }
+
+ get nightImage() {
+ return this._nightImage;
+ }
+
+ get nightHumidity() {
+ return this._nightHumidity;
+ }
+
+ get nightWind() {
+ return this._nightWind;
+ }
+
+ get morningTemperatureLabel() {
+ return this._morningTemperatureLabel;
+ }
+
+ get morningImage() {
+ return this._morningImage;
+ }
+
+ get morningHumidity() {
+ return this._morningHumidity;
+ }
+
+ get morningWind() {
+ return this._morningWind;
+ }
+
+ get afternoonTemperatureLabel() {
+ return this._afternoonTemperatureLabel;
+ }
+
+ get afternoonImage() {
+ return this._afternoonImage;
+ }
+
+ get afternoonHumidity() {
+ return this._afternoonHumidity;
+ }
+
+ get afternoonWind() {
+ return this._afternoonWind;
+ }
+
+ get eveningTemperatureLabel() {
+ return this._eveningTemperatureLabel;
+ }
+
+ get eveningImage() {
+ return this._eveningImage;
+ }
+
+ get eveningHumidity() {
+ return this._eveningHumidity;
+ }
+
+ get eveningWind() {
+ return this._eveningWind;
+ }
+});
diff --git a/src/app/hourlyForecast.js b/src/app/hourlyForecast.js
new file mode 100644
index 0000000..c3f378d
--- /dev/null
+++ b/src/app/hourlyForecast.js
@@ -0,0 +1,198 @@
+// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
+//
+// Copyright (c) 2012 Giovanni Campagna <scampa giovanni gmail com>
+//
+// Gnome Weather 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 2 of the License, or (at your
+// option) any later version.
+//
+// Gnome Weather 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 Gnome Weather; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Gdk = imports.gi.Gdk;
+const Gtk = imports.gi.Gtk;
+const GWeather = imports.gi.GWeather;
+
+const Util = imports.misc.util;
+
+// In microseconds
+const TWENTY_FOUR_HOURS = 24 * 3600 * 1000 * 1000;
+
+var HourlyForecastFrame = GObject.registerClass(class ForecastFrame extends Gtk.Frame {
+
+ _init(params) {
+ super._init(Object.assign({
+ shadow_type: Gtk.ShadowType.IN,
+ name: 'hourly-forecast-frame',
+ }, params));
+ this.get_accessible().accessible_name = _('Hourly Forecast');
+
+ this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
+
+ this._box = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
+ spacing: 0});
+ this.add(this._box);
+
+ this._hourlyInfo = [];
+
+ this._hasForecastInfo = false;
+ }
+
+ // Ensure that infos are sufficiently spaced, and
+ // remove infos for the wrong day
+ _preprocess(now, infos) {
+ let ret = [];
+
+ for (let i = 0; i < infos.length; i++) {
+ let info = infos[i];
+
+ let [ok, date] = info.get_value_update();
+ let datetime = GLib.DateTime.new_from_unix_utc(date).to_timezone(now.get_timezone());
+
+ if (datetime.difference(now) <= 0)
+ continue;
+
+ if (datetime.difference(now) >= TWENTY_FOUR_HOURS)
+ break;
+
+ ret.push(info);
+ }
+
+ return ret;
+ }
+
+ update(infos, tz) {
+ let now = GLib.DateTime.new_now(tz);
+ let hourlyInfo = this._preprocess(now, infos);
+
+ if (hourlyInfo.length > 0) {
+ for (let i = 0; i < hourlyInfo.length; i++) {
+ let info = hourlyInfo[i];
+ this._addHourEntry(info, tz);
+
+ if (i < hourlyInfo.length - 1)
+ this._addSeparator();
+ }
+ } else {
+ let label = new Gtk.Label({ label: _('Forecast not available'),
+ use_markup: true,
+ visible: true });
+ this._box.pack_start(label, true, false, 0);
+ }
+
+ this._hourlyInfo = hourlyInfo;
+ }
+
+ _addHourEntry(info, tz) {
+ let [ok, date] = info.get_value_update();
+ let datetime = GLib.DateTime.new_from_unix_utc(date).to_timezone(tz);
+
+ let timeSetting = this._settings.get_string('clock-format');
+ let timeFormat = null;
+
+ if (timeSetting == '12h')
+ /* Translators: this is a time format without date used for AM/PM */
+ timeFormat = _('%l∶%M %p');
+ else
+ timeFormat = '%R';
+
+ let hourEntry = new HourEntry();
+ hourEntry.timeLabel.label = datetime.format(timeFormat);
+ hourEntry.image.iconName = info.get_symbolic_icon_name();
+ hourEntry.temperatureLabel.label = info.get_temp_summary();
+
+ this._box.pack_start(hourEntry, false, false, 0);
+
+ this._hasForecastInfo = true;
+ }
+
+ _addSeparator() {
+ let separator = new Gtk.Separator({ orientation: Gtk.Orientation.VERTICAL,
+ visible: true});
+ this._box.pack_start(separator, false, false, 0);
+ }
+
+ clear() {
+ this._box.foreach(function(w) { w.destroy(); });
+ }
+
+ hasForecastInfo() {
+ return this._hasForecastInfo;
+ }
+
+ vfunc_draw(cr) {
+ let hourlyInfo = this._hourlyInfo;
+
+ let temps = hourlyInfo.map(info => {
+ let [ok, t] = info.get_value_temp(GWeather.TemperatureUnit.DEFAULT);
+ return t;
+ });
+ let maxTemp = Math.max(...temps);
+ temps = temps.map(t => t / maxTemp);
+ let n = temps.length;
+
+ let width = this.get_allocated_width();
+ let height = this.get_allocated_height();
+
+ let top_padding = 80;
+ let bottom_padding = 40;
+
+ let canvas_height = height - top_padding - bottom_padding;
+ let step = (width - (n - 1)) / n;
+
+ let [, borderColor] = this.get_style_context().lookup_color('temp_graph_border_color');
+ Gdk.cairo_set_source_rgba(cr, borderColor);
+ cr.setLineWidth(2);
+
+ cr.moveTo (0, top_padding + ((1 - temps[0]) * canvas_height));
+ for (let i = 0; i < n; i++)
+ cr.lineTo((i * step) + step / 2, top_padding + ((1 - temps[i]) * canvas_height));
+ cr.lineTo(width, top_padding + ((1 - temps[n - 1]) * canvas_height));
+ cr.strokePreserve();
+
+ cr.lineTo(width, height);
+ cr.lineTo(0, height);
+
+ let [, backgroundColor] = this.get_style_context().lookup_color('temp_graph_background_color');
+ Gdk.cairo_set_source_rgba(cr, backgroundColor);
+
+ cr.fill();
+
+ super.vfunc_draw(cr);
+ cr.$dispose();
+
+ return Gdk.EVENT_PROPAGATE;
+ }
+});
+
+var HourEntry = GObject.registerClass({
+ Template: 'resource:///org/gnome/Weather/hour-entry.ui',
+ InternalChildren: ['timeLabel', 'image', 'temperatureLabel'],
+}, class HourEntry extends Gtk.Box {
+
+ _init(params) {
+ super._init(params);
+ }
+
+ get timeLabel() {
+ return this._timeLabel;
+ }
+
+ get image() {
+ return this._image;
+ }
+
+ get temperatureLabel() {
+ return this._temperatureLabel;
+ }
+});
diff --git a/src/app/main.js b/src/app/main.js
index 158254b..6e93fa9 100644
--- a/src/app/main.js
+++ b/src/app/main.js
@@ -90,9 +90,6 @@ const Application = GObject.registerClass(
Util.loadStyleSheet('/org/gnome/Weather/application.css');
- let settings = Gtk.Settings.get_for_screen(Gdk.Screen.get_default());
- settings.gtk_application_prefer_dark_theme = true;
-
this.world = GWeather.Location.get_world();
this.model = new World.WorldModel(this.world, true);
this.model.load();
diff --git a/src/app/window.js b/src/app/window.js
index c1bde7c..201b457 100644
--- a/src/app/window.js
+++ b/src/app/window.js
@@ -43,6 +43,8 @@ var MainWindow = GObject.registerClass(
this._currentPage = Page.SEARCH;
this._pageWidgets = [[],[]];
+ this.set_default_size(650, 520);
+
let aboutAction = new Gio.SimpleAction({
enabled: true,
name: 'about'
@@ -71,14 +73,9 @@ var MainWindow = GObject.registerClass(
let grid = builder.get_object('main-panel');
this._header = builder.get_object('header-bar');
this.set_titlebar(this._header);
- let [title, subtitle] = this._getTitle();
- this._header.title = title;
- this._header.subtitle = subtitle;
-
- this._worldView = new WorldView.WorldContentView(this.application, this, { visible: true });
- this._worldView.hide();
+ this._header.set_title(_('Select Location'));
- this._model = this._worldView.model;
+ this._model = this.application.model;
this._searchView = builder.get_object('initial-grid');
@@ -87,11 +84,6 @@ var MainWindow = GObject.registerClass(
this._searchLocationChanged(entry);
});
- let placesButton = builder.get_object('places-button');
- this._pageWidgets[Page.CITY].push(placesButton);
-
- placesButton.set_popover(this._worldView);
-
let refresh = builder.get_object('refresh-button');
this._pageWidgets[Page.CITY].push(refresh);
@@ -103,10 +95,13 @@ var MainWindow = GObject.registerClass(
this._stack = builder.get_object('main-stack');
- this._cityView = new City.WeatherView({ hexpand: true,
- vexpand: true });
+ this._cityView = new City.WeatherView(this.application, this,
+ { hexpand: true, vexpand: true });
this._stack.add(this._cityView);
+ this._forecastStackSwitcher = new Gtk.StackSwitcher({visible: true});
+ this._forecastStackSwitcher.set_stack(this._cityView.getInfoPage().getForecastStack());
+
this._stack.set_visible_child(this._searchView);
this.add(grid);
@@ -134,24 +129,11 @@ var MainWindow = GObject.registerClass(
}
}
- _getTitle() {
- if (this._currentPage == Page.SEARCH)
- return [_("Select Location"), null];
-
- let location = this._cityView.info.location;
- let city = location;
- if (location.get_level() == GWeather.LocationLevel.WEATHER_STATION)
- city = location.get_parent();
-
- let country = city.get_parent();
- while (country &&
- country.get_level() > GWeather.LocationLevel.COUNTRY)
- country = country.get_parent();
-
- if (country)
- return [city.get_name(), country.get_name()];
+ _setTitle(page) {
+ if (page == Page.CITY)
+ this._header.set_custom_title(this._forecastStackSwitcher);
else
- return [city.get_name(), null];
+ this._header.set_custom_title(null);
}
_goToPage(page) {
@@ -164,11 +146,9 @@ var MainWindow = GObject.registerClass(
this._pageWidgets[page][i].show();
}
- this._currentPage = page;
+ this._setTitle(page);
- let [title, subtitle] = this._getTitle();
- this._header.title = title;
- this._header.subtitle = subtitle;
+ this._currentPage = page;
}
showDefault() {
@@ -218,14 +198,6 @@ var MainWindow = GObject.registerClass(
this.currentInfo = info;
this._cityView.info = info;
- let isCurrentTimezone = false;
- let currentLocation = this.application.currentLocationController.currentLocation;
- if (currentLocation) {
- isCurrentTimezone = currentLocation.get_timezone().get_tzid() ==
info.location.get_timezone().get_tzid();
- }
- this._cityView.setTimeVisible(!isCurrentTimezone);
-
- this._worldView.refilter();
this._stack.set_visible_child(this._cityView);
this._goToPage(Page.CITY);
}
diff --git a/src/misc/util.js b/src/misc/util.js
index f63cbd8..0494e5e 100644
--- a/src/misc/util.js
+++ b/src/misc/util.js
@@ -156,3 +156,48 @@ function easeOutCubic(value) {
let t = value - 1;
return t * t * t + 1;
}
+
+function getNight(date) {
+ return GLib.DateTime.new_local(date.get_year(),
+ date.get_month(),
+ date.get_day_of_month(),
+ 2, 0, 0);
+}
+
+function getMorning(date) {
+ return GLib.DateTime.new_local(date.get_year(),
+ date.get_month(),
+ date.get_day_of_month(),
+ 7, 0, 0);
+}
+
+function getDay(date) {
+ return GLib.DateTime.new_local(date.get_year(),
+ date.get_month(),
+ date.get_day_of_month(),
+ 12, 0, 0);
+}
+
+function getAfternoon(date) {
+ return GLib.DateTime.new_local(date.get_year(),
+ date.get_month(),
+ date.get_day_of_month(),
+ 17, 0, 0);
+}
+
+function getEvening(date) {
+ return GLib.DateTime.new_local(date.get_year(),
+ date.get_month(),
+ date.get_day_of_month(),
+ 22, 0, 0);
+}
+
+function getDateTime(info) {
+ let [ok, date] = info.get_value_update();
+ return GLib.DateTime.new_from_unix_local(date);
+}
+
+function getTemp(info) {
+ let [ok, temp] = info.get_value_temp(GWeather.TemperatureUnit.DEFAULT);
+ return temp;
+}
diff --git a/src/org.gnome.Weather.src.gresource.xml.in b/src/org.gnome.Weather.src.gresource.xml.in
index 7234183..17b7432 100644
--- a/src/org.gnome.Weather.src.gresource.xml.in
+++ b/src/org.gnome.Weather.src.gresource.xml.in
@@ -3,8 +3,8 @@
<gresource prefix="/org/gnome/Weather@profile@/js">
<file>app/city.js</file>
<file>app/currentLocationController.js</file>
- <file>app/forecast.js</file>
- <file>app/weeklyForecast.js</file>
+ <file>app/hourlyForecast.js</file>
+ <file>app/dailyForecast.js</file>
<file>app/main.js</file>
<file>app/window.js</file>
<file>app/world.js</file>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]