Ejemplo n.º 1
0
class PartyEditor(DirectObject, FSM):
    """
    This class creates the grid and scrolled list needed for players to
    drag and drop activities and decorations onto their party grounds.
    """
    notify = directNotify.newCategory("PartyEditor")

    def __init__(self, partyPlanner, parent):
        FSM.__init__(self, self.__class__.__name__)
        self.partyPlanner = partyPlanner
        self.parent = parent
        self.partyEditorGrid = PartyEditorGrid(self)
        self.currentElement = None

        self.defaultTransitions = {
            "Hidden": ["Idle", "Cleanup"],
            "Idle": ["DraggingElement", "Hidden", "Cleanup"],
            "DraggingElement":
            ["Idle", "DraggingElement", "Hidden", "Cleanup"],
            "Cleanup": [],
        }
        self.initElementList()
        self.initPartyClock()
        self.initTrashCan()

    def initElementList(self):
        self.activityIconsModel = loader.loadModel(
            "phase_4/models/parties/eventSignIcons")
        self.decorationModels = loader.loadModel(
            "phase_4/models/parties/partyDecorations")
        pos = self.partyPlanner.gui.find(
            "**/step_05_activitiesIcon_locator").getPos()
        self.elementList = DirectScrolledList(
            parent=self.parent,
            relief=None,
            # inc and dec are DirectButtons
            decButton_image=(
                self.partyPlanner.gui.find("**/activitiesButtonUp_up"),
                self.partyPlanner.gui.find("**/activitiesButtonUp_down"),
                self.partyPlanner.gui.find("**/activitiesButtonUp_rollover"),
                self.partyPlanner.gui.find("**/activitiesButtonUp_inactive"),
            ),
            decButton_relief=None,
            decButton_pos=(-0.05, 0.0, -0.38),
            incButton_image=(
                self.partyPlanner.gui.find("**/activitiesButtonDown_up"),
                self.partyPlanner.gui.find("**/activitiesButtonDown_down"),
                self.partyPlanner.gui.find("**/activitiesButtonDown_rollover"),
                self.partyPlanner.gui.find("**/activitiesButtonDown_inactive"),
            ),
            incButton_relief=None,
            incButton_pos=(-0.05, 0.0, -0.94),

            # itemFrame is a DirectFrame
            itemFrame_pos=(pos[0], pos[1], pos[2] + 0.04),
            itemFrame_relief=None,
            # each item is a button with text on it
            numItemsVisible=1,
            items=[],
        )

        for activityId in PartyGlobals.PartyEditorActivityOrder:
            if activityId in PartyGlobals.VictoryPartyActivityIds:
                holidayIds = base.cr.newsManager.getHolidayIdList()
                if ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds:
                    pele = PartyEditorListElement(self, activityId)
                    self.elementList.addItem(pele)
            elif activityId in PartyGlobals.VictoryPartyReplacementActivityIds:
                holidayIds = base.cr.newsManager.getHolidayIdList()
                if not ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds:
                    pele = PartyEditorListElement(self, activityId)
                    self.elementList.addItem(pele)
            else:
                pele = PartyEditorListElement(self, activityId)
                self.elementList.addItem(pele)
                if activityId == PartyGlobals.ActivityIds.PartyClock:
                    self.partyClockElement = pele

        for decorationId in PartyGlobals.DecorationIds:
            decorName = PartyGlobals.DecorationIds.getString(decorationId)
            if (decorName == "HeartTarget") \
            or (decorName == "HeartBanner") \
            or (decorName == "FlyingHeart"):
                holidayIds = base.cr.newsManager.getHolidayIdList()
                if ToontownGlobals.VALENTINES_DAY in holidayIds:
                    pele = PartyEditorListElement(self,
                                                  decorationId,
                                                  isDecoration=True)
                    self.elementList.addItem(pele)
            elif decorationId in PartyGlobals.VictoryPartyDecorationIds:
                holidayIds = base.cr.newsManager.getHolidayIdList()
                if ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds:
                    pele = PartyEditorListElement(self,
                                                  decorationId,
                                                  isDecoration=True)
                    self.elementList.addItem(pele)
            elif decorationId in PartyGlobals.VictoryPartyReplacementDecorationIds:
                holidayIds = base.cr.newsManager.getHolidayIdList()
                if not ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds:
                    pele = PartyEditorListElement(self,
                                                  decorationId,
                                                  isDecoration=True)
                    self.elementList.addItem(pele)
            else:
                pele = PartyEditorListElement(self,
                                              decorationId,
                                              isDecoration=True)
                self.elementList.addItem(pele)
        self.elementList.refresh()
        self.elementList['command'] = self.scrollItemChanged

    def initPartyClock(self):
        self.partyClockElement.buyButtonClicked((8, 7))

    def initTrashCan(self):
        trashcanGui = loader.loadModel("phase_3/models/gui/trashcan_gui")
        self.trashCanButton = DirectButton(
            parent=self.parent,
            relief=None,
            pos=Point3(*PartyGlobals.TrashCanPosition),
            scale=PartyGlobals.TrashCanScale,
            geom=(
                trashcanGui.find("**/TrashCan_CLSD"),
                trashcanGui.find("**/TrashCan_OPEN"),
                trashcanGui.find("**/TrashCan_RLVR"),
                trashcanGui.find("**/TrashCan_RLVR"),
            ),
            command=self.trashCanClicked,
        )
        self.trashCanButton.bind(DirectGuiGlobals.ENTER, self.mouseEnterTrash)
        self.trashCanButton.bind(DirectGuiGlobals.EXIT, self.mouseExitTrash)
        self.mouseOverTrash = False
        self.oldInstructionText = ""
        self.trashCanLastClickedTime = 0

    def scrollItemChanged(self):
        if not self.elementList["items"]:
            # we are probably closing the gui, do nothing
            return
        self.currentElement = self.elementList["items"][
            self.elementList.getSelectedIndex()]
        self.elementList["items"][
            self.elementList.getSelectedIndex()].elementSelectedFromList()
        if self.elementList["items"][
                self.elementList.getSelectedIndex()].isDecoration:
            self.partyPlanner.instructionLabel[
                "text"] = TTLocalizer.PartyPlannerEditorInstructionsClickedElementDecoration
        else:
            self.partyPlanner.instructionLabel[
                "text"] = TTLocalizer.PartyPlannerEditorInstructionsClickedElementActivity

    def listElementClicked(self):
        self.request("DraggingElement")

    def listElementReleased(self):
        self.request("Idle", True)

    def trashCanClicked(self):
        currentTime = time.time()
        # Check for double click, if so, clear the party grounds
        if currentTime - self.trashCanLastClickedTime < 0.2:
            self.clearPartyGrounds()
        self.trashCanLastClickedTime = time.time()

    def clearPartyGrounds(self):
        for item in self.elementList["items"]:
            item.clearPartyGrounds()
        self.initPartyClock()
        if self.currentElement:
            self.currentElement.checkSoldOutAndPaidStatusAndAffordability()

    def buyCurrentElement(self):
        if self.currentElement:
            purchaseSuccessful = self.currentElement.buyButtonClicked()
            if purchaseSuccessful:
                # The buying and placement of the item was successful
                self.handleMutuallyExclusiveActivities()
                pass
            else:
                # The buying and placement of the item was not successful
                self.partyPlanner.instructionLabel[
                    "text"] = TTLocalizer.PartyPlannerEditorInstructionsNoRoom

    def mouseEnterTrash(self, mouseEvent):
        self.mouseOverTrash = True
        self.oldInstructionText = self.partyPlanner.instructionLabel["text"]
        self.partyPlanner.instructionLabel[
            "text"] = TTLocalizer.PartyPlannerEditorInstructionsTrash

    def mouseExitTrash(self, mouseEvent):
        self.mouseOverTrash = False
        self.partyPlanner.instructionLabel["text"] = self.oldInstructionText

    ### FSM Methods ###

    def enterHidden(self):
        PartyEditor.notify.debug("Enter Hidden")

    def exitHidden(self):
        PartyEditor.notify.debug("Exit Hidden")

    def enterIdle(self, fromDragging=False):
        PartyEditor.notify.debug("Enter Idle")
        if not fromDragging:
            self.elementList.scrollTo(0)
            self.elementList["items"][0].elementSelectedFromList()
            self.currentElement = self.elementList["items"][
                self.elementList.getSelectedIndex()]
            self.currentElement.checkSoldOutAndPaidStatusAndAffordability()
        self.partyPlanner.instructionLabel[
            "text"] = TTLocalizer.PartyPlannerEditorInstructionsIdle
        self.updateCostsAndBank()
        self.handleMutuallyExclusiveActivities()

    def handleMutuallyExclusiveActivities(self):
        """Smartly removed the older activity and inform the user."""
        mutSet = self.getMutuallyExclusiveActivities()
        if not mutSet:
            return
        # our mutset doesn't tell us which one is older
        currentActivities = self.partyEditorGrid.getActivitiesElementsOnGrid()
        lastActivity = self.partyEditorGrid.lastActivityIdPlaced
        for act in currentActivities:
            if (act.id in mutSet) and not (lastActivity == act.id):
                act.removeFromGrid()
                removedName = TTLocalizer.PartyActivityNameDict[
                    act.id]["editor"]
                addedName = TTLocalizer.PartyActivityNameDict[lastActivity][
                    "editor"]
                instr = TTLocalizer.PartyPlannerEditorInstructionsRemoved % \
                        {"removed" : removedName, "added" : addedName}
                self.partyPlanner.instructionLabel["text"] = instr
                self.updateCostsAndBank()
                # deliberately no break here, in case they manage to
                # get 3 jukeboxes into the editor somehow

    def getMutuallyExclusiveActivities(self):
        """Return the set of activities on the grid that are mutually exclusive, None otherwise."""
        # create a set of activity Ids
        currentActivities = self.partyEditorGrid.getActivitiesOnGrid()
        actSet = Set([])
        for act in currentActivities:
            actSet.add(act[0])
        result = None
        for mutuallyExclusiveTuples in PartyGlobals.MutuallyExclusiveActivities:
            mutSet = Set(mutuallyExclusiveTuples)
            inter = mutSet.intersection(actSet)
            if len(inter) > 1:
                result = inter
                break
        return result

    def updateCostsAndBank(self):
        """
        We need to update the total cost of the party and what they will have
        left in their bank.
        """
        currentActivities = self.partyEditorGrid.getActivitiesOnGrid()
        currentDecorations = self.partyEditorGrid.getDecorationsOnGrid()
        newCost = 0
        for elementTuple in currentActivities:
            newCost += PartyGlobals.ActivityInformationDict[
                elementTuple[0]]["cost"]
        for elementTuple in currentDecorations:
            newCost += PartyGlobals.DecorationInformationDict[
                elementTuple[0]]["cost"]
        self.partyPlanner.costLabel[
            "text"] = TTLocalizer.PartyPlannerTotalCost % newCost
        if len(currentActivities) > 0 or len(currentDecorations) > 0:
            self.partyPlanner.setNextButtonState(enabled=True)
        else:
            self.partyPlanner.setNextButtonState(enabled=False)
        self.partyPlanner.totalCost = newCost
        self.partyPlanner.beanBank["text"] = str(
            int(self.partyPlanner.totalMoney - self.partyPlanner.totalCost))

    def exitIdle(self):
        PartyEditor.notify.debug("Exit Idle")

    def enterDraggingElement(self):
        PartyEditor.notify.debug("Enter DraggingElement")
        if self.currentElement.isDecoration:
            self.partyPlanner.instructionLabel[
                "text"] = TTLocalizer.PartyPlannerEditorInstructionsDraggingDecoration
        else:
            self.partyPlanner.instructionLabel[
                "text"] = TTLocalizer.PartyPlannerEditorInstructionsDraggingActivity

    def exitDraggingElement(self):
        PartyEditor.notify.debug("Exit DraggingElement")

    def enterCleanup(self):
        PartyEditor.notify.debug("Enter Cleanup")
        self.partyEditorGrid.destroy()
        self.elementList.removeAndDestroyAllItems()
        self.elementList.destroy()
        self.trashCanButton.unbind(DirectGuiGlobals.ENTER)
        self.trashCanButton.unbind(DirectGuiGlobals.EXIT)
        self.trashCanButton.destroy()

    def exitCleanup(self):
        PartyEditor.notify.debug("Exit Cleanup")
Ejemplo n.º 2
0
class CalendarGuiDay(DirectFrame):
    notify = directNotify.newCategory('CalendarGuiDay')
    ScrollListTextSize = 0.03

    def __init__(self, parent, myDate, startDate, dayClickCallback = None, onlyFutureDaysClickable = False):
        self.origParent = parent
        self.startDate = startDate
        self.myDate = myDate
        self.dayClickCallback = dayClickCallback
        self.onlyFutureDaysClickable = onlyFutureDaysClickable
        DirectFrame.__init__(self, parent=parent)
        self.timedEvents = []
        self.partiesInvitedToToday = []
        self.hostedPartiesToday = []
        self.yearlyHolidaysToday = []
        self.showMarkers = base.config.GetBool('show-calendar-markers', 0)
        self.filter = ToontownGlobals.CalendarFilterShowAll
        self.load()
        self.createGuiObjects()
        self.update()

    def createDummyLocators(self):
        self.dayButtonLocator = self.attachNewNode('dayButtonLocator')
        self.dayButtonLocator.setX(0.1)
        self.dayButtonLocator.setZ(-0.05)
        self.numberLocator = self.attachNewNode('numberLocator')
        self.numberLocator.setX(0.09)
        self.scrollLocator = self.attachNewNode('scrollLocator')
        self.selectedLocator = self.attachNewNode('selectedLocator')
        self.selectedLocator.setX(0.11)
        self.selectedLocator.setZ(-0.06)

    def load(self):
        dayAsset = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_box')
        dayAsset.reparentTo(self)
        self.dayButtonLocator = self.find('**/loc_origin')
        self.numberLocator = self.find('**/loc_number')
        self.scrollLocator = self.find('**/loc_topLeftList')
        self.selectedLocator = self.find('**/loc_origin')
        self.todayBox = self.find('**/boxToday')
        self.todayBox.hide()
        self.selectedFrame = self.find('**/boxHover')
        self.selectedFrame.hide()
        self.defaultBox = self.find('**/boxBlank')
        self.scrollBottomRightLocator = self.find('**/loc_bottomRightList')
        self.scrollDownLocator = self.find('**/loc_scrollDown')
        self.attachMarker(self.scrollDownLocator)
        self.scrollUpLocator = self.find('**/loc_scrollUp')
        self.attachMarker(self.scrollUpLocator)

    def attachMarker(self, parent, scale = 0.005, 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 createGuiObjects(self):
        self.dayButton = DirectButton(parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, pressEffect=1, rolloverSound=None, clickSound=None)
        self.numberWidget = DirectLabel(parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1))
        self.attachMarker(self.numberLocator)
        self.listXorigin = 0
        self.listFrameSizeX = self.scrollBottomRightLocator.getX() - self.scrollLocator.getX()
        self.scrollHeight = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ()
        self.listZorigin = self.scrollBottomRightLocator.getZ()
        self.listFrameSizeZ = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ()
        self.arrowButtonXScale = 1
        self.arrowButtonZScale = 1
        self.itemFrameXorigin = 0
        self.itemFrameZorigin = 0
        self.buttonXstart = self.itemFrameXorigin + 0.21
        self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
        buttonOffSet = -0.01
        incButtonPos = (0.0, 0, 0)
        decButtonPos = (0.0, 0, 0)
        itemFrameMinZ = self.listZorigin
        itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ
        arrowUp = self.find('**/downScroll_up')
        arrowDown = self.find('**/downScroll_down')
        arrowHover = self.find('**/downScroll_hover')
        self.scrollList = DirectScrolledList(parent=self.scrollLocator, relief=None, pos=(0, 0, 0), incButton_image=(arrowUp,
         arrowDown,
         arrowHover,
         arrowUp), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(arrowUp,
         arrowDown,
         arrowHover,
         arrowUp), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), numItemsVisible=4, incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed)
        itemFrameParent = self.scrollList.itemFrame.getParent()
        self.scrollList.incButton.reparentTo(self.scrollDownLocator)
        self.scrollList.decButton.reparentTo(self.scrollUpLocator)
        arrowUp.removeNode()
        arrowDown.removeNode()
        arrowHover.removeNode()
        clipper = PlaneNode('clipper')
        clipper.setPlane(Plane(Vec3(-1, 0, 0), Point3(0.23, 0, 0)))
        clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper)
        self.scrollList.component('itemFrame').setClipPlane(clipNP)
        return

    def scrollButtonPressed(self):
        self.__clickedOnDay()

    def adjustForMonth(self):
        curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
        if self.onlyFutureDaysClickable:
            if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day:
                self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5)
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
            else:
                self.numberWidget.setColorScale(1, 1, 1, 1)
        if self.myDate.month != self.startDate.month:
            self.setColorScale(0.75, 0.75, 0.75, 1.0)
            if self.dayClickCallback is not None:
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
        else:
            self.setColorScale(1, 1, 1, 1)
        if self.myDate.date() == curServerDate.date():
            self.defaultBox.hide()
            self.todayBox.show()
        else:
            self.defaultBox.show()
            self.todayBox.hide()
        return

    def destroy(self):
        if self.dayClickCallback is not None:
            self.numberWidget.destroy()
        self.dayClickCallback = None
        self.notify.debug('desroying %s' % self.myDate)
        try:
            for item in self.scrollList['items']:
                if hasattr(item, 'description') and item.description and hasattr(item.description, 'destroy'):
                    self.notify.debug('desroying description of item %s' % item)
                    item.unbind(DGG.ENTER)
                    item.unbind(DGG.EXIT)
                    item.description.destroy()

        except e:
            self.notify.debug('pass %s' % self.myDate)

        self.scrollList.removeAndDestroyAllItems()
        self.scrollList.destroy()
        self.dayButton.destroy()
        DirectFrame.destroy(self)
        return

    def addWeeklyHolidays(self):
        if not self.filter == ToontownGlobals.CalendarFilterShowAll and not self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays:
            return
        if base.cr.newsManager:
            holidays = base.cr.newsManager.getHolidaysForWeekday(self.myDate.weekday())
            holidayName = ''
            holidayDesc = ''
            for holidayId in holidays:
                if holidayId in TTLocalizer.HolidayNamesInCalendar:
                    holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
                    holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
                else:
                    holidayName = TTLocalizer.UnknownHoliday % holidayId
                self.addTitleAndDescToScrollList(holidayName, holidayDesc)

            self.scrollList.refresh()
        if base.config.GetBool('calendar-test-items', 0):
            if self.myDate.date() + datetime.timedelta(days=-1) == base.cr.toontownTimeManager.getCurServerDateTime().date():
                testItems = ('1:00 AM Party', '2:00 AM CEO', '11:15 AM Party', '5:30 PM CJ', '11:00 PM Party', 'Really Really Long String')
                for text in testItems:
                    newItem = DirectLabel(relief=None, text=text, text_scale=self.ScrollListTextSize, text_align=TextNode.ALeft)
                    self.scrollList.addItem(newItem)

            if self.myDate.date() + datetime.timedelta(days=-2) == base.cr.toontownTimeManager.getCurServerDateTime().date():
                testItems = ('1:00 AM Party', '3:00 AM CFO', '11:00 AM Party')
                textSize = self.ScrollListTextSize
                for text in testItems:
                    newItem = DirectLabel(relief=None, text=text, text_scale=textSize, text_align=TextNode.ALeft)
                    self.scrollList.addItem(newItem)

    def updateArrowButtons(self):
        numItems = 0
        try:
            numItems = len(self.scrollList['items'])
        except e:
            numItems = 0

        if numItems <= self.scrollList.numItemsVisible:
            self.scrollList.incButton.hide()
            self.scrollList.decButton.hide()
        else:
            self.scrollList.incButton.show()
            self.scrollList.decButton.show()

    def collectTimedEvents(self):
        self.timedEvents = []
        if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties:
            for party in localAvatar.partiesInvitedTo:
                if party.startTime.date() == self.myDate.date():
                    self.partiesInvitedToToday.append(party)
                    self.timedEvents.append((party.startTime.time(), party))

            for party in localAvatar.hostedParties:
                if party.startTime.date() == self.myDate.date():
                    self.hostedPartiesToday.append(party)
                    self.timedEvents.append((party.startTime.time(), party))

        if base.cr.newsManager and (self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays):
            yearlyHolidays = base.cr.newsManager.getYearlyHolidaysForDate(self.myDate)
            for holiday in yearlyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.month and holidayStart[1] == self.myDate.day:
                    myTime = datetime.time(holidayStart[2], holidayStart[3])
                elif holidayEnd[0] == self.myDate.month and holidayEnd[1] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[2], holidayEnd[3])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            oncelyHolidays = base.cr.newsManager.getOncelyHolidaysForDate(self.myDate)
            for holiday in oncelyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.year and holidayStart[1] == self.myDate.month and holidayStart[2] == self.myDate.day:
                    myTime = datetime.time(holidayStart[3], holidayStart[4])
                elif holidayEnd[0] == self.myDate.year and holidayEnd[1] == self.myDate.month and holidayEnd[2] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[3], holidayEnd[4])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            multipleStartHolidays = base.cr.newsManager.getMultipleStartHolidaysForDate(self.myDate)
            for holiday in multipleStartHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.year and holidayStart[1] == self.myDate.month and holidayStart[2] == self.myDate.day:
                    myTime = datetime.time(holidayStart[3], holidayStart[4])
                elif holidayEnd[0] == self.myDate.year and holidayEnd[1] == self.myDate.month and holidayEnd[2] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[3], holidayEnd[4])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            relativelyHolidays = base.cr.newsManager.getRelativelyHolidaysForDate(self.myDate)
            for holiday in relativelyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.month and holidayStart[1] == self.myDate.day:
                    myTime = datetime.time(holidayStart[2], holidayStart[3])
                elif holidayEnd[0] == self.myDate.month and holidayEnd[1] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[2], holidayEnd[3])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

        def timedEventCompare(te1, te2):
            if te1[0] < te2[0]:
                return -1
            elif te1[0] == te2[0]:
                return 0
            else:
                return 1

        self.timedEvents.sort(cmp=timedEventCompare)
        for timedEvent in self.timedEvents:
            if isinstance(timedEvent[1], PartyInfo):
                self.addPartyToScrollList(timedEvent[1])
            elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.YearlyHolidayType:
                self.addYearlyHolidayToScrollList(timedEvent[1])
            elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.OncelyHolidayType:
                self.addOncelyHolidayToScrollList(timedEvent[1])
            elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.OncelyMultipleStartHolidayType:
                self.addOncelyMultipleStartHolidayToScrollList(timedEvent[1])
            elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.RelativelyHolidayType:
                self.addRelativelyHolidayToScrollList(timedEvent[1])

    def addYearlyHolidayToScrollList(self, holiday):
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ''
        startTime = datetime.time(holidayStart[2], holidayStart[3])
        endTime = datetime.time(holidayEnd[2], holidayEnd[3])
        startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1])
        endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1])
        if endDate < startDate:
            endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day)
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = TTLocalizer.UnknownHoliday % holidayId
        if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[1]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime)
        elif self.myDate.month == holidayStart[0] and self.myDate.day == holidayStart[1]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc = holidayName + '. ' + holidayDesc
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.month == holidayEnd[0] and self.myDate.day == holidayEnd[1]:
            holidayText = myStrftime(endTime)
            holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime)
        else:
            self.notify.error('unhandled case')
        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addOncelyHolidayToScrollList(self, holiday):
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ''
        startTime = datetime.time(holidayStart[3], holidayStart[4])
        endTime = datetime.time(holidayEnd[3], holidayEnd[4])
        startDate = datetime.date(holidayStart[0], holidayStart[1], holidayStart[2])
        endDate = datetime.date(holidayStart[0], holidayEnd[1], holidayEnd[2])
        if endDate < startDate:
            endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day)
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = ''
        if holidayStart[1] == holidayEnd[1] and holidayStart[2] == holidayEnd[2]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc = holidayName + '. ' + holidayDesc
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime)
        elif self.myDate.year == holidayStart[0] and self.myDate.month == holidayStart[1] and self.myDate.day == holidayStart[2]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc = holidayName + '. ' + holidayDesc
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.year == holidayEnd[0] and self.myDate.month == holidayEnd[1] and self.myDate.day == holidayEnd[2]:
            holidayText = myStrftime(endTime)
            holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime)
        else:
            self.notify.error('unhandled case')
        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addOncelyMultipleStartHolidayToScrollList(self, holiday):
        self.addOncelyHolidayToScrollList(holiday)

    def addRelativelyHolidayToScrollList(self, holiday):
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ''
        startTime = datetime.time(holidayStart[2], holidayStart[3])
        endTime = datetime.time(holidayEnd[2], holidayEnd[3])
        startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1])
        endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1])
        if endDate < startDate:
            endDate.year += 1
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = ''
        if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[1]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime)
        elif self.myDate.month == holidayStart[0] and self.myDate.day == holidayStart[1]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc = holidayName + '. ' + holidayDesc
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.month == holidayEnd[0] and self.myDate.day == holidayEnd[1]:
            holidayText = myStrftime(endTime)
            holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime)
        else:
            self.notify.error('unhandled case')
        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addTitleAndDescToScrollList(self, title, desc):
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(relief=None, text=title, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem)
        scrollItemHeight = newItem.getHeight()
        descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
        descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
        descUnderItemZAdjust = -descUnderItemZAdjust
        descZAdjust = descUnderItemZAdjust
        newItem.description = DirectLabel(parent=newItem, pos=(0.115, 0, descZAdjust), text='', text_wordwrap=15, pad=(0.02, 0.02), text_scale=descTextSize, text_align=TextNode.ACenter, textMayChange=0)
        newItem.description.checkedHeight = False
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()
        newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, desc, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
        self.scrollList.addItem(newItem)
        return

    def exitedTextItem(self, newItem, mousepos):
        newItem.description.hide()

    def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos):
        if not newItem.description.checkedHeight:
            newItem.description.checkedHeight = True
            newItem.description['text'] = descText
            bounds = newItem.description.getBounds()
            descHeight = newItem.description.getHeight()
            scrollItemHeight = newItem.getHeight()
            descOverItemZAdjust = descHeight - scrollItemHeight / 2.0
            descZPos = self.getPos(aspect2d)[2] + descUnderItemZAdjust - descHeight
            if descZPos < -1.0:
                newItem.description.setZ(descOverItemZAdjust)
            descWidth = newItem.description.getWidth()
            brightFrame = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg')
            newItem.description['geom'] = brightFrame
            newItem.description['geom_scale'] = (descWidth, 1, descHeight)
            descGeomZ = (bounds[2] - bounds[3]) / 2.0
            descGeomZ += bounds[3]
            newItem.description['geom_pos'] = (0, 0, descGeomZ)
        newItem.description.show()

    def addPartyToScrollList(self, party):
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        partyTitle = myStrftime(party.startTime)
        partyTitle = partyTitle + ' ' + TTLocalizer.EventsPageCalendarTabParty
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(relief=None, text=partyTitle, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem)
        scrollItemHeight = newItem.getHeight()
        descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
        descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
        descUnderItemZAdjust = -descUnderItemZAdjust
        descZAdjust = descUnderItemZAdjust
        self.scrollList.addItem(newItem)
        newItem.description = MiniInviteVisual(newItem, party)
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()
        newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, newItem.description, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
        return

    def __clickedOnScrollItem(self):
        self.__clickedOnDay()

    def __clickedOnDay(self):
        acceptClick = True
        if self.onlyFutureDaysClickable:
            curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
            if self.myDate.date() < curServerDate.date():
                acceptClick = False
        if not acceptClick:
            return
        if self.dayClickCallback:
            self.dayClickCallback(self)
        self.notify.debug('we got clicked on %s' % self.myDate.date())
        messenger.send('clickedOnDay', [self.myDate.date()])

    def updateSelected(self, selected):
        multiplier = 1.1
        if selected:
            self.selectedFrame.show()
            self.setScale(multiplier)
            self.setPos(-0.01, 0, 0.01)
            grandParent = self.origParent.getParent()
            self.origParent.reparentTo(grandParent)
        else:
            self.selectedFrame.hide()
            self.setScale(1.0)
            self.setPos(0, 0, 0)

    def changeDate(self, startDate, myDate):
        self.startDate = startDate
        self.myDate = myDate
        self.scrollList.removeAndDestroyAllItems()
        self.update()

    def update(self):
        self.numberWidget['text'] = str(self.myDate.day)
        self.adjustForMonth()
        self.addWeeklyHolidays()
        self.collectTimedEvents()
        self.updateArrowButtons()

    def changeFilter(self, filter):
        oldFilter = self.filter
        self.filter = filter
        if self.filter != oldFilter:
            self.scrollList.removeAndDestroyAllItems()
            self.update()
Ejemplo n.º 3
0
class PartyEditor(DirectObject, FSM):
    notify = directNotify.newCategory('PartyEditor')

    def __init__(self, partyPlanner, parent):
        FSM.__init__(self, self.__class__.__name__)
        self.partyPlanner = partyPlanner
        self.parent = parent
        self.partyEditorGrid = PartyEditorGrid(self)
        self.currentElement = None
        self.defaultTransitions = {'Hidden': ['Idle', 'Cleanup'],
         'Idle': ['DraggingElement', 'Hidden', 'Cleanup'],
         'DraggingElement': ['Idle',
                             'DraggingElement',
                             'Hidden',
                             'Cleanup'],
         'Cleanup': []}
        self.initElementList()
        self.initPartyClock()
        self.initTrashCan()
        return

    def initElementList(self):
        self.activityIconsModel = loader.loadModel('phase_4/models/parties/eventSignIcons')
        self.decorationModels = loader.loadModel('phase_4/models/parties/partyDecorations')
        pos = self.partyPlanner.gui.find('**/step_05_activitiesIcon_locator').getPos()
        self.elementList = DirectScrolledList(parent=self.parent, relief=None, decButton_image=(self.partyPlanner.gui.find('**/activitiesButtonUp_up'),
         self.partyPlanner.gui.find('**/activitiesButtonUp_down'),
         self.partyPlanner.gui.find('**/activitiesButtonUp_rollover'),
         self.partyPlanner.gui.find('**/activitiesButtonUp_inactive')), decButton_relief=None, decButton_pos=(-0.05, 0.0, -0.38), incButton_image=(self.partyPlanner.gui.find('**/activitiesButtonDown_up'),
         self.partyPlanner.gui.find('**/activitiesButtonDown_down'),
         self.partyPlanner.gui.find('**/activitiesButtonDown_rollover'),
         self.partyPlanner.gui.find('**/activitiesButtonDown_inactive')), incButton_relief=None, incButton_pos=(-0.05, 0.0, -0.94), itemFrame_pos=(pos[0], pos[1], pos[2] + 0.04), itemFrame_relief=None, numItemsVisible=1, items=[])
        holidayIds = base.cr.newsManager.getHolidayIdList()
        isWinter = ToontownGlobals.WINTER_DECORATIONS in holidayIds or ToontownGlobals.WACKY_WINTER_DECORATIONS in holidayIds
        isVictory = ToontownGlobals.VICTORY_PARTY_HOLIDAY in holidayIds
        isValentine = ToontownGlobals.VALENTINES_DAY in holidayIds
        for activityId in PartyGlobals.PartyEditorActivityOrder:
            if not isVictory and activityId in PartyGlobals.VictoryPartyActivityIds or not isWinter and activityId in PartyGlobals.WinterPartyActivityIds or not isValentine and activityId in PartyGlobals.ValentinePartyActivityIds:
                pass
            elif isVictory and activityId in PartyGlobals.VictoryPartyReplacementActivityIds or isWinter and activityId in PartyGlobals.WinterPartyReplacementActivityIds or isValentine and activityId in PartyGlobals.ValentinePartyReplacementActivityIds:
                pass
            else:
                pele = PartyEditorListElement(self, activityId)
                self.elementList.addItem(pele)
                if activityId == PartyGlobals.ActivityIds.PartyClock:
                    self.partyClockElement = pele

        for decorationId in PartyGlobals.DecorationIds:
            if not isVictory and decorationId in PartyGlobals.VictoryPartyDecorationIds or not isWinter and decorationId in PartyGlobals.WinterPartyDecorationIds or not isValentine and decorationId in PartyGlobals.ValentinePartyDecorationIds:
                pass
            elif isVictory and decorationId in PartyGlobals.VictoryPartyReplacementDecorationIds or isValentine and decorationId in PartyGlobals.ValentinePartyReplacementDecorationIds:
                pass
            elif decorationId in PartyGlobals.TTIUnreleasedDecor:
                pass
            else:
                pele = PartyEditorListElement(self, decorationId, isDecoration=True)
                self.elementList.addItem(pele)

        self.elementList.refresh()
        self.elementList['command'] = self.scrollItemChanged
        return

    def initPartyClock(self):
        self.partyClockElement.buyButtonClicked((8, 7))

    def initTrashCan(self):
        trashcanGui = loader.loadModel('phase_3/models/gui/trashcan_gui')
        self.trashCanButton = DirectButton(parent=self.parent, relief=None, pos=Point3(*PartyGlobals.TrashCanPosition), scale=PartyGlobals.TrashCanScale, geom=(trashcanGui.find('**/TrashCan_CLSD'),
         trashcanGui.find('**/TrashCan_OPEN'),
         trashcanGui.find('**/TrashCan_RLVR'),
         trashcanGui.find('**/TrashCan_RLVR')), command=self.trashCanClicked)
        self.trashCanButton.bind(DirectGuiGlobals.ENTER, self.mouseEnterTrash)
        self.trashCanButton.bind(DirectGuiGlobals.EXIT, self.mouseExitTrash)
        self.mouseOverTrash = False
        self.oldInstructionText = ''
        self.trashCanLastClickedTime = 0
        return

    def scrollItemChanged(self):
        if not self.elementList['items']:
            return
        self.currentElement = self.elementList['items'][self.elementList.getSelectedIndex()]
        self.elementList['items'][self.elementList.getSelectedIndex()].elementSelectedFromList()
        if self.elementList['items'][self.elementList.getSelectedIndex()].isDecoration:
            self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsClickedElementDecoration
        else:
            self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsClickedElementActivity

    def listElementClicked(self):
        self.request('DraggingElement')

    def listElementReleased(self):
        self.request('Idle', True)

    def trashCanClicked(self):
        currentTime = time.time()
        if currentTime - self.trashCanLastClickedTime < 0.2:
            self.clearPartyGrounds()
        self.trashCanLastClickedTime = time.time()

    def clearPartyGrounds(self):
        for item in self.elementList['items']:
            item.clearPartyGrounds()

        self.initPartyClock()
        if self.currentElement:
            self.currentElement.checkSoldOutAndPaidStatusAndAffordability()

    def buyCurrentElement(self):
        if self.currentElement:
            purchaseSuccessful = self.currentElement.buyButtonClicked()
            if purchaseSuccessful:
                self.handleMutuallyExclusiveActivities()
            else:
                self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsNoRoom

    def mouseEnterTrash(self, mouseEvent):
        self.mouseOverTrash = True
        self.oldInstructionText = self.partyPlanner.instructionLabel['text']
        self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsTrash

    def mouseExitTrash(self, mouseEvent):
        self.mouseOverTrash = False
        self.partyPlanner.instructionLabel['text'] = self.oldInstructionText

    def enterHidden(self):
        PartyEditor.notify.debug('Enter Hidden')

    def exitHidden(self):
        PartyEditor.notify.debug('Exit Hidden')

    def enterIdle(self, fromDragging = False):
        PartyEditor.notify.debug('Enter Idle')
        if not fromDragging:
            self.elementList.scrollTo(0)
            self.elementList['items'][0].elementSelectedFromList()
            self.currentElement = self.elementList['items'][self.elementList.getSelectedIndex()]
            self.currentElement.checkSoldOutAndPaidStatusAndAffordability()
        self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsIdle
        self.updateCostsAndBank()
        self.handleMutuallyExclusiveActivities()

    def handleMutuallyExclusiveActivities(self):
        mutSet = self.getMutuallyExclusiveActivities()
        if not mutSet:
            return
        currentActivities = self.partyEditorGrid.getActivitiesElementsOnGrid()
        lastActivity = self.partyEditorGrid.lastActivityIdPlaced
        for act in currentActivities:
            if act.id in mutSet and not lastActivity == act.id:
                act.removeFromGrid()
                removedName = TTLocalizer.PartyActivityNameDict[act.id]['editor']
                addedName = TTLocalizer.PartyActivityNameDict[lastActivity]['editor']
                instr = TTLocalizer.PartyPlannerEditorInstructionsRemoved % {'removed': removedName,
                 'added': addedName}
                self.partyPlanner.instructionLabel['text'] = instr
                self.updateCostsAndBank()

    def getMutuallyExclusiveActivities(self):
        currentActivities = self.partyEditorGrid.getActivitiesOnGrid()
        actSet = Set([])
        for act in currentActivities:
            actSet.add(act[0])

        result = None
        for mutuallyExclusiveTuples in PartyGlobals.MutuallyExclusiveActivities:
            mutSet = Set(mutuallyExclusiveTuples)
            inter = mutSet.intersection(actSet)
            if len(inter) > 1:
                result = inter
                break

        return result

    def updateCostsAndBank(self):
        currentActivities = self.partyEditorGrid.getActivitiesOnGrid()
        currentDecorations = self.partyEditorGrid.getDecorationsOnGrid()
        newCost = 0
        for elementTuple in currentActivities:
            newCost += PartyGlobals.ActivityInformationDict[elementTuple[0]]['cost']

        for elementTuple in currentDecorations:
            newCost += PartyGlobals.DecorationInformationDict[elementTuple[0]]['cost']

        self.partyPlanner.costLabel['text'] = TTLocalizer.PartyPlannerTotalCost % newCost
        if len(currentActivities) > 0 or len(currentDecorations) > 0:
            self.partyPlanner.setNextButtonState(enabled=True)
        else:
            self.partyPlanner.setNextButtonState(enabled=False)
        self.partyPlanner.totalCost = newCost
        self.partyPlanner.beanBank['text'] = str(int(self.partyPlanner.totalMoney - self.partyPlanner.totalCost))

    def exitIdle(self):
        PartyEditor.notify.debug('Exit Idle')

    def enterDraggingElement(self):
        PartyEditor.notify.debug('Enter DraggingElement')
        if self.currentElement.isDecoration:
            self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsDraggingDecoration
        else:
            self.partyPlanner.instructionLabel['text'] = TTLocalizer.PartyPlannerEditorInstructionsDraggingActivity

    def exitDraggingElement(self):
        PartyEditor.notify.debug('Exit DraggingElement')

    def enterCleanup(self):
        PartyEditor.notify.debug('Enter Cleanup')
        self.partyEditorGrid.destroy()
        self.elementList.removeAndDestroyAllItems()
        self.elementList.destroy()
        self.trashCanButton.unbind(DirectGuiGlobals.ENTER)
        self.trashCanButton.unbind(DirectGuiGlobals.EXIT)
        self.trashCanButton.destroy()

    def exitCleanup(self):
        PartyEditor.notify.debug('Exit Cleanup')
