text: import calendar
  from datetime import timedelta, datetime
  from panda3d.core import Vec4, TextNode
  from direct.gui.DirectGui import DirectFrame, DirectLabel, DirectButton, DirectScrolledList, DGG
  from toontown.toonbase import TTLocalizer
  from toontown.toonbase import ToontownGlobals
  from toontown.parties.CalendarGuiDay import CalendarGuiDay
  
  class CalendarGuiMonth(DirectFrame):
      notify = directNotify.newCategory('CalendarGuiMonth')
  
      def __init__(self, parent, startingDateTime, scale = 1.0, pos = (0, 0, -0.1), dayClickCallback = None, onlyFutureDaysClickable = False, onlyFutureMonthsClickable = False):
          self.startDate = startingDateTime
          self.curDate = startingDateTime
          self.dayClickCallback = dayClickCallback
          self.onlyFutureDaysClickable = onlyFutureDaysClickable
          self.onlyFutureMonthsClickable = onlyFutureMonthsClickable
          if self.onlyFutureDaysClickable:
              self.onlyFutureMonthsClickable = True
          DirectFrame.__init__(self, parent=parent, scale=scale, pos=pos)
          self.showMarkers = base.config.GetBool('show-calendar-markers', 0)
          self.load()
          self.createGuiObjects()
          self.lastSelectedDate = None
          self.accept('clickedOnDay', self.clickedOnDay)
          return
  
      def createDummyLocators(self):
          self.monthLocator = self.attachNewNode('monthLocator')
          self.monthLocator.setZ(0.6)
          self.weekDayLocators = []
          for i in xrange(7):
              self.weekDayLocators.append(self.attachNewNode('weekDayLocator-%d' % i))
              self.weekDayLocators[i].setZ(0.5)
              self.weekDayLocators[i].setX(i * 0.24 + -0.75)
  
          dayTopLeftX = -0.8
          dayTopLeftZ = 0.4
          self.dayLocators = []
          for row in xrange(6):
              oneWeek = []
              for col in xrange(7):
                  newDayLoc = self.attachNewNode('dayLocator-row-%d-col-%d' % (row, col))
                  newDayLoc.setX(col * 0.24 + dayTopLeftX)
                  newDayLoc.setZ(row * -0.18 + dayTopLeftZ)
                  oneWeek.append(newDayLoc)
  
              self.dayLocators.append(oneWeek)
  
          self.monthLeftLocator = self.attachNewNode('monthLeft')
          self.monthLeftLocator.setPos(-0.3, 0, 0.65)
          self.monthRightLocator = self.attachNewNode('monthRight')
          self.monthRightLocator.setPos(0.3, 0, 0.65)
  
      def attachMarker(self, parent, scale = 0.01, color = (1, 0, 0)):
          if self.showMarkers:
              marker = loader.loadModel('phase_3/models/misc/sphere')
              marker.reparentTo(parent)
              marker.setScale(scale)
              marker.setColor(*color)
  
      def load(self):
          monthAsset = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar')
          monthAsset.reparentTo(self)
          self.monthLocator = self.find('**/locator_month/locator_month')
          self.attachMarker(self.monthLocator)
          self.weekDayLocators = []
          for weekday in ('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'):
              weekDayLoc = self.find('**/loc_%s' % weekday)
              self.weekDayLocators.append(weekDayLoc)
              self.attachMarker(weekDayLoc)
  
          self.dayLocators = []
          for row in xrange(6):
              oneWeek = []
              for col in xrange(7):
                  newDayLoc = self.find('**/loc_box_%s_%s' % (row, col))
                  oneWeek.append(newDayLoc)
  
              self.dayLocators.append(oneWeek)
  
          self.monthLeftLocator = self.find('**/locator_month_arrowL')
          self.monthRightLocator = self.find('**/locator_month_arrowR')
          self.filterLocator = self.find('**/locator_filter')
          self.filterLocatorArrowUp = self.find('**/locator_filter_arrowTop')
          self.filterLocatorArrowDown = self.find('**/locator_filter_arrowBottom')
          self.yearLocator = self.attachNewNode('yearLocator')
          self.yearLocator.setPos(self.monthLocator, 0, 0, -0.03)
  
      def createGuiObjects(self):
          self.monthLabel = DirectLabel(parent=self.monthLocator, relief=None, text=TTLocalizer.Months[self.startDate.month], text_scale=0.075, text_font=ToontownGlobals.getMinnieFont(), text_fg=(40 / 255.0,
           140 / 255.0,
           246 / 255.0,
           1.0))
          self.yearLabel = DirectLabel(parent=self.yearLocator, relief=None, text=str(self.startDate.year), text_scale=0.03, text_font=ToontownGlobals.getMinnieFont(), text_fg=(140 / 255.0,
           140 / 255.0,
           246 / 255.0,
           1.0))
          self.weekdayLabels = []
          for posIndex in xrange(7):
              adjustedNameIndex = (posIndex - 1) % 7
              self.weekdayLabels.append(DirectLabel(parent=self.weekDayLocators[posIndex], relief=None, text=TTLocalizer.DayNamesAbbrev[adjustedNameIndex], text_font=ToontownGlobals.getInterfaceFont(), text_fg=(255 / 255.0,
               146 / 255.0,
               113 / 255.0,
               1.0), text_scale=0.05))
  
          self.createGuiDays()
          arrowUp = self.find('**/month_arrowR_up')
          arrowDown = self.find('**/month_arrowR_down')
          arrowHover = self.find('**/month_arrowR_hover')
          self.monthLeftArrow = DirectButton(parent=self.monthLeftLocator, relief=None, image=(arrowUp,
           arrowDown,
           arrowHover,
           arrowUp), image3_color=Vec4(1, 1, 1, 0.5), scale=(-1.0, 1.0, 1.0), command=self.__doMonthLeft)
          if self.onlyFutureMonthsClickable:
              self.monthLeftArrow.hide()
          self.monthRightArrow = DirectButton(parent=self.monthRightLocator, relief=None, image=(arrowUp,
           arrowDown,
           arrowHover,
           arrowUp), image3_color=Vec4(1, 1, 1, 0.5), command=self.__doMonthRight)
  
          def makeLabel(itemName, itemNum, *extraArgs):
              return DirectLabel(text=itemName, frameColor=(0, 0, 0, 0), text_scale=0.04)
  
          gui = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_box')
          arrowUp = gui.find('**/downScroll_up')
          arrowDown = gui.find('**/downScroll_down')
          arrowHover = gui.find('**/downScroll_hover')
          filterLocatorUpPos = self.filterLocatorArrowUp.getPos(self.filterLocator)
          filterLocatorDownPos = self.filterLocatorArrowDown.getPos(self.filterLocator)
          self.filterList = DirectScrolledList(parent=self.filterLocator, relief=None, pos=(0, 0, 0), image=None, text_scale=0.025, incButton_image=(arrowUp,
           arrowDown,
           arrowHover,
           arrowUp), incButton_relief=None, incButton_pos=filterLocatorDownPos, incButton_image3_color=Vec4(1, 1, 1, 0.2), incButtonCallback=self.filterChanged, decButton_image=(arrowUp,
           arrowDown,
           arrowHover,
           arrowUp), decButton_relief=None, decButton_pos=filterLocatorUpPos, decButton_scale=(1, 1, -1), decButton_image3_color=Vec4(1, 1, 1, 0.2), decButtonCallback=self.filterChanged, numItemsVisible=1, itemMakeFunction=makeLabel, items=[TTLocalizer.CalendarShowAll, TTLocalizer.CalendarShowOnlyHolidays, TTLocalizer.CalendarShowOnlyParties], itemFrame_frameSize=(-.2, 0.2, -.02, 0.05), itemFrame_frameColor=(0, 0, 0, 0))
          gui.removeNode()
          return
  
      def getTopLeftDate(self):
          firstOfTheMonth = self.curDate.replace(day=1)
          daysAwayFromSunday = (firstOfTheMonth.weekday() - 6) % 7
          topLeftDate = firstOfTheMonth + timedelta(days=-daysAwayFromSunday)
          return topLeftDate
  
      def createGuiDays(self):
          topLeftDate = self.getTopLeftDate()
          curDate = topLeftDate
          self.guiDays = []
          for row in self.dayLocators:
              for oneLocator in row:
                  self.guiDays.append(CalendarGuiDay(oneLocator, curDate, self.curDate, self.dayClickCallback, self.onlyFutureDaysClickable))
                  curDate += timedelta(days=1)
  
      def changeDateForGuiDays(self):
          topLeftDate = self.getTopLeftDate()
          guiDayDate = topLeftDate
          for guiDay in self.guiDays:
              guiDay.changeDate(self.curDate, guiDayDate)
              guiDayDate += timedelta(days=1)
  
      def changeMonth(self, monthChange):
          if monthChange != 0:
              newMonth = self.curDate.month + monthChange
              newYear = self.curDate.year
              while newMonth > 12:
                  newYear += 1
                  newMonth -= 12
  
              while newMonth < 1:
                  if newYear - 1 > 1899:
                      newMonth += 12
                      newYear -= 1
                  else:
                      newMonth += 1
  
              self.curDate = datetime(newYear, newMonth, 1, self.curDate.time().hour, self.curDate.time().minute, self.curDate.time().second, self.curDate.time().microsecond, self.curDate.tzinfo)
          self.monthLabel['text'] = (TTLocalizer.Months[self.curDate.month],)
          self.yearLabel['text'] = (str(self.curDate.year),)
          startTime = globalClock.getRealTime()
          self.changeDateForGuiDays()
          endTime = globalClock.getRealTime()
          self.notify.debug('changeDate took %f seconds' % (endTime - startTime))
          self.updateSelectedDate()
          if monthChange != 0:
              if self.onlyFutureMonthsClickable and newMonth == self.startDate.month and newYear == self.startDate.year:
                  self.monthLeftArrow.hide()
  
      def __doMonthLeft(self):
          self.changeMonth(-1)
  
      def __doMonthRight(self):
          self.monthLeftArrow.show()
          self.changeMonth(1)
  
      def destroy(self):
          self.ignoreAll()
          self.dayClickCallback = None
          self.monthLeftArrow.destroy()
          self.monthRightArrow.destroy()
          for day in self.guiDays:
              if day is not None:
                  day.destroy()
              day = None
  
          self.filterList.destroy()
          DirectFrame.destroy(self)
          return
  
      def clickedOnDay(self, dayDate):
          self.lastSelectedDate = dayDate
          self.updateSelectedDate()
  
      def updateSelectedDate(self):
          if self.lastSelectedDate:
              for oneGuiDay in self.guiDays:
                  if oneGuiDay.myDate.date() == self.lastSelectedDate:
                      oneGuiDay.updateSelected(True)
                  else:
                      oneGuiDay.updateSelected(False)
  
      def clearSelectedDay(self):
          for oneGuiDay in self.guiDays:
              oneGuiDay.updateSelected(False)
  
      def filterChanged(self):
          newFilter = self.filterList.getSelectedIndex()
          for guiDay in self.guiDays:
              guiDay.changeFilter(newFilter)
  