~strycore/ubuntu/vivid/gnome-weather/fix-for-1456400

« back to all changes in this revision

Viewing changes to src/app/city.js

  • Committer: Package Import Robot
  • Author(s): Jackson Doak
  • Date: 2014-12-20 18:32:08 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20141220183208-e2895ntfyv23x1m3
Tags: 3.14.1-0ubuntu1
* New upstream release.
* Fix a typo in watch file
* Change binary to arch: all
* Update d/copyright for this release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
 
2
//
 
3
// Copyright (c) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
 
4
//
 
5
// Gnome Weather is free software; you can redistribute it and/or modify
 
6
// it under the terms of the GNU General Public License as published by the
 
7
// Free Software Foundation; either version 2 of the License, or (at your
 
8
// option) any later version.
 
9
//
 
10
// Gnome Weather is distributed in the hope that it will be useful, but
 
11
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
12
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
13
// for more details.
 
14
//
 
15
// You should have received a copy of the GNU General Public License along
 
16
// with Gnome Weather; if not, write to the Free Software Foundation,
 
17
// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 
 
19
const Gtk = imports.gi.Gtk;
 
20
const GLib = imports.gi.GLib;
 
21
const Gnome = imports.gi.GnomeDesktop;
 
22
const Lang = imports.lang;
 
23
 
 
24
const Forecast = imports.app.forecast;
 
25
const WForecast = imports.app.weeklyForecast;
 
26
const Params = imports.misc.params;
 
27
const Util = imports.misc.util;
 
28
 
 
29
const SPINNER_SIZE = 128;
 
