/ *
*
* Weather extension for GNOME Shell
* - Displays a small weather information on the top panel .
* - On click , gives a popup with details about the weather .
*
* Copyright ( C ) 2011
* ecyrbe < ecyrbe + spam @ gmail . com > ,
* Timur Kristof < venemo @ msn . com > ,
* Elad Alfassa < elad @ fedoraproject . org > ,
* Simon Legner < Simon . Legner @ gmail . com >
*
*
* This file is part of gnome - shell - extension - weather .
*
* gnome - shell - extension - 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 3 of the License , or
* ( at your option ) any later version .
*
* gnome - shell - extension - 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 - shell - extension - weather . If not , see < http : //www.gnu.org/licenses/>.
*
* /
const Cairo = imports . cairo ;
const Gettext = imports . gettext . domain ( 'gnome-shell-extension-weather' ) ;
const Gio = imports . gi . Gio ;
const Gtk = imports . gi . Gtk ;
const Json = imports . gi . Json ;
const Lang = imports . lang ;
const Mainloop = imports . mainloop ;
const Soup = imports . gi . Soup ;
const St = imports . gi . St ;
const Util = imports . misc . util ;
const _ = Gettext . gettext ;
const Main = imports . ui . main ;
const PanelMenu = imports . ui . panelMenu ;
const PopupMenu = imports . ui . popupMenu ;
// Settings
const WEATHER _SETTINGS _SCHEMA = 'org.gnome.shell.extensions.weather' ;
const WEATHER _UNIT _KEY = 'unit' ;
const WEATHER _CITY _KEY = 'city' ;
const WEATHER _WOEID _KEY = 'woeid' ;
const WEATHER _TRANSLATE _CONDITION _KEY = 'translate-condition' ;
const WEATHER _USE _SYMBOLIC _ICONS _KEY = 'use-symbolic-icons' ;
const WEATHER _SHOW _TEXT _IN _PANEL _KEY = 'show-text-in-panel' ;
const WEATHER _POSITION _IN _PANEL _KEY = 'position-in-panel' ;
const WEATHER _SHOW _COMMENT _IN _PANEL _KEY = 'show-comment-in-panel' ;
// Keep enums in sync with GSettings schemas
const WeatherUnits = {
CELSIUS : 0 ,
FAHRENHEIT : 1
}
const WeatherPosition = {
CENTER : 0 ,
RIGHT : 1 ,
LEFT : 2
}
function WeatherMenuButton ( ) {
this . _init ( ) ;
}
function getSettings ( schema ) {
if ( Gio . Settings . list _schemas ( ) . indexOf ( schema ) == - 1 )
throw _ ( "Schema \"%s\" not found." ) . format ( schema ) ;
return new Gio . Settings ( { schema : schema } ) ;
}
WeatherMenuButton . prototype = {
_ _proto _ _ : PanelMenu . Button . prototype ,
_init : function ( ) {
// Load settings
this . _settings = getSettings ( WEATHER _SETTINGS _SCHEMA ) ;
this . _units = this . _settings . get _enum ( WEATHER _UNIT _KEY ) ;
this . _city = this . _settings . get _string ( WEATHER _CITY _KEY ) ;
this . _woeid = this . _settings . get _string ( WEATHER _WOEID _KEY ) ;
this . _translate _condition = this . _settings . get _boolean ( WEATHER _TRANSLATE _CONDITION _KEY ) ;
this . _icon _type = this . _settings . get _boolean ( WEATHER _USE _SYMBOLIC _ICONS _KEY ) ? St . IconType . SYMBOLIC : St . IconType . FULLCOLOR ;
this . _text _in _panel = this . _settings . get _boolean ( WEATHER _SHOW _TEXT _IN _PANEL _KEY ) ;
this . _position _in _panel = this . _settings . get _enum ( WEATHER _POSITION _IN _PANEL _KEY ) ;
this . _comment _in _panel = this . _settings . get _boolean ( WEATHER _SHOW _COMMENT _IN _PANEL _KEY ) ;
// Watch settings for changes
let load _settings _and _refresh _weather = Lang . bind ( this , function ( ) {
this . _units = this . _settings . get _enum ( WEATHER _UNIT _KEY ) ;
this . _city = this . _settings . get _string ( WEATHER _CITY _KEY ) ;
this . _woeid = this . _settings . get _string ( WEATHER _WOEID _KEY ) ;
this . _translate _condition = this . _settings . get _boolean ( WEATHER _TRANSLATE _CONDITION _KEY ) ;
this . _icon _type = this . _settings . get _boolean ( WEATHER _USE _SYMBOLIC _ICONS _KEY ) ? St . IconType . SYMBOLIC : St . IconType . FULLCOLOR ;
this . _comment _in _panel = this . _settings . get _boolean ( WEATHER _SHOW _COMMENT _IN _PANEL _KEY ) ;
this . refreshWeather ( false ) ;
} ) ;
this . _settings . connect ( 'changed::' + WEATHER _UNIT _KEY , load _settings _and _refresh _weather ) ;
this . _settings . connect ( 'changed::' + WEATHER _CITY _KEY , load _settings _and _refresh _weather ) ;
this . _settings . connect ( 'changed::' + WEATHER _WOEID _KEY , load _settings _and _refresh _weather ) ;
this . _settings . connect ( 'changed::' + WEATHER _TRANSLATE _CONDITION _KEY , load _settings _and _refresh _weather ) ;
this . _settings . connect ( 'changed::' + WEATHER _SHOW _COMMENT _IN _PANEL _KEY , load _settings _and _refresh _weather ) ;
this . _settings . connect ( 'changed::' + WEATHER _USE _SYMBOLIC _ICONS _KEY , Lang . bind ( this , function ( ) {
this . _icon _type = this . _settings . get _boolean ( WEATHER _USE _SYMBOLIC _ICONS _KEY ) ? St . IconType . SYMBOLIC : St . IconType . FULLCOLOR ;
this . _weatherIcon . icon _type = this . _icon _type ;
this . _currentWeatherIcon . icon _type = this . _icon _type ;
this . _forecast [ 0 ] . Icon . icon _type = this . _icon _type ;
this . _forecast [ 1 ] . Icon . icon _type = this . _icon _type ;
this . refreshWeather ( false ) ;
} ) ) ;
// Panel icon
this . _weatherIcon = new St . Icon ( {
icon _type : this . _icon _type ,
icon _name : 'view-refresh-symbolic' ,
style _class : 'system-status-icon weather-icon' + ( Main . panel . actor . get _direction ( ) == St . TextDirection . RTL ? '-rtl' : '' )
} ) ;
// Label
this . _weatherInfo = new St . Label ( { text : _ ( '...' ) } ) ;
// Panel menu item - the current class
let menuAlignment = 0.25 ;
if ( St . Widget . get _default _direction ( ) == St . TextDirection . RTL )
menuAlignment = 1.0 - menuAlignment ;
PanelMenu . Button . prototype . _init . call ( this , menuAlignment ) ;
// Putting the panel item together
let topBox = new St . BoxLayout ( ) ;
topBox . add _actor ( this . _weatherIcon ) ;
if ( this . _text _in _panel )
topBox . add _actor ( this . _weatherInfo ) ;
this . actor . add _actor ( topBox ) ;
let children = null ;
switch ( this . _position _in _panel ) {
case WeatherPosition . LEFT :
children = Main . panel . _leftBox . get _children ( ) ;
Main . panel . _leftBox . insert _actor ( this . actor , children . length - 1 ) ;
break ;
case WeatherPosition . CENTER :
Main . panel . _centerBox . add ( this . actor , { y _fill : true } ) ;
break ;
case WeatherPosition . RIGHT :
children = Main . panel . _rightBox . get _children ( ) ;
Main . panel . _rightBox . insert _actor ( this . actor , children . length - 1 ) ;
break ;
}
Main . panel . _menus . addMenu ( this . menu ) ;
// Current weather
this . _currentWeather = new St . Bin ( { style _class : 'current' } ) ;
// Future weather
this . _futureWeather = new St . Bin ( { style _class : 'forecast' /*, x_align: St.Align.START*/ } ) ;
// Separator (copied from Gnome shell's popupMenu.js)
this . _separatorArea = new St . DrawingArea ( { style _class : 'popup-separator-menu-item' } ) ;
this . _separatorArea . width = 200 ;
this . _separatorArea . connect ( 'repaint' , Lang . bind ( this , this . _onSeparatorAreaRepaint ) ) ;
// Putting the popup item together
let mainBox = new St . BoxLayout ( { vertical : true } ) ;
mainBox . add _actor ( this . _currentWeather ) ;
mainBox . add _actor ( this . _separatorArea ) ;
mainBox . add _actor ( this . _futureWeather ) ;
this . menu . addActor ( mainBox ) ;
/ * T O D O i n s t a l l s c r i p t v i a M a k e f i l e
this . menu . addMenuItem ( new PopupMenu . PopupSeparatorMenuItem ( ) ) ;
let item = new PopupMenu . PopupMenuItem ( _ ( "Preferences..." ) ) ;
item . connect ( 'activate' , function ( ) {
Util . spawn ( [ "weather-extension-configurator" ] ) ;
} ) ;
this . menu . addMenuItem ( item ) ;
* /
// Items
this . showLoadingUi ( ) ;
this . rebuildCurrentWeatherUi ( ) ;
this . rebuildFutureWeatherUi ( ) ;
// Show weather
Mainloop . timeout _add _seconds ( 3 , Lang . bind ( this , function ( ) {
this . refreshWeather ( true ) ;
} ) ) ;
} ,
unit _to _url : function ( ) {
return this . _units == WeatherUnits . FAHRENHEIT ? 'f' : 'c' ;
} ,
unit _to _unicode : function ( ) {
return this . _units == WeatherUnits . FAHRENHEIT ? '\u2109' : '\u2103' ;
} ,
get _weather _url : function ( ) {
return 'http://query.yahooapis.com/v1/public/yql?format=json&q=select location,wind,atmosphere,units,item.condition,item.forecast from weather.forecast where location="' + this . _woeid + '" and u="' + this . unit _to _url ( ) + '"' ;
} ,
get _weather _icon : function ( code ) {
/* see http://developer.yahoo.com/weather/#codetable */
/* fallback icons are: weather-clear-night weather-clear weather-few-clouds-night weather-few-clouds weather-fog weather-overcast weather-severe-alert weather-showers weather-showers-scattered weather-snow weather-storm */
switch ( parseInt ( code , 10 ) ) {
case 0 : /* tornado */
return [ 'weather-severe-alert' ] ;
case 1 : /* tropical storm */
return [ 'weather-severe-alert' ] ;
case 2 : /* hurricane */
return [ 'weather-severe-alert' ] ;
case 3 : /* severe thunderstorms */
return [ 'weather-severe-alert' ] ;
case 4 : /* thunderstorms */
return [ 'weather-storm' ] ;
case 5 : /* mixed rain and snow */
return [ 'weather-snow-rain' , 'weather-snow' ] ;
case 6 : /* mixed rain and sleet */
return [ 'weather-snow-rain' , 'weather-snow' ] ;
case 7 : /* mixed snow and sleet */
return [ 'weather-snow' ] ;
case 8 : /* freezing drizzle */
return [ 'weather-freezing-rain' , 'weather-showers' ] ;
case 9 : /* drizzle */
return [ 'weather-fog' ] ;
case 10 : /* freezing rain */
return [ 'weather-freezing-rain' , 'weather-showers' ] ;
case 11 : /* showers */
return [ 'weather-showers' ] ;
case 12 : /* showers */
return [ 'weather-showers' ] ;
case 13 : /* snow flurries */
return [ 'weather-snow' ] ;
case 14 : /* light snow showers */
return [ 'weather-snow' ] ;
case 15 : /* blowing snow */
return [ 'weather-snow' ] ;
case 16 : /* snow */
return [ 'weather-snow' ] ;
case 17 : /* hail */
return [ 'weather-snow' ] ;
case 18 : /* sleet */
return [ 'weather-snow' ] ;
case 19 : /* dust */
return [ 'weather-fog' ] ;
case 20 : /* foggy */
return [ 'weather-fog' ] ;
case 21 : /* haze */
return [ 'weather-fog' ] ;
case 22 : /* smoky */
return [ 'weather-fog' ] ;
case 23 : /* blustery */
return [ 'weather-few-clouds' ] ;
case 24 : /* windy */
return [ 'weather-few-clouds' ] ;
case 25 : /* cold */
return [ 'weather-few-clouds' ] ;
case 26 : /* cloudy */
return [ 'weather-overcast' ] ;
case 27 : /* mostly cloudy (night) */
return [ 'weather-clouds-night' , 'weather-few-clouds-night' ] ;
case 28 : /* mostly cloudy (day) */
return [ 'weather-clouds' , 'weather-overcast' ] ;
case 29 : /* partly cloudy (night) */
return [ 'weather-few-clouds-night' ] ;
case 30 : /* partly cloudy (day) */
return [ 'weather-few-clouds' ] ;
case 31 : /* clear (night) */
return [ 'weather-clear-night' ] ;
case 32 : /* sunny */
return [ 'weather-clear' ] ;
case 33 : /* fair (night) */
return [ 'weather-clear-night' ] ;
case 34 : /* fair (day) */
return [ 'weather-clear' ] ;
case 35 : /* mixed rain and hail */
return [ 'weather-snow-rain' , 'weather-showers' ] ;
case 36 : /* hot */
return [ 'weather-clear' ] ;
case 37 : /* isolated thunderstorms */
return [ 'weather-storm' ] ;
case 38 : /* scattered thunderstorms */
return [ 'weather-storm' ] ;
case 39 : /* http://developer.yahoo.com/forum/YDN-Documentation/Yahoo-Weather-API-Wrong-Condition-Code/1290534174000-1122fc3d-da6d-34a2-9fb9-d0863e6c5bc6 */
case 40 : /* scattered showers */
return [ 'weather-showers-scattered' , 'weather-showers' ] ;
case 41 : /* heavy snow */
return [ 'weather-snow' ] ;
case 42 : /* scattered snow showers */
return [ 'weather-snow' ] ;
case 43 : /* heavy snow */
return [ 'weather-snow' ] ;
case 44 : /* partly cloudy */
return [ 'weather-few-clouds' ] ;
case 45 : /* thundershowers */
return [ 'weather-storm' ] ;
case 46 : /* snow showers */
return [ 'weather-snow' ] ;
case 47 : /* isolated thundershowers */
return [ 'weather-storm' ] ;
case 3200 : /* not available */
default :
return [ 'weather-severe-alert' ] ;
}
} ,
get _weather _icon _safely : function ( code ) {
let iconname = this . get _weather _icon ( code ) ;
for ( let i = 0 ; i < iconname . length ; i ++ ) {
if ( this . has _icon ( iconname [ i ] ) )
return iconname [ i ] ;
}
return 'weather-severe-alert' ;
} ,
has _icon : function ( icon ) {
//TODO correct symbolic name? (cf. symbolic_names_for_icon)
return Gtk . IconTheme . get _default ( ) . has _icon ( icon + ( this . _icon _type == St . IconType . SYMBOLIC ? '-symbolic' : '' ) ) ;
} ,
get _weather _condition : function ( code ) {
switch ( parseInt ( code , 10 ) ) {
case 0 : /* tornado */
return _ ( 'Tornado' ) ;
case 1 : /* tropical storm */
return _ ( 'Tropical storm' ) ;
case 2 : /* hurricane */
return _ ( 'Hurricane' ) ;
case 3 : /* severe thunderstorms */
return _ ( 'Severe thunderstorms' ) ;
case 4 : /* thunderstorms */
return _ ( 'Thunderstorms' ) ;
case 5 : /* mixed rain and snow */
return _ ( 'Mixed rain and snow' ) ;
case 6 : /* mixed rain and sleet */
return _ ( 'Mixed rain and sleet' ) ;
case 7 : /* mixed snow and sleet */
return _ ( 'Mixed snow and sleet' ) ;
case 8 : /* freezing drizzle */
return _ ( 'Freezing drizzle' ) ;
case 9 : /* drizzle */
return _ ( 'Drizzle' ) ;
case 10 : /* freezing rain */
return _ ( 'Freezing rain' ) ;
case 11 : /* showers */
return _ ( 'Showers' ) ;
case 12 : /* showers */
return _ ( 'Showers' ) ;
case 13 : /* snow flurries */
return _ ( 'Snow flurries' ) ;
case 14 : /* light snow showers */
return _ ( 'Light snow showers' ) ;
case 15 : /* blowing snow */
return _ ( 'Blowing snow' ) ;
case 16 : /* snow */
return _ ( 'Snow' ) ;
case 17 : /* hail */
return _ ( 'Hail' ) ;
case 18 : /* sleet */
return _ ( 'Sleet' ) ;
case 19 : /* dust */
return _ ( 'Dust' ) ;
case 20 : /* foggy */
return _ ( 'Foggy' ) ;
case 21 : /* haze */
return _ ( 'Haze' ) ;
case 22 : /* smoky */
return _ ( 'Smoky' ) ;
case 23 : /* blustery */
return _ ( 'Blustery' ) ;
case 24 : /* windy */
return _ ( 'Windy' ) ;
case 25 : /* cold */
return _ ( 'Cold' ) ;
case 26 : /* cloudy */
return _ ( 'Cloudy' ) ;
case 27 : /* mostly cloudy (night) */
case 28 : /* mostly cloudy (day) */
return _ ( 'Mostly cloudy' ) ;
case 29 : /* partly cloudy (night) */
case 30 : /* partly cloudy (day) */
return _ ( 'Partly cloudy' ) ;
case 31 : /* clear (night) */
return _ ( 'Clear' ) ;
case 32 : /* sunny */
return _ ( 'Sunny' ) ;
case 33 : /* fair (night) */
case 34 : /* fair (day) */
return _ ( 'Fair' ) ;
case 35 : /* mixed rain and hail */
return _ ( 'Mixed rain and hail' ) ;
case 36 : /* hot */
return _ ( 'Hot' ) ;
case 37 : /* isolated thunderstorms */
return _ ( 'Isolated thunderstorms' ) ;
case 38 : /* scattered thunderstorms */
case 39 : /* scattered thunderstorms */
return _ ( 'Scattered thunderstorms' ) ;
case 40 : /* scattered showers */
return _ ( 'Scattered showers' ) ;
case 41 : /* heavy snow */
return _ ( 'Heavy snow' ) ;
case 42 : /* scattered snow showers */
return _ ( 'Scattered snow showers' ) ;
case 43 : /* heavy snow */
return _ ( 'Heavy snow' ) ;
case 44 : /* partly cloudy */
return _ ( 'Partly cloudy' ) ;
case 45 : /* thundershowers */
return _ ( 'Thundershowers' ) ;
case 46 : /* snow showers */
return _ ( 'Snow showers' ) ;
case 47 : /* isolated thundershowers */
return _ ( 'Isolated thundershowers' ) ;
case 3200 : /* not available */
default :
return _ ( 'Not available' ) ;
}
} ,
parse _day : function ( abr ) {
let yahoo _days = [ 'monday' , 'tuesday' , 'wednesday' , 'thursday' , 'friday' , 'saturday' , 'sunday' ] ;
for ( var i = 0 ; i < yahoo _days . length ; i ++ ) {
if ( yahoo _days [ i ] . substr ( 0 , abr . length ) == abr . toLowerCase ( ) ) {
return i ;
}
}
return 0 ;
} ,
get _locale _day : function ( abr ) {
let days = [ _ ( 'Monday' ) , _ ( 'Tuesday' ) , _ ( 'Wednesday' ) , _ ( 'Thursday' ) , _ ( 'Friday' ) , _ ( 'Saturday' ) , _ ( 'Sunday' ) ] ;
return days [ this . parse _day ( abr ) ] ;
} ,
load _json _async : function ( url , fun ) {
let here = this ;
let session = new Soup . SessionAsync ( ) ;
if ( Soup . Session . prototype . add _feature != null )
Soup . Session . prototype . add _feature . call ( session , new Soup . ProxyResolverDefault ( ) ) ;
let message = Soup . Message . new ( 'GET' , url ) ;
session . queue _message ( message , function ( session , message ) {
let jp = new Json . Parser ( ) ;
jp . load _from _data ( message . response _body . data , - 1 ) ;
fun . call ( here , jp . get _root ( ) . get _object ( ) ) ;
} ) ;
} ,
refreshWeather : function ( recurse ) {
this . load _json _async ( this . get _weather _url ( ) , function ( json ) {
let weather = json . get _object _member ( 'query' ) . get _object _member ( 'results' ) . get _object _member ( 'channel' ) ;
let weather _c = weather . get _object _member ( 'item' ) . get _object _member ( 'condition' ) ;
let forecast = weather . get _object _member ( 'item' ) . get _array _member ( 'forecast' ) . get _elements ( ) ;
/ * T O D O w o n ' t w o r k w i t h t h e n e w U R L
// Fixes wrong woeid if necessary
try {
// Wrong woeid specified
if ( weather . has _member ( 'code' ) && weather . get _int _member ( 'code' ) == 500 ) {
// Fetch correct woeid
this . load _json _async ( this . get _weather _url ( ) . replace ( 'p=' , 'w=' ) , function ( weather ) {
try {
// Take correct woeid, update gsettings
this . _woeid = weather . get _object _member ( 'location' ) . get _string _member ( 'location_id' ) ;
this . _settings . set _string ( WEATHER _WOEID _KEY , this . _woeid ) ;
// Load weather with correct woeid
this . refreshWeather ( false ) ;
} catch ( e ) {
}
} ) ;
return ;
}
} catch ( e ) {
global . log ( 'A ' + e . name + ' has occured: ' + e . message ) ;
}
* /
let location = weather . get _object _member ( 'location' ) . get _string _member ( 'city' ) ;
if ( this . _city != null && this . _city . length > 0 )
location = this . _city ;
// Refresh current weather
let comment = weather _c . get _string _member ( 'text' ) ;
if ( this . _translate _condition )
comment = this . get _weather _condition ( weather _c . get _string _member ( 'code' ) ) ;
let temperature = weather _c . get _string _member ( 'temp' ) ;
let humidity = weather . get _object _member ( 'atmosphere' ) . get _string _member ( 'humidity' ) + ' %' ;
let pressure = weather . get _object _member ( 'atmosphere' ) . get _string _member ( 'pressure' ) ;
let pressure _unit = weather . get _object _member ( 'units' ) . get _string _member ( 'pressure' ) ;
let wind _direction = weather . get _object _member ( 'wind' ) . get _string _member ( 'direction' ) ;
let wind = weather . get _object _member ( 'wind' ) . get _string _member ( 'speed' ) ;
let wind _unit = weather . get _object _member ( 'units' ) . get _string _member ( 'speed' ) ;
let iconname = this . get _weather _icon _safely ( weather _c . get _string _member ( 'code' ) ) ;
this . _currentWeatherIcon . icon _name = this . _weatherIcon . icon _name = iconname ;
if ( this . _comment _in _panel )
this . _weatherInfo . text = ( comment + ' ' + temperature + ' ' + this . unit _to _unicode ( ) ) ;
else
this . _weatherInfo . text = ( temperature + ' ' + this . unit _to _unicode ( ) ) ;
this . _currentWeatherSummary . text = comment ;
this . _currentWeatherLocation . text = location ;
this . _currentWeatherTemperature . text = temperature + ' ' + this . unit _to _unicode ( ) ;
this . _currentWeatherHumidity . text = humidity ;
this . _currentWeatherPressure . text = pressure + ' ' + pressure _unit ;
this . _currentWeatherWind . text = ( wind _direction ? wind _direction + ' ' : '' ) + wind + ' ' + wind _unit ;
// Refresh forecast
let date _string = [ _ ( 'Today' ) , _ ( 'Tomorrow' ) ] ;
for ( let i = 0 ; i <= 1 ; i ++ ) {
let forecastUi = this . _forecast [ i ] ;
let forecastData = forecast [ i ] . get _object ( ) ;
let code = forecastData . get _string _member ( 'code' ) ;
let t _low = forecastData . get _string _member ( 'low' ) ;
let t _high = forecastData . get _string _member ( 'high' ) ;
let comment = forecastData . get _string _member ( 'text' ) ;
if ( this . _translate _condition )
comment = this . get _weather _condition ( code ) ;
forecastUi . Day . text = date _string [ i ] + ' (' + this . get _locale _day ( forecastData . get _string _member ( 'day' ) ) + ')' ;
forecastUi . Temperature . text = t _low + '\u2013' + t _high + ' ' + this . unit _to _unicode ( ) ;
forecastUi . Summary . text = comment ;
forecastUi . Icon . icon _name = this . get _weather _icon _safely ( code ) ;
}
} ) ;
// Repeatedly refresh weather if recurse is set
if ( recurse ) {
Mainloop . timeout _add _seconds ( 60 * 4 , Lang . bind ( this , function ( ) {
this . refreshWeather ( true ) ;
} ) ) ;
}
} ,
destroyCurrentWeather : function ( ) {
if ( this . _currentWeather . get _child ( ) != null )
this . _currentWeather . get _child ( ) . destroy ( ) ;
} ,
destroyFutureWeather : function ( ) {
if ( this . _futureWeather . get _child ( ) != null )
this . _futureWeather . get _child ( ) . destroy ( ) ;
} ,
showLoadingUi : function ( ) {
this . destroyCurrentWeather ( ) ;
this . destroyFutureWeather ( ) ;
this . _currentWeather . set _child ( new St . Label ( { text : _ ( 'Loading current weather ...' ) } ) ) ;
this . _futureWeather . set _child ( new St . Label ( { text : _ ( 'Loading future weather ...' ) } ) ) ;
} ,
rebuildCurrentWeatherUi : function ( ) {
this . destroyCurrentWeather ( ) ;
// This will hold the icon for the current weather
this . _currentWeatherIcon = new St . Icon ( {
icon _type : this . _icon _type ,
icon _size : 64 ,
icon _name : 'view-refresh-symbolic' ,
style _class : 'weather-current-icon'
} ) ;
// The summary of the current weather
this . _currentWeatherSummary = new St . Label ( {
text : _ ( 'Loading ...' ) ,
style _class : 'weather-current-summary'
} ) ;
this . _currentWeatherLocation = new St . Label ( { text : _ ( 'Please wait' ) } ) ;
let bb = new St . BoxLayout ( {
vertical : true ,
style _class : 'weather-current-summarybox'
} ) ;
bb . add _actor ( this . _currentWeatherLocation ) ;
bb . add _actor ( this . _currentWeatherSummary ) ;
// Other labels
this . _currentWeatherTemperature = new St . Label ( { text : '...' } ) ;
this . _currentWeatherHumidity = new St . Label ( { text : '...' } ) ;
this . _currentWeatherPressure = new St . Label ( { text : '...' } ) ;
this . _currentWeatherWind = new St . Label ( { text : '...' } ) ;
let rb = new St . BoxLayout ( {
style _class : 'weather-current-databox'
} ) ;
let rb _captions = new St . BoxLayout ( {
vertical : true ,
style _class : 'weather-current-databox-captions'
} ) ;
let rb _values = new St . BoxLayout ( {
vertical : true ,
style _class : 'weather-current-databox-values'
} ) ;
rb . add _actor ( rb _captions ) ;
rb . add _actor ( rb _values ) ;
rb _captions . add _actor ( new St . Label ( { text : _ ( 'Temperature:' ) } ) ) ;
rb _values . add _actor ( this . _currentWeatherTemperature ) ;
rb _captions . add _actor ( new St . Label ( { text : _ ( 'Humidity:' ) } ) ) ;
rb _values . add _actor ( this . _currentWeatherHumidity ) ;
rb _captions . add _actor ( new St . Label ( { text : _ ( 'Pressure:' ) } ) ) ;
rb _values . add _actor ( this . _currentWeatherPressure ) ;
rb _captions . add _actor ( new St . Label ( { text : _ ( 'Wind:' ) } ) ) ;
rb _values . add _actor ( this . _currentWeatherWind ) ;
let xb = new St . BoxLayout ( ) ;
xb . add _actor ( bb ) ;
xb . add _actor ( rb ) ;
let box = new St . BoxLayout ( {
style _class : 'weather-current-iconbox'
} ) ;
box . add _actor ( this . _currentWeatherIcon ) ;
box . add _actor ( xb ) ;
this . _currentWeather . set _child ( box ) ;
} ,
rebuildFutureWeatherUi : function ( ) {
this . destroyFutureWeather ( ) ;
this . _forecast = [ ] ;
this . _forecastBox = new St . BoxLayout ( ) ;
this . _futureWeather . set _child ( this . _forecastBox ) ;
for ( let i = 0 ; i <= 1 ; i ++ ) {
let forecastWeather = { } ;
forecastWeather . Icon = new St . Icon ( {
icon _type : this . _icon _type ,
icon _size : 48 ,
icon _name : 'view-refresh-symbolic' ,
style _class : 'weather-forecast-icon'
} ) ;
forecastWeather . Day = new St . Label ( {
style _class : 'weather-forecast-day'
} ) ;
forecastWeather . Summary = new St . Label ( {
style _class : 'weather-forecast-summary'
} ) ;
forecastWeather . Temperature = new St . Label ( {
style _class : 'weather-forecast-temperature'
} ) ;
let by = new St . BoxLayout ( {
vertical : true ,
style _class : 'weather-forecast-databox'
} ) ;
by . add _actor ( forecastWeather . Day ) ;
by . add _actor ( forecastWeather . Summary ) ;
by . add _actor ( forecastWeather . Temperature ) ;
let bb = new St . BoxLayout ( {
style _class : 'weather-forecast-box'
} ) ;
bb . add _actor ( forecastWeather . Icon ) ;
bb . add _actor ( by ) ;
this . _forecast [ i ] = forecastWeather ;
this . _forecastBox . add _actor ( bb ) ;
}
} ,
// Copied from Gnome shell's popupMenu.js
_onSeparatorAreaRepaint : function ( area ) {
let cr = area . get _context ( ) ;
let themeNode = area . get _theme _node ( ) ;
let [ width , height ] = area . get _surface _size ( ) ;
let margin = themeNode . get _length ( '-margin-horizontal' ) ;
let gradientHeight = themeNode . get _length ( '-gradient-height' ) ;
let startColor = themeNode . get _color ( '-gradient-start' ) ;
let endColor = themeNode . get _color ( '-gradient-end' ) ;
let gradientWidth = ( width - margin * 2 ) ;
let gradientOffset = ( height - gradientHeight ) / 2 ;
let pattern = new Cairo . LinearGradient ( margin , gradientOffset , width - margin , gradientOffset + gradientHeight ) ;
pattern . addColorStopRGBA ( 0 , startColor . red / 255 , startColor . green / 255 , startColor . blue / 255 , startColor . alpha / 255 ) ;
pattern . addColorStopRGBA ( 0.5 , endColor . red / 255 , endColor . green / 255 , endColor . blue / 255 , endColor . alpha / 255 ) ;
pattern . addColorStopRGBA ( 1 , startColor . red / 255 , startColor . green / 255 , startColor . blue / 255 , startColor . alpha / 255 ) ;
cr . setSource ( pattern ) ;
cr . rectangle ( margin , gradientOffset , gradientWidth , gradientHeight ) ;
cr . fill ( ) ;
}
} ;
let weatherMenu ;
function init ( ) {
}
function enable ( ) {
weatherMenu = new WeatherMenuButton ( ) ;
Main . panel . addToStatusArea ( 'weatherMenu' , weatherMenu ) ;
}
function disable ( ) {
weatherMenu . destroy ( ) ;
}
// vim:set ts=4 sw=4 et: