#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright 2008 Gary C. Martin # This program 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. # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Activity web site: http://wiki.laptop.org/go/Moon # Created: Febuary 2008 # Author: gary@garycmartin.com # Home page: http://www.garycmartin.com/ # Febrero 2012 # Correcciones, Simplificación y Reestructuración Modular: # Desarrollo de CalendarButton + MoonCalendar: # Instalador y Portado a gnome y Gtk 3: # Flavio Danesse CeibalJAM! - Uruguay - Activity Central import math import time import os import calendar import gi from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import GObject from gettext import gettext as _ import MoonGlobals as MG class CalendarButton(Gtk.EventBox): __gsignals__ = { "clicked":(GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT, )), "clickederecho":(GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT, ))} def __init__(self, anio, mes, d, hora): Gtk.EventBox.__init__(self) self.set_visible_window(True) self.modify_bg(Gtk.StateType.NORMAL, MG.BACKGROUND) self.add_events( Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK) self.imagen_size = 50 self.image_pixmap = None icono = os.path.join(MG.ICONOS,"moon.jpg") self.moon_stamp = GdkPixbuf.Pixbuf.new_from_file(icono) self.image = Gtk.Image() self.fixed = Gtk.Fixed() self.hemisphere_view = _('Sur') self.show_grid = False self.fixed.put(self.image, 0, 0) self.add(self.fixed) self.show_all() self.anio, self.mes, self.dia, self.hora = anio, mes, d, hora self.hoy = "%s-%s-%s %s" % (self.anio, self.mes, self.dia, self.hora) if self.dia > 0: self.ahora = time.mktime(time.strptime(self.hoy, MG.format)) #self.data_model.update_moon_calculations(ahora) # para recalcular la fase self.data_model = DataModel(self.ahora) dias= [] for d in calendar.day_name: if d: dias.append(d) meses= [] for m in calendar.month_name: if m: meses.append(m) t = time.strptime(self.hoy, MG.format) mes= meses[t.tm_mon -1] dia= dias[t.tm_wday] fecha= "%s %s de %s de %s" % (dia, self.dia, mes, self.anio) self.set_tooltip_text(fecha) label = Gtk.Label(str(self.dia)) label.modify_fg(Gtk.StateType.NORMAL, MG.FOREGROUND) self.fixed.put(label, 0, 0) self.connect("button_press_event", self.button_press) self.connect("button_release_event", self.button_release) self.connect("enter-notify-event", self.enter_notify_event) self.connect("leave-notify-event", self.leave_notify_event) # --------------------------- EVENTOS -------------------------- def button_release(self, widget, event): pass def leave_notify_event(self, widget, event): pass def enter_notify_event(self, widget, event): pass def button_press(self, widget, event): if event.button == 1: self.emit("clicked", event) if event.button == 3: self.emit("clickederecho", event) # --------------------------- EVENTOS -------------------------- def toggle_grid_clicked(self, widget= None): if self.show_grid == True: self.show_grid = False else: self.show_grid = True def toggle_hemisphere_clicked(self, widget= None): if self.hemisphere_view == _('Norte'): self.hemisphere_view = _('Sur') else: self.hemisphere_view = _('Norte') def repaint(self, tamanioboton): if tamanioboton != self.imagen_size: self.imagen_size = tamanioboton if self.dia > 0: self.actualizar() def actualizar(self): pass # FIXME: Reimplementar. ''' if self.dia <= 0: return self.image_pixmap = Gtk.gdk.Pixmap(self.window, self.imagen_size, self.imagen_size) gc = self.image_pixmap.new_gc(foreground=MG.BACKGROUND) self.image.set_from_pixmap(self.image_pixmap, None) self.image_pixmap.draw_rectangle(gc, True, 0, 0, self.imagen_size, self.imagen_size) # Create a 1bit shadow mask mask_pixmap = Gtk.gdk.Pixmap(None, self.imagen_size, self.imagen_size, depth=1) kgc = mask_pixmap.new_gc(foreground=MG.BACKGROUND) wgc = mask_pixmap.new_gc(foreground=MG.FOREGROUND) mask_pixmap.draw_rectangle(kgc, True, 0, 0, self.imagen_size, self.imagen_size) mask_pixmap = self.draw_fase_moon(mask_pixmap, kgc, wgc) maskgc = self.image_pixmap.new_gc(clip_mask=mask_pixmap) moon_pixbuf = self.moon_stamp.scale_simple(self.imagen_size, self.imagen_size, Gtk.gdk.INTERP_BILINEAR) # Composite bright Moon image and semi-transparant Moon for shadow detail dark_pixbuf = Gtk.gdk.Pixbuf(Gtk.gdk.COLORSPACE_RGB, True, 8, self.imagen_size, self.imagen_size) dark_pixbuf.fill(0x00000000) uno = (self.data_model.next_lunar_eclipse_sec == -1 and self.data_model.last_lunar_eclipse_sec > 7200) dos = (self.data_model.next_lunar_eclipse_sec > 7200 and self.data_model.last_lunar_eclipse_sec == -1) tres = min([self.data_model.next_lunar_eclipse_sec, self.data_model.last_lunar_eclipse_sec]) > 7200 if uno or dos or tres: #print "Normal Moon phase render" moon_pixbuf.composite(dark_pixbuf, 0, 0, self.imagen_size, self.imagen_size, 0, 0, 1, 1, Gtk.gdk.INTERP_BILINEAR, 127) self.image_pixmap.draw_pixbuf(gc, dark_pixbuf, 0, 0, 0, 0) # parte oscura self.image_pixmap.draw_pixbuf(maskgc, moon_pixbuf, 0, 0, 0, 0) # parte iluminada else: #print "Reddening eclipse effect, 2hrs (7200sec) before and after (by masking out green & blue)" if self.data_model.next_lunar_eclipse_sec == -1: eclipse_alpha = self.data_model.last_lunar_eclipse_sec / 7200.0 * 256 elif self.data_model.last_lunar_eclipse_sec == -1: eclipse_alpha = self.data_model.next_lunar_eclipse_sec / 7200.0 * 256 else: eclipse_alpha = min([self.data_model.next_lunar_eclipse_sec, self.data_model.last_lunar_eclipse_sec]) / 7200.0 * 256 moon_pixbuf.composite(dark_pixbuf, 0, 0, self.imagen_size, self.imagen_size, 0, 0, 1, 1, Gtk.gdk.INTERP_BILINEAR, int(196 - eclipse_alpha / 2)) self.image_pixmap.draw_pixbuf(gc, dark_pixbuf, 0, 0, 0, 0) dark_pixbuf = Gtk.gdk.Pixbuf(Gtk.gdk.COLORSPACE_RGB, True, 8, self.imagen_size, self.imagen_size) moon_pixbuf.composite(dark_pixbuf, 0, 0, self.imagen_size, self.imagen_size, 0, 0, 1, 1, Gtk.gdk.INTERP_BILINEAR, int(eclipse_alpha)) rgc = self.image_pixmap.new_gc(foreground=MG.BLUEGREENMASK, function=Gtk.gdk.AND) self.image_pixmap.draw_rectangle(rgc, True, 0, 0, self.imagen_size, self.imagen_size) self.image_pixmap.draw_pixbuf(gc, dark_pixbuf, 0, 0, 0, 0) if self.hemisphere_view == _('Sur'): #print "Rotate final image for a view from Norte or Sur hemisphere" rot_pixbuf = Gtk.gdk.Pixbuf(Gtk.gdk.COLORSPACE_RGB, False, 8, self.imagen_size, self.imagen_size) rot_pixbuf.get_from_drawable(self.image_pixmap, self.image_pixmap.get_colormap(), 0, 0, 0, 0, -1, -1) rot_pixbuf = rot_pixbuf.rotate_simple(Gtk.gdk.PIXBUF_ROTATE_UPSIDEDOWN) self.image_pixmap.draw_pixbuf(gc, rot_pixbuf, 0, 0, 0, 0) if self.show_grid: self.draw_grid(_("SNWE")) else: if self.show_grid: self.draw_grid(_("NSEW"))''' def draw_grid(self, compass_text): pass # FIXME: Reimplementar. ''' # Draw Selenographic grid line data. rgc = self.image_pixmap.new_gc(foreground=MG.RED) bgc = self.image_pixmap.new_gc(foreground=MG.BLUE) wgc = self.image_pixmap.new_gc(foreground=MG.FOREGROUND) pango_layout = self.image.create_pango_layout("") pango_layout.set_text("0°") self.image_pixmap.draw_rectangle(bgc, True, self.imagen_size/2 + 2, self.imagen_size/2, 24, 22) self.image_pixmap.draw_layout(wgc, self.imagen_size/2 + 2, self.imagen_size/2, pango_layout) pango_layout.set_text("30°") self.image_pixmap.draw_rectangle(bgc, True, self.imagen_size/2 + 2, int(self.imagen_size/2 * 0.5), 36, 22) self.image_pixmap.draw_rectangle(bgc, True, self.imagen_size/2 + 2, int(self.imagen_size/2 * 1.5), 36, 22) self.image_pixmap.draw_layout(wgc, self.imagen_size/2 + 2, int(self.imagen_size/2 * 0.5), pango_layout) self.image_pixmap.draw_layout(wgc, self.imagen_size/2 + 2, int(self.imagen_size/2 * 1.5), pango_layout) pango_layout.set_text("60°") self.image_pixmap.draw_rectangle(bgc, True, self.imagen_size/2 + 2, int(self.imagen_size/2 * 0.15), 36, 22) self.image_pixmap.draw_rectangle(bgc, True, self.imagen_size/2 + 2, int(self.imagen_size/2 * 1.85), 36, 22) self.image_pixmap.draw_layout(wgc, self.imagen_size/2 + 2, int(self.imagen_size/2 * 0.15), pango_layout) self.image_pixmap.draw_layout(wgc, self.imagen_size/2 + 2, int(self.imagen_size/2 * 1.85), pango_layout) pango_layout.set_text("30°") self.image_pixmap.draw_rectangle(rgc, True, int(self.imagen_size/2 * 0.48) + 2, self.imagen_size/2, 36, 22) self.image_pixmap.draw_rectangle(rgc, True, int(self.imagen_size/2 * 1.52) + 2, self.imagen_size/2, 36, 22) self.image_pixmap.draw_layout(wgc, int(self.imagen_size/2 * 0.48) + 2, self.imagen_size/2, pango_layout) self.image_pixmap.draw_layout(wgc, int(self.imagen_size/2 * 1.52) + 2, self.imagen_size/2, pango_layout) pango_layout.set_text("60°") self.image_pixmap.draw_rectangle(rgc, True, int(self.imagen_size/2 * 0.15) + 2, self.imagen_size/2, 36, 22) self.image_pixmap.draw_rectangle(rgc, True, int(self.imagen_size/2 * 1.85) + 2, self.imagen_size/2, 36, 22) self.image_pixmap.draw_layout(wgc, int(self.imagen_size/2 * 0.15) + 2, self.imagen_size/2, pango_layout) self.image_pixmap.draw_layout(wgc, int(self.imagen_size/2 * 1.85) + 2, self.imagen_size/2, pango_layout) for i in (-1, 0, 1): self.image_pixmap.draw_line(rgc, self.imagen_size/2 + i, 0, self.imagen_size/2 + i, self.imagen_size) self.image_pixmap.draw_arc(rgc, False, int(self.imagen_size/2 * 0.15) + i, 0, self.imagen_size - int(self.imagen_size * 0.15), self.imagen_size, 0, 360*64) self.image_pixmap.draw_arc(rgc, False, int(self.imagen_size/2 * 0.48) + i, 0, self.imagen_size - int(self.imagen_size * 0.48) , self.imagen_size, 0, 360*64) for i in (-1, 0, 1): self.image_pixmap.draw_line(bgc, 0, self.imagen_size/2 + i, self.imagen_size, self.imagen_size/2 + i) self.image_pixmap.draw_line(bgc, int(self.imagen_size/2 * 0.15), int(self.imagen_size/2 * 0.5) + i, self.imagen_size - int(self.imagen_size/2 * 0.15), int(self.imagen_size/2 * 0.5) + i) self.image_pixmap.draw_line(bgc, int(self.imagen_size/2 * 0.15), int(self.imagen_size/2 * 1.5) + i, self.imagen_size - int(self.imagen_size/2 * 0.15), int(self.imagen_size/2 * 1.5) + i) self.image_pixmap.draw_line(bgc, int(self.imagen_size/2 * 0.5), int(self.imagen_size/2 * 0.15) + i, self.imagen_size - int(self.imagen_size/2 * 0.5), int(self.imagen_size/2 * 0.15) + i) self.image_pixmap.draw_line(bgc, int(self.imagen_size/2 * 0.5), int(self.imagen_size/2 * 1.85) + i, self.imagen_size - int(self.imagen_size/2 * 0.5), int(self.imagen_size/2 * 1.85) + i) pango_layout.set_text(_("Latitude")) self.image_pixmap.draw_layout(bgc, 15, self.imagen_size - 48 - 15, pango_layout) pango_layout.set_text(_("Longitude")) self.image_pixmap.draw_layout(rgc, 15, self.imagen_size - 24 - 15, pango_layout) # Compass # TODO: fix string index to support multi-byte texts for i in (-1, 0, 1): self.image_pixmap.draw_line(rgc, 22 + 15, 48 + 15 + i, 68 + 15, 48 + 15 + i) for i in (-1, 0, 1): self.image_pixmap.draw_line(bgc, 45 + 15 + i, 24 + 15, 45 + 15 + i, 68 + 15) pango_layout.set_text(compass_text[0]) self.image_pixmap.draw_layout(bgc, 38 + 15, 15, pango_layout) pango_layout.set_text(compass_text[1]) self.image_pixmap.draw_layout(bgc, 38 + 15, 72 + 15, pango_layout) pango_layout.set_text(compass_text[2]) self.image_pixmap.draw_layout(rgc, 72 + 15, 36 + 15, pango_layout) pango_layout.set_text(compass_text[3]) self.image_pixmap.draw_layout(rgc, 15, 36 + 15, pango_layout)''' def draw_fase_moon(self, mask_pixmap, kgc, wgc): pass # FIXME: Reimplementar. ''' if self.data_model.phase_of_moon <= .25: #print "New Moon to First Quarter" phase_shadow_adjust = self.data_model.phase_of_moon - abs(math.sin(self.data_model.phase_of_moon * math.pi * 4) / 18.0) arc_scale = int(self.imagen_size * (1 - (phase_shadow_adjust * 4))) mask_pixmap.draw_rectangle(wgc, True, self.imagen_size/2 + 1, 0, self.imagen_size/2, self.imagen_size - 1) mask_pixmap.draw_arc(kgc, True, self.imagen_size/2 - int(arc_scale / 2), 0, arc_scale, self.imagen_size, 17280, 11520) elif self.data_model.phase_of_moon <= .5: #print "First Quarter to Full Moon" phase_shadow_adjust = self.data_model.phase_of_moon + abs(math.sin(self.data_model.phase_of_moon * math.pi * 4) / 18.0) arc_scale = int(self.imagen_size * ((phase_shadow_adjust - .25) * 4)) mask_pixmap.draw_rectangle(wgc, True, self.imagen_size/2, 0, self.imagen_size/2, self.imagen_size) mask_pixmap.draw_arc(wgc, True, self.imagen_size/2 - int(arc_scale / 2), 0, arc_scale, self.imagen_size, 5760, 11520) elif self.data_model.phase_of_moon <= .75: #print "Full Moon to Last Quarter" phase_shadow_adjust = self.data_model.phase_of_moon - abs(math.sin(self.data_model.phase_of_moon * math.pi * 4) / 18.0) arc_scale = int(self.imagen_size * (1 - ((phase_shadow_adjust - .5) * 4))) mask_pixmap.draw_rectangle(wgc, True, 0, 0, self.imagen_size/2 + 1, self.imagen_size) mask_pixmap.draw_arc(wgc, True, self.imagen_size/2 - int(arc_scale / 2), 0, arc_scale, self.imagen_size, 17280, 11520) else: #print "Last Quarter to New Moon" phase_shadow_adjust = self.data_model.phase_of_moon + abs(math.sin(self.data_model.phase_of_moon * math.pi * 4) / 18.0) arc_scale = int(self.imagen_size * ((phase_shadow_adjust - .75) * 4)) mask_pixmap.draw_rectangle(wgc, True, 0, 0, self.imagen_size/2, self.imagen_size) # mitad de luna blanca mask_pixmap.draw_arc(kgc, True, self.imagen_size/2 - int(arc_scale / 2), 0, arc_scale, self.imagen_size, 5760, 11520) return mask_pixmap''' class DataModel(): def __init__(self, ahora): self.ahora = ahora self.new_moon_array = MG.new_moon_array self.full_moon_array = MG.full_moon_array self.first_quarter_array = MG.first_quarter_array self.last_quarter_array = MG.last_quarter_array self.percent_of_full_moon = None self.julian_date = None self.lunation = None self.days_old = None self.hours_old = None self.minutes_old = None self.days_until_new_moon = None self.next_new_moon_date = None self.days_until_full_moon = None self.next_full_moon_date = None self.next_lunar_eclipse_sec = None self.next_solar_eclipse_sec = None self.last_lunar_eclipse_sec = None self.days_until_lunar_eclipse = None self.next_lunar_eclipse_date = None self.days_until_solar_eclipse = None self.next_solar_eclipse_date = None self.phase_of_moon = None self.update_moon_calculations(self.ahora) def update_moon_calculations(self, the_date): self.ahora = the_date # Generate all Moon data ready for display. last_new_moon_sec = MG.last_new_moon_sec_at_time(the_date) next_new_moon_sec = MG.next_new_moon_sec_at_time(the_date) last_full_moon_sec = MG.last_full_moon_sec_at_time(the_date) next_full_moon_sec = MG.next_full_moon_sec_at_time(the_date) last_quarter_moon_sec = MG.last_quarter_moon_sec_at_time(the_date) next_quarter_moon_sec = MG.next_quarter_moon_sec_at_time(the_date) self.phase_of_moon = MG.RecalcularFase(the_date) # Generate interesting human readable values self.percent_of_full_moon = (math.cos(((self.phase_of_moon + .5) / .5 * math.pi)) + 1) * .5 self.julian_date = 2452135 + ((the_date - 997700400.0) / MG.SECONDS_PER_DAY) self.lunation = MG.lunation_at_time(the_date) day_with_fraction = last_new_moon_sec / MG.SECONDS_PER_DAY self.days_old = math.floor(day_with_fraction) self.hours_old = math.floor((day_with_fraction - self.days_old) * 24) self.minutes_old = math.floor((((day_with_fraction - self.days_old) * 24) - self.hours_old) * 60) self.days_until_new_moon = next_new_moon_sec / MG.SECONDS_PER_DAY self.next_new_moon_date = the_date + next_new_moon_sec - MG.correct_for_tz_and_dst(the_date + next_new_moon_sec) self.days_until_full_moon = next_full_moon_sec / MG.SECONDS_PER_DAY self.next_full_moon_date = the_date + next_full_moon_sec - MG.correct_for_tz_and_dst(the_date + next_full_moon_sec) # Eclipse information self.next_lunar_eclipse_sec = MG.next_lunar_eclipse_sec_at_time(the_date) self.next_solar_eclipse_sec = MG.next_solar_eclipse_sec_at_time(the_date) self.last_lunar_eclipse_sec = MG.last_lunar_eclipse_sec_at_time(the_date) self.days_until_lunar_eclipse = self.next_lunar_eclipse_sec / MG.SECONDS_PER_DAY self.next_lunar_eclipse_date = the_date + self.next_lunar_eclipse_sec - MG.correct_for_tz_and_dst(the_date + self.next_lunar_eclipse_sec) self.days_until_solar_eclipse = self.next_solar_eclipse_sec / MG.SECONDS_PER_DAY self.next_solar_eclipse_date = the_date + self.next_solar_eclipse_sec - MG.correct_for_tz_and_dst(the_date + self.next_solar_eclipse_sec) # Selenographic terminator longitude selenographic_tmp = 270 + (self.phase_of_moon * 360) if selenographic_tmp >= 360: selenographic_tmp -= 360 if selenographic_tmp >= 270: selenographic_tmp -= 360 elif selenographic_tmp >= 180: selenographic_tmp -= 180 elif selenographic_tmp >= 90: selenographic_tmp -= 180 selenographic_tmp = -selenographic_tmp if selenographic_tmp < 0: self.west_or_east = _("west") else: self.west_or_east = _("east") self.selenographic_deg = abs(selenographic_tmp) if self.phase_of_moon >= .5: self.rise_or_set = _("Sunset") else: self.rise_or_set = _("Sunrise") def moon_phase_name(self, phase_of_moon): # Return the moon image name for a given phase value. if phase_of_moon >= 0 and phase_of_moon < 0.025: return _("New Moon") elif phase_of_moon >= 0.025 and phase_of_moon < 0.225: return _("Waxing Crescent") elif phase_of_moon >= 0.225 and phase_of_moon < 0.275: return _("First Quarter") elif phase_of_moon >= 0.275 and phase_of_moon < 0.475: return _("Waxing Gibbous") elif phase_of_moon >= 0.475 and phase_of_moon < 0.525: return _("Full Moon") elif phase_of_moon >= 0.525 and phase_of_moon < 0.735: return _("Waning Gibbous") elif phase_of_moon >= 0.735 and phase_of_moon < 0.775: return _("Last Quarter") elif phase_of_moon >= 0.775 and phase_of_moon < 0.975: return _("Waning Crescent") else: return _("New Moon") class MoonCalendar(Gtk.AspectFrame): def __init__(self): Gtk.AspectFrame.__init__(self) self.modify_bg(Gtk.StateType.NORMAL, MG.BACKGROUND) self.anio = None self.mes = None self.fecha = None self.hora = None self.semanas = None self.label_mes = None self.matriz = None self.layout() def layout(self): base = Gtk.VBox() caja_control = Gtk.HBox() view_tool_bar = Gtk.Toolbar() view_tool_bar.modify_bg(Gtk.StateType.NORMAL, MG.BACKGROUND) boton = Gtk.ToggleToolButton() boton.connect('clicked', self.anterior) pixbuf= GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(MG.ICONOS,'flecha-ico.svg'), 32, 32) imagen = Gtk.Image() imagen.set_from_pixbuf(pixbuf) boton.set_icon_widget(imagen) imagen.show() boton.show() view_tool_bar.insert(boton, -1) boton.modify_bg(Gtk.StateType.NORMAL, MG.BACKGROUND) caja_control.pack_start(view_tool_bar, False, False, 0) self.label_mes = Gtk.Label() self.label_mes.modify_bg(Gtk.StateType.NORMAL, MG.BACKGROUND) self.label_mes.modify_fg(Gtk.StateType.NORMAL, MG.FOREGROUND) self.label_mes.show() caja_control.pack_start(self.label_mes, True, True, 0) view_tool_bar = Gtk.Toolbar() view_tool_bar.modify_bg(Gtk.StateType.NORMAL, MG.BACKGROUND) boton = Gtk.ToggleToolButton() boton.connect('clicked', self.siguiente) pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( os.path.join(MG.ICONOS,'flecha-ico.svg'), 32, 32) pixbuf = pixbuf.flip(1) imagen = Gtk.Image() imagen.set_from_pixbuf(pixbuf) boton.set_icon_widget(imagen) imagen.show() boton.show() view_tool_bar.insert(boton, -1) boton.modify_bg(Gtk.StateType.NORMAL, MG.BACKGROUND) caja_control.pack_end(view_tool_bar, False, False, 0) caja_dias = Gtk.HBox() for dia in [_("Lun"), _("Mar"), _("Mie"), _("Jue"), _("Vie"), _("Sáb"), _("Dom")]: label = Gtk.Label(dia) label.modify_fg(Gtk.StateType.NORMAL, MG.FOREGROUND) caja_dias.pack_start(label, True, True, 0) self.matriz = MatrizMoonCalendar() base.pack_start(caja_control, False, False, 0) base.pack_start(caja_dias, False, False, 5) base.pack_start(self.matriz, True, True, 5) self.add(base) self.show_all() def anterior(self, widget= None): if self.mes == 1: self.mes = 12 self.anio -= 1 else: self.mes -= 1 self.set_mes(self.anio, self.mes, self.fecha, self.hora) self.show_all() def siguiente(self, widget= None): if self.mes == 12: self.mes = 1 self.anio += 1 else: self.mes += 1 self.set_mes(self.anio, self.mes, self.fecha, self.hora) self.show_all() def set_mes(self, anio, mes, fecha, hora): self.anio, self.mes, self.fecha, self.hora = (anio, mes, 1, hora) self.matriz.set_mes(self.anio, self.mes, self.fecha, self.hora) dias= [] for d in calendar.day_name: if d: dias.append(d) self.hoy = "%s-%s-%s %s" % (self.matriz.anio, self.matriz.mes, self.matriz.fecha, self.matriz.hora) meses= [] for m in calendar.month_name: if m: meses.append(m) t = time.strptime(self.hoy, MG.format) mes= meses[t.tm_mon -1] dia= dias[t.tm_wday] self.label_mes.set_text("%s %s" % (_(mes), self.matriz.anio)) def toggle_grid_clicked(self, widget= None, actualizar= False): for linea in self.matriz.calendarbuttons: for boton in linea: boton.toggle_grid_clicked() if actualizar: boton.actualizar() def toggle_hemisphere_clicked(self, widget= None, actualizar= False): for linea in self.matriz.calendarbuttons: for boton in linea: boton.toggle_hemisphere_clicked() if actualizar: boton.actualizar() class MatrizMoonCalendar(Gtk.EventBox): def __init__(self): Gtk.EventBox.__init__(self) self.set_visible_window(True) self.modify_bg(Gtk.StateType.NORMAL, MG.BACKGROUND) self.fixed = Gtk.Fixed() self.add(self.fixed) self.show_all() self.anio = None self.mes = None self.fecha = None self.hora = None self.semanas = [] self.fixes = [] self.calendarbuttons = [] self.tamanioboton = 0 self.connect("draw", self.repaint) def repaint(self, widget= None, event= None): if not self.fixes: return rect = self.get_allocation() anchoboton = rect.width/len(self.fixes[0]) altoboton = rect.height/len(self.fixes) tamanioboton = min( [anchoboton,altoboton] ) if self.tamanioboton != tamanioboton: self.tamanioboton = tamanioboton posy = 0 for fixed in self.fixes: self.fixed.move(fixed, 0, posy) posy += self.tamanioboton posx = 0 for fixed in self.fixes: for boton in self.calendarbuttons[self.fixes.index(fixed)]: fixed.move(boton, posx, 0) boton.repaint(self.tamanioboton) posx += self.tamanioboton posx = 0 def set_mes(self, anio, mes, fecha, hora): self.anio, self.mes, self.fecha, self.hora = anio, mes, fecha, hora self.fixes = [] self.calendarbuttons = [] self.semanas = MG.get_semanas_del_mes(anio, mes) for child in self.fixed.get_children(): self.fixed.remove(child) child.destroy() for sem in self.semanas: listadias = [] fixed = Gtk.Fixed() self.fixes.append(fixed) self.fixed.put(fixed, 0,0) for dia in sem: boton = CalendarButton(self.anio, self.mes, dia, self.hora) listadias.append(boton) fixed.put(boton, 0,0) self.calendarbuttons.append(listadias)