/// <summary> /// Paints the forecast temperatures as a chart. /// </summary> /// <param name="cr"> /// A <see cref="Cairo.Context"/> to do the painting. /// </param> void DrawTempGraph(Cairo.Context cr) { int max = -1000, min = 1000; for (int day = 0; day < WeatherController.Weather.ForecastDays; day++) { if (WeatherController.Weather.Forecasts [day].high > max) { max = WeatherController.Weather.Forecasts [day].high; } if (WeatherController.Weather.Forecasts [day].low > max) { max = WeatherController.Weather.Forecasts [day].low; } if (WeatherController.Weather.Forecasts [day].high < min) { min = WeatherController.Weather.Forecasts [day].high; } if (WeatherController.Weather.Forecasts [day].low < min) { min = WeatherController.Weather.Forecasts [day].low; } } if (max <= min) { return; } using (Pango.Layout layout = DockServices.Drawing.ThemedPangoLayout()) { Pango.Rectangle inkRect, logicalRect; layout.FontDescription = new Gtk.Style().FontDescription; layout.FontDescription.Weight = Pango.Weight.Bold; layout.Ellipsize = Pango.EllipsizeMode.None; layout.FontDescription.AbsoluteSize = Pango.Units.FromPixels((int)(Allocation.Height / 5)); // high/low temp layout.Width = Pango.Units.FromPixels(Allocation.Height); cr.Color = colorHigh; layout.SetText(string.Format("{0}{1}", max, AbstractWeatherSource.TempUnit)); layout.GetPixelExtents(out inkRect, out logicalRect); cr.MoveTo(Allocation.Width - Allocation.Height + (Allocation.Height - inkRect.Width) / 2 - BUTTON_SIZE, Allocation.Height / 6 - logicalRect.Height / 2); Pango.CairoHelper.LayoutPath(cr, layout); cr.Fill(); cr.Color = colorLow; layout.SetText(string.Format("{0}{1}", min, AbstractWeatherSource.TempUnit)); layout.GetPixelExtents(out inkRect, out logicalRect); cr.MoveTo(Allocation.Width - Allocation.Height + (Allocation.Height - inkRect.Width) / 2 - BUTTON_SIZE, Allocation.Height * 6 / 9 - logicalRect.Height / 2); Pango.CairoHelper.LayoutPath(cr, layout); cr.Fill(); // day names layout.Width = Pango.Units.FromPixels(2 * Allocation.Height); cr.Color = colorTitle; for (int day = 0; day < WeatherController.Weather.ForecastDays; day++) { layout.SetText(WeatherForecast.DayShortName(WeatherController.Weather.Forecasts [day].dow)); layout.GetPixelExtents(out inkRect, out logicalRect); cr.MoveTo(BUTTON_SIZE + day * Allocation.Height * 2 + (Allocation.Height - inkRect.Width) / 2, Allocation.Height * 8 / 9 - logicalRect.Height / 2); Pango.CairoHelper.LayoutPath(cr, layout); } cr.Fill(); cr.Save(); layout.FontDescription.Dispose(); layout.Context.Dispose(); } // draw tick lines cr.Color = new Cairo.Color(0.627, 0.627, 0.627, .8); cr.LineWidth = 1; cr.LineCap = LineCap.Round; int lines = 5; for (int line = 0; line < lines - 1; line++) { cr.MoveTo(BUTTON_SIZE + Allocation.Height / 4, 4.5 + Allocation.Height * line / lines); cr.LineTo(BUTTON_SIZE + (2 * WeatherController.Weather.ForecastDays - 1) * Allocation.Height - Allocation.Height / 4, 4.5 + Allocation.Height * line / lines); cr.Stroke(); } for (int line = 0; ; line++) { double x = BUTTON_SIZE + Allocation.Height / 2 + line * 2 * Allocation.Height - 0.5; if (x >= BUTTON_SIZE + (2 * WeatherController.Weather.ForecastDays - 1) * Allocation.Height - Allocation.Height / 4) { break; } cr.MoveTo(x, 4.5); cr.LineTo(x, 4.5 + Allocation.Height * (lines - 2) / lines); cr.Stroke(); } cr.Restore(); cr.LineWidth = 3; double height = ((double)Allocation.Height * 2 / 3 - 5) / (max - min); // high temp graph cr.Color = colorHigh; cr.MoveTo(BUTTON_SIZE + Allocation.Height / 2, 5 + height * (max - WeatherController.Weather.Forecasts [0].high)); for (int day = 1; day < WeatherController.Weather.ForecastDays; day++) { cr.LineTo(BUTTON_SIZE + day * Allocation.Height * 2 + Allocation.Height / 2, 5 + height * (max - WeatherController.Weather.Forecasts [day].high)); } cr.Stroke(); // low temp graph cr.Color = colorLow; cr.MoveTo(BUTTON_SIZE + Allocation.Height / 2, 5 + height * (max - WeatherController.Weather.Forecasts [0].low)); for (int day = 1; day < WeatherController.Weather.ForecastDays; day++) { cr.LineTo(BUTTON_SIZE + day * Allocation.Height * 2 + Allocation.Height / 2, 5 + height * (max - WeatherController.Weather.Forecasts [day].low)); } cr.Stroke(); // high temp points for (int day = 0; day < WeatherController.Weather.ForecastDays; day++) { DrawDataPoint(cr, Allocation.Height, height, max, day, WeatherController.Weather.Forecasts [day].high); } // low temp points for (int day = 0; day < WeatherController.Weather.ForecastDays; day++) { DrawDataPoint(cr, Allocation.Height, height, max, day, WeatherController.Weather.Forecasts [day].low); } }
protected override MenuList OnGetMenuItems() { MenuList list = base.OnGetMenuItems(); if (WeatherController.Weather.Condition != null) { list[MenuListContainer.Header].Add(new MenuItem(Catalog.GetString("Radar _Map"), WeatherController.Weather.Image, (o, a) => WeatherController.Weather.ShowRadar())); } list.SetContainerTitle(MenuListContainer.Actions, Mono.Unix.Catalog.GetString("Forecasts")); for (int i = 0; i < WeatherController.Weather.ForecastDays; i++) { if (WeatherController.Weather.Forecasts [i].dow != null) { list[MenuListContainer.Actions].Add(new ForecastMenuItem(i, string.Format("{0}", WeatherForecast.DayName(WeatherController.Weather.Forecasts [i].dow)), WeatherController.Weather.Forecasts [i].image)); } } list[MenuListContainer.CustomOne].Add(new MenuItem(Catalog.GetString("_Settings"), Gtk.Stock.Preferences, delegate { if (Config == null) { Config = new WeatherConfigDialog(); } Config.Show(); })); if (WeatherController.CurrentLocation != "") { list[MenuListContainer.CustomOne].Add(new MenuItem(Catalog.GetString("Check _Weather"), Gtk.Stock.Refresh, delegate { Status = WeatherDockletStatus.ManualReload; State |= ItemState.Wait; QueueRedraw(); WeatherController.ResetTimer(); })); } return(list); }
/// <summary> /// Paints an overview of the forecast including high/low temps and a condition icon. /// </summary> /// <param name="cr"> /// A <see cref="Cairo.Context"/> to do the painting. /// </param> void DrawVertForecast(Cairo.Context cr) { int cellHeight = (int)((Allocation.Height - BUTTON_SIZE) / WeatherController.Weather.ForecastDays / 1.5); double xOffset = 0; double yOffset = cellHeight / 4.0; using (Pango.Layout layout = DockServices.Drawing.ThemedPangoLayout()) { Pango.Rectangle inkRect, logicalRect; layout.FontDescription = new Gtk.Style().FontDescription; layout.FontDescription.Weight = Pango.Weight.Bold; layout.Ellipsize = Pango.EllipsizeMode.None; layout.Width = Pango.Units.FromPixels(cellHeight); for (int day = 0; day < WeatherController.Weather.ForecastDays; day++) { layout.FontDescription.AbsoluteSize = Pango.Units.FromPixels((int)(cellHeight / 5)); cr.Color = colorTitle; layout.SetText(string.Format("{0}", WeatherForecast.DayShortName(WeatherController.Weather.Forecasts [day].dow))); layout.GetPixelExtents(out inkRect, out logicalRect); cr.MoveTo(xOffset + (cellHeight - inkRect.Width) / 2, yOffset); Pango.CairoHelper.LayoutPath(cr, layout); cr.Fill(); cr.Color = colorHigh; layout.SetText(string.Format("{0}{1}", WeatherController.Weather.Forecasts [day].high, AbstractWeatherSource.TempUnit)); layout.GetPixelExtents(out inkRect, out logicalRect); cr.MoveTo(xOffset + (cellHeight - inkRect.Width) / 2, yOffset + (cellHeight - logicalRect.Height) / 2); Pango.CairoHelper.LayoutPath(cr, layout); cr.Fill(); cr.Color = colorLow; layout.SetText(string.Format("{0}{1}", WeatherController.Weather.Forecasts [day].low, AbstractWeatherSource.TempUnit)); layout.GetPixelExtents(out inkRect, out logicalRect); cr.MoveTo(xOffset + (cellHeight - inkRect.Width) / 2, yOffset + cellHeight - logicalRect.Height); Pango.CairoHelper.LayoutPath(cr, layout); cr.Fill(); using (Gdk.Pixbuf pbuf = DockServices.Drawing.LoadIcon(WeatherController.Weather.Forecasts [day].image, cellHeight - 5)) { Gdk.CairoHelper.SetSourcePixbuf(cr, pbuf, xOffset + 5 + cellHeight, yOffset + 2); cr.PaintWithAlpha(WeatherController.Weather.Forecasts [day].chanceOf ? .6 : 1); } if (WeatherController.Weather.Forecasts [day].chanceOf) { layout.FontDescription.AbsoluteSize = Pango.Units.FromPixels((int)(cellHeight / 2)); layout.SetText("?"); layout.GetPixelExtents(out inkRect, out logicalRect); cr.MoveTo(xOffset + cellHeight + (cellHeight - inkRect.Width) / 2, yOffset + (cellHeight - logicalRect.Height) / 2); cr.LineWidth = 4; cr.Color = new Cairo.Color(0, 0, 0, 0.3); Pango.CairoHelper.LayoutPath(cr, layout); cr.StrokePreserve(); cr.Color = new Cairo.Color(1, 1, 1, .6); cr.Fill(); } yOffset += (int)(1.5 * cellHeight); } layout.FontDescription.Dispose(); layout.Context.Dispose(); } }
/// <summary> /// Creates a new weather source object. /// </summary> protected AbstractWeatherSource () { Image = DefaultImage; Forecasts = new WeatherForecast [ForecastDays]; for (int i = 0; i < ForecastDays; i++) Forecasts [i].image = DefaultImage; GLib.Timeout.Add (MAXXMLCACHEAGE, () => { xml_cache.RemoveAll (data => ((DateTime.Now - data.Time).TotalMilliseconds > MAXXMLCACHEAGE)); return true; }); }