30
 
 
31
const WeatherWidget = new Lang.Class({
 
32
    Name: 'WeatherWidget',
 
33
    Extends: Gtk.Frame,
 
34
 
 
35
    _init: function(params) {
 
36
        params = Params.fill(params, { shadow_type: Gtk.ShadowType.NONE,
 
37
                                       name: 'weather-page' });
 
38
        this.parent(params);
 
39
 
 
40
        this._currentStyle = null;
 
41
        this._info = null;
 
42
 
 
43
        let builder = new Gtk.Builder();
 
44
        builder.add_from_resource('/org/gnome/Weather/Application/city.ui');
 
45
 
 
46
        let outerBox = builder.get_object('outer-box');
 
47
        this._contentFrame = builder.get_object('content-frame');
 
48
        this._outerGrid = builder.get_object('outer-grid');
 
49
        this._forecastGrid = builder.get_object('forecast-grid');
 
50
        this._wForecastFrame = builder.get_object('weekly-forecast-frame');
 
51
        let forecastScrollingWindow = builder.get_object('forecast-scrolled-window');
 
52
        this._icon = builder.get_object('conditions-image');
 
53
        this._temperature = builder.get_object('temperature-label');
 
54
        this._conditions = builder.get_object('conditions-label');
 
55
        this.timeLabel = builder.get_object('time-label');
 
56
        this.timeGrid = builder.get_object('time-grid');
 
57
        this._dayStack = builder.get_object('day-stack');
 
58
        this._leftButton = builder.get_object('left-button');
 
59
        this._rightButton = builder.get_object('right-button');
 
60
 
 
61
        this._forecasts = new Forecast.ForecastBox({ hexpand: false });
 
62
        this._forecastGrid.attach(this._forecasts, 0, 0, 1, 1);
 
63
 
 
64
        this._weeklyForecasts = new WForecast.WeeklyForecastFrame();
 
65
        this._outerGrid.attach(this._weeklyForecasts, 1, 0, 1, 2);
 
66
 
 
67
        this._hscrollbar = forecastScrollingWindow.get_hscrollbar();
 
68
        this._hscrollbar.set_opacity(0.0);
 
69
 
 
70
        this._hadjustment = forecastScrollingWindow.get_hadjustment();
 
71
 
 
72
        this._hadjustment.connect('changed', Lang.bind(this, function() {
 
73
            if ((this._hadjustment.get_upper() - this._hadjustment.get_lower()) == this._hadjustment.page_size) {
 
74
                this._leftButton.set_sensitive(false);
 
75
                this._rightButton.set_sensitive(false);
 
76
            } else if (this._hadjustment.value == this._hadjustment.get_lower()){
 
77
                this._leftButton.set_sensitive(false);
 
78
                this._rightButton.set_sensitive(true);
 
79
            } else if (this._hadjustment.value >= (this._hadjustment.get_upper() - this._hadjustment.page_size)){
 
80
                this._leftButton.set_sensitive(true);
 
81
                this._rightButton.set_sensitive(false);
 
82
            } else {
 
83
                this._leftButton.set_sensitive(true);
 
84
                this._rightButton.set_sensitive(true);
 
85
            }
 
86
        }));
 
87
 
 
88
        this._dayStack.connect('notify::visible-child', Lang.bind(this, function() {
 
89
            this.clear();
 
90
            if (this._info) {
 
91
                let forecasts = this._info.get_forecast_list();
 
92
                this._forecasts.update(forecasts, this._dayStack.get_visible_child_name());
 
93
                this._hadjustment.value = this._hadjustment.get_lower();
 
94
                this._forecasts.show();
 
95
            }
 
96
        }));
 
97
 
 
98
        this._leftButton.connect('clicked', Lang.bind(this, function() {
 
99
            this._target = this._hadjustment.value - this._hadjustment.page_size;
 
100
            if (this._target <= this._hadjustment.get_lower()) {
 
101
                this._leftButton.set_sensitive(false);
 
102
                this._rightButton.set_sensitive(true);
 
103
            } else
 
104
                this._rightButton.set_sensitive(true);
 
105
 
 
106
            this._start = new Date().getTime();
 
107
            this._end = this._start + 328;
 
108
            this._tickId = this._forecastGrid.add_tick_callback(Lang.bind(this, this._animate));
 
109
        }));
 
110
 
 
111
        this._rightButton.connect('clicked', Lang.bind(this, function() {
 
112
            this._target = this._hadjustment.value + this._hadjustment.page_size;
 
113
            if (this._target >= this._hadjustment.get_upper() - this._hadjustment.page_size) {
 
114
                this._rightButton.set_sensitive(false);
 
115
                this._leftButton.set_sensitive(true);
 
116
            } else
 
117
                this._leftButton.set_sensitive(true);
 
118
 
 
119
            this._start = new Date().getTime();
 
120
            this._end = this._start + 328;
 
121
            this._tickId = this._forecastGrid.add_tick_callback(Lang.bind(this, this._animate));
 
122
        }));
 
123
 
 
124
        this.add(outerBox);
 
125
    },
 
126
 
 
127
    _animate: function() {
 
128
        let value = this._hadjustment.value;
 
129
        let t = 1.0;
 
130
        let now = new Date().getTime();
 
131
        if (now < this._end) {
 
132
            t = (now - this._start) / 700;
 
133
            t = this._easeOutCubic (t);
 
134
            this._hadjustment.value = value + t * (this._target - value);
 
135
            return true;
 
136
        } else {
 
137
            this._hadjustment.value = value + t * (this._target - value);
 
138
            this._forecastGrid.remove_tick_callback(this._tickId);
 
139
            return false;
 
140
        }
 
141
    },
 
142
 
 
143
    _easeOutCubic: function(value) {
 
144
        let temp = value - 1;
 
145
        return temp * temp * temp + 1;
 
146
    },
 
147
 
 
148
    clear: function() {
 
149
        this._forecasts.clear();
 
150
    },
 
151
 
 
152
    _get_style_class: function(info) {
 
153
        let icon = info.get_icon_name();
 
154
        let name = icon.replace(/(-\d{3})/, "");
 
155
        return name;
 
156
    },
 
157
 
 
158
    update: function(info) {
 
159
        this._info = info;
 
160
 
 
161
        this._conditions.label = Util.getWeatherConditions(info);
 
162
        this._temperature.label = info.get_temp_summary();
 
163
 
 
164
        this._icon.icon_name = info.get_symbolic_icon_name();
 
165
        let context = this._contentFrame.get_style_context();
 
166
        if (this._currentStyle)
 
167
            context.remove_class(this._currentStyle);
 
168
        this._currentStyle = this._get_style_class(info);
 
169
        context.add_class(this._currentStyle);
 
170
 
 
171
        let forecasts = info.get_forecast_list();
 
172
        this._forecasts.update(forecasts, this._dayStack.get_visible_child_name());
 
173
        this._forecasts.show();
 
174
 
 
175
        if (forecasts.length == 0) {
 
176
            this._weeklyForecasts.hide();
 
177
        } else {
 
178
            this._weeklyForecasts.show();
 
179
            this._weeklyForecasts.update(forecasts);
 
180
        }
 
181
    }
 
182
});
 