Ejemplo n.º 4
0
class NamePage(StateData):
    notify = directNotify.newCategory('NamePage')

    def __init__(self, book, parentFSM):
        self.book = book
        self.parentFSM = parentFSM
        StateData.__init__(self, 'namePageDone')
        self.fsm = ClassicFSM('NamePage', [
            State('off', self.enterOff, self.exitOff),
            State('basePage', self.enterBasePage, self.exitBasePage)
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.parentFSM.getStateNamed('namePage').addChild(self.fsm)
        self.nameServ = base.cr.nameServicesManager
        self.baseRequestIndex = 0
        self.requestsPerCluster = 5
        self.requestsContainer = {}
        self.loadingLabel = None
        self.selectedName = None
        self.nameButtons = []
        self.avId2NameData = {}
        geom = CIGlobals.getDefaultBtnGeom()
        self.acceptBtn = DirectButton(geom=geom,
                                      text_scale=0.04,
                                      relief=None,
                                      scale=0.5,
                                      text='Accept',
                                      pos=(0.5, posY, 0),
                                      text_pos=(0, -0.01),
                                      command=self.acceptName)
        self.acceptBtn.hide()
        self.declineBtn = DirectButton(geom=geom,
                                       text_scale=0.04,
                                       relief=None,
                                       scale=0.5,
                                       text='Decline',
                                       pos=(0.75, posY, 0),
                                       text_pos=(0, -0.01),
                                       command=self.declineName)
        self.declineBtn.hide()
        self.avIdLbl = OnscreenText(text='',
                                    scale=0.08,
                                    pos=(0.3, 0, 0.5),
                                    align=TextNode.ACenter)
        self.avIdLbl.hide()
        self.accIdLbl = OnscreenText(text='',
                                     scale=0.08,
                                     pos=(0.3, 0, 0.3),
                                     align=TextNode.ACenter)
        self.accIdLbl.hide()
        return

    def handleRequests(self):
        gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        self.nameList = DirectScrolledList(
            relief=None,
            pos=(-0.54, 0, 0.08),
            incButton_image=(gui.find('**/FndsLst_ScrollUp'),
                             gui.find('**/FndsLst_ScrollDN'),
                             gui.find('**/FndsLst_ScrollUp_Rllvr'),
                             gui.find('**/FndsLst_ScrollUp')),
            incButton_relief=None,
            incButton_scale=(arrowButtonScale, arrowButtonScale,
                             -arrowButtonScale),
            incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999),
            incButton_image3_color=Vec4(1, 1, 1, 0.2),
            incButton_command=self.__moveItems,
            incButton_extraArgs=[1],
            decButton_image=(gui.find('**/FndsLst_ScrollUp'),
                             gui.find('**/FndsLst_ScrollDN'),
                             gui.find('**/FndsLst_ScrollUp_Rllvr'),
                             gui.find('**/FndsLst_ScrollUp')),
            decButton_relief=None,
            decButton_scale=(arrowButtonScale, arrowButtonScale,
                             arrowButtonScale),
            decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125),
            decButton_image3_color=Vec4(1, 1, 1, 0.2),
            decButton_command=self.__moveItems,
            decButton_extraArgs=[0],
            itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin),
            itemFrame_scale=1.0,
            itemFrame_relief=DGG.SUNKEN,
            itemFrame_frameSize=(listXorigin, listXorigin + listFrameSizeX,
                                 listZorigin, listZorigin + listFrameSizeZ),
            itemFrame_frameColor=(0.85, 0.95, 1, 1),
            itemFrame_borderWidth=(0.01, 0.01),
            numItemsVisible=5,
            forceHeight=0.075,
            items=self.nameButtons)
        self.__buildItems()
        return

    def __moveItems(self, direction):
        if direction == 0:
            self.baseRequestIndex += 1
        else:
            if direction == 1:
                self.baseRequestIndex -= 1
        self.clearItems()
        self.__buildItems()

    def clearItems(self):
        for btn in self.nameButtons:
            btn.destroy()

        self.nameButtons = []
        self.nameList.removeAndDestroyAllItems()

    def __buildItems(self):
        for i in xrange(self.requestsPerCluster):
            request = self.nameServ.getNameRequests()[self.baseRequestIndex +
                                                      i]
            date = request['date']
            date = date.replace(' ', '-')
            data = NameData(request['name'], date, request['avId'],
                            request['accId'])
            self.avId2NameData[data.avId] = data
            btn = DirectButton(relief=None,
                               text=data.name,
                               text_scale=0.07,
                               text_align=TextNode.ALeft,
                               text1_bg=textDownColor,
                               text2_bg=textRolloverColor,
                               text3_fg=textDisabledColor,
                               textMayChange=0,
                               command=self.__handleNameButton,
                               extraArgs=[data],
                               text_pos=(0, 0, 0.0))
            data.btn = btn
            self.nameButtons.append(btn)

        self.loadingLabel.hide()
        return

    def __handleNameButton(self, data):
        self.selectedName = data
        data.btn['state'] = DGG.DISABLED
        self.avIdLbl.setText('Avatar ID:\n' + str(data.avId))
        self.avIdLbl.show()
        self.accIdLbl.setText('Account ID:\n' + str(data.accId))
        self.accIdLbl.show()
        self.acceptBtn.show()
        self.declineBtn.show()

    def acceptName(self):
        pass

    def load(self):
        StateData.load(self)
        self.loadingLabel = OnscreenText(text='Loading...',
                                         font=CIGlobals.getToonFont(),
                                         pos=(0, 0.1, 0),
                                         scale=0.08,
                                         parent=aspect2d)

    def unload(self):
        StateData.unload(self)
        self.loadingLabel.destroy()
        self.loadingLabel = None
        for request in self.requestsContainer.values():
            for element in request:
                element.destroy()

        self.requestsContainer = {}
        return

    def enter(self):
        StateData.enter(self)
        self.fsm.request('basePage')
        base.acceptOnce(self.nameServ.getRequestCompleteName(),
                        self.handleRequests)
        self.nameServ.d_requestNameData()

    def exit(self):
        self.fsm.requestFinalState()
        StateData.exit(self)

    def enterBasePage(self):
        self.book.createPageButtons('adminPage', None)
        self.book.setTitle('Name Approval')
        return

    def exitBasePage(self):
        self.book.deletePageButtons(True, False)
        self.book.clearTitle()

    def enterOff(self):
        pass

    def exitOff(self):
        pass