183
 
 
184
const WeatherView = new Lang.Class({
 
185
    Name: 'WeatherView',
 
186
    Extends: Gtk.Stack,
 
187
 
 
188
    _init: function(params) {
 
189
        this.parent(params);
 
190
        this.get_accessible().accessible_name = _("City view");
 
191
 
 
192
        let loadingPage = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL,
 
193
                                         halign: Gtk.Align.CENTER,
 
194
                                         valign: Gtk.Align.CENTER });
 
195
 
 
196
        this._spinner = new Gtk.Spinner({ height_request: SPINNER_SIZE,
 
197
                                          width_request: SPINNER_SIZE });
 
198
        loadingPage.add(this._spinner);
 
199
        loadingPage.add(new Gtk.Label({ label: _("Loading…"),
 
200
                                        name: "loading-label" }));
 
201
        this.add_named(loadingPage, 'loading');
 
202
 
 
203
        this.infoPage = new WeatherWidget();
 
204
        this.add_named(this.infoPage, 'info');
 
205
 
 
206
        this._info = null;
 
207
        this._updateId = 0;
 
208
 
 
209
        this.connect('destroy', Lang.bind(this, this._onDestroy));
 
210
 
 
211
        this._wallClock = new Gnome.WallClock();
 
212
        this._clockHandlerId = null;
 
213
    },
 
214
 
 
215
    get info() {
 
216
        return this._info;
 
217
    },
 
218
 
 
219
    set info(info) {
 
220
        if (this._updateId) {
 
221
            this._info.disconnect(this._updateId);
 
222
            this._updateId = 0;
 
223
 
 
224
            this.infoPage.clear();
 
225
        }
 
226
 
 
227
        this._info = info;
 
228
 
 
229
        if (info) {
 
230
            this._updateId = this._info.connect('updated',
 
231
                                                Lang.bind(this, this._onUpdate));
 
232
            if (info.is_valid())
 
233
                this._onUpdate(info);
 
234
        }
 
235
    },
 
236
 
 
237
    _onDestroy: function() {
 
238
        if (this._updateId) {
 
239
            this._info.disconnect(this._updateId);
 
240
            this._updateId = 0;
 
241
        }
 
242
    },
 
243
 
 
244
    update: function() {
 
245
        this.visible_child_name = 'loading';
 
246
        this._spinner.start();
 
247
        this.infoPage.clear();
 
248
 
 
249
        getApp().model.updateInfo(this._info);
 
250
    },
 
251
 
 
252
    _onUpdate: function(info) {
 
253
        this.infoPage.clear();
 
254
        this.infoPage.update(info);
 
255
        this._updateTime();
 
256
        this._spinner.stop();
 
257
        this.visible_child_name = 'info';
 
258
    },
 
259
 
 
260
    connectClock: function() {
 
261
        this._clockHandlerId = this._wallClock.connect('notify::clock', Lang.bind(this, this._updateTime));
 
262
    },
 
263
 
 
264
    _updateTime: function() {
 
265
        this.infoPage.timeLabel.label = this._getTime();
 
266
    },
 
267
 
 
268
    _getTime: function() {
 
269
        if (this._info != null) {
 
270
            let location = this._info.location;
 
271
            let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
 
272
            let dt = GLib.DateTime.new_now(tz);
 
273
            return dt.format(_("%H:%M"));
 
274
        }
 
275
        return null;
 
276
    },
 
277
 
 
278
    disconnectClock: function() {
 
279
        if (this._clockHandlerId) {
 
280
            this._wallClock.disconnect(this._clockHandlerId);
 
281
            this._clockHandlerId = null;
 
282
        }
 
283
    }
 
284
});