Ejemplo n.º 5
0
class CalendarGuiDay(DirectFrame):
    notify = directNotify.newCategory('CalendarGuiDay')
    ScrollListTextSize = 0.03

    def __init__(self,
                 parent,
                 myDate,
                 startDate,
                 dayClickCallback=None,
                 onlyFutureDaysClickable=False):
        self.origParent = parent
        self.startDate = startDate
        self.myDate = myDate
        self.dayClickCallback = dayClickCallback
        self.onlyFutureDaysClickable = onlyFutureDaysClickable
        DirectFrame.__init__(self, parent=parent)
        self.timedEvents = []
        self.partiesInvitedToToday = []
        self.hostedPartiesToday = []
        self.yearlyHolidaysToday = []
        self.showMarkers = base.config.GetBool('show-calendar-markers', 0)
        self.filter = ToontownGlobals.CalendarFilterShowAll
        self.load()
        self.createGuiObjects()
        self.update()

    def createDummyLocators(self):
        self.dayButtonLocator = self.attachNewNode('dayButtonLocator')
        self.dayButtonLocator.setX(0.1)
        self.dayButtonLocator.setZ(-0.05)
        self.numberLocator = self.attachNewNode('numberLocator')
        self.numberLocator.setX(0.09)
        self.scrollLocator = self.attachNewNode('scrollLocator')
        self.selectedLocator = self.attachNewNode('selectedLocator')
        self.selectedLocator.setX(0.11)
        self.selectedLocator.setZ(-0.06)

    def load(self):
        dayAsset = loader.loadModel(
            'phase_4/models/parties/tt_m_gui_sbk_calendar_box')
        dayAsset.reparentTo(self)
        self.dayButtonLocator = self.find('**/loc_origin')
        self.numberLocator = self.find('**/loc_number')
        self.scrollLocator = self.find('**/loc_topLeftList')
        self.selectedLocator = self.find('**/loc_origin')
        self.todayBox = self.find('**/boxToday')
        self.todayBox.hide()
        self.selectedFrame = self.find('**/boxHover')
        self.selectedFrame.hide()
        self.defaultBox = self.find('**/boxBlank')
        self.scrollBottomRightLocator = self.find('**/loc_bottomRightList')
        self.scrollDownLocator = self.find('**/loc_scrollDown')
        self.attachMarker(self.scrollDownLocator)
        self.scrollUpLocator = self.find('**/loc_scrollUp')
        self.attachMarker(self.scrollUpLocator)

    def attachMarker(self, parent, scale=0.005, 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 createGuiObjects(self):
        self.dayButton = DirectButton(parent=self.dayButtonLocator,
                                      image=self.selectedFrame,
                                      relief=None,
                                      command=self.__clickedOnDay,
                                      pressEffect=1,
                                      rolloverSound=None,
                                      clickSound=None)
        self.numberWidget = DirectLabel(
            parent=self.numberLocator,
            relief=None,
            text=str(self.myDate.day),
            text_scale=0.04,
            text_align=TextNode.ACenter,
            text_font=ToontownGlobals.getInterfaceFont(),
            text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1))
        self.attachMarker(self.numberLocator)
        self.listXorigin = 0
        self.listFrameSizeX = self.scrollBottomRightLocator.getX(
        ) - self.scrollLocator.getX()
        self.scrollHeight = self.scrollLocator.getZ(
        ) - self.scrollBottomRightLocator.getZ()
        self.listZorigin = self.scrollBottomRightLocator.getZ()
        self.listFrameSizeZ = self.scrollLocator.getZ(
        ) - self.scrollBottomRightLocator.getZ()
        self.arrowButtonXScale = 1
        self.arrowButtonZScale = 1
        self.itemFrameXorigin = 0
        self.itemFrameZorigin = 0
        self.buttonXstart = self.itemFrameXorigin + 0.21
        self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
        buttonOffSet = -0.01
        incButtonPos = (0.0, 0, 0)
        decButtonPos = (0.0, 0, 0)
        itemFrameMinZ = self.listZorigin
        itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ
        arrowUp = self.find('**/downScroll_up')
        arrowDown = self.find('**/downScroll_down')
        arrowHover = self.find('**/downScroll_hover')
        self.scrollList = DirectScrolledList(
            parent=self.scrollLocator,
            relief=None,
            pos=(0, 0, 0),
            incButton_image=(arrowUp, arrowDown, arrowHover, arrowUp),
            incButton_relief=None,
            incButton_scale=(self.arrowButtonXScale, 1,
                             self.arrowButtonZScale),
            incButton_pos=incButtonPos,
            incButton_image3_color=Vec4(1, 1, 1, 0.2),
            decButton_image=(arrowUp, arrowDown, arrowHover, arrowUp),
            decButton_relief=None,
            decButton_scale=(self.arrowButtonXScale, 1,
                             -self.arrowButtonZScale),
            decButton_pos=decButtonPos,
            decButton_image3_color=Vec4(1, 1, 1, 0.2),
            itemFrame_pos=(self.itemFrameXorigin, 0, -0.03),
            numItemsVisible=4,
            incButtonCallback=self.scrollButtonPressed,
            decButtonCallback=self.scrollButtonPressed)
        itemFrameParent = self.scrollList.itemFrame.getParent()
        self.scrollList.incButton.reparentTo(self.scrollDownLocator)
        self.scrollList.decButton.reparentTo(self.scrollUpLocator)
        arrowUp.removeNode()
        arrowDown.removeNode()
        arrowHover.removeNode()
        clipper = PlaneNode('clipper')
        clipper.setPlane(Plane(Vec3(-1, 0, 0), Point3(0.23, 0, 0)))
        clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper)
        self.scrollList.component('itemFrame').setClipPlane(clipNP)
        return

    def scrollButtonPressed(self):
        self.__clickedOnDay()

    def adjustForMonth(self):
        curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
        if self.onlyFutureDaysClickable:
            if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day:
                self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5)
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
            else:
                self.numberWidget.setColorScale(1, 1, 1, 1)
        if self.myDate.month != self.startDate.month:
            self.setColorScale(0.75, 0.75, 0.75, 1.0)
            if self.dayClickCallback is not None:
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
        else:
            self.setColorScale(1, 1, 1, 1)
        if self.myDate.date() == curServerDate.date():
            self.defaultBox.hide()
            self.todayBox.show()
        else:
            self.defaultBox.show()
            self.todayBox.hide()
        return

    def destroy(self):
        if self.dayClickCallback is not None:
            self.numberWidget.destroy()
        self.dayClickCallback = None
        self.notify.debug('desroying %s' % self.myDate)
        try:
            for item in self.scrollList['items']:
                if hasattr(item,
                           'description') and item.description and hasattr(
                               item.description, 'destroy'):
                    self.notify.debug('desroying description of item %s' %
                                      item)
                    item.unbind(DGG.ENTER)
                    item.unbind(DGG.EXIT)
                    item.description.destroy()

        except e:
            self.notify.debug('pass %s' % self.myDate)

        self.scrollList.removeAndDestroyAllItems()
        self.scrollList.destroy()
        self.dayButton.destroy()
        DirectFrame.destroy(self)
        return

    def addWeeklyHolidays(self):
        if not self.filter == ToontownGlobals.CalendarFilterShowAll and not self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays:
            return
        if base.cr.newsManager:
            holidays = base.cr.newsManager.getHolidaysForWeekday(
                self.myDate.weekday())
            holidayName = ''
            holidayDesc = ''
            for holidayId in holidays:
                if holidayId in TTLocalizer.HolidayNamesInCalendar:
                    holidayName = TTLocalizer.HolidayNamesInCalendar[
                        holidayId][0]
                    holidayDesc = TTLocalizer.HolidayNamesInCalendar[
                        holidayId][1]
                else:
                    holidayName = TTLocalizer.UnknownHoliday % holidayId
                self.addTitleAndDescToScrollList(holidayName, holidayDesc)

            self.scrollList.refresh()
        if base.config.GetBool('calendar-test-items', 0):
            if self.myDate.date() + datetime.timedelta(
                    days=-1
            ) == base.cr.toontownTimeManager.getCurServerDateTime().date():
                testItems = ('1:00 AM Party', '2:00 AM CEO', '11:15 AM Party',
                             '5:30 PM CJ', '11:00 PM Party',
                             'Really Really Long String')
                for text in testItems:
                    newItem = DirectLabel(relief=None,
                                          text=text,
                                          text_scale=self.ScrollListTextSize,
                                          text_align=TextNode.ALeft)
                    self.scrollList.addItem(newItem)

            if self.myDate.date() + datetime.timedelta(
                    days=-2
            ) == base.cr.toontownTimeManager.getCurServerDateTime().date():
                testItems = ('1:00 AM Party', '3:00 AM CFO', '11:00 AM Party')
                textSize = self.ScrollListTextSize
                for text in testItems:
                    newItem = DirectLabel(relief=None,
                                          text=text,
                                          text_scale=textSize,
                                          text_align=TextNode.ALeft)
                    self.scrollList.addItem(newItem)

    def updateArrowButtons(self):
        numItems = 0
        try:
            numItems = len(self.scrollList['items'])
        except e:
            numItems = 0

        if numItems <= self.scrollList.numItemsVisible:
            self.scrollList.incButton.hide()
            self.scrollList.decButton.hide()
        else:
            self.scrollList.incButton.show()
            self.scrollList.decButton.show()

    def collectTimedEvents(self):
        self.timedEvents = []
        if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties:
            for party in localAvatar.partiesInvitedTo:
                if party.startTime.date() == self.myDate.date():
                    self.partiesInvitedToToday.append(party)
                    self.timedEvents.append((party.startTime.time(), party))

            for party in localAvatar.hostedParties:
                if party.startTime.date() == self.myDate.date():
                    self.hostedPartiesToday.append(party)
                    self.timedEvents.append((party.startTime.time(), party))

        if base.cr.newsManager and (
                self.filter == ToontownGlobals.CalendarFilterShowAll or
                self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays):
            yearlyHolidays = base.cr.newsManager.getYearlyHolidaysForDate(
                self.myDate)
            for holiday in yearlyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.month and holidayStart[
                        1] == self.myDate.day:
                    myTime = datetime.time(holidayStart[2], holidayStart[3])
                elif holidayEnd[0] == self.myDate.month and holidayEnd[
                        1] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[2], holidayEnd[3])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            oncelyHolidays = base.cr.newsManager.getOncelyHolidaysForDate(
                self.myDate)
            for holiday in oncelyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.year and holidayStart[
                        1] == self.myDate.month and holidayStart[
                            2] == self.myDate.day:
                    myTime = datetime.time(holidayStart[3], holidayStart[4])
                elif holidayEnd[0] == self.myDate.year and holidayEnd[
                        1] == self.myDate.month and holidayEnd[
                            2] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[3], holidayEnd[4])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            multipleStartHolidays = base.cr.newsManager.getMultipleStartHolidaysForDate(
                self.myDate)
            for holiday in multipleStartHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.year and holidayStart[
                        1] == self.myDate.month and holidayStart[
                            2] == self.myDate.day:
                    myTime = datetime.time(holidayStart[3], holidayStart[4])
                elif holidayEnd[0] == self.myDate.year and holidayEnd[
                        1] == self.myDate.month and holidayEnd[
                            2] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[3], holidayEnd[4])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            relativelyHolidays = base.cr.newsManager.getRelativelyHolidaysForDate(
                self.myDate)
            for holiday in relativelyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.month and holidayStart[
                        1] == self.myDate.day:
                    myTime = datetime.time(holidayStart[2], holidayStart[3])
                elif holidayEnd[0] == self.myDate.month and holidayEnd[
                        1] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[2], holidayEnd[3])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

        def timedEventCompare(te1, te2):
            if te1[0] < te2[0]:
                return -1
            elif te1[0] == te2[0]:
                return 0
            else:
                return 1

        self.timedEvents.sort(cmp=timedEventCompare)
        for timedEvent in self.timedEvents:
            if isinstance(timedEvent[1], PartyInfo):
                self.addPartyToScrollList(timedEvent[1])
            elif isinstance(
                    timedEvent[1], tuple
            ) and timedEvent[1][0] == NewsManager.YearlyHolidayType:
                self.addYearlyHolidayToScrollList(timedEvent[1])
            elif isinstance(
                    timedEvent[1], tuple
            ) and timedEvent[1][0] == NewsManager.OncelyHolidayType:
                self.addOncelyHolidayToScrollList(timedEvent[1])
            elif isinstance(timedEvent[1], tuple) and timedEvent[1][
                    0] == NewsManager.OncelyMultipleStartHolidayType:
                self.addOncelyMultipleStartHolidayToScrollList(timedEvent[1])
            elif isinstance(
                    timedEvent[1], tuple
            ) and timedEvent[1][0] == NewsManager.RelativelyHolidayType:
                self.addRelativelyHolidayToScrollList(timedEvent[1])

    def addYearlyHolidayToScrollList(self, holiday):
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ''
        startTime = datetime.time(holidayStart[2], holidayStart[3])
        endTime = datetime.time(holidayEnd[2], holidayEnd[3])
        startDate = datetime.date(self.myDate.year, holidayStart[0],
                                  holidayStart[1])
        endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1])
        if endDate < startDate:
            endDate = datetime.date(endDate.year + 1, endDate.month,
                                    endDate.day)
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = TTLocalizer.UnknownHoliday % holidayId
        if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[
                1]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(
                endTime)
        elif self.myDate.month == holidayStart[
                0] and self.myDate.day == holidayStart[1]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc = holidayName + '. ' + holidayDesc
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.month == holidayEnd[
                0] and self.myDate.day == holidayEnd[1]:
            holidayText = myStrftime(endTime)
            holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(startTime)
        else:
            self.notify.error('unhandled case')
        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addOncelyHolidayToScrollList(self, holiday):
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ''
        startTime = datetime.time(holidayStart[3], holidayStart[4])
        endTime = datetime.time(holidayEnd[3], holidayEnd[4])
        startDate = datetime.date(holidayStart[0], holidayStart[1],
                                  holidayStart[2])
        endDate = datetime.date(holidayStart[0], holidayEnd[1], holidayEnd[2])
        if endDate < startDate:
            endDate = datetime.date(endDate.year + 1, endDate.month,
                                    endDate.day)
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = ''
        if holidayStart[1] == holidayEnd[1] and holidayStart[2] == holidayEnd[
                2]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc = holidayName + '. ' + holidayDesc
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(
                endTime)
        elif self.myDate.year == holidayStart[
                0] and self.myDate.month == holidayStart[
                    1] and self.myDate.day == holidayStart[2]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc = holidayName + '. ' + holidayDesc
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.year == holidayEnd[
                0] and self.myDate.month == holidayEnd[
                    1] and self.myDate.day == holidayEnd[2]:
            holidayText = myStrftime(endTime)
            holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(startTime)
        else:
            self.notify.error('unhandled case')
        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addOncelyMultipleStartHolidayToScrollList(self, holiday):
        self.addOncelyHolidayToScrollList(holiday)

    def addRelativelyHolidayToScrollList(self, holiday):
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ''
        startTime = datetime.time(holidayStart[2], holidayStart[3])
        endTime = datetime.time(holidayEnd[2], holidayEnd[3])
        startDate = datetime.date(self.myDate.year, holidayStart[0],
                                  holidayStart[1])
        endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1])
        if endDate < startDate:
            endDate.year += 1
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = ''
        if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[
                1]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(
                endTime)
        elif self.myDate.month == holidayStart[
                0] and self.myDate.day == holidayStart[1]:
            holidayText = myStrftime(startTime)
            holidayText += ' ' + holidayName
            holidayDesc = holidayName + '. ' + holidayDesc
            holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.month == holidayEnd[
                0] and self.myDate.day == holidayEnd[1]:
            holidayText = myStrftime(endTime)
            holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(startTime)
        else:
            self.notify.error('unhandled case')
        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addTitleAndDescToScrollList(self, title, desc):
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(relief=None,
                               text=title,
                               text_scale=textSize,
                               text_align=TextNode.ALeft,
                               rolloverSound=None,
                               clickSound=None,
                               pressEffect=0,
                               command=self.__clickedOnScrollItem)
        scrollItemHeight = newItem.getHeight()
        descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
        descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
        descUnderItemZAdjust = -descUnderItemZAdjust
        descZAdjust = descUnderItemZAdjust
        newItem.description = DirectLabel(parent=newItem,
                                          pos=(0.115, 0, descZAdjust),
                                          text='',
                                          text_wordwrap=15,
                                          pad=(0.02, 0.02),
                                          text_scale=descTextSize,
                                          text_align=TextNode.ACenter,
                                          textMayChange=0)
        newItem.description.checkedHeight = False
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()
        newItem.bind(DGG.ENTER,
                     self.enteredTextItem,
                     extraArgs=[newItem, desc, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
        self.scrollList.addItem(newItem)
        return

    def exitedTextItem(self, newItem, mousepos):
        newItem.description.hide()

    def enteredTextItem(self, newItem, descText, descUnderItemZAdjust,
                        mousePos):
        if not newItem.description.checkedHeight:
            newItem.description.checkedHeight = True
            newItem.description['text'] = descText
            bounds = newItem.description.getBounds()
            descHeight = newItem.description.getHeight()
            scrollItemHeight = newItem.getHeight()
            descOverItemZAdjust = descHeight - scrollItemHeight / 2.0
            descZPos = self.getPos(
                aspect2d)[2] + descUnderItemZAdjust - descHeight
            if descZPos < -1.0:
                newItem.description.setZ(descOverItemZAdjust)
            descWidth = newItem.description.getWidth()
            brightFrame = loader.loadModel(
                'phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg')
            newItem.description['geom'] = brightFrame
            newItem.description['geom_scale'] = (descWidth, 1, descHeight)
            descGeomZ = (bounds[2] - bounds[3]) / 2.0
            descGeomZ += bounds[3]
            newItem.description['geom_pos'] = (0, 0, descGeomZ)
        newItem.description.show()

    def addPartyToScrollList(self, party):
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        partyTitle = myStrftime(party.startTime)
        partyTitle = partyTitle + ' ' + TTLocalizer.EventsPageCalendarTabParty
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(relief=None,
                               text=partyTitle,
                               text_scale=textSize,
                               text_align=TextNode.ALeft,
                               rolloverSound=None,
                               clickSound=None,
                               pressEffect=0,
                               command=self.__clickedOnScrollItem)
        scrollItemHeight = newItem.getHeight()
        descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
        descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
        descUnderItemZAdjust = -descUnderItemZAdjust
        descZAdjust = descUnderItemZAdjust
        self.scrollList.addItem(newItem)
        newItem.description = MiniInviteVisual(newItem, party)
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()
        newItem.bind(
            DGG.ENTER,
            self.enteredTextItem,
            extraArgs=[newItem, newItem.description, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
        return

    def __clickedOnScrollItem(self):
        self.__clickedOnDay()

    def __clickedOnDay(self):
        acceptClick = True
        if self.onlyFutureDaysClickable:
            curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
            if self.myDate.date() < curServerDate.date():
                acceptClick = False
        if not acceptClick:
            return
        if self.dayClickCallback:
            self.dayClickCallback(self)
        self.notify.debug('we got clicked on %s' % self.myDate.date())
        messenger.send('clickedOnDay', [self.myDate.date()])

    def updateSelected(self, selected):
        multiplier = 1.1
        if selected:
            self.selectedFrame.show()
            self.setScale(multiplier)
            self.setPos(-0.01, 0, 0.01)
            grandParent = self.origParent.getParent()
            self.origParent.reparentTo(grandParent)
        else:
            self.selectedFrame.hide()
            self.setScale(1.0)
            self.setPos(0, 0, 0)

    def changeDate(self, startDate, myDate):
        self.startDate = startDate
        self.myDate = myDate
        self.scrollList.removeAndDestroyAllItems()
        self.update()

    def update(self):
        self.numberWidget['text'] = str(self.myDate.day)
        self.adjustForMonth()
        self.addWeeklyHolidays()
        self.collectTimedEvents()
        self.updateArrowButtons()

    def changeFilter(self, filter):
        oldFilter = self.filter
        self.filter = filter
        if self.filter != oldFilter:
            self.scrollList.removeAndDestroyAllItems()
            self.update()
class FriendsList(DirectFrame):
    notify = DirectNotifyGlobal.directNotify.newCategory("FriendsList")

    GRAYED_OUT_COLOR = (128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 1.0)
    NORMAL_COLOR = (1.0, 1.0, 1.0, 1.0)

    def __init__(self):
        DirectFrame.__init__(self,
                             parent=base.a2dTopRight,
                             pos=(-0.2235, 0.0, -0.457))
        gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        self['image'] = gui.find('**/FriendsBox_Open')

        self.headingText = OnscreenText(text="",
                                        parent=self,
                                        pos=(0.01, 0.2),
                                        fg=(0.1, 0.1, 0.4, 1.0),
                                        scale=0.04)

        self.frameForNames = DirectScrolledList(
            frameSize=(0.0, 0.35, 0, 0.35),
            incButton_geom=(gui.find('**/FndsLst_ScrollUp'),
                            gui.find('**/FndsLst_ScrollDN'),
                            gui.find('**/FndsLst_ScrollUp_Rllvr'),
                            gui.find('**/FndsLst_ScrollUp')),
            incButton_relief=None,
            incButton_hpr=(0, 0, 180),
            incButton_pos=(0.17, 0, -0.04),
            decButton_geom=(gui.find('**/FndsLst_ScrollUp'),
                            gui.find('**/FndsLst_ScrollDN'),
                            gui.find('**/FndsLst_ScrollUp_Rllvr'),
                            gui.find('**/FndsLst_ScrollUp')),
            decButton_relief=None,
            decButton_pos=(0.17, 0, 0.395),
            pos=(-0.1625, 0.0, -0.27),
            parent=self,
            numItemsVisible=9,
            forceHeight=0.04,
            itemFrame_frameSize=(-0.15, 0.15, 0, -0.35),
            itemFrame_pos=(0, 0, 0.3275),
            itemFrame_relief=None,
            relief=None)

        self.fwdBtn = CIGlobals.makeDirectionalBtn(1,
                                                   self, (0.17, 0.0, -0.38),
                                                   command=self.doState)
        self.backBtn = CIGlobals.makeDirectionalBtn(0,
                                                    self, (-0.15, 0.0, -0.38),
                                                    command=self.doState)

        self.closeBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(),
                                     relief=None,
                                     parent=self,
                                     command=self.exitClicked)
        self.closeBtn.setPos(0.015, 0.0, -0.375)

        gui.removeNode()
        del gui

        self.hide()

        self.friends = {}
        self.onlineFriends = {}

        self.fsm = ClassicFSM.ClassicFSM('FriendsList', [
            State.State('off', self.enterOff, self.exitOff),
            State.State('onlineFriendsList', self.enterOnlineFriendsList,
                        self.exitOnlineFriendsList),
            State.State('allFriendsList', self.enterAllFriendsList,
                        self.exitAllFriendsList)
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.accept('gotFriendsList', self.handleFriendsList)

    def destroy(self):
        self.ignore('gotFriendsList')
        self.fsm.requestFinalState()
        del self.fsm
        self.headingText.destroy()
        del self.headingText
        self.frameForNames.destroy()
        del self.frameForNames
        self.fwdBtn.destroy()
        del self.fwdBtn
        self.backBtn.destroy()
        del self.backBtn
        self.closeBtn.destroy()
        del self.closeBtn
        del self.friends
        del self.onlineFriends
        DirectFrame.destroy(self)

    def doState(self, state):
        self.fsm.request(state)

    def exitClicked(self):
        self.fsm.request('off')
        base.localAvatar.showFriendButton()

    def setButtons(self, fwd=None, back=None):
        if fwd:
            self.fwdBtn['extraArgs'] = [fwd]
            self.fwdBtn['state'] = DGG.NORMAL
            self.fwdBtn.setColorScale(self.NORMAL_COLOR)
        else:
            self.fwdBtn['extraArgs'] = []
            self.fwdBtn['state'] = DGG.DISABLED
            self.fwdBtn.setColorScale(self.GRAYED_OUT_COLOR)

        if back:
            self.backBtn['extraArgs'] = [back]
            self.backBtn['state'] = DGG.NORMAL
            self.backBtn.setColorScale(self.NORMAL_COLOR)
        else:
            self.backBtn['extraArgs'] = []
            self.backBtn['state'] = DGG.DISABLED
            self.backBtn.setColorScale(self.GRAYED_OUT_COLOR)

        if self.frameForNames.incButton['state'] == DGG.DISABLED:
            self.frameForNames.incButton.setColorScale(self.GRAYED_OUT_COLOR)
        else:
            self.frameForNames.incButton.setColorScale(self.NORMAL_COLOR)

        if self.frameForNames.decButton['state'] == DGG.DISABLED:
            self.frameForNames.decButton.setColorScale(self.GRAYED_OUT_COLOR)
        else:
            self.frameForNames.decButton.setColorScale(self.NORMAL_COLOR)

    def handleFriendsList(self, friendIdArray, nameArray, flags, accessLevels):
        self.friends = {}
        self.onlineFriends = {}
        for i in xrange(len(friendIdArray)):
            avatarId = friendIdArray[i]
            name = nameArray[i]
            accessLevel = accessLevels[i]
            self.friends[avatarId] = [name, accessLevel]
            if flags[i] == 1:
                # This friend is online
                self.onlineFriends[avatarId] = [name, accessLevel]

    def enterOff(self):
        self.hide()

    def exitOff(self):
        self.show()

    def addFriend(self, name, avatarId, accessLevel):
        text_fg = AdminCommands.Roles.get(
            accessLevel
        ).token.color if accessLevel > AdminCommands.NoAccess else (0, 0, 0, 1)
        self.frameForNames.addItem(
            DirectButton(text=name,
                         extraArgs=[avatarId],
                         command=self.friendClicked,
                         scale=0.035,
                         relief=None,
                         text_fg=text_fg,
                         text1_bg=textDownColor,
                         text2_bg=textRolloverColor,
                         text_align=TextNode.ALeft))

    def friendClicked(self, avatarId):
        base.localAvatar.panel.makePanel(avatarId)

    def maybeShowList(self):
        if self.isHidden() and self.fsm.getCurrentState().getName() != 'off':
            base.localAvatar.hideFriendButton()
            self.show()

    def resetAll(self):
        self.headingText.setText("")
        self.frameForNames.removeAndDestroyAllItems()
        self.setButtons(None, None)

    def sortListItems(self):
        self.frameForNames['items'].sort(key=lambda x: x['text'])
        self.frameForNames.refresh()

    def enterAllFriendsList(self):
        self.headingText.setText("ALL\nFRIENDS")
        for friendId, data in self.friends.items():
            name = data[0]
            accessLevel = data[1]
            self.addFriend(name, friendId, accessLevel)
        self.sortListItems()
        self.setButtons(None, 'onlineFriendsList')

    def exitAllFriendsList(self):
        self.resetAll()

    def enterOnlineFriendsList(self):
        self.headingText.setText("ONLINE\nFRIENDS")
        for friendId, data in self.onlineFriends.items():
            name = data[0]
            accessLevel = data[1]
            self.addFriend(name, friendId, accessLevel)
        self.sortListItems()
        self.setButtons('allFriendsList', None)

    def exitOnlineFriendsList(self):
        self.resetAll()
class CalendarGuiDay(DirectFrame):
    notify = directNotify.newCategory('CalendarGuiDay')
    ScrollListTextSize = 0.03

    def __init__(self, parent, myDate, startDate, dayClickCallback = None, onlyFutureDaysClickable = False):
        self.origParent = parent
        self.startDate = startDate
        self.myDate = myDate
        self.dayClickCallback = dayClickCallback
        self.onlyFutureDaysClickable = onlyFutureDaysClickable
        DirectFrame.__init__(self, parent=parent)
        self.timedEvents = []
        self.partiesInvitedToToday = []
        self.hostedPartiesToday = []
        self.yearlyHolidaysToday = []
        self.showMarkers = base.config.GetBool('show-calendar-markers', 0)
        self.filter = ToontownGlobals.CalendarFilterShowAll
        self.load()
        self.createGuiObjects()
        self.update()

    def createDummyLocators(self):
        self.dayButtonLocator = self.attachNewNode('dayButtonLocator')
        self.dayButtonLocator.setX(0.1)
        self.dayButtonLocator.setZ(-0.05)
        self.numberLocator = self.attachNewNode('numberLocator')
        self.numberLocator.setX(0.09)
        self.scrollLocator = self.attachNewNode('scrollLocator')
        self.selectedLocator = self.attachNewNode('selectedLocator')
        self.selectedLocator.setX(0.11)
        self.selectedLocator.setZ(-0.06)

    def load(self):
        dayAsset = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_box')
        dayAsset.reparentTo(self)
        self.dayButtonLocator = self.find('**/loc_origin')
        self.numberLocator = self.find('**/loc_number')
        self.scrollLocator = self.find('**/loc_topLeftList')
        self.selectedLocator = self.find('**/loc_origin')
        self.todayBox = self.find('**/boxToday')
        self.todayBox.hide()
        self.selectedFrame = self.find('**/boxHover')
        self.selectedFrame.hide()
        self.defaultBox = self.find('**/boxBlank')
        self.scrollBottomRightLocator = self.find('**/loc_bottomRightList')
        self.scrollDownLocator = self.find('**/loc_scrollDown')
        self.attachMarker(self.scrollDownLocator)
        self.scrollUpLocator = self.find('**/loc_scrollUp')
        self.attachMarker(self.scrollUpLocator)

    def attachMarker(self, parent, scale = 0.005, 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 createGuiObjects(self):
        self.dayButton = DirectButton(parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, pressEffect=1, rolloverSound=None, clickSound=None)
        self.numberWidget = DirectLabel(parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1))
        self.attachMarker(self.numberLocator)
        self.listXorigin = 0
        self.listFrameSizeX = self.scrollBottomRightLocator.getX() - self.scrollLocator.getX()
        self.scrollHeight = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ()
        self.listZorigin = self.scrollBottomRightLocator.getZ()
        self.listFrameSizeZ = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ()
        self.arrowButtonXScale = 1
        self.arrowButtonZScale = 1
        self.itemFrameXorigin = 0
        self.itemFrameZorigin = 0
        self.buttonXstart = self.itemFrameXorigin + 0.21
        self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
        buttonOffSet = -0.01
        incButtonPos = (0.0, 0, 0)
        decButtonPos = (0.0, 0, 0)
        itemFrameMinZ = self.listZorigin
        itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ
        arrowUp = self.find('**/downScroll_up')
        arrowDown = self.find('**/downScroll_down')
        arrowHover = self.find('**/downScroll_hover')
        self.scrollList = DirectScrolledList(parent=self.scrollLocator, relief=None, pos=(0, 0, 0), incButton_image=(arrowUp,
         arrowDown,
         arrowHover,
         arrowUp), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, incButton_image3_color=(1, 1, 1, 0.2), decButton_image=(arrowUp,
         arrowDown,
         arrowHover,
         arrowUp), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, decButton_image3_color=(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), numItemsVisible=4, incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed)
        itemFrameParent = self.scrollList.itemFrame.getParent()
        self.scrollList.incButton.reparentTo(self.scrollDownLocator)
        self.scrollList.decButton.reparentTo(self.scrollUpLocator)
        arrowUp.removeNode()
        arrowDown.removeNode()
        arrowHover.removeNode()
        clipper = PlaneNode('clipper')
        clipper.setPlane(Plane((-1, 0, 0), (0.23, 0, 0)))
        clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper)
        self.scrollList.component('itemFrame').setClipPlane(clipNP)
        return

    def scrollButtonPressed(self):
        self.__clickedOnDay()

    def adjustForMonth(self):
        curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
        if self.onlyFutureDaysClickable:
            if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day:
                self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5)
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
            else:
                self.numberWidget.setColorScale(1, 1, 1, 1)
        if self.myDate.month != self.startDate.month:
            self.setColorScale(0.75, 0.75, 0.75, 1.0)
            if self.dayClickCallback is not None:
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
        else:
            self.setColorScale(1, 1, 1, 1)
        if self.myDate.date() == curServerDate.date():
            self.defaultBox.hide()
            self.todayBox.show()
        else:
            self.defaultBox.show()
            self.todayBox.hide()
        return

    def destroy(self):
        if self.dayClickCallback is not None:
            self.numberWidget.destroy()
        self.dayClickCallback = None
        self.notify.debug('desroying %s' % self.myDate)
        try:
            for item in self.scrollList['items']:
                if hasattr(item, 'description') and item.description and hasattr(item.description, 'destroy'):
                    self.notify.debug('desroying description of item %s' % item)
                    item.unbind(DGG.ENTER)
                    item.unbind(DGG.EXIT)
                    item.description.destroy()

        except e:
            self.notify.debug('pass %s' % self.myDate)

        self.scrollList.removeAndDestroyAllItems()
        self.scrollList.destroy()
        self.dayButton.destroy()
        DirectFrame.destroy(self)

    def updateArrowButtons(self):
        numItems = 0
        try:
            numItems = len(self.scrollList['items'])
        except e:
            numItems = 0

        if numItems <= self.scrollList.numItemsVisible:
            self.scrollList.incButton.hide()
            self.scrollList.decButton.hide()
        else:
            self.scrollList.incButton.show()
            self.scrollList.decButton.show()

    def collectTimedEvents(self):

        if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties:
            for party in localAvatar.partiesInvitedTo:
                if party.startTime.date() == self.myDate.date():
                    self.addPartyToScrollList(party)

            for party in localAvatar.hostedParties:
                if party.startTime.date() == self.myDate.date():
                    self.addPartyToScrollList(party)

        if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays:
            for id, holiday in HolidayGlobals.Holidays.iteritems():
                title, description = TTLocalizer.HolidayNamesInCalendar[id]

                if 'weekDay' in holiday:
                    if self.myDate.weekday() == holiday['weekDay']:
                        self.addTitleAndDescToScrollList(title, description)
                elif 'startMonth' in holiday or 'startDay' in holiday:
                    startDate = HolidayGlobals.getStartDate(holiday, self.myDate)
                    endDate = HolidayGlobals.getEndDate(holiday, self.myDate)
                    if self.isDateMatch(self.myDate, startDate):
                        if self.isDateMatch(startDate, endDate):
                            description = '%s. %s' % (title, description)
                        else:
                            description = '%s. %s %s %s' % (title, description, TTLocalizer.CalendarEndsAt, endDate.strftime('%b %d'))
                        self.addTitleAndDescToScrollList(title, description)
                    elif self.isDateMatch(self.myDate, endDate):
                        title = '%s %s' % (TTLocalizer.CalendarEndOf, title)
                        description = '%s. %s %s' % (title, TTLocalizer.CalendarStartedOn, startDate.strftime('%b %d'))
                        self.addTitleAndDescToScrollList(title, description)

    def isDateMatch(self, date1, date2):
        return date1.day == date2.day and date1.month == date2.month

    def addTitleAndDescToScrollList(self, title, desc):
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(relief=None, text=title, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem)
        scrollItemHeight = newItem.getHeight()
        descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
        descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
        descUnderItemZAdjust = -descUnderItemZAdjust
        descZAdjust = descUnderItemZAdjust
        newItem.description = DirectLabel(parent=newItem, pos=(0.115, 0, descZAdjust), text='', text_wordwrap=15, pad=(0.02, 0.02), text_scale=descTextSize, text_align=TextNode.ACenter, textMayChange=0)
        newItem.description.checkedHeight = False
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()
        newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, desc, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
        self.scrollList.addItem(newItem)
        return

    def exitedTextItem(self, newItem, mousepos):
        newItem.description.hide()

    def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos):
        if not newItem.description.checkedHeight:
            newItem.description.checkedHeight = True
            newItem.description['text'] = descText
            bounds = newItem.description.getBounds()
            descHeight = newItem.description.getHeight()
            scrollItemHeight = newItem.getHeight()
            descOverItemZAdjust = descHeight - scrollItemHeight / 2.0
            descZPos = self.getPos(aspect2d)[2] + descUnderItemZAdjust - descHeight
            if descZPos < -1.0:
                newItem.description.setZ(descOverItemZAdjust)
            descWidth = newItem.description.getWidth()
            brightFrame = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg')
            newItem.description['geom'] = brightFrame
            newItem.description['geom_scale'] = (descWidth, 1, descHeight)
            descGeomZ = (bounds[2] - bounds[3]) / 2.0
            descGeomZ += bounds[3]
            newItem.description['geom_pos'] = (0, 0, descGeomZ)
        newItem.description.show()

    def addPartyToScrollList(self, party):
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        partyTitle = myStrftime(party.startTime)
        partyTitle = partyTitle + ' ' + TTLocalizer.EventsPageCalendarTabParty
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(relief=None, text=partyTitle, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem)
        scrollItemHeight = newItem.getHeight()
        descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
        descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
        descUnderItemZAdjust = -descUnderItemZAdjust
        descZAdjust = descUnderItemZAdjust
        self.scrollList.addItem(newItem)
        newItem.description = MiniInviteVisual(newItem, party)
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()
        newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, newItem.description, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
        return

    def __clickedOnScrollItem(self):
        self.__clickedOnDay()

    def __clickedOnDay(self):
        acceptClick = True
        if self.onlyFutureDaysClickable:
            curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
            if self.myDate.date() < curServerDate.date():
                acceptClick = False
        if not acceptClick:
            return
        if self.dayClickCallback:
            self.dayClickCallback(self)
        self.notify.debug('we got clicked on %s' % self.myDate.date())
        messenger.send('clickedOnDay', [self.myDate.date()])

    def updateSelected(self, selected):
        multiplier = 1.1
        if selected:
            self.selectedFrame.show()
            self.setScale(multiplier)
            self.setPos(-0.01, 0, 0.01)
            grandParent = self.origParent.getParent()
            self.origParent.reparentTo(grandParent)
        else:
            self.selectedFrame.hide()
            self.setScale(1.0)
            self.setPos(0, 0, 0)

    def changeDate(self, startDate, myDate):
        self.startDate = startDate
        self.myDate = myDate
        self.scrollList.removeAndDestroyAllItems()
        self.update()

    def update(self):
        self.numberWidget['text'] = str(self.myDate.day)
        self.adjustForMonth()
        self.collectTimedEvents()
        self.updateArrowButtons()

    def changeFilter(self, filter):
        oldFilter = self.filter
        self.filter = filter
        if self.filter != oldFilter:
            self.scrollList.removeAndDestroyAllItems()
            self.update()
Ejemplo n.º 8
0
class CalendarGuiDay(DirectFrame):
    """A class to represent the gui for one day in the month.
    Do not put references to the shtiker page or book,  so this
    class may be extended later."""

    notify = directNotify.newCategory("CalendarGuiDay")
    ScrollListTextSize = 0.03

    def __init__(self,
                 parent,
                 myDate,
                 startDate,
                 dayClickCallback=None,
                 onlyFutureDaysClickable=False):
        """Construct ourself."""
        self.origParent = parent
        self.startDate = startDate
        self.myDate = myDate
        self.dayClickCallback = dayClickCallback
        # If true, only allow clicks on days in the future
        self.onlyFutureDaysClickable = onlyFutureDaysClickable
        DirectFrame.__init__(self, parent=parent)

        self.timedEvents = []
        self.partiesInvitedToToday = []
        self.hostedPartiesToday = []
        self.yearlyHolidaysToday = []  # either ending or starting today

        self.showMarkers = base.config.GetBool('show-calendar-markers', 0)

        self.filter = ToontownGlobals.CalendarFilterShowAll

        self.load()
        # self.createDummyLocators()
        self.createGuiObjects()
        self.update()

    def createDummyLocators(self):
        """Put some programming locators until we get the real art assets."""
        self.dayButtonLocator = self.attachNewNode('dayButtonLocator')
        self.dayButtonLocator.setX(0.1)
        self.dayButtonLocator.setZ(-0.05)
        self.numberLocator = self.attachNewNode('numberLocator')
        self.numberLocator.setX(0.09)
        self.scrollLocator = self.attachNewNode('scrollLocator')
        self.selectedLocator = self.attachNewNode('selectedLocator')
        self.selectedLocator.setX(0.11)
        self.selectedLocator.setZ(-0.06)

    def load(self):
        """Load the assets, and make sure locators are there."""
        dayAsset = loader.loadModel(
            'phase_4/models/parties/tt_m_gui_sbk_calendar_box')
        dayAsset.reparentTo(self)
        self.dayButtonLocator = self.find('**/loc_origin')
        self.numberLocator = self.find('**/loc_number')
        self.scrollLocator = self.find('**/loc_topLeftList')
        self.selectedLocator = self.find('**/loc_origin')
        self.todayBox = self.find('**/boxToday')
        self.todayBox.hide()
        self.selectedFrame = self.find('**/boxHover')
        self.selectedFrame.hide()
        self.defaultBox = self.find('**/boxBlank')
        self.scrollBottomRightLocator = self.find('**/loc_bottomRightList')
        self.scrollDownLocator = self.find('**/loc_scrollDown')
        self.attachMarker(self.scrollDownLocator)

        self.scrollUpLocator = self.find('**/loc_scrollUp')
        self.attachMarker(self.scrollUpLocator)

    def attachMarker(self, parent, scale=0.005, color=(1, 0, 0)):
        """Attach a marker to the parent to aid in visual debugging."""
        if self.showMarkers:
            marker = loader.loadModel("phase_3/models/misc/sphere")
            marker.reparentTo(parent)
            marker.setScale(scale)
            marker.setColor(*color)

    def createGuiObjects(self):
        """Create the other gui objects in the month, assumes we have proper locators."""
        # we create an invisible button so the day can be clicked on
        self.dayButton = DirectButton(
            parent=self.dayButtonLocator,
            image=self.selectedFrame,
            relief=None,
            command=self.__clickedOnDay,
            # next three settings are for debug
            pressEffect=1,
            rolloverSound=None,
            clickSound=None)

        self.numberWidget = DirectLabel(
            parent=self.numberLocator,
            relief=None,
            text=str(self.myDate.day),
            text_scale=0.04,
            text_align=TextNode.ACenter,
            text_font=ToontownGlobals.getInterfaceFont(),
            text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1),
        )

        self.attachMarker(self.numberLocator)

        self.listXorigin = 0
        self.listFrameSizeX = self.scrollBottomRightLocator.getX(
        ) - self.scrollLocator.getX()
        self.scrollHeight = self.scrollLocator.getZ(
        ) - self.scrollBottomRightLocator.getZ()
        self.listZorigin = self.scrollBottomRightLocator.getZ()
        self.listFrameSizeZ = self.scrollLocator.getZ(
        ) - self.scrollBottomRightLocator.getZ()
        self.arrowButtonXScale = 1
        self.arrowButtonZScale = 1
        self.itemFrameXorigin = 0
        self.itemFrameZorigin = 0
        self.buttonXstart = self.itemFrameXorigin + 0.21
        self.gui = loader.loadModel("phase_3.5/models/gui/friendslist_gui")
        buttonOffSet = -0.01

        # these settings put the arrow buttons on the top
        incButtonPos = (0.0, 0, 0)
        decButtonPos = (0.0, 0, 0)

        # these settings put the arrow buttons on the right side
        # incButtonPos = (self.buttonXstart,0,self.listZorigin - buttonOffSet)
        # decButtonPos = (self.buttonXstart, 0, self.listZorigin + self.listFrameSizeZ + buttonOffSet)
        itemFrameMinZ = self.listZorigin
        itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ

        arrowUp = self.find("**/downScroll_up")
        arrowDown = self.find("**/downScroll_down")
        arrowHover = self.find("**/downScroll_hover")

        self.scrollList = DirectScrolledList(
            parent=self.scrollLocator,
            relief=None,
            pos=(0, 0, 0),
            # inc and dec are DirectButtons
            # incButton is on the bottom of page, decButton is on the top!
            incButton_image=(
                arrowUp,
                arrowDown,
                arrowHover,
                arrowUp,
            ),
            incButton_relief=None,
            incButton_scale=(self.arrowButtonXScale, 1,
                             self.arrowButtonZScale),
            incButton_pos=incButtonPos,

            # Make the disabled button fade out
            incButton_image3_color=Vec4(1, 1, 1, 0.2),
            decButton_image=(
                arrowUp,
                arrowDown,
                arrowHover,
                arrowUp,
            ),
            decButton_relief=None,
            decButton_scale=(self.arrowButtonXScale, 1,
                             -self.arrowButtonZScale),
            decButton_pos=decButtonPos,
            # Make the disabled button fade out
            decButton_image3_color=Vec4(1, 1, 1, 0.2),

            # itemFrame is a DirectFrame, shift it down a bit to match top left scroll
            itemFrame_pos=(self.itemFrameXorigin, 0, -0.03),

            # each item is a button with text on it
            numItemsVisible=4,

            # so we select the day when we click on a scroll button
            incButtonCallback=self.scrollButtonPressed,
            decButtonCallback=self.scrollButtonPressed,
        )
        # make sure the arrow buttons appear over item frame
        itemFrameParent = self.scrollList.itemFrame.getParent()
        self.scrollList.incButton.reparentTo(self.scrollDownLocator)
        self.scrollList.decButton.reparentTo(self.scrollUpLocator)

        arrowUp.removeNode()
        arrowDown.removeNode()
        arrowHover.removeNode()

        # Set up a clipping plane to truncate names that would extend
        # off the right end of the scrolled list.
        clipper = PlaneNode('clipper')
        clipper.setPlane(Plane(Vec3(-1, 0, 0), Point3(0.23, 0, 0)))
        clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper)
        self.scrollList.component('itemFrame').setClipPlane(clipNP)

    def scrollButtonPressed(self):
        """Select the current day when the scroll button is pressed."""
        self.__clickedOnDay()

    def adjustForMonth(self):
        """Darken us if we are not in the same month as startDate."""
        # make us glow if are equal to the serverDate
        curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()

        if self.onlyFutureDaysClickable:
            if self.myDate.year < curServerDate.year or \
               ( self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month ) or \
               ( self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day ):
                self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5)
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
            else:
                self.numberWidget.setColorScale(1, 1, 1, 1)
        if self.myDate.month != self.startDate.month:
            self.setColorScale(0.75, 0.75, 0.75, 1.0)
            if self.dayClickCallback is not None:
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
        else:
            self.setColorScale(1, 1, 1, 1)

        if self.myDate.date() == curServerDate.date():
            self.defaultBox.hide()
            self.todayBox.show()
        else:
            self.defaultBox.show()
            self.todayBox.hide()

    def destroy(self):
        if self.dayClickCallback is not None:
            self.numberWidget.destroy()
        self.dayClickCallback = None
        self.notify.debug('desroying %s' % self.myDate)
        try:
            for item in self.scrollList['items']:
                if hasattr(item,
                           "description") and item.description and hasattr(
                               item.description, 'destroy'):
                    self.notify.debug('desroying description of item %s' %
                                      item)
                    item.unbind(DGG.ENTER)
                    item.unbind(DGG.EXIT)
                    item.description.destroy()
        except e:
            self.notify.debug('pass %s' % self.myDate)
            # an empty scroll list will come to this point
            pass
        self.scrollList.removeAndDestroyAllItems()

        self.scrollList.destroy()
        self.dayButton.destroy()
        DirectFrame.destroy(self)

    def addWeeklyHolidays(self):
        """Add weekly holidays to our scroll list."""
        if not (self.filter == ToontownGlobals.CalendarFilterShowAll or \
                self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays):
            return
        if base.cr.newsManager:
            holidays = base.cr.newsManager.getHolidaysForWeekday(
                self.myDate.weekday())
            holidayName = ""
            holidayDesc = ""
            for holidayId in holidays:
                if holidayId in TTLocalizer.HolidayNamesInCalendar:
                    holidayName = TTLocalizer.HolidayNamesInCalendar[
                        holidayId][0]
                    holidayDesc = TTLocalizer.HolidayNamesInCalendar[
                        holidayId][1]
                else:
                    holidayName = TTLocalizer.UnknownHoliday % holidayId

                self.addTitleAndDescToScrollList(holidayName, holidayDesc)
            self.scrollList.refresh()

        if base.config.GetBool('calendar-test-items', 0):
            # add test items just so we see scroll list arrows
            if self.myDate.date() + datetime.timedelta(
                    days=-1
            ) == base.cr.toontownTimeManager.getCurServerDateTime().date():
                testItems = ("1:00 AM Party", "2:00 AM CEO", "11:15 AM Party",
                             "5:30 PM CJ", "11:00 PM Party",
                             "Really Really Long String")
                for text in testItems:
                    newItem = DirectLabel(
                        relief=None,
                        text=text,
                        text_scale=self.ScrollListTextSize,
                        text_align=TextNode.ALeft,
                    )

                    self.scrollList.addItem(newItem)
            if self.myDate.date() + datetime.timedelta(
                    days=-2
            ) == base.cr.toontownTimeManager.getCurServerDateTime().date():
                testItems = (
                    "1:00 AM Party",
                    "3:00 AM CFO",
                    "11:00 AM Party",
                )
                textSize = self.ScrollListTextSize
                for text in testItems:
                    newItem = DirectLabel(
                        relief=None,
                        text=text,
                        text_scale=textSize,
                        text_align=TextNode.ALeft,
                    )

                    self.scrollList.addItem(newItem)

    def updateArrowButtons(self):
        """If we don't have anything in out scroll list, hide the arrow buttons."""
        numItems = 0
        try:
            numItems = len(self.scrollList['items'])
        except e:
            numItems = 0
        if numItems <= self.scrollList.numItemsVisible:
            self.scrollList.incButton.hide()
            self.scrollList.decButton.hide()
        else:
            self.scrollList.incButton.show()
            self.scrollList.decButton.show()

    def collectTimedEvents(self):
        """Sort by time the events in my day."""
        # possible events would be yearly holidays,
        # oncely holidays and relatively holidays
        # parties
        # and in the future planned boss battle raids
        self.timedEvents = []
        if (self.filter == ToontownGlobals.CalendarFilterShowAll or \
            self.filter == ToontownGlobals.CalendarFilterShowOnlyParties):
            for party in localAvatar.partiesInvitedTo:
                #if self.myDate.month == 9 and self.myDate.day == 1:
                #    import pdb; pdb.set_trace()
                if party.startTime.date() == self.myDate.date():
                    self.partiesInvitedToToday.append(party)
                    self.timedEvents.append((party.startTime.time(), party))
            for party in localAvatar.hostedParties:
                if party.startTime.date() == self.myDate.date():
                    self.hostedPartiesToday.append(party)
                    self.timedEvents.append((party.startTime.time(), party))

        if base.cr.newsManager and (self.filter == ToontownGlobals.CalendarFilterShowAll or \
                self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays):
            yearlyHolidays = base.cr.newsManager.getYearlyHolidaysForDate(
                self.myDate)
            for holiday in yearlyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.month and \
                   holidayStart[1] == self.myDate.day:
                    myTime = datetime.time(holidayStart[2], holidayStart[3])
                elif holidayEnd[0] == self.myDate.month and \
                   holidayEnd[1] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[2], holidayEnd[3])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            oncelyHolidays = base.cr.newsManager.getOncelyHolidaysForDate(
                self.myDate)
            for holiday in oncelyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.year and \
                   holidayStart[1] == self.myDate.month and \
                   holidayStart[2] == self.myDate.day:
                    myTime = datetime.time(holidayStart[3], holidayStart[4])
                elif holidayEnd[0] == self.myDate.year and \
                   holidayEnd[1] == self.myDate.month and \
                   holidayEnd[2] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[3], holidayEnd[4])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            multipleStartHolidays = base.cr.newsManager.getMultipleStartHolidaysForDate(
                self.myDate)
            for holiday in multipleStartHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.year and \
                   holidayStart[1] == self.myDate.month and \
                   holidayStart[2] == self.myDate.day:
                    myTime = datetime.time(holidayStart[3], holidayStart[4])
                elif holidayEnd[0] == self.myDate.year and \
                   holidayEnd[1] == self.myDate.month and \
                   holidayEnd[2] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[3], holidayEnd[4])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

            relativelyHolidays = base.cr.newsManager.getRelativelyHolidaysForDate(
                self.myDate)
            for holiday in relativelyHolidays:
                holidayId = holiday[1]
                holidayStart = holiday[2]
                holidayEnd = holiday[3]
                holidayType = holiday[0]
                if holidayStart[0] == self.myDate.month and \
                   holidayStart[1] == self.myDate.day:
                    myTime = datetime.time(holidayStart[2], holidayStart[3])
                elif holidayEnd[0] == self.myDate.month and \
                   holidayEnd[1] == self.myDate.day:
                    myTime = datetime.time(holidayEnd[2], holidayEnd[3])
                else:
                    self.notify.error('holiday is not today %s' % holiday)
                self.timedEvents.append((myTime, holiday))

        # sort timedEvents
        def timedEventCompare(te1, te2):
            if te1[0] < te2[0]:
                return -1
            elif te1[0] == te2[0]:
                return 0
            else:
                return 1

        self.timedEvents.sort(cmp=timedEventCompare)

        # now add them to the scroll list
        for timedEvent in self.timedEvents:
            if isinstance(timedEvent[1], PartyInfo):
                self.addPartyToScrollList(timedEvent[1])
            elif isinstance(
                    timedEvent[1], tuple
            ) and timedEvent[1][0] == NewsManager.YearlyHolidayType:
                self.addYearlyHolidayToScrollList(timedEvent[1])
            elif isinstance(
                    timedEvent[1], tuple
            ) and timedEvent[1][0] == NewsManager.OncelyHolidayType:
                self.addOncelyHolidayToScrollList(timedEvent[1])
            elif isinstance(timedEvent[1], tuple) and timedEvent[1][
                    0] == NewsManager.OncelyMultipleStartHolidayType:
                self.addOncelyMultipleStartHolidayToScrollList(timedEvent[1])
            elif isinstance(
                    timedEvent[1], tuple
            ) and timedEvent[1][0] == NewsManager.RelativelyHolidayType:
                self.addRelativelyHolidayToScrollList(timedEvent[1])

    def addYearlyHolidayToScrollList(self, holiday):
        """Add a yearly holiday to the scroll list. Could be start date or end date"""
        # first figure out if it ends on the same day
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ""
        startTime = datetime.time(holidayStart[2], holidayStart[3])
        endTime = datetime.time(holidayEnd[2], holidayEnd[3])
        startDate = datetime.date(self.myDate.year, holidayStart[0],
                                  holidayStart[1])
        endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1])
        if endDate < startDate:
            endDate = datetime.date(endDate.year + 1, endDate.month,
                                    endDate.day)
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = TTLocalizer.UnknownHoliday % holidayId

        if holidayStart[0] == holidayEnd[0] and \
           holidayStart[1] == holidayEnd[1]:
            # end of holiday is on the same day
            holidayText = myStrftime(startTime)
            holidayText += " " + holidayName
            holidayDesc += " " + TTLocalizer.CalendarEndsAt + myStrftime(
                endTime)
        elif self.myDate.month == holidayStart[0] and \
             self.myDate.day == holidayStart[1]:
            holidayText = myStrftime(startTime)
            holidayText += " " + holidayName
            holidayDesc = holidayName + ". " + holidayDesc
            holidayDesc += " " + TTLocalizer.CalendarEndsAt + endDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.month == holidayEnd[0] and \
             self.myDate.day == holidayEnd[1]:
            holidayText = myStrftime(endTime)
            holidayText += " " + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += ". " + TTLocalizer.CalendarStartedOn + startDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(startTime)

        else:
            self.notify.error('unhandled case')

        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addOncelyHolidayToScrollList(self, holiday):
        """Add a oncely holiday to the scroll list. Could be start date or end date"""
        # first figure out if it ends on the same day
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ""
        startTime = datetime.time(holidayStart[3], holidayStart[4])
        endTime = datetime.time(holidayEnd[3], holidayEnd[4])
        startDate = datetime.date(holidayStart[0], holidayStart[1],
                                  holidayStart[2])
        endDate = datetime.date(holidayStart[0], holidayEnd[1], holidayEnd[2])
        if endDate < startDate:
            endDate = datetime.date(endDate.year + 1, endDate.month,
                                    endDate.day)
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = ""

        if holidayStart[1] == holidayEnd[1] and \
           holidayStart[2] == holidayEnd[2]:
            # end of holiday is on the same day
            holidayText = myStrftime(startTime)
            holidayText += " " + holidayName
            holidayDesc = holidayName + ". " + holidayDesc
            holidayDesc += " " + TTLocalizer.CalendarEndsAt + myStrftime(
                endTime)
        elif self.myDate.year == holidayStart[0] and \
             self.myDate.month == holidayStart[1] and \
             self.myDate.day == holidayStart[2]:
            holidayText = myStrftime(startTime)
            holidayText += " " + holidayName
            holidayDesc = holidayName + ". " + holidayDesc
            holidayDesc += " " + TTLocalizer.CalendarEndsAt + endDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.year == holidayEnd[0] and \
             self.myDate.month == holidayEnd[1] and \
             self.myDate.day == holidayEnd[2]:
            holidayText = myStrftime(endTime)
            holidayText += " " + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += ". " + TTLocalizer.CalendarStartedOn + startDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(startTime)

        else:
            self.notify.error('unhandled case')

        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addOncelyMultipleStartHolidayToScrollList(self, holiday):
        """Add a multiple start holiday to the scroll list. Could be start date or end date"""
        # I can't think of anything different we'd do from addOncely, so just call that
        self.addOncelyHolidayToScrollList(holiday)

    def addRelativelyHolidayToScrollList(self, holiday):
        """Add a relatively holiday to the scroll list. Could be start date or end date"""
        # first figure out if it ends on the same day
        holidayId = holiday[1]
        holidayStart = holiday[2]
        holidayEnd = holiday[3]
        holidayType = holiday[0]
        holidayText = ""
        startTime = datetime.time(holidayStart[2], holidayStart[3])
        endTime = datetime.time(holidayEnd[2], holidayEnd[3])
        startDate = datetime.date(self.myDate.year, holidayStart[0],
                                  holidayStart[1])
        endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1])
        if endDate < startDate:
            endDate.year += 1
        if holidayId in TTLocalizer.HolidayNamesInCalendar:
            holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
            holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
        else:
            holidayName = TTLocalizer.UnknownHoliday % holidayId
            holidayDesc = ""

        if holidayStart[0] == holidayEnd[0] and \
           holidayStart[1] == holidayEnd[1]:
            # end of holiday is on the same day
            holidayText = myStrftime(startTime)
            holidayText += " " + holidayName
            holidayDesc += " " + TTLocalizer.CalendarEndsAt + myStrftime(
                endTime)
        elif self.myDate.month == holidayStart[0] and \
             self.myDate.day == holidayStart[1]:
            holidayText = myStrftime(startTime)
            holidayText += " " + holidayName
            holidayDesc = holidayName + ". " + holidayDesc
            holidayDesc += " " + TTLocalizer.CalendarEndsAt + endDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(endTime)
        elif self.myDate.month == holidayEnd[0] and \
             self.myDate.day == holidayEnd[1]:
            holidayText = myStrftime(endTime)
            holidayText += " " + TTLocalizer.CalendarEndDash + holidayName
            holidayDesc = TTLocalizer.CalendarEndOf + holidayName
            holidayDesc += ". " + TTLocalizer.CalendarStartedOn + startDate.strftime(
                TTLocalizer.HolidayFormat) + myStrftime(startTime)

        else:
            self.notify.error('unhandled case')

        self.addTitleAndDescToScrollList(holidayText, holidayDesc)

    def addTitleAndDescToScrollList(self, title, desc):
        """Add a text title and popup description to the scrollList."""
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(
            relief=None,
            text=title,
            text_scale=textSize,
            text_align=TextNode.ALeft,
            rolloverSound=None,
            clickSound=None,
            pressEffect=0,
            command=self.__clickedOnScrollItem,
        )

        # lower tool tip a little
        scrollItemHeight = newItem.getHeight()

        descUnderItemZAdjust = (scrollItemHeight * descTextSize / textSize)
        descUnderItemZAdjust = max(
            0.0534, descUnderItemZAdjust)  # ensure minimum height
        descUnderItemZAdjust = -descUnderItemZAdjust
        # self.notify.debug('scrollItemHeight of %s = %f' % (title, scrollItemHeight))
        descZAdjust = descUnderItemZAdjust
        # self.notify.debug('descUnderItemZAdjust of %s = %f' % (title, descUnderItemZAdjust))

        newItem.description = DirectLabel(
            parent=newItem,
            pos=(0.115, 0, descZAdjust),
            text='',
            text_wordwrap=15,
            pad=(0.02, 0.02),
            text_scale=descTextSize,
            text_align=TextNode.ACenter,
            textMayChange=0,
        )
        # if we set text here, it really slows down changing the month
        # do it when we first enter the scroll item instead
        newItem.description.checkedHeight = False

        # # workaround to stop getting clipped by plane node
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()

        newItem.bind(DGG.ENTER,
                     self.enteredTextItem,
                     extraArgs=[newItem, desc, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])

        self.scrollList.addItem(newItem)

    def exitedTextItem(self, newItem, mousepos):
        newItem.description.hide()

    def enteredTextItem(self, newItem, descText, descUnderItemZAdjust,
                        mousePos):
        # compute if we go over edge, then adjust if needed
        if not newItem.description.checkedHeight:
            newItem.description.checkedHeight = True

            newItem.description['text'] = descText
            bounds = newItem.description.getBounds()
            descHeight = newItem.description.getHeight()
            # lets see if we go down too far
            scrollItemHeight = newItem.getHeight()
            descOverItemZAdjust = descHeight - (scrollItemHeight / 2.0)
            descZPos = self.getPos(
                aspect2d)[2] + descUnderItemZAdjust - descHeight
            if descZPos < -1.0:
                newItem.description.setZ(descOverItemZAdjust)

            descWidth = newItem.description.getWidth()
            brightFrame = loader.loadModel(
                'phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg')
            newItem.description['geom'] = brightFrame
            newItem.description['geom_scale'] = (descWidth, 1, descHeight)

            descGeomZ = (bounds[2] - bounds[3]) / 2.0
            descGeomZ += bounds[3]
            # self.notify.debug('descGeomZ=%s' % descGeomZ)
            newItem.description['geom_pos'] = (0, 0, descGeomZ)
            # self.notify.debug('descWidth=%s descHeight=%s' % (descWidth, descHeight))

        newItem.description.show()

    def addPartyToScrollList(self, party):
        """Add a party to the scroll list."""
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        partyTitle = myStrftime(party.startTime)
        partyTitle = partyTitle + " " + TTLocalizer.EventsPageCalendarTabParty

        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(
            relief=None,
            text=partyTitle,
            text_scale=textSize,
            text_align=TextNode.ALeft,
            rolloverSound=None,
            clickSound=None,
            pressEffect=0,
            command=self.__clickedOnScrollItem,
        )

        # lower tool tip a little
        scrollItemHeight = newItem.getHeight()

        descUnderItemZAdjust = (scrollItemHeight * descTextSize / textSize)
        descUnderItemZAdjust = max(
            0.0534, descUnderItemZAdjust)  # ensure minimum height
        descUnderItemZAdjust = -descUnderItemZAdjust
        # self.notify.debug('scrollItemHeight of %s = %f' % (title, scrollItemHeight))
        descZAdjust = descUnderItemZAdjust
        # self.notify.debug('descUnderItemZAdjust of %s = %f' % (title, descUnderItemZAdjust))
        self.scrollList.addItem(newItem)

        newItem.description = MiniInviteVisual(newItem, party)
        # # workaround to stop getting clipped by plane node
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()

        newItem.bind(
            DGG.ENTER,
            self.enteredTextItem,
            extraArgs=[newItem, newItem.description, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])

    def __clickedOnScrollItem(self):
        """Handle the user clicking on a scroll item."""
        self.__clickedOnDay()

    def __clickedOnDay(self):
        """Handle user clicking on us a day square."""
        acceptClick = True
        if self.onlyFutureDaysClickable:
            curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
            if self.myDate.date() < curServerDate.date():
                acceptClick = False

        if not acceptClick:
            return

        if self.dayClickCallback:
            self.dayClickCallback(self)
        self.notify.debug('we got clicked on %s' % self.myDate.date())

        # tell the calendarGuiMonth
        messenger.send('clickedOnDay', [self.myDate.date()])

    def updateSelected(self, selected):
        # note set multiplier to 1.0 if we don't want to pop selected days
        multiplier = 1.1
        if selected:
            self.selectedFrame.show()
            self.setScale(multiplier)
            self.setPos(-0.01, 0, 0.01)
            grandParent = self.origParent.getParent()
            self.origParent.reparentTo(grandParent)
        else:
            self.selectedFrame.hide()
            self.setScale(1.0)
            self.setPos(0, 0, 0)

    def changeDate(self, startDate, myDate):
        """Change the date that we are displaying."""
        self.startDate = startDate
        self.myDate = myDate
        self.scrollList.removeAndDestroyAllItems()
        self.update()

    def update(self):
        """Fill in the day with the proper contents."""
        self.numberWidget['text'] = str(self.myDate.day)
        self.adjustForMonth()
        self.addWeeklyHolidays()
        self.collectTimedEvents()
        self.updateArrowButtons()

    def changeFilter(self, filter):
        """Change our fliter, update scroll items if needed."""
        oldFilter = self.filter
        self.filter = filter
        if self.filter != oldFilter:
            self.scrollList.removeAndDestroyAllItems()
            self.update()
Ejemplo n.º 9
0
class FriendsList(DirectFrame):
    notify = DirectNotifyGlobal.directNotify.newCategory('FriendsList')

    def __init__(self):
        DirectFrame.__init__(self, parent=base.a2dTopRight, pos=(-0.25, 0.0, -0.46))
        gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        self['image'] = gui.find('**/FriendsBox_Open')
        self.headingText = OnscreenText(text='', parent=self, pos=(0.01, 0.2), fg=(0.1, 0.1, 0.4, 1.0), scale=0.04)
        self.frameForNames = DirectScrolledList(frameSize=(0.0, 0.35, 0, 0.35), incButton_geom=(gui.find('**/FndsLst_ScrollUp'),
         gui.find('**/FndsLst_ScrollDN'),
         gui.find('**/FndsLst_ScrollUp_Rllvr'),
         gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_hpr=(0, 0, 180), incButton_pos=(0.17, 0, -0.04), decButton_geom=(gui.find('**/FndsLst_ScrollUp'),
         gui.find('**/FndsLst_ScrollDN'),
         gui.find('**/FndsLst_ScrollUp_Rllvr'),
         gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_pos=(0.17, 0, 0.395), pos=(-0.1625, 0.0, -0.27), parent=self, numItemsVisible=9, forceHeight=0.04, itemFrame_frameSize=(-0.15, 0.15, 0, -0.35), itemFrame_pos=(0, 0, 0.3275), itemFrame_relief=None, relief=None)
        self.fwdBtn = DirectButton(geom=(gui.find('**/Horiz_Arrow_UP'),
         gui.find('**/Horiz_Arrow_DN'),
         gui.find('**/Horiz_Arrow_Rllvr'),
         gui.find('**/Horiz_Arrow_UP')), relief=None, parent=self, pos=(0.17, 0.0, -0.38), command=self.doState)
        self.backBtn = DirectButton(geom=(gui.find('**/Horiz_Arrow_UP'),
         gui.find('**/Horiz_Arrow_DN'),
         gui.find('**/Horiz_Arrow_Rllvr'),
         gui.find('**/Horiz_Arrow_UP')), relief=None, parent=self, pos=(-0.15, 0.0, -0.38), hpr=(180, 0, 0), command=self.doState)
        self.closeBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(), relief=None, parent=self, command=self.exitClicked)
        self.closeBtn.setPos(0.015, 0.0, -0.375)
        gui.removeNode()
        del gui
        self.hide()
        self.friends = {}
        self.onlineFriends = {}
        self.fsm = ClassicFSM.ClassicFSM('FriendsList', [State.State('off', self.enterOff, self.exitOff), State.State('onlineFriendsList', self.enterOnlineFriendsList, self.exitOnlineFriendsList), State.State('allFriendsList', self.enterAllFriendsList, self.exitAllFriendsList)], 'off', 'off')
        self.fsm.enterInitialState()
        self.accept('gotFriendsList', self.handleFriendsList)
        return

    def destroy(self):
        self.ignore('gotFriendsList')
        self.fsm.requestFinalState()
        del self.fsm
        self.headingText.destroy()
        del self.headingText
        self.frameForNames.destroy()
        del self.frameForNames
        self.fwdBtn.destroy()
        del self.fwdBtn
        self.backBtn.destroy()
        del self.backBtn
        self.closeBtn.destroy()
        del self.closeBtn
        del self.friends
        del self.onlineFriends
        DirectFrame.destroy(self)

    def doState(self, state):
        self.fsm.request(state)

    def exitClicked(self):
        self.fsm.request('off')
        base.localAvatar.showFriendButton()

    def setButtons(self, fwd = None, back = None):
        if fwd:
            self.fwdBtn['extraArgs'] = [fwd]
            self.fwdBtn['state'] = DGG.NORMAL
        else:
            self.fwdBtn['extraArgs'] = []
            self.fwdBtn['state'] = DGG.DISABLED
        if back:
            self.backBtn['extraArgs'] = [back]
            self.backBtn['state'] = DGG.NORMAL
        else:
            self.backBtn['extraArgs'] = []
            self.backBtn['state'] = DGG.DISABLED

    def handleFriendsList(self, friendIdArray, nameArray, flags):
        self.friends = {}
        self.onlineFriends = {}
        for i in xrange(len(friendIdArray)):
            avatarId = friendIdArray[i]
            name = nameArray[i]
            self.friends[avatarId] = name
            if flags[i] == 1:
                self.onlineFriends[avatarId] = name

    def enterOff(self):
        self.hide()

    def exitOff(self):
        self.show()

    def addFriend(self, name, avatarId):
        self.frameForNames.addItem(DirectButton(text=name, extraArgs=[avatarId], command=self.friendClicked, scale=0.035, relief=None, text1_bg=textDownColor, text2_bg=textRolloverColor, text_align=TextNode.ALeft))
        return

    def friendClicked(self, avatarId):
        self.fsm.request('off')
        base.localAvatar.panel.makePanel(avatarId)

    def resetAll(self):
        self.headingText.setText('')
        self.frameForNames.removeAndDestroyAllItems()
        self.setButtons(None, None)
        return

    def sortListItems(self):
        self.frameForNames['items'].sort(key=lambda x: x['text'])
        self.frameForNames.refresh()

    def enterAllFriendsList(self):
        self.headingText.setText('All\nFriends')
        for friendId, name in self.friends.items():
            self.addFriend(name, friendId)

        self.sortListItems()
        self.setButtons(None, 'onlineFriendsList')
        return

    def exitAllFriendsList(self):
        self.resetAll()

    def enterOnlineFriendsList(self):
        self.headingText.setText('Online\nFriends')
        for friendId, name in self.onlineFriends.items():
            self.addFriend(name, friendId)

        self.sortListItems()
        self.setButtons('allFriendsList', None)
        return

    def exitOnlineFriendsList(self):
        self.resetAll()
Ejemplo n.º 10
0
class CalendarGuiDay(DirectFrame):
    notify = directNotify.newCategory('CalendarGuiDay')
    ScrollListTextSize = 0.03

    def __init__(self,
                 parent,
                 myDate,
                 startDate,
                 dayClickCallback=None,
                 onlyFutureDaysClickable=False):
        self.origParent = parent
        self.startDate = startDate
        self.myDate = myDate
        self.dayClickCallback = dayClickCallback
        self.onlyFutureDaysClickable = onlyFutureDaysClickable
        DirectFrame.__init__(self, parent=parent)
        self.timedEvents = []
        self.partiesInvitedToToday = []
        self.hostedPartiesToday = []
        self.yearlyHolidaysToday = []
        self.showMarkers = base.config.GetBool('show-calendar-markers', 0)
        self.filter = ToontownGlobals.CalendarFilterShowAll
        self.load()
        self.createGuiObjects()
        self.update()

    def createDummyLocators(self):
        self.dayButtonLocator = self.attachNewNode('dayButtonLocator')
        self.dayButtonLocator.setX(0.1)
        self.dayButtonLocator.setZ(-0.05)
        self.numberLocator = self.attachNewNode('numberLocator')
        self.numberLocator.setX(0.09)
        self.scrollLocator = self.attachNewNode('scrollLocator')
        self.selectedLocator = self.attachNewNode('selectedLocator')
        self.selectedLocator.setX(0.11)
        self.selectedLocator.setZ(-0.06)

    def load(self):
        dayAsset = loader.loadModel(
            'phase_4/models/parties/tt_m_gui_sbk_calendar_box')
        dayAsset.reparentTo(self)
        self.dayButtonLocator = self.find('**/loc_origin')
        self.numberLocator = self.find('**/loc_number')
        self.scrollLocator = self.find('**/loc_topLeftList')
        self.selectedLocator = self.find('**/loc_origin')
        self.todayBox = self.find('**/boxToday')
        self.todayBox.hide()
        self.selectedFrame = self.find('**/boxHover')
        self.selectedFrame.hide()
        self.defaultBox = self.find('**/boxBlank')
        self.scrollBottomRightLocator = self.find('**/loc_bottomRightList')
        self.scrollDownLocator = self.find('**/loc_scrollDown')
        self.attachMarker(self.scrollDownLocator)
        self.scrollUpLocator = self.find('**/loc_scrollUp')
        self.attachMarker(self.scrollUpLocator)

    def attachMarker(self, parent, scale=0.005, 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 createGuiObjects(self):
        self.dayButton = DirectButton(parent=self.dayButtonLocator,
                                      image=self.selectedFrame,
                                      relief=None,
                                      command=self.__clickedOnDay,
                                      pressEffect=1,
                                      rolloverSound=None,
                                      clickSound=None)
        self.numberWidget = DirectLabel(
            parent=self.numberLocator,
            relief=None,
            text=str(self.myDate.day),
            text_scale=0.04,
            text_align=TextNode.ACenter,
            text_font=ToontownGlobals.getInterfaceFont(),
            text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1))
        self.attachMarker(self.numberLocator)
        self.listXorigin = 0
        self.listFrameSizeX = self.scrollBottomRightLocator.getX(
        ) - self.scrollLocator.getX()
        self.scrollHeight = self.scrollLocator.getZ(
        ) - self.scrollBottomRightLocator.getZ()
        self.listZorigin = self.scrollBottomRightLocator.getZ()
        self.listFrameSizeZ = self.scrollLocator.getZ(
        ) - self.scrollBottomRightLocator.getZ()
        self.arrowButtonXScale = 1
        self.arrowButtonZScale = 1
        self.itemFrameXorigin = 0
        self.itemFrameZorigin = 0
        self.buttonXstart = self.itemFrameXorigin + 0.21
        self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
        buttonOffSet = -0.01
        incButtonPos = (0.0, 0, 0)
        decButtonPos = (0.0, 0, 0)
        itemFrameMinZ = self.listZorigin
        itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ
        arrowUp = self.find('**/downScroll_up')
        arrowDown = self.find('**/downScroll_down')
        arrowHover = self.find('**/downScroll_hover')
        self.scrollList = DirectScrolledList(
            parent=self.scrollLocator,
            relief=None,
            pos=(0, 0, 0),
            incButton_image=(arrowUp, arrowDown, arrowHover, arrowUp),
            incButton_relief=None,
            incButton_scale=(self.arrowButtonXScale, 1,
                             self.arrowButtonZScale),
            incButton_pos=incButtonPos,
            incButton_image3_color=(1, 1, 1, 0.2),
            decButton_image=(arrowUp, arrowDown, arrowHover, arrowUp),
            decButton_relief=None,
            decButton_scale=(self.arrowButtonXScale, 1,
                             -self.arrowButtonZScale),
            decButton_pos=decButtonPos,
            decButton_image3_color=(1, 1, 1, 0.2),
            itemFrame_pos=(self.itemFrameXorigin, 0, -0.03),
            numItemsVisible=4,
            incButtonCallback=self.scrollButtonPressed,
            decButtonCallback=self.scrollButtonPressed)
        itemFrameParent = self.scrollList.itemFrame.getParent()
        self.scrollList.incButton.reparentTo(self.scrollDownLocator)
        self.scrollList.decButton.reparentTo(self.scrollUpLocator)
        arrowUp.removeNode()
        arrowDown.removeNode()
        arrowHover.removeNode()
        clipper = PlaneNode('clipper')
        clipper.setPlane(Plane((-1, 0, 0), (0.23, 0, 0)))
        clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper)
        self.scrollList.component('itemFrame').setClipPlane(clipNP)
        return

    def scrollButtonPressed(self):
        self.__clickedOnDay()

    def adjustForMonth(self):
        curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
        if self.onlyFutureDaysClickable:
            if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day:
                self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5)
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
            else:
                self.numberWidget.setColorScale(1, 1, 1, 1)
        if self.myDate.month != self.startDate.month:
            self.setColorScale(0.75, 0.75, 0.75, 1.0)
            if self.dayClickCallback is not None:
                self.numberWidget['state'] = DirectGuiGlobals.DISABLED
        else:
            self.setColorScale(1, 1, 1, 1)
        if self.myDate.date() == curServerDate.date():
            self.defaultBox.hide()
            self.todayBox.show()
        else:
            self.defaultBox.show()
            self.todayBox.hide()
        return

    def destroy(self):
        if self.dayClickCallback is not None:
            self.numberWidget.destroy()
        self.dayClickCallback = None
        self.notify.debug('desroying %s' % self.myDate)
        try:
            for item in self.scrollList['items']:
                if hasattr(item,
                           'description') and item.description and hasattr(
                               item.description, 'destroy'):
                    self.notify.debug('desroying description of item %s' %
                                      item)
                    item.unbind(DGG.ENTER)
                    item.unbind(DGG.EXIT)
                    item.description.destroy()

        except e:
            self.notify.debug('pass %s' % self.myDate)

        self.scrollList.removeAndDestroyAllItems()
        self.scrollList.destroy()
        self.dayButton.destroy()
        DirectFrame.destroy(self)

    def updateArrowButtons(self):
        numItems = 0
        try:
            numItems = len(self.scrollList['items'])
        except e:
            numItems = 0

        if numItems <= self.scrollList.numItemsVisible:
            self.scrollList.incButton.hide()
            self.scrollList.decButton.hide()
        else:
            self.scrollList.incButton.show()
            self.scrollList.decButton.show()

    def collectTimedEvents(self):

        if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties:
            for party in localAvatar.partiesInvitedTo:
                if party.startTime.date() == self.myDate.date():
                    self.addPartyToScrollList(party)

            for party in localAvatar.hostedParties:
                if party.startTime.date() == self.myDate.date():
                    self.addPartyToScrollList(party)

        if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays:
            for id, holiday in HolidayGlobals.Holidays.iteritems():
                title, description = TTLocalizer.HolidayNamesInCalendar[id]

                if 'weekDay' in holiday:
                    if self.myDate.weekday() == holiday['weekDay']:
                        self.addTitleAndDescToScrollList(title, description)
                elif 'startMonth' in holiday or 'startDay' in holiday:
                    startDate = HolidayGlobals.getStartDate(
                        holiday, self.myDate)
                    endDate = HolidayGlobals.getEndDate(holiday, self.myDate)
                    if self.isDateMatch(self.myDate, startDate):
                        if self.isDateMatch(startDate, endDate):
                            description = '%s. %s' % (title, description)
                        else:
                            description = '%s. %s %s %s' % (
                                title, description, TTLocalizer.CalendarEndsAt,
                                endDate.strftime('%b %d'))
                        self.addTitleAndDescToScrollList(title, description)
                    elif self.isDateMatch(self.myDate, endDate):
                        title = '%s %s' % (TTLocalizer.CalendarEndOf, title)
                        description = '%s. %s %s' % (
                            title, TTLocalizer.CalendarStartedOn,
                            startDate.strftime('%b %d'))
                        self.addTitleAndDescToScrollList(title, description)

    def isDateMatch(self, date1, date2):
        return date1.day == date2.day and date1.month == date2.month

    def addTitleAndDescToScrollList(self, title, desc):
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(relief=None,
                               text=title,
                               text_scale=textSize,
                               text_align=TextNode.ALeft,
                               rolloverSound=None,
                               clickSound=None,
                               pressEffect=0,
                               command=self.__clickedOnScrollItem)
        scrollItemHeight = newItem.getHeight()
        descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
        descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
        descUnderItemZAdjust = -descUnderItemZAdjust
        descZAdjust = descUnderItemZAdjust
        newItem.description = DirectLabel(parent=newItem,
                                          pos=(0.115, 0, descZAdjust),
                                          text='',
                                          text_wordwrap=15,
                                          pad=(0.02, 0.02),
                                          text_scale=descTextSize,
                                          text_align=TextNode.ACenter,
                                          textMayChange=0)
        newItem.description.checkedHeight = False
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()
        newItem.bind(DGG.ENTER,
                     self.enteredTextItem,
                     extraArgs=[newItem, desc, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
        self.scrollList.addItem(newItem)
        return

    def exitedTextItem(self, newItem, mousepos):
        newItem.description.hide()

    def enteredTextItem(self, newItem, descText, descUnderItemZAdjust,
                        mousePos):
        if not newItem.description.checkedHeight:
            newItem.description.checkedHeight = True
            newItem.description['text'] = descText
            bounds = newItem.description.getBounds()
            descHeight = newItem.description.getHeight()
            scrollItemHeight = newItem.getHeight()
            descOverItemZAdjust = descHeight - scrollItemHeight / 2.0
            descZPos = self.getPos(
                aspect2d)[2] + descUnderItemZAdjust - descHeight
            if descZPos < -1.0:
                newItem.description.setZ(descOverItemZAdjust)
            descWidth = newItem.description.getWidth()
            brightFrame = loader.loadModel(
                'phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg')
            newItem.description['geom'] = brightFrame
            newItem.description['geom_scale'] = (descWidth, 1, descHeight)
            descGeomZ = (bounds[2] - bounds[3]) / 2.0
            descGeomZ += bounds[3]
            newItem.description['geom_pos'] = (0, 0, descGeomZ)
        newItem.description.show()

    def addPartyToScrollList(self, party):
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        partyTitle = myStrftime(party.startTime)
        partyTitle = partyTitle + ' ' + TTLocalizer.EventsPageCalendarTabParty
        textSize = self.ScrollListTextSize
        descTextSize = 0.05
        newItem = DirectButton(relief=None,
                               text=partyTitle,
                               text_scale=textSize,
                               text_align=TextNode.ALeft,
                               rolloverSound=None,
                               clickSound=None,
                               pressEffect=0,
                               command=self.__clickedOnScrollItem)
        scrollItemHeight = newItem.getHeight()
        descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
        descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
        descUnderItemZAdjust = -descUnderItemZAdjust
        descZAdjust = descUnderItemZAdjust
        self.scrollList.addItem(newItem)
        newItem.description = MiniInviteVisual(newItem, party)
        newItem.description.setBin('gui-popup', 0)
        newItem.description.hide()
        newItem.bind(
            DGG.ENTER,
            self.enteredTextItem,
            extraArgs=[newItem, newItem.description, descUnderItemZAdjust])
        newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
        return

    def __clickedOnScrollItem(self):
        self.__clickedOnDay()

    def __clickedOnDay(self):
        acceptClick = True
        if self.onlyFutureDaysClickable:
            curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
            if self.myDate.date() < curServerDate.date():
                acceptClick = False
        if not acceptClick:
            return
        if self.dayClickCallback:
            self.dayClickCallback(self)
        self.notify.debug('we got clicked on %s' % self.myDate.date())
        messenger.send('clickedOnDay', [self.myDate.date()])

    def updateSelected(self, selected):
        multiplier = 1.1
        if selected:
            self.selectedFrame.show()
            self.setScale(multiplier)
            self.setPos(-0.01, 0, 0.01)
            grandParent = self.origParent.getParent()
            self.origParent.reparentTo(grandParent)
        else:
            self.selectedFrame.hide()
            self.setScale(1.0)
            self.setPos(0, 0, 0)

    def changeDate(self, startDate, myDate):
        self.startDate = startDate
        self.myDate = myDate
        self.scrollList.removeAndDestroyAllItems()
        self.update()

    def update(self):
        self.numberWidget['text'] = str(self.myDate.day)
        self.adjustForMonth()
        self.collectTimedEvents()
        self.updateArrowButtons()

    def changeFilter(self, filter):
        oldFilter = self.filter
        self.filter = filter
        if self.filter != oldFilter:
            self.scrollList.removeAndDestroyAllItems()
            self.update()
Ejemplo n.º 11
0
class FriendsList(DirectFrame):
    notify = DirectNotifyGlobal.directNotify.newCategory('FriendsList')

    def __init__(self):
        DirectFrame.__init__(self,
                             parent=base.a2dTopRight,
                             pos=(-0.25, 0.0, -0.46))
        gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        self['image'] = gui.find('**/FriendsBox_Open')
        self.headingText = OnscreenText(text='',
                                        parent=self,
                                        pos=(0.01, 0.2),
                                        fg=(0.1, 0.1, 0.4, 1.0),
                                        scale=0.04)
        self.frameForNames = DirectScrolledList(
            frameSize=(0.0, 0.35, 0, 0.35),
            incButton_geom=(gui.find('**/FndsLst_ScrollUp'),
                            gui.find('**/FndsLst_ScrollDN'),
                            gui.find('**/FndsLst_ScrollUp_Rllvr'),
                            gui.find('**/FndsLst_ScrollUp')),
            incButton_relief=None,
            incButton_hpr=(0, 0, 180),
            incButton_pos=(0.17, 0, -0.04),
            decButton_geom=(gui.find('**/FndsLst_ScrollUp'),
                            gui.find('**/FndsLst_ScrollDN'),
                            gui.find('**/FndsLst_ScrollUp_Rllvr'),
                            gui.find('**/FndsLst_ScrollUp')),
            decButton_relief=None,
            decButton_pos=(0.17, 0, 0.395),
            pos=(-0.1625, 0.0, -0.27),
            parent=self,
            numItemsVisible=9,
            forceHeight=0.04,
            itemFrame_frameSize=(-0.15, 0.15, 0, -0.35),
            itemFrame_pos=(0, 0, 0.3275),
            itemFrame_relief=None,
            relief=None)
        self.fwdBtn = DirectButton(geom=(gui.find('**/Horiz_Arrow_UP'),
                                         gui.find('**/Horiz_Arrow_DN'),
                                         gui.find('**/Horiz_Arrow_Rllvr'),
                                         gui.find('**/Horiz_Arrow_UP')),
                                   relief=None,
                                   parent=self,
                                   pos=(0.17, 0.0, -0.38),
                                   command=self.doState)
        self.backBtn = DirectButton(geom=(gui.find('**/Horiz_Arrow_UP'),
                                          gui.find('**/Horiz_Arrow_DN'),
                                          gui.find('**/Horiz_Arrow_Rllvr'),
                                          gui.find('**/Horiz_Arrow_UP')),
                                    relief=None,
                                    parent=self,
                                    pos=(-0.15, 0.0, -0.38),
                                    hpr=(180, 0, 0),
                                    command=self.doState)
        self.closeBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(),
                                     relief=None,
                                     parent=self,
                                     command=self.exitClicked)
        self.closeBtn.setPos(0.015, 0.0, -0.375)
        gui.removeNode()
        del gui
        self.hide()
        self.friends = {}
        self.onlineFriends = {}
        self.fsm = ClassicFSM.ClassicFSM('FriendsList', [
            State.State('off', self.enterOff, self.exitOff),
            State.State('onlineFriendsList', self.enterOnlineFriendsList,
                        self.exitOnlineFriendsList),
            State.State('allFriendsList', self.enterAllFriendsList,
                        self.exitAllFriendsList)
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.accept('gotFriendsList', self.handleFriendsList)
        return

    def destroy(self):
        self.ignore('gotFriendsList')
        self.fsm.requestFinalState()
        del self.fsm
        self.headingText.destroy()
        del self.headingText
        self.frameForNames.destroy()
        del self.frameForNames
        self.fwdBtn.destroy()
        del self.fwdBtn
        self.backBtn.destroy()
        del self.backBtn
        self.closeBtn.destroy()
        del self.closeBtn
        del self.friends
        del self.onlineFriends
        DirectFrame.destroy(self)

    def doState(self, state):
        self.fsm.request(state)

    def exitClicked(self):
        self.fsm.request('off')
        base.localAvatar.showFriendButton()

    def setButtons(self, fwd=None, back=None):
        if fwd:
            self.fwdBtn['extraArgs'] = [fwd]
            self.fwdBtn['state'] = DGG.NORMAL
        else:
            self.fwdBtn['extraArgs'] = []
            self.fwdBtn['state'] = DGG.DISABLED
        if back:
            self.backBtn['extraArgs'] = [back]
            self.backBtn['state'] = DGG.NORMAL
        else:
            self.backBtn['extraArgs'] = []
            self.backBtn['state'] = DGG.DISABLED

    def handleFriendsList(self, friendIdArray, nameArray, flags, adminTokens):
        self.friends = {}
        self.onlineFriends = {}
        for i in xrange(len(friendIdArray)):
            avatarId = friendIdArray[i]
            name = nameArray[i]
            adminToken = adminTokens[i]
            self.friends[avatarId] = [name, adminToken]
            if flags[i] == 1:
                self.onlineFriends[avatarId] = [name, adminToken]

    def enterOff(self):
        self.hide()

    def exitOff(self):
        self.show()

    def addFriend(self, name, avatarId, adminToken):
        text_fg = CIGlobals.TextColorByAdminToken[adminToken]
        self.frameForNames.addItem(
            DirectButton(text=name,
                         extraArgs=[avatarId],
                         command=self.friendClicked,
                         scale=0.035,
                         relief=None,
                         text_fg=text_fg,
                         text1_bg=textDownColor,
                         text2_bg=textRolloverColor,
                         text_align=TextNode.ALeft))
        return

    def friendClicked(self, avatarId):
        self.fsm.request('off')
        base.localAvatar.panel.makePanel(avatarId)

    def resetAll(self):
        self.headingText.setText('')
        self.frameForNames.removeAndDestroyAllItems()
        self.setButtons(None, None)
        return

    def sortListItems(self):
        self.frameForNames['items'].sort(key=lambda x: x['text'])
        self.frameForNames.refresh()

    def enterAllFriendsList(self):
        self.headingText.setText('All\nFriends')
        for friendId, data in self.friends.items():
            name = data[0]
            adminToken = data[1]
            self.addFriend(name, friendId, adminToken)

        self.sortListItems()
        self.setButtons(None, 'onlineFriendsList')
        return

    def exitAllFriendsList(self):
        self.resetAll()

    def enterOnlineFriendsList(self):
        self.headingText.setText('Online\nFriends')
        for friendId, data in self.onlineFriends.items():
            name = data[0]
            adminToken = data[1]
            self.addFriend(name, friendId, adminToken)

        self.sortListItems()
        self.setButtons('allFriendsList', None)
        return

    def exitOnlineFriendsList(self):
        self.resetAll()
class CalendarGuiDay(DirectFrame):
	notify = directNotify.newCategory('CalendarGuiDay')
	ScrollListTextSize = 0.03
	LargeTextSize = 0.0232

	def __init__(self, parent, myDate, startDate, dayClickCallback = None, onlyFutureDaysClickable = False):
		self.origParent = parent
		self.startDate = startDate
		self.myDate = myDate
		
		self.dayClickCallback = dayClickCallback
		self.onlyFutureDaysClickable = onlyFutureDaysClickable
		DirectFrame.__init__(self, parent=parent)
		self.timedEvents = []
		self.partiesInvitedToToday = []
		self.hostedPartiesToday = []
		self.yearlyHolidaysToday = []
		self.showMarkers = config.GetBool('show-calendar-markers', 0)
		self.filter = ToontownGlobals.CalendarFilterShowAll
		self.load()
		self.createGuiObjects()
		self.update()

	def createDummyLocators(self):
		self.dayButtonLocator = self.attachNewNode('dayButtonLocator')
		self.dayButtonLocator.setX(0.1)
		self.dayButtonLocator.setZ(-0.05)
		self.numberLocator = self.attachNewNode('numberLocator')
		self.numberLocator.setX(0.09)
		self.scrollLocator = self.attachNewNode('scrollLocator')
		self.selectedLocator = self.attachNewNode('selectedLocator')
		self.selectedLocator.setX(0.11)
		self.selectedLocator.setZ(-0.06)

	def load(self):
		dayAsset = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_box')
		dayAsset.reparentTo(self)
		self.dayButtonLocator = self.find('**/loc_origin')
		self.numberLocator = self.find('**/loc_number')
		self.scrollLocator = self.find('**/loc_topLeftList')
		self.selectedLocator = self.find('**/loc_origin')
		self.todayBox = self.find('**/boxToday')
		self.todayBox.hide()
		self.selectedFrame = self.find('**/boxHover')
		self.selectedFrame.hide()
		self.defaultBox = self.find('**/boxBlank')
		self.scrollBottomRightLocator = self.find('**/loc_bottomRightList')
		self.scrollDownLocator = self.find('**/loc_scrollDown')
		self.attachMarker(self.scrollDownLocator)
		self.scrollUpLocator = self.find('**/loc_scrollUp')
		self.attachMarker(self.scrollUpLocator)

	def attachMarker(self, parent, scale = 0.005, 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 createGuiObjects(self):
		self.dayButton = DirectButton(parent=self.dayButtonLocator, image=self.selectedFrame, relief=None, command=self.__clickedOnDay, pressEffect=1, rolloverSound=None, clickSound=None)
		self.numberWidget = DirectLabel(parent=self.numberLocator, relief=None, text=str(self.myDate.day), text_scale=0.04, text_align=TextNode.ACenter, text_font=ToontownGlobals.getInterfaceFont(), text_fg=Vec4(110 / 255.0, 126 / 255.0, 255 / 255.0, 1))
		self.attachMarker(self.numberLocator)
		self.listXorigin = 0
		self.listFrameSizeX = self.scrollBottomRightLocator.getX() - self.scrollLocator.getX()
		self.scrollHeight = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ()
		self.listZorigin = self.scrollBottomRightLocator.getZ()
		self.listFrameSizeZ = self.scrollLocator.getZ() - self.scrollBottomRightLocator.getZ()
		self.arrowButtonXScale = 1
		self.arrowButtonZScale = 1
		self.itemFrameXorigin = 0
		self.itemFrameZorigin = 0
		self.buttonXstart = self.itemFrameXorigin + 0.21
		self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
		buttonOffSet = -0.01
		incButtonPos = (0.0, 0, 0)
		decButtonPos = (0.0, 0, 0)
		itemFrameMinZ = self.listZorigin
		itemFrameMaxZ = self.listZorigin + self.listFrameSizeZ
		arrowUp = self.find('**/downScroll_up')
		arrowDown = self.find('**/downScroll_down')
		arrowHover = self.find('**/downScroll_hover')
		self.scrollList = DirectScrolledList(parent=self.scrollLocator, relief=None, pos=(0, 0, 0), incButton_image=(arrowUp,
		 arrowDown,
		 arrowHover,
		 arrowUp), incButton_relief=None, incButton_scale=(self.arrowButtonXScale, 1, self.arrowButtonZScale), incButton_pos=incButtonPos, incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(arrowUp,
		 arrowDown,
		 arrowHover,
		 arrowUp), decButton_relief=None, decButton_scale=(self.arrowButtonXScale, 1, -self.arrowButtonZScale), decButton_pos=decButtonPos, decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(self.itemFrameXorigin, 0, -0.03), numItemsVisible=4, incButtonCallback=self.scrollButtonPressed, decButtonCallback=self.scrollButtonPressed)
		itemFrameParent = self.scrollList.itemFrame.getParent()
		self.scrollList.incButton.reparentTo(self.scrollDownLocator)
		self.scrollList.decButton.reparentTo(self.scrollUpLocator)
		arrowUp.removeNode()
		arrowDown.removeNode()
		arrowHover.removeNode()
		clipper = PlaneNode('clipper')
		clipper.setPlane(Plane(Vec3(-1, 0, 0), Point3(0.23, 0, 0)))
		clipNP = self.scrollList.component('itemFrame').attachNewNode(clipper)
		self.scrollList.component('itemFrame').setClipPlane(clipNP)

	def scrollButtonPressed(self):
		self.__clickedOnDay()

	def adjustForMonth(self):
		curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
		if self.onlyFutureDaysClickable:
			if self.myDate.year < curServerDate.year or self.myDate.year == curServerDate.year and self.myDate.month < curServerDate.month or self.myDate.year == curServerDate.year and self.myDate.month == curServerDate.month and self.myDate.day < curServerDate.day:
				self.numberWidget.setColorScale(0.5, 0.5, 0.5, 0.5)
				self.numberWidget['state'] = DirectGuiGlobals.DISABLED
			else:
				self.numberWidget.setColorScale(1, 1, 1, 1)
		if self.myDate.month != self.startDate.month:
			self.setColorScale(0.75, 0.75, 0.75, 1.0)
			if self.dayClickCallback is not None:
				self.numberWidget['state'] = DirectGuiGlobals.DISABLED
		else:
			self.setColorScale(1, 1, 1, 1)
		if self.myDate.date() == curServerDate.date():
			self.defaultBox.hide()
			self.todayBox.show()
		else:
			self.defaultBox.show()
			self.todayBox.hide()

	def destroy(self):
		if self.dayClickCallback is not None:
			self.numberWidget.destroy()
		self.dayClickCallback = None
		self.notify.debug('desroying %s' % self.myDate)
		try:
			for item in self.scrollList['items']:
				if hasattr(item, 'description') and item.description and hasattr(item.description, 'destroy'):
					self.notify.debug('desroying description of item %s' % item)
					item.unbind(DGG.ENTER)
					item.unbind(DGG.EXIT)
					item.description.destroy()

		except e:
			self.notify.debug('pass %s' % self.myDate)

		self.scrollList.removeAndDestroyAllItems()
		self.scrollList.destroy()
		self.dayButton.destroy()
		DirectFrame.destroy(self)

	def addWeeklyHolidays(self):
		if not self.filter == ToontownGlobals.CalendarFilterShowAll and not self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays:
			return
		if base.cr.newsManager:
			holidays = base.cr.newsManager.getHolidaysForWeekday(self.myDate.weekday())
			holidayName = ''
			holidayDesc = ''
			for holidayId in holidays:
				if holidayId in TTLocalizer.HolidayNamesInCalendar:
					holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
					holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
				else:
					holidayName = TTLocalizer.UnknownHoliday % holidayId
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)

			self.scrollList.refresh()
		if config.GetBool('calendar-test-items', 0):
			if self.myDate.date() + datetime.timedelta(days=-1) == base.cr.toontownTimeManager.getCurServerDateTime().date():
				testItems = ('1:00 AM Party', '2:00 AM CEO', '11:15 AM Party', '5:30 PM CJ', '11:00 PM Party', 'Really Really Long String')
				for text in testItems:
					newItem = DirectLabel(relief=None, text=text, text_scale=self.ScrollListTextSize, text_align=TextNode.ALeft)
					self.scrollList.addItem(newItem)

			if self.myDate.date() + datetime.timedelta(days=-2) == base.cr.toontownTimeManager.getCurServerDateTime().date():
				testItems = ('1:00 AM Party', '3:00 AM CFO', '11:00 AM Party')
				textSize = self.ScrollListTextSize
				for text in testItems:
					newItem = DirectLabel(relief=None, text=text, text_scale=textSize, text_align=TextNode.ALeft)
					self.scrollList.addItem(newItem)

	def updateArrowButtons(self):
		numItems = 0
		try:
			numItems = len(self.scrollList['items'])
		except e:
			numItems = 0

		if numItems <= self.scrollList.numItemsVisible:
			self.scrollList.incButton.hide()
			self.scrollList.decButton.hide()
		else:
			self.scrollList.incButton.show()
			self.scrollList.decButton.show()

	def collectTimedEvents(self):
		self.timedEvents = []
		if self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyParties:
			for party in localAvatar.partiesInvitedTo:
				if party.startTime.date() == self.myDate.date():
					self.partiesInvitedToToday.append(party)
					self.timedEvents.append((party.startTime.time(), party))

			for party in localAvatar.hostedParties:
				if party.startTime.date() == self.myDate.date():
					self.hostedPartiesToday.append(party)
					self.timedEvents.append((party.startTime.time(), party))

		if base.cr.newsManager and (self.filter == ToontownGlobals.CalendarFilterShowAll or self.filter == ToontownGlobals.CalendarFilterShowOnlyHolidays):
			# December 14th - Winter
			if self.myDate.month == 12 and self.myDate.day == 14:
				holidayName = 'Winter Holiday'
				holidayDesc = 'Celebrate the Winter Holiday with Toontastic decorations,Cattlelog items and more!'
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			if self.myDate.weekday() == 4 or self.myDate.weekday() == 5:
				holidayName = 'Fish Bingo!'
				holidayDesc = 'Celebrate the weekend with bingo!'
			# Janurary 4th - end of Winter
			if self.myDate.month == 1 and self.myDate.day == 4:
				holidayName = 'Winter Holiday End'
				holidayDesc = 'The end of the Winter Holiday!'
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# December 30th - New year's fireworks
			if self.myDate.month == 12 and self.myDate.day == 30:
				holidayName = "New Year's Fireworks"
				holidayDesc = "Let us light the skys with Toontastic fireworks!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# December 31st - New year's fireworks
			if self.myDate.month == 12 and self.myDate.day == 31:
				holidayName = "New Year's Fireworks"
				holidayDesc = "Let us light the skys with Toontastic fireworks!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# October 21st - Halloween
			if self.myDate.month == 10 and self.myDate.day == 21:
				holidayName = "Halloween Holiday"
				holidayDesc = "Celebrate Halloween as spooky trees and streetlights transform Toontown!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# November 1st - end of halloween
			if self.myDate.month == 11 and self.myDate.day == 1:
				holidayName = " End of Halloween Holiday"
				holidayDesc = "The end of the Halloween Holiday!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# March 14th - Ides of March
			if self.myDate.month == 3 and self.myDate.day == 14:
				holidayName = "Ides of March Invasion"
				holidayDesc = "Beware the Ides of March! Stop the Backstabber Cogs from invading Toontown!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# March 15th - Ides of March
			if self.myDate.month == 3 and self.myDate.day == 15:
				holidayName = "Ides of March Invasion"
				holidayDesc = "Beware the Ides of March! Stop the Backstabber Cogs from invading Toontown!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# July 29th - XP week
			if self.myDate.month == 7 and self.myDate.day == 29:
				holidayName = "Triple XP Week"
				holidayDesc = "Celebrate Toontown with extra XP on ALL wacky gags!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# August 5th - end of XP week
			if self.myDate.month == 8 and self.myDate.day == 5:
				holidayName = "End of Triple XP Week"
				holidayDesc = "The end of the triple XP on gags"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)

			if self.myDate.month == 6 and self.myDate.day == 29:
				holidayName = "Summer Fireworks"
				holidayDesc = "Celebrate Summer with a fireworks show every hour in each playground!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# March 29th - April Toons' Week
			if self.myDate.month == 3 and self.myDate.day == 29:
				holidayName = "April Toons' Week"
				holidayDesc = "Celebrate April Toons' Week - a holiday built by Toons for Toons!!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# April 11th - April Toons end
			if self.myDate.month == 4 and self.myDate.day == 11:
				holidayName = "April Toons End"
				holidayDesc = "Here lies then end of all the April Toons' Sillyness!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)

			if self.myDate.month == 7 and self.myDate.day == 15:
				holidayName = "End of Summer Fireworks"
				holidayDesc = "Here lies the end of the Toontastic Summer Fireworks!"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			# 15th of April
			if self.myDate.month == 4 and self.myDate.day == 15:
				holidayName = "Tax Day Invasion"
				holidayDesc = "Number Crunchers are invading us. Apperntly we owe taxes! What are taxes?"
				self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 15 and not self.myDate.month == 4:
			# 	holidayName = "V2.0 Mover & Shakers"
			# 	holidayDesc = "V2.0 Mover & Shakers Cogs are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 31 and self.myDate.month == 1:
			# 	holidayName = "Skelecog Legal Eagle"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 31 and self.myDate.month == 3:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 31 and self.myDate.month == 5:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 31 and self.myDate.month == 7:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 31 and self.myDate.month == 8:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 31 and self.myDate.month == 10 :
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 31 and  self.myDate.month == 12:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 30 and self.myDate.month == 4:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 30 and self.myDate.month == 6:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 30 and self.myDate.month == 9:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 30 and self.myDate.month == 11:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			#
			# if self.myDate.day == 29 and self.myDate.month == 2:
			# 	holidayName = "Skelecog Legal Eagles"
			# 	holidayDesc = "Skelecog Legal Eagles are invading Toontown in masses! Stop them!"
			# 	self.addTitleAndDescToScrollList(holidayName, holidayDesc)
			
			oncelyHolidays = base.cr.newsManager.getOncelyHolidaysForDate(self.myDate)
			for holiday in oncelyHolidays:
				holidayId = holiday[1]
				holidayStart = holiday[2]
				holidayEnd = holiday[3]
				holidayType = holiday[0]
				if holidayStart[0] == self.myDate.year and holidayStart[1] == self.myDate.month and holidayStart[2] == self.myDate.day:
					myTime = datetime.time(holidayStart[3], holidayStart[4])
				elif holidayEnd[0] == self.myDate.year and holidayEnd[1] == self.myDate.month and holidayEnd[2] == self.myDate.day:
					myTime = datetime.time(holidayEnd[3], holidayEnd[4])
				else:
					self.notify.error('holiday is not today %s' % holiday)
				self.timedEvents.append((myTime, holiday))

			multipleStartHolidays = base.cr.newsManager.getMultipleStartHolidaysForDate(self.myDate)
			for holiday in multipleStartHolidays:
				holidayId = holiday[1]
				holidayStart = holiday[2]
				holidayEnd = holiday[3]
				holidayType = holiday[0]
				if holidayStart[0] == self.myDate.year and holidayStart[1] == self.myDate.month and holidayStart[2] == self.myDate.day:
					myTime = datetime.time(holidayStart[3], holidayStart[4])
				elif holidayEnd[0] == self.myDate.year and holidayEnd[1] == self.myDate.month and holidayEnd[2] == self.myDate.day:
					myTime = datetime.time(holidayEnd[3], holidayEnd[4])
				else:
					self.notify.error('holiday is not today %s' % holiday)
				self.timedEvents.append((myTime, holiday))

			relativelyHolidays = base.cr.newsManager.getRelativelyHolidaysForDate(self.myDate)
			for holiday in relativelyHolidays:
				holidayId = holiday[1]
				holidayStart = holiday[2]
				holidayEnd = holiday[3]
				holidayType = holiday[0]
				if holidayStart[0] == self.myDate.month and holidayStart[1] == self.myDate.day:
					myTime = datetime.time(holidayStart[2], holidayStart[3])
				elif holidayEnd[0] == self.myDate.month and holidayEnd[1] == self.myDate.day:
					myTime = datetime.time(holidayEnd[2], holidayEnd[3])
				else:
					self.notify.error('holiday is not today %s' % holiday)
				self.timedEvents.append((myTime, holiday))

		def timedEventCompare(te1, te2):
			if te1[0] < te2[0]:
				return -1
			elif te1[0] == te2[0]:
				return 0
			else:
				return 1

		self.timedEvents.sort(cmp=timedEventCompare)
		for timedEvent in self.timedEvents:
			if isinstance(timedEvent[1], PartyInfo):
				self.addPartyToScrollList(timedEvent[1])
			elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.YearlyHolidayType:
				self.addYearlyHolidayToScrollList(timedEvent[1])
			elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.OncelyHolidayType:
				self.addOncelyHolidayToScrollList(timedEvent[1])
			elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.OncelyMultipleStartHolidayType:
				self.addOncelyMultipleStartHolidayToScrollList(timedEvent[1])
			elif isinstance(timedEvent[1], tuple) and timedEvent[1][0] == NewsManager.RelativelyHolidayType:
				self.addRelativelyHolidayToScrollList(timedEvent[1])

	def addYearlyHolidayToScrollList(self, holiday):
		holidayId = holiday[1]
		holidayStart = holiday[2]
		holidayEnd = holiday[3]
		holidayType = holiday[0]
		holidayText = ''
		startTime = datetime.time(holidayStart[2], holidayStart[3])
		endTime = datetime.time(holidayEnd[2], holidayEnd[3])
		startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1])
		endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1])
		if endDate < startDate:
			endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day)
		if holidayId in TTLocalizer.HolidayNamesInCalendar:
			holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
			holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
		else:
			holidayName = TTLocalizer.UnknownHoliday % holidayId
			holidayDesc = TTLocalizer.UnknownHoliday % holidayId
		if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[1]:
			holidayText = myStrftime(startTime)
			holidayText += ' ' + holidayName
			holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime)
		elif self.myDate.month == holidayStart[0] and self.myDate.day == holidayStart[1]:
			holidayText = myStrftime(startTime)
			holidayText += ' ' + holidayName
			holidayDesc = holidayName + '. ' + holidayDesc
			holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime)
		elif self.myDate.month == holidayEnd[0] and self.myDate.day == holidayEnd[1]:
			holidayText = myStrftime(endTime)
			holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
			holidayDesc = TTLocalizer.CalendarEndOf + holidayName
			holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime)
		else:
			self.notify.error('unhandled case')
		self.addTitleAndDescToScrollList(holidayText, holidayDesc)

	def addOncelyHolidayToScrollList(self, holiday):
		holidayId = holiday[1]
		holidayStart = holiday[2]
		holidayEnd = holiday[3]
		holidayType = holiday[0]
		holidayText = ''
		startTime = datetime.time(holidayStart[3], holidayStart[4])
		endTime = datetime.time(holidayEnd[3], holidayEnd[4])
		startDate = datetime.date(holidayStart[0], holidayStart[1], holidayStart[2])
		endDate = datetime.date(holidayStart[0], holidayEnd[1], holidayEnd[2])
		if endDate < startDate:
			endDate = datetime.date(endDate.year + 1, endDate.month, endDate.day)
		if holidayId in TTLocalizer.HolidayNamesInCalendar:
			holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
			holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
		else:
			holidayName = TTLocalizer.UnknownHoliday % holidayId
			holidayDesc = ''
		if holidayStart[1] == holidayEnd[1] and holidayStart[2] == holidayEnd[2]:
			holidayText = myStrftime(startTime)
			holidayText += ' ' + holidayName
			holidayDesc = holidayName + '. ' + holidayDesc
			holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime)
		elif self.myDate.year == holidayStart[0] and self.myDate.month == holidayStart[1] and self.myDate.day == holidayStart[2]:
			holidayText = myStrftime(startTime)
			holidayText += ' ' + holidayName
			holidayDesc = holidayName + '. ' + holidayDesc
			holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime)
		elif self.myDate.year == holidayEnd[0] and self.myDate.month == holidayEnd[1] and self.myDate.day == holidayEnd[2]:
			holidayText = myStrftime(endTime)
			holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
			holidayDesc = TTLocalizer.CalendarEndOf + holidayName
			holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime)
		else:
			self.notify.error('unhandled case')
		self.addTitleAndDescToScrollList(holidayText, holidayDesc)

	def addOncelyMultipleStartHolidayToScrollList(self, holiday):
		self.addOncelyHolidayToScrollList(holiday)

	def addRelativelyHolidayToScrollList(self, holiday):
		holidayId = holiday[1]
		holidayStart = holiday[2]
		holidayEnd = holiday[3]
		holidayType = holiday[0]
		holidayText = ''
		startTime = datetime.time(holidayStart[2], holidayStart[3])
		endTime = datetime.time(holidayEnd[2], holidayEnd[3])
		startDate = datetime.date(self.myDate.year, holidayStart[0], holidayStart[1])
		endDate = datetime.date(self.myDate.year, holidayEnd[0], holidayEnd[1])
		if endDate < startDate:
			endDate.year += 1
		if holidayId in TTLocalizer.HolidayNamesInCalendar:
			holidayName = TTLocalizer.HolidayNamesInCalendar[holidayId][0]
			holidayDesc = TTLocalizer.HolidayNamesInCalendar[holidayId][1]
		else:
			holidayName = TTLocalizer.UnknownHoliday % holidayId
			holidayDesc = ''
		if holidayStart[0] == holidayEnd[0] and holidayStart[1] == holidayEnd[1]:
			holidayText = myStrftime(startTime)
			holidayText += ' ' + holidayName
			holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + myStrftime(endTime)
		elif self.myDate.month == holidayStart[0] and self.myDate.day == holidayStart[1]:
			holidayText = myStrftime(startTime)
			holidayText += ' ' + holidayName
			holidayDesc = holidayName + '. ' + holidayDesc
			holidayDesc += ' ' + TTLocalizer.CalendarEndsAt + endDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(endTime)
		elif self.myDate.month == holidayEnd[0] and self.myDate.day == holidayEnd[1]:
			holidayText = myStrftime(endTime)
			holidayText += ' ' + TTLocalizer.CalendarEndDash + holidayName
			holidayDesc = TTLocalizer.CalendarEndOf + holidayName
			holidayDesc += '. ' + TTLocalizer.CalendarStartedOn + startDate.strftime(TTLocalizer.HolidayFormat) + myStrftime(startTime)
		else:
			self.notify.error('unhandled case')
		self.addTitleAndDescToScrollList(holidayText, holidayDesc)

	def addTitleAndDescToScrollList(self, title, desc):
		textSize = self.ScrollListTextSize
		descTextSize = 0.05
		newItem = DirectButton(relief=None, text=title, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem)
		scrollItemHeight = newItem.getHeight()
		descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
		descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
		descUnderItemZAdjust = -descUnderItemZAdjust
		descZAdjust = descUnderItemZAdjust
		newItem.description = DirectLabel(parent=newItem, pos=(0.115, 0, descZAdjust), text='', text_wordwrap=15, pad=(0.02, 0.02), text_scale=descTextSize, text_align=TextNode.ACenter, textMayChange=0)
		newItem.description.checkedHeight = False
		newItem.description.setBin('gui-popup', 0)
		newItem.description.hide()
		newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, desc, descUnderItemZAdjust])
		newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])
		self.scrollList.addItem(newItem)

	def exitedTextItem(self, newItem, mousepos):
		newItem.description.hide()

	def enteredTextItem(self, newItem, descText, descUnderItemZAdjust, mousePos):
		if not newItem.description.checkedHeight:
			newItem.description.checkedHeight = True
			newItem.description['text'] = descText
			bounds = newItem.description.getBounds()
			descHeight = newItem.description.getHeight()
			scrollItemHeight = newItem.getHeight()
			descOverItemZAdjust = descHeight - scrollItemHeight / 2.0
			descZPos = self.getPos(aspect2d)[2] + descUnderItemZAdjust - descHeight
			if descZPos < -1.0:
				newItem.description.setZ(descOverItemZAdjust)
			descWidth = newItem.description.getWidth()
			brightFrame = loader.loadModel('phase_4/models/parties/tt_m_gui_sbk_calendar_popUp_bg')
			newItem.description['geom'] = brightFrame
			newItem.description['geom_scale'] = (descWidth, 1, descHeight)
			descGeomZ = (bounds[2] - bounds[3]) / 2.0
			descGeomZ += bounds[3]
			newItem.description['geom_pos'] = (0, 0, descGeomZ)
		newItem.description.show()

	def addPartyToScrollList(self, party):
		textSize = self.ScrollListTextSize
		descTextSize = 0.05
		partyTitle = myStrftime(party.startTime)
		partyTitle = partyTitle + ' ' + TTLocalizer.EventsPageCalendarTabParty
		textSize = self.ScrollListTextSize
		descTextSize = 0.05
		newItem = DirectButton(relief=None, text=partyTitle, text_scale=textSize, text_align=TextNode.ALeft, rolloverSound=None, clickSound=None, pressEffect=0, command=self.__clickedOnScrollItem)
		scrollItemHeight = newItem.getHeight()
		descUnderItemZAdjust = scrollItemHeight * descTextSize / textSize
		descUnderItemZAdjust = max(0.0534, descUnderItemZAdjust)
		descUnderItemZAdjust = -descUnderItemZAdjust
		descZAdjust = descUnderItemZAdjust
		self.scrollList.addItem(newItem)
		newItem.description = MiniInviteVisual(newItem, party)
		newItem.description.setBin('gui-popup', 0)
		newItem.description.hide()
		newItem.bind(DGG.ENTER, self.enteredTextItem, extraArgs=[newItem, newItem.description, descUnderItemZAdjust])
		newItem.bind(DGG.EXIT, self.exitedTextItem, extraArgs=[newItem])

	def __clickedOnScrollItem(self):
		self.__clickedOnDay()

	def __clickedOnDay(self):
		acceptClick = True
		if self.onlyFutureDaysClickable:
			curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
			if self.myDate.date() < curServerDate.date():
				acceptClick = False
		if not acceptClick:
			return
		if self.dayClickCallback:
			self.dayClickCallback(self)
		self.notify.debug('we got clicked on %s' % self.myDate.date())
		messenger.send('clickedOnDay', [self.myDate.date()])

	def updateSelected(self, selected):
		multiplier = 1.1
		if selected:
			self.selectedFrame.show()
			self.setScale(multiplier)
			self.setPos(-0.01, 0, 0.01)
			grandParent = self.origParent.getParent()
			self.origParent.reparentTo(grandParent)
		else:
			self.selectedFrame.hide()
			self.setScale(1.0)
			self.setPos(0, 0, 0)

	def changeDate(self, startDate, myDate):
		self.startDate = startDate
		self.myDate = myDate
		self.scrollList.removeAndDestroyAllItems()
		self.update()

	def update(self):
		self.numberWidget['text'] = str(self.myDate.day)
		self.adjustForMonth()
		self.addWeeklyHolidays()
		self.collectTimedEvents()
		self.updateArrowButtons()

	def changeFilter(self, filter):
		oldFilter = self.filter
		self.filter = filter
		if self.filter != oldFilter:
			self.scrollList.removeAndDestroyAllItems()
			self.update()