def InitDisplay(self, nav): super(ValueChangeScreen, self).InitDisplay({}) # why do we pass in the nav keys here? self.ReInitDisplay() # self.PaintBase() # write the title with name of var? maybe button should be "accept" for i in range(len(self.changevals)): fho = self.chgval[i][0][0] fvo = self.chgval[i][0][1] hw.screen.blit( self.chgval[i][1], self.offsetpoint(self.uparrowcenter[i], (fho, -self.arrowht / 2 + self.arrowht / 10))) hw.screen.blit( self.chgval[i][1], self.offsetpoint( self.dnarrowcenter[i], (fho, self.arrowht / 2 - fvo - self.arrowht / 10))) draw.lines(hw.screen, wc(self.Outline), True, self.uparrowverts[i], 5) draw.lines(hw.screen, wc(self.Outline), True, self.dnarrowverts[i], 5) # need to add in the value to change by l hw.screen.blit(self.labelrend, self.labelloc) self.Keys['accept'].SetKeyImages(("Accept", str(self.Value))) self.PaintKeys() pygame.display.update() pass
def BumpTemp(self, heat, change): # heat: True if heat setpoint touched False for cool # change: 1 for up, -1 for down if self.TimeBumpSP is not None: self.TimeBumpSP.cancel() # cancel any pending timer self.LocalOnly[not heat] = 0.50 if heat: self.t_low += change hw.screen.blit(self.SetPointSurf, (self.SPHPosL - self.SPWdt // 2, self.SPVPos)) rL = fonts.fonts.Font(self.fsize[2]).render( "{:2d}".format(self.t_low), 0, wc(self.CharColor, factor=self.LocalOnly[0])) hw.screen.blit(rL, (self.SPHPosL - self.SPWdt // 2, self.SPVPos)) pygame.display.update( pygame.Rect(self.SPHPosL - self.SPWdt // 2, self.SPVPos, self.SPWdt, self.SPHgt)) else: self.t_high += change hw.screen.blit(self.SetPointSurf, (self.SPHPosR - self.SPWdt // 2, self.SPVPos)) rH = fonts.fonts.Font(self.fsize[2]).render( "{:2d}".format(self.t_high), 0, wc(self.CharColor, factor=self.LocalOnly[1])) hw.screen.blit(rH, (self.SPHPosR - self.SPWdt // 2, self.SPVPos)) pygame.display.update( pygame.Rect(self.SPHPosR - self.SPWdt // 2, self.SPVPos, self.SPWdt, self.SPHgt)) self.TimerName += 1 self.TimeBumpSP = timers.OnceTimer(2.0, name='ThermostatSP' + str(self.TimerName), proc=self.PushTemp) self.TimeBumpSP.start()
def DisplayListSelect(self): for i in range(self.firstitem, min(len(self.itemlist), self.firstitem + self.NumSlots)): slot = i - self.firstitem clr = self.DullKeyColor if i == self.selection else self.CharColor rs, h, w = screenutil.CreateTextBlock(self.itemlist[i], self.sourceheight, clr, False, FitLine=True, MaxWidth=hw.screenwidth - self.HorizBorder * 2) voff = self.SlotsVPos[slot] + (self.sourceheight - h) // 2 hw.screen.blit(rs, (self.HorizBorder, voff)) upcolor = wc( self.CharColor) if self.firstitem != 0 else self.DullKeyColor dncolor = wc(self.CharColor) if self.firstitem + self.NumSlots < len( self.itemlist) else self.DullKeyColor pygame.draw.polygon( hw.screen, upcolor, _TriangleCorners(self.SrcPrev, self.sourceheight, False), 3) pygame.draw.polygon( hw.screen, dncolor, _TriangleCorners(self.SrcNext, self.sourceheight, True), 3) pygame.display.update()
def FinishKey(self, center, size, firstfont=0, shrink=True): if size[0] != 0: # if size is not zero then set the pos/size of the key; otherwise it was previously set in manual creation self.Center = center self.Size = size if self.label == ['']: try: if self.ControlObj.FriendlyName != '': self.label = [self.ControlObj.FriendlyName] except AttributeError: # noinspection PyAttributeOutsideInit self.label = [self.name] if self.KeyLabelOn == [ '', ]: self.KeyLabelOn = self.label if self.KeyLabelOff == [ '', ]: self.KeyLabelOff = self.label self.BuildKey(wc(self.KeyColorOn), wc(self.KeyColorOff)) # dull the OFF key if self.autocolordull: s = pygame.Surface(self.Size) s.set_alpha(150) s.fill(wc("white")) self.KeyOffImageBase.blit(s, (0, 0)) # Add the labels self.SetKeyImages(self.KeyLabelOn, self.KeyLabelOff, firstfont, shrink)
def BuildKey(self, coloron, coloroff): if self.usekeygaps: self.GappedSize = (self.Size[0] - self.Screen.HorizButGap, self.Size[1] - self.Screen.VertButGap) else: self.GappedSize = self.Size buttonsmaller = (self.GappedSize[0] - scaleW(6), self.GappedSize[1] - scaleH(6)) # create image of ON key self.KeyOnImageBase = pygame.Surface(self.GappedSize) pygame.draw.rect(self.KeyOnImageBase, coloron, ((0, 0), self.Size), 0) bord = self.KeyOutlineOffset pygame.draw.rect(self.KeyOnImageBase, wc(self.KeyOnOutlineColor), ((scaleW(bord), scaleH(bord)), buttonsmaller), bord) # create image of OFF key self.KeyOffImageBase = pygame.Surface(self.GappedSize) pygame.draw.rect(self.KeyOffImageBase, coloroff, ((0, 0), self.Size), 0) bord = self.KeyOutlineOffset pygame.draw.rect(self.KeyOffImageBase, wc(self.KeyOffOutlineColor), ((scaleW(bord), scaleH(bord)), buttonsmaller), bord) self.KeyUnknownOverlay = pygame.Surface(self.Size) pygame.draw.line(self.KeyUnknownOverlay, wc(self.KeyCharColorOn), (0, 0), self.Size, bord) pygame.draw.line(self.KeyUnknownOverlay, wc(self.KeyCharColorOn), (0, self.Size[1]), (self.Size[0], 0), bord) self.KeyUnknownOverlay.set_alpha(128)
def SourceSelectScreen(self): # show a list of sources starting with startsource item last item is either next or return # compute sources per screen as usable vertical height div item pixel height self.Keys = self.KeysSrc self.ReInitDisplay() for i in range( self.SourceItem, min(len(self.SourceSet), self.SourceItem + self.sourceslots)): slot = i - self.SourceItem clr = self.DullKeyColor if self.SourceSet[ i] == self.SourceSelection else self.CharColor rs, h, w = screenutil.CreateTextBlock(self.SourceSet[i], self.sourceheight, clr, False, FitLine=True, MaxWidth=hw.screenwidth - self.HorizBorder * 2) self.SourceSlot[slot] = self.SourceSet[i] voff = self.SrcSlotsVPos[slot] + (self.sourceheight - h) // 2 hw.screen.blit(rs, (self.HorizBorder, voff)) pygame.draw.polygon( hw.screen, wc(self.CharColor), supportscreens._TriangleCorners(self.SrcPrev, self.sourceheight, False), 3) pygame.draw.polygon( hw.screen, wc(self.CharColor), supportscreens._TriangleCorners(self.SrcNext, self.sourceheight, True), 3)
def repaintClock(self, param=None): if not self.Active: return # handle race conditions where repaint queued just before screen switch h = 0 l = [] for i in range(len(self.OutFormat)): l.append( fonts.fonts.Font(self.CharSize[i], self.Font).render(time.strftime(self.OutFormat[i]), 0, wc(self.CharColor))) h = h + l[i].get_height() if self.ExtraSize[0] != 0: cb = CreateWeathBlock(self.ExtraFormat, self.DecodedExtraFields, self.Font, self.ExtraSize, self.CharColor, None, True, useicon=False) h = h + cb.get_height() s = (self.useablevertspace - h) / (len(l)) self.ReInitDisplay() vert_off = self.startvertspace for i in range(len(l)): horiz_off = (hw.screenwidth - l[i].get_width()) // 2 hw.screen.blit(l[i], (horiz_off, vert_off)) vert_off = vert_off + s + l[i].get_height() if self.ExtraSize[0] != 0: # noinspection PyUnboundLocalVariable horiz_off = (hw.screenwidth - cb.get_width()) // 2 hw.screen.blit(cb, (horiz_off, vert_off)) pygame.display.update()
def ShowScreen(self): self.ReInitDisplay() # self.PaintBase() r = fonts.fonts.Font(self.TitleFontSize, '', True, True).render("Console Maintenance", 0, wc(self.CharColor)) rl = (hw.screenwidth - r.get_width()) / 2 hw.screen.blit(r, (rl, self.TopBorder)) r = fonts.fonts.Font(self.SubFontSize, '', True, True).render( "Up: " + interval_str(time.time() - config.sysStore.ConsoleStartTime), 0, wc(self.CharColor)) rl = (hw.screenwidth - r.get_width()) / 2 hw.screen.blit(r, (rl, self.TopBorder + self.TitleFontSize)) self.PaintKeys() pygame.display.update()
def AddTitle(self, surface, label, fontchoice, color): lines = len(label) for i in range(lines): ren = fonts.fonts.Font(fontchoice, bold=True).render(label[i], 0, wc(color)) vert_off = ((i + 1) * self.GappedSize[1] / (1 + lines)) - ren.get_height() / 2 horiz_off = (self.GappedSize[0] - ren.get_width()) / 2 surface.blit(ren, (horiz_off, vert_off))
def GroupScreen(self, gpentity): self.nms = [] self.Keys = self.KeysGpCtl self.ReInitDisplay() i = 0 for p in self.SonosGroups[gpentity]: self.nms.append(self.SonosNodes[p]) rn = screenutil.CreateTextBlock(self.nms[-1].FriendlyName, self.ctlhgt, self.CharColor, True, FitLine=True, MaxWidth=hw.screenwidth - 2 * self.HorizBorder + 10) vol = self.nms[-1].volume * 100 volrndr, h, w = screenutil.CreateTextBlock(str(int(vol)), .8 * self.ctlhgt, self.CharColor, True, FitLine=True) volx = (self.ButLocSize[i]['Dn'][0][0] + self.ButLocSize[i]['Up'][0][0] - w) // 2 hw.screen.blit(volrndr, (volx, self.ButLocSize[i]['Dn'][0][1] - h // 2)) hw.screen.blit(rn[0], (20, self.GPCtlVPos[i])) pygame.draw.polygon( hw.screen, wc(self.CharColor), supportscreens._TriangleCorners(self.ButLocSize[i]['Dn'][0], self.ButLocSize[i]['Dn'][1][0], True), 2) pygame.draw.polygon( hw.screen, wc(self.CharColor), supportscreens._TriangleCorners(self.ButLocSize[i]['Up'][0], self.ButLocSize[i]['Up'][1][0], False), 2) spkr, diagbar = self._Speaker(self.ButLocSize[i]['Mute'][0], self.ButLocSize[i]['Mute'][1][0]) pygame.draw.polygon(hw.screen, wc(self.CharColor), spkr, 2) if self.nms[-1].muted: pygame.draw.line(hw.screen, wc(self.CharColor), diagbar[0], diagbar[1], 4) i += 1
def SetScreenTitle(self, name, fontsz, color): if self.ScreenTitleBlk is not None: return # User explicitly set a title so don't override it self.ScreenTitleBlk = fonts.fonts.Font(fontsz).render(name, 0, wc(color)) h = self.ScreenTitleBlk.get_height() w = self.ScreenTitleBlk.get_width() titlegap = h // 10 # todo is this the best way to space? if fix - fix clear also self.startvertspace = self.startvertspace + h + titlegap self.useablevertspace = self.useablevertspace - h - titlegap self.titleoffset = self.starthorizspace + (self.useablehorizspace - w) // 2
def ShowScreen(self): m = self.modes.index(self.mode) self.modes = self.modes[m:] + self.modes[:m] m = self.fanstates.index(self.fan) self.fanstates = self.fanstates[m:] + self.fanstates[:m] self.ReInitDisplay() r = fonts.fonts.Font(self.fsize[3], bold=True).render(u"{:4.1f}".format(self.t_cur), 0, wc(self.CharColor)) hw.screen.blit(r, ((hw.screenwidth - r.get_width()) // 2, self.TempPos)) r = fonts.fonts.Font(self.fsize[0]).render(self.t_state.capitalize(), 0, wc(self.CharColor)) hw.screen.blit(r, ((hw.screenwidth - r.get_width()) // 2, self.StatePos)) rL = fonts.fonts.Font(self.fsize[2]).render( "{:2d}".format(self.t_low), 0, wc(self.CharColor, factor=self.LocalOnly[0])) rH = fonts.fonts.Font(self.fsize[2]).render( "{:2d}".format(self.t_high), 0, wc(self.CharColor, factor=self.LocalOnly[1])) hw.screen.blit(self.SetPointSurf, (self.SPHPosL - self.SPWdt // 2, self.SPVPos)) hw.screen.blit(self.SetPointSurf, (self.SPHPosR - self.SPWdt // 2, self.SPVPos)) hw.screen.blit(rL, (self.SPHPosL - self.SPWdt // 2, self.SPVPos)) hw.screen.blit(rH, (self.SPHPosR - self.SPWdt // 2, self.SPVPos)) hw.screen.blit(self.AdjButSurf, (0, self.AdjButTops)) r1 = fonts.fonts.Font(self.fsize[1]).render( self.mode.capitalize(), 0, wc(self.CharColor, factor=self.ModeLocal)) r2 = fonts.fonts.Font(self.fsize[1]).render( self.fan.capitalize(), 0, wc(self.CharColor, factor=self.FanLocal)) hw.screen.blit( r1, (self.Keys['Mode'].Center[0] - r1.get_width() // 2, self.ModesPos)) hw.screen.blit( r2, (self.Keys['Fan'].Center[0] - r2.get_width() // 2, self.ModesPos)) pygame.display.update()
def __init__(self, screensection, screenname): debug.debugPrint('Screen', "New Nest ThermostatScreenDesc ", screenname) screen.BaseKeyScreenDesc.__init__(self, screensection, screenname) screen.IncorporateParams( self, 'NestThermostatScreen', {'KeyColor', 'KeyOffOutlineColor', 'KeyOnOutlineColor'}, screensection) nominalfontsz = (30, 50, 80, 160) nominalspacers = (5, 20, 25, 40, 50, 85) self.fsize = [] self.spacer = [] self.HA = self.DefaultHubObj self.ThermNode = self.HA.GetNode(screenname)[0] # use ControlObj (0) if self.ThermNode is None: logsupport.Logs.Log("No Thermostat: " + screenname, severity=ConsoleWarning) raise ValueError # if isinstance(self.DefaultHub,hasshub.HA): # self.HA = self.DefaultHub # self.ThermNode = self.HA.GetNode(screenname)[0] # use ControlObj (0) # if self.ThermNode is None: # logsupport.Logs.Log("No Thermostat: " + screenname, severity=ConsoleWarning) # raise ValueError # else: # logsupport.Logs.Log("Nest Thermostat screen only works with HA hub", severity=ConsoleError) # self.self.ThermNode = None # raise ValueError self.SetScreenTitle(screen.FlatenScreenLabel(self.label), nominalfontsz[1], self.CharColor) self.TempPos = self.startvertspace ''' Size and positions based on nominal 480 vertical screen less top/bottom borders less default title size of 50 Compute other fonts sizes based on what is left after that given user ability to set actual title size ''' tempsurf = fonts.fonts.Font(50).render('Temp', 0, wc(self.CharColor)) useable = self.useablevertspace / (self.useablevertspace - tempsurf.get_height()) for fs in nominalfontsz: self.fsize.append(int(fs * useable)) for fs in nominalspacers: self.spacer.append(int(fs * useable)) self.StatePos = self.TempPos + fonts.fonts.Font( self.fsize[3]).get_linesize() - scaleH(self.spacer[1]) self.SPVPos = self.StatePos + scaleH(self.spacer[2]) sp = fonts.fonts.Font(self.fsize[2]).render("{:2d}".format(99), 0, wc(self.CharColor)) self.SPHgt = sp.get_height() self.SPWdt = sp.get_width() self.SetPointSurf = pygame.Surface((self.SPWdt, self.SPHgt)) self.SetPointSurf.fill(wc(self.BackgroundColor)) self.AdjButSurf = pygame.Surface( (hw.screenwidth, scaleH(self.spacer[3]))) self.AdjButTops = self.SPVPos + fonts.fonts.Font( self.fsize[2]).get_linesize() - scaleH(self.spacer[0]) centerspacing = hw.screenwidth // 5 self.SPHPosL = int(1.5 * centerspacing) self.SPHPosR = int(3.5 * centerspacing) self.AdjButSurf.fill(wc(self.BackgroundColor)) self.LocalOnly = [0.0, 0.0 ] # Heat setpoint, Cool setpoint: 0 is normal color self.ModeLocal = 0.0 self.FanLocal = 0.0 arrowsize = scaleH( 40) # pixel todo should this be other than a constant? self.t_low = 0 self.t_high = 99 self.t_cur = 0 self.t_state = "Unknown" self.mode = 'auto' self.fan = 'auto' self.modes, self.fanstates = self.ThermNode.GetModeInfo() self.TimeBumpSP = None self.TimeBumpModes = None self.TimeBumpFan = None self.TimerName = 0 for i in range(4): gfxdraw.filled_trigon( self.AdjButSurf, *trifromtop(centerspacing, arrowsize // 2, i + 1, arrowsize, wc(("red", "blue", "red", "blue")[i]), i % 2 != 0)) self.Keys['temp' + str(i)] = toucharea.TouchPoint( 'temp' + str(i), (centerspacing * (i + 1), self.AdjButTops + arrowsize // 2), (arrowsize * 1.2, arrowsize * 1.2), proc=functools.partial(self.BumpTemp, (True, True, False, False)[i], (1, -1, 1, -1)[i])) self.ModeButPos = self.AdjButTops + scaleH(self.spacer[5]) # pixel bsize = (scaleW(100), scaleH(self.spacer[4])) # pixel self.Keys['Mode'] = toucharea.ManualKeyDesc( self, "Mode", ["Mode"], self.KeyColor, self.CharColor, self.CharColor, center=(self.SPHPosL, self.ModeButPos), size=bsize, KOn=self.KeyOffOutlineColor, proc=self.BumpMode) self.Keys['Fan'] = toucharea.ManualKeyDesc(self, "Fan", ["Fan"], self.KeyColor, self.CharColor, self.CharColor, center=(self.SPHPosR, self.ModeButPos), size=bsize, KOn=self.KeyOffOutlineColor, proc=self.BumpFan) self.ModesPos = self.ModeButPos + bsize[1] // 2 + scaleH( self.spacer[0]) if self.ThermNode is not None: self.HubInterestList[self.HA.name] = { self.ThermNode.address: self.Keys['Mode'] } # placeholder for thermostat node utilities.register_example("NestThermostatScreenDesc", self)
def SummaryScreen(self): if self.numplayers == 0: errmsg, _, _ = screenutil.CreateTextBlock( [' ', 'No Players', 'Found', 'Check', 'Configuration', ' '], 30, 'white', True) hw.screen.blit(errmsg, (self.HorizBorder + 15, 40)) pygame.display.update() return self.Keys = self.KeysSum self.ReInitDisplay() slot = 0 pygame.draw.line(hw.screen, wc(self.CharColor), (self.HorizBorder, self.NodeVPos[0]), (hw.screenwidth - self.HorizBorder, self.NodeVPos[0]), 3) for e, g in self.SonosGroups.items(): ginfo = self.SonosNodes[g[0]] if ginfo.internalstate == -1: unav, ht, wd = screenutil.CreateTextBlock( '<player info unavailable>', self.roomheight // (sum(self.roomdisplayinfo) / self.roomdisplayinfo[1]), self.CharColor, False, FitLine=True, MaxWidth=hw.screenwidth - 2 * self.HorizBorder - 15) hw.screen.blit( unav, (self.HorizBorder + 15, self.NodeVPos[slot] + self.roomheight // (sum(self.roomdisplayinfo) / self.roomdisplayinfo[0]))) else: song, ht, wd = screenutil.CreateTextBlock( [ginfo.song, ginfo.artist, ginfo.album], self.roomheight // (sum(self.roomdisplayinfo) / self.roomdisplayinfo[1]), self.CharColor, False, FitLine=True, MaxWidth=hw.screenwidth - 2 * self.HorizBorder - 15) hw.screen.blit( song, (self.HorizBorder + 15, self.NodeVPos[slot] + self.roomheight // (sum(self.roomdisplayinfo) / self.roomdisplayinfo[0]))) for n in g: hw.screen.blit(self.RoomNames[n][0], (self.HorizBorder + 5, self.NodeVPos[slot])) self.SlotToGp[slot] = e slot += 1 lineoff = self.NodeVPos[slot] # noinspection PyUnboundLocalVariable pygame.draw.line(hw.screen, wc(self.CharColor), (self.HorizBorder, lineoff), (hw.screenwidth - self.HorizBorder, lineoff), 3) pygame.draw.line(hw.screen, wc(self.CharColor), (self.HorizBorder, self.NodeVPos[0]), (self.HorizBorder, lineoff), 3) pygame.draw.line(hw.screen, wc(self.CharColor), (hw.screenwidth - self.HorizBorder, self.NodeVPos[0]), (hw.screenwidth - self.HorizBorder, lineoff), 3)
def __init__(self, screensection, screenname): config.SonosScreen = self # todo hack to handle late appearing players debug.debugPrint('Screen', "New SonosScreenDesc ", screenname) screen.BaseKeyScreenDesc.__init__(self, screensection, screenname) screen.IncorporateParams(self, 'SonosScreen', {'KeyColor'}, screensection) self.DullKeyColor = wc(self.KeyColor, .5, self.BackgroundColor) self.HA = self.DefaultHubObj self.Subscreen = -1 self.SetScreenTitle( 'Sonos', hw.screenheight / 12, self.CharColor ) # todo correct the fontsize and maybe the color choice and change to useable vert if not isinstance(self.DefaultHubObj, hasshub.HA): logsupport.Logs.Log("Sonos Default Hub is not HA hub", severity=ConsoleError, tb=False) return self.SetScreenContents() if self.numplayers == 0: logsupport.Logs.Log("No Sonos Players reported - check network", severity=ConsoleWarning) return # set up source selection screen self.SourceSlot = [] vpos = self.startvertspace # todo add buffer? self.sourceslots = 8 self.sourceheight = self.useablevertspace // ( self.sourceslots + 1) # allow space at bottom right for arrow for i in range(self.sourceslots): self.SrcSlotsVPos.append(vpos) self.KeysSrc['Src' + str(i)] = toucharea.TouchPoint( 'Scr' + str(i), (hw.screenwidth // 2, vpos + self.sourceheight // 2), (hw.screenwidth, self.sourceheight), proc=functools.partial(self.PickSource, i)) vpos += self.sourceheight self.SourceSlot.append('') self.SrcPrev = ( hw.screenwidth - self.sourceheight - self.HorizBorder, self.startvertspace - self.sourceheight // 2 ) # todo change to horizstart + useablehoriz - sourceheight self.SrcNext = (hw.screenwidth - self.sourceheight - self.HorizBorder, vpos + self.sourceheight // 2 + 10) # for appearance self.KeysSrc['Prev'] = toucharea.TouchPoint( 'Prev', self.SrcPrev, (self.sourceheight, self.sourceheight), proc=functools.partial(self.PrevNext, False)) self.KeysSrc['Next'] = toucharea.TouchPoint( 'Next', self.SrcNext, (self.sourceheight, self.sourceheight), proc=functools.partial(self.PrevNext, True)) self.KeysSrc['OKSrc'] = toucharea.ManualKeyDesc( self, 'OKSrc', ['OK'], self.BackgroundColor, self.CharColor, self.CharColor, center=(self.SrcNext[0] - 2.5 * self.sourceheight, self.SrcNext[1]), size=(2 * self.sourceheight, self.sourceheight), KOn='', KOff='', proc=functools.partial(self.PickSourceOK, True)) self.KeysSrc['CnclSrc'] = toucharea.ManualKeyDesc( self, 'CnclSrc', ['Back'], self.BackgroundColor, self.CharColor, self.CharColor, center=(self.SrcNext[0] - 5 * self.sourceheight, self.SrcNext[1]), size=(2 * self.sourceheight, self.sourceheight), KOn='', KOff='', proc=functools.partial(self.PickSourceOK, False)) utilities.register_example("SonosScreenDesc", self)
def repaintClock(self, param=None): if not self.Active: return # handle race condition where repaint queued just before switch h = 0 renderedforecast = [] sizeindex = 0 renderedtime = [] renderedtimelabel = [] self.store.BlockRefresh() tw = 0 for i in range(len(self.TimeFormat)): renderedtime.append( fonts.fonts.Font(self.ClockSize, self.Font).render( time.strftime(self.TimeFormat[i]), 0, wc(self.CharColor))) h = h + renderedtime[-1].get_height() if renderedtime[-1].get_width() > tw: tw = renderedtime[-1].get_width() sizeindex += 1 renderedtimelabel.append(pygame.Surface((tw, h))) renderedtimelabel[-1].set_colorkey(wc('black')) v = 0 for l in renderedtime: renderedtimelabel[0].blit(l, (((tw - l.get_width()) / 2), v)) v = v + l.get_height() spaces = 1 if self.LocationSize != 0: renderedtimelabel.append( fonts.fonts.Font(self.LocationSize, self.Font).render( self.fmt.format("{d}", d=self.scrlabel), 0, wc(self.CharColor))) h = h + renderedtimelabel[-1].get_height() spaces += 1 sizeindex += 1 if not self.store.ValidWeather: # todo font size for error? renderedlines = [ fonts.fonts.Font(30, self.Font).render(x, 0, wc(self.CharColor)) for x in self.store.Status ] vert_off = self.startvertspace self.ReInitDisplay() for tmlbl in renderedtimelabel: horiz_off = (hw.screenwidth - tmlbl.get_width()) / 2 hw.screen.blit(tmlbl, (horiz_off, vert_off)) vert_off = vert_off + 20 + tmlbl.get_height() for l in renderedlines: hw.screen.blit( l, ((hw.screenwidth - l.get_width()) / 2, vert_off)) vert_off += l.get_height() else: cb = CreateWeathBlock(self.ConditionFormat, self.DecodedCondFields, self.Font, self.CondSize, self.CharColor, self.condicon, self.FcstLayout == 'LineCentered', maxiconsize=round(self.IconSizePct / 100 * self.useablehorizspace)) h = h + cb.get_height() maxfcstwidth = 0 forecastlines = 0 spaces += 1 maxfcsticon = round( self.IconSizePct / 100 * self.useablehorizspace / (2 if self.FcstLayout in ('2ColVert', '2ColHoriz') else 1)) for dy in range(self.ForecastDays): fb = CreateWeathBlock(self.ForecastFormat, self.DecodedFcstFields, self.Font, self.FcstSize, self.CharColor, self.fcsticon, self.FcstLayout == 'LineCentered', day=dy + self.SkipDays, maxiconsize=maxfcsticon) renderedforecast.append(fb) if fb.get_width() > maxfcstwidth: maxfcstwidth = fb.get_width() forecastlines += 1 forecastitemheight = renderedforecast[-1].get_height() if self.FcstLayout in ('2ColVert', '2ColHoriz'): h = h + forecastitemheight * ((self.ForecastDays + 1) // 2) forecastlines = (forecastlines + 1) // 2 usewidth = hw.screenwidth // 2 else: h = h + forecastitemheight * self.ForecastDays usewidth = hw.screenwidth s = (self.useablevertspace - h) / (spaces + forecastlines - 1) extraspace = (self.useablevertspace - h - s * (spaces + forecastlines - 1)) / spaces vert_off = self.startvertspace self.ReInitDisplay() for tmlbl in renderedtimelabel: horiz_off = (hw.screenwidth - tmlbl.get_width()) // 2 hw.screen.blit(tmlbl, (horiz_off, vert_off)) vert_off = vert_off + s + tmlbl.get_height() + extraspace hw.screen.blit(cb, ((hw.screenwidth - cb.get_width()) // 2, vert_off)) vert_off = vert_off + s + cb.get_height() + extraspace startvert = vert_off maxvert = startvert fcstvert = renderedforecast[0].get_height() horiz_off = (usewidth - maxfcstwidth) // 2 for dy, fcst in enumerate(renderedforecast): h_off = horiz_off v_off = vert_off if self.FcstLayout == '2ColHoriz': h_off = horiz_off + (dy % 2) * usewidth vert_off = vert_off + (dy % 2) * (s + fcstvert) elif self.FcstLayout == '2ColVert': vert_off = vert_off + s + fcstvert if dy == (self.ForecastDays + 1) // 2 - 1: horiz_off = horiz_off + usewidth vert_off = startvert elif self.FcstLayout in ('BlockCentered', 'LineCentered'): vert_off = vert_off + s + fcstvert h_off = (usewidth - fcst.get_width()) // 2 else: vert_off = vert_off + s + fcstvert if v_off > maxvert: maxvert = v_off hw.screen.blit(fcst, (h_off, v_off)) if self.FcstLayout == '2ColVert': pygame.draw.line(hw.screen, wc('white'), (usewidth, startvert + fcstvert // 3), (usewidth, maxvert + 2 * fcstvert / 3)) pygame.display.update()
def __init__(self, masterscreen, choosername, slots, screenhgt, voffset, proc): """ Create subscreen(s) that allow choosing from a list :param masterscreen: the real screen for which this operates :param slots: number of slots to create per selection screen :param screenhgt: height of the area to be used for the list :param voffset: vertical offset for start of area to be used :param proc: function called with resultant selection index or -1 if cancelled """ screen.ScreenDesc.__init__(self, {}, masterscreen.name + '-' + choosername + '-Chooser', parentscreen=masterscreen) self.Result = proc self.masterscreen = masterscreen self.selection = -1 self.itemlist = [] self.firstitem = 0 self.NumSlots = slots self.ListKeySlots = {} self.SlotsVPos = [] self.SlotItem = [] vpos = voffset self.BackgroundColor = self.masterscreen.BackgroundColor self.DullKeyColor = wc(self.masterscreen.KeyColor, .5, self.BackgroundColor) self.CharColor = self.masterscreen.CharColor self.sourceheight = screenhgt // (self.NumSlots + 1) for i in range(self.NumSlots): self.SlotsVPos.append(vpos) self.ListKeySlots['Src' + str(i)] = toucharea.TouchPoint( 'Slot' + str(i), (hw.screenwidth // 2, vpos + self.sourceheight // 2), (hw.screenwidth, self.sourceheight), proc=functools.partial(self.PickItem, i)) vpos += self.sourceheight self.SlotItem.append('') self.SrcPrev = (hw.screenwidth - self.sourceheight - self.HorizBorder, voffset - self.sourceheight // 2) self.SrcNext = (hw.screenwidth - self.sourceheight - self.HorizBorder, vpos + self.sourceheight // 2 + 10) # for appearance self.ListKeySlots['Prev'] = toucharea.TouchPoint( 'Prev', self.SrcPrev, (self.sourceheight, self.sourceheight), proc=functools.partial(self.PrevNext, False)) self.ListKeySlots['Next'] = toucharea.TouchPoint( 'Next', self.SrcNext, (self.sourceheight, self.sourceheight), proc=functools.partial(self.PrevNext, True)) self.ListKeySlots['OKSrc'] = toucharea.ManualKeyDesc( self, 'OKSrc', ['OK'], self.BackgroundColor, self.CharColor, self.CharColor, center=(self.SrcNext[0] - 2.5 * self.sourceheight, self.SrcNext[1]), size=(2 * self.sourceheight, self.sourceheight), KOn='', KOff='', proc=functools.partial(self.PickItemOK, True)) '''
def CreateWeathBlock(Format, Fields, WeathFont, FontSize, WeathColor, icon, centered, day=-1, useicon=True, maxiconsize=0): rf = [] fh = 0 fw = 0 FS = FontSize[:] if isinstance(FontSize, list) else [FontSize] fsize = int(FS.pop(0)) usefont = fonts.fonts.Font(fsize, WeathFont) fcstdays = 0 fld = '' vals = [] try: for fld in Fields: if day == -1: t = valuestore.GetVal(fld) if callable(t): vals.append(t()) else: vals.append(t) else: fcstdays = valuestore.GetVal((fld[0], 'FcstDays')) if day < fcstdays: t = valuestore.GetVal(fld + (day,)) if callable(t): vals.append(t()) else: vals.append(t) else: vals.append(None) logsupport.Logs.Log( "Attempt to forecast(day " + str(day) + ") beyond " + str(fcstdays) + " returned", severity=ConsoleDetailHigh) except Exception as e: logsupport.Logs.Log('Weather Block field access error: ' + str(fld) + ' Exc: ' + str(e)) try: for f in Format: rf.append(usefont.render(WFormatter().format(f, d=vals), 0, wc(WeathColor))) fh += rf[-1].get_height() if rf[-1].get_width() > fw: fw = rf[-1].get_width() if FS: fsize = int(FS.pop(0)) usefont = fonts.fonts.Font(fsize, WeathFont) except Exception as e: logsupport.Logs.Log('TimeTemp Weather Formatting Error: ', repr(e), severity=ConsoleWarning) if isinstance(e, KeyError): logsupport.Logs.Log(' No such weather field: ', e.args, severity=ConsoleWarning) rf.append(usefont.render('Weather N/A', 0, wc(WeathColor))) fh = rf[-1].get_height() * len(Format) # force the height to always be equal even if error if rf[-1].get_width() > fw: fw = rf[-1].get_width() if icon is not None: iconsize = fh if maxiconsize == 0 else min(fh, maxiconsize) totw = fw + iconsize + ICONSPACE hoff = iconsize + ICONSPACE if day == -1: iconref = icon[1:] else: if day < fcstdays: iconref = icon[1:] + (day,) else: iconref = None logsupport.Logs.Log( "Attempt to forecast(day " + str(day) + ") beyond " + str(fcstdays) + " returned by provider", severity=ConsoleDetailHigh) else: iconref = None iconsize = 0 totw = fw hoff = 0 fsfc = pygame.Surface((totw, fh)) fsfc.set_colorkey(wc('black')) v = 0 # noinspection PyBroadException try: if iconref is not None: tmp = pygame.transform.smoothscale(valuestore.ValueStores[icon[0]].GetVal(iconref), (iconsize, iconsize)) # R = pygame.Rect((0, 0), (tmp.get_height(), tmp.get_width())) # pygame.draw.rect(fsfc, (128, 128, 128), R, 3) # print('Scale: '+str(tmp.get_height())+ ' ' + str(valuestore.ValueStores[icon[0]].GetVal(iconref)) ) fsfc.blit(tmp, (0, (fh - iconsize) // 2)) except: if useicon: logsupport.Logs.Log("Internal error - missing icon for: ", str(icon[0]), str(iconref), severity=ConsoleWarning) # logsupport.Logs.Log("Temp msg: ", valuestore.ValueStores([icon[0], ('Cond', 'IconURL')])) for l in rf: if centered: fsfc.blit(l, (hoff + (fw - l.get_width()) / 2, v)) else: fsfc.blit(l, (hoff, v)) v += l.get_height() return fsfc
def __init__(self, screensection, screenname): debug.debugPrint('Screen', "New ThermostatScreenDesc ", screenname) screen.BaseKeyScreenDesc.__init__(self, screensection, screenname) screen.IncorporateParams( self, 'ThermostatScreen', {'KeyColor', 'KeyOffOutlineColor', 'KeyOnOutlineColor'}, screensection) self.info = {} self.oldinfo = {} nominalfontsz = (30, 50, 80, 160) nominalspacers = (5, 20, 25, 40, 50, 85) self.fsize = [] self.spacer = [] if isinstance(self.DefaultHubObj, isy.ISY): self.isy = self.DefaultHubObj self.ISYObj = self.isy.GetNode(screenname)[0] # use ControlObj (0) if self.ISYObj is None: logsupport.Logs.Log("No Thermostat: " + screenname, severity=ConsoleWarning) else: logsupport.Logs.Log("Thermostat screen only works with ISY hub", severity=ConsoleError) self.ISYObj = None self.SetScreenTitle(screen.FlatenScreenLabel(self.label), nominalfontsz[1], self.CharColor) self.TempPos = self.startvertspace ''' Size and positions based on vertical screen space less top/bottom borders less default title size of 50 Compute other fonts sizes based on what is left after that given user ability to set actual title size ''' tempsurf = fonts.fonts.Font(50).render('Temp', 0, wc( self.CharColor)) # todo should the 50 be scaled now? sizingratio = self.useablevertspace / (self.useablevertspace - tempsurf.get_height()) for fs in nominalfontsz: self.fsize.append(int(fs * sizingratio)) for fs in nominalspacers: self.spacer.append(int(fs * sizingratio)) self.StatePos = self.TempPos + fonts.fonts.Font( self.fsize[3]).get_linesize() - scaleH(self.spacer[1]) self.SPPos = self.StatePos + scaleH(self.spacer[2]) self.AdjButSurf = pygame.Surface( (hw.screenwidth, scaleH(self.spacer[3]))) self.AdjButTops = self.SPPos + fonts.fonts.Font( self.fsize[2]).get_linesize() - scaleH(self.spacer[0]) centerspacing = hw.screenwidth // 5 self.SPHPosL = int(1.5 * centerspacing) self.SPHPosR = int(3.5 * centerspacing) self.AdjButSurf.fill(wc(self.BackgroundColor)) arrowsize = scaleH(self.spacer[3]) # pixel for i in range(4): gfxdraw.filled_trigon( self.AdjButSurf, *trifromtop(centerspacing, arrowsize // 2, i + 1, arrowsize, wc(("red", "blue", "red", "blue")[i]), i % 2 != 0)) self.Keys['temp' + str(i)] = toucharea.TouchPoint( 'temp' + str(i), (centerspacing * (i + 1), self.AdjButTops + arrowsize // 2), (arrowsize * 1.2, arrowsize * 1.2), proc=functools.partial(self.BumpTemp, ('CLISPH', 'CLISPH', 'CLISPC', 'CLISPC')[i], (2, -2, 2, -2)[i])) self.ModeButPos = self.AdjButTops + scaleH(self.spacer[5]) # pixel bsize = (scaleW(100), scaleH(self.spacer[4])) # pixel self.Keys['Mode'] = toucharea.ManualKeyDesc( self, "Mode", ["Mode"], self.KeyColor, self.CharColor, self.CharColor, center=(self.SPHPosL, self.ModeButPos), size=bsize, KOn=self.KeyOffOutlineColor, proc=functools.partial(self.BumpMode, 'CLIMD', range(8))) self.Keys['Fan'] = toucharea.ManualKeyDesc( self, "Fan", ["Fan"], self.KeyColor, self.CharColor, self.CharColor, center=(self.SPHPosR, self.ModeButPos), size=bsize, KOn=self.KeyOffOutlineColor, proc=functools.partial(self.BumpMode, 'CLIFS', (7, 8))) self.ModesPos = self.ModeButPos + bsize[1] // 2 + scaleH( self.spacer[0]) if self.ISYObj is not None: self.HubInterestList[self.isy.name] = { self.ISYObj.address: self.Keys['Mode'] } # placeholder for thermostat node utilities.register_example("ThermostatScreenDesc", self)
def __init__(self, screensection, screenname): global alertscreens screen.ScreenDesc.__init__(self, screensection, screenname) debug.debugPrint('Screen', "Build Alerts Screen") self.NavKeysShowing = False self.DefaultNavKeysShowing = False screen.IncorporateParams(self, screenname, {'KeyColor', 'KeyCharColorOn', 'KeyCharColorOff'}, screensection) screen.AddUndefaultedParams(self, screensection, CharSize=[20], Font=fonts.monofont, MessageBack='', Message=[], DeferTime="2 minutes", BlinkTime=0) if self.MessageBack == '': self.MessageBack = self.BackgroundColor self.DimTO = 0 # alert screens don't dim or yield voluntarily self.PersistTO = 0 self.BlinkTimer = None self.TimerName = 0 self.DeferTimer = None self.Msg = True messageareapart = .7 messageareaheight = ( hw.screenheight - 2 * self.TopBorder) * messageareapart # no Nav keys todo switch to new screen sizing alertbutheight = (hw.screenheight - messageareaheight - 2 * self.TopBorder) / 2 self.upperleft = (self.HorizBorder, self.TopBorder) self.Defer = utilities.get_timedelta(self.DeferTime) self.Keys = {'defer': toucharea.ManualKeyDesc(self, 'defer', ['Defer'], self.KeyColor, self.KeyCharColorOn, self.KeyCharColorOff, center=(hw.screenwidth / 2, self.TopBorder + messageareaheight + 0.5 * alertbutheight), size=( hw.screenwidth - 2 * self.HorizBorder, alertbutheight), proc=self.DeferAction)} if 'Action' in screensection: action = screensection['Action'] self.Keys['action'] = keyspecs.CreateKey(self, action, '*Action*') # this is only case so far that is a user descibed key that gets explicit positioning so just do it here self.Keys['action'].Center = ( hw.screenwidth / 2, self.TopBorder + messageareaheight + 1.5 * alertbutheight) self.Keys['action'].Size = (hw.screenwidth - 2 * self.HorizBorder, alertbutheight) self.Keys['action'].State = True # for appearance only self.Keys['action'].FinishKey((0, 0), (0, 0)) else: pass # no key created - just a blank spot on the alert screen # for i in range(len(self.CharSize), len(self.Message)): self.CharSize.append(self.CharSize[-1]) h = 0 l = [] for i, ln in enumerate(self.Message): l.append( fonts.fonts.Font(self.CharSize[i], self.Font).render(ln, 0, wc(self.KeyCharColorOn))) h = h + l[i].get_height() s = (messageareaheight - h) / (len(l)) self.messageimage = pygame.Surface((hw.screenwidth - 2 * self.HorizBorder, messageareaheight)) self.messageblank = pygame.Surface((hw.screenwidth - 2 * self.HorizBorder, messageareaheight)) self.messageimage.fill(wc(self.MessageBack)) self.messageblank.fill(wc(self.BackgroundColor)) vert_off = s / 2 for i in range(len(l)): horiz_off = (hw.screenwidth - l[i].get_width()) / 2 - self.HorizBorder self.messageimage.blit(l[i], (horiz_off, vert_off)) vert_off = vert_off + s + l[i].get_height() self.Alert = None # gets filled in by code that parses/defines an alert that invokes the screen alertscreens[screenname] = self self.DimTO = 0 self.PersistTO = 0 utilities.register_example("AlertsScreen", self)
def __init__(self, screensection, screenname, parentscreen=None): self.userstore = paramstore.ParamStore('Screen-' + screenname, dp=screenStore if parentscreen is None else parentscreen.userstore, locname=screenname) # todo add routine to update allowable mods per screen - but rationalize with incorp parameters from hight level guys self.markradius = int(min(hw.screenwidth, hw.screenheight) * .025) self.name = screenname self.Active = False # true if actually on screen self.ScreenTimers = [] self.DefaultNavKeysShowing = True self.NavKeysShowing = True self.NavKeys = collections.OrderedDict() self.Keys = collections.OrderedDict() self.WithNav = True self.useablevertspace = hw.screenheight - self.TopBorder - self.BotBorder self.useablevertspacesansnav = hw.screenheight - self.TopBorder - self.BotBorderWONav self.useablehorizspace = hw.screenwidth - 2 * self.HorizBorder self.startvertspace = self.TopBorder self.starthorizspace = self.HorizBorder self.titleoffset = 0 self.HubInterestList = {} # one entry per hub, each entry is a dict mapping addr to Node self.ScreenTitleBlk = None self.prevkey = None self.nextkey = None self.NavKeyWidth = (hw.screenwidth - 2 * self.HorizBorder) // 2 cvertcenter = hw.screenheight - self.BotBorder / 2 # print("NKW {} {} {} {}".format(self.NavKeyWidth, self.HorizBorder, self.HorizButGap, cvertcenter)) self.homekey = toucharea.ManualKeyDesc(self, 'Back<' + 'Home', ('Home',), self.CmdKeyCol, self.CmdCharCol, self.CmdCharCol, proc=functools.partial(GoToScreen, HOMETOKEN), center=( self.starthorizspace + .5 * (self.NavKeyWidth), cvertcenter), size=(self.NavKeyWidth, self.NavKeyHeight), gaps=True) self.backkey = toucharea.ManualKeyDesc(self, 'Nav>' + 'Back', ('Back',), self.CmdKeyCol, self.CmdCharCol, self.CmdCharCol, proc=functools.partial(GoToScreen, BACKTOKEN), center=( self.starthorizspace + 1.5 * (self.NavKeyWidth), cvertcenter), size=(self.NavKeyWidth, self.NavKeyHeight), gaps=True) IncorporateParams(self, 'Screen', {'CharColor', 'DimTO', 'PersistTO', 'BackgroundColor', 'CmdKeyCol', 'CmdCharCol', 'DefaultHub', 'ScreenTitle', 'ScreenTitleColor', 'ScreenTitleSize'}, screensection) AddUndefaultedParams(self, screensection, label=[screenname]) try: self.DefaultHubObj = hubs.hubs.Hubs[self.DefaultHub] except KeyError: self.DefaultHubObj = None # todo test what happens later or force this to be an exiting error logsupport.Logs.Log("Bad default hub name for screen: ", screenname, severity=ConsoleError) if self.ScreenTitle != '': # adjust space for a title self.ScreenTitleBlk = fonts.fonts.Font(self.ScreenTitleSize, bold=True).render(self.ScreenTitle, 0, wc(self.ScreenTitleColor)) h = self.ScreenTitleBlk.get_height() w = self.ScreenTitleBlk.get_width() titlegap = h // 10 # todo is this the best way to space? self.startvertspace = self.startvertspace + h + titlegap self.useablevertspace = self.useablevertspace - h - titlegap self.titleoffset = self.starthorizspace + (self.useablehorizspace - w) // 2 utilities.register_example('ScreenDesc', self)
def ShowScreen(self, conditions): # todo given the useable vert space change should check for overflow or auto size font self.store.BlockRefresh() vert_off = self.startvertspace if not self.store.ValidWeather: renderedlines = [ fonts.fonts.Font(45, "").render(x, 0, wc(self.CharColor)) for x in self.store.Status ] for l in renderedlines: hw.screen.blit( l, ((hw.screenwidth - l.get_width()) / 2, vert_off)) vert_off = vert_off + 60 # todo use useable space stuff and vert start else: renderedlines = [] if self.LocationSize != 0: locblk = fonts.fonts.Font(self.LocationSize, "").render( self.fmt.format("{d}", d=self.store.GetVal(('Cond', 'Location'))), 0, wc(self.CharColor)) hw.screen.blit( locblk, ((hw.screenwidth - locblk.get_width()) / 2, vert_off)) vert_off = vert_off + locblk.get_height( ) + 10 # todo gap of 10 pixels is arbitrary h = vert_off if conditions: renderedlines.append( CreateWeathBlock(self.condformat, self.condfields, "", [45, 25, 35], self.CharColor, (self.location, 'Cond', 'Icon'), False)) h = h + renderedlines[-1].get_height() renderedlines.append( CreateWeathBlock(self.dayformat, self.dayfields, "", [30], self.CharColor, None, True)) h = h + renderedlines[-1].get_height() renderedlines.append( CreateWeathBlock(self.footformat, self.footfields, "", [25], self.CharColor, None, True)) h = h + renderedlines[-1].get_height() s = (self.useablevertspace - h) / ( len(renderedlines) - 1) if len(renderedlines) > 1 else 0 for l in renderedlines: hw.screen.blit( l, ((hw.screenwidth - l.get_width()) / 2, vert_off)) vert_off = vert_off + l.get_height() + s else: fcstlines = 0 fcstdays = valuestore.GetVal((self.location, 'FcstDays')) maxfcstwidth = 0 if fcstdays > 0: for i in range(fcstdays): renderedlines.append( CreateWeathBlock( self.fcstformat, self.fcstfields, "", [25], self.CharColor, # todo compute font size based on useable (self.location, 'Fcst', 'Icon'), False, day=i)) if renderedlines[-1].get_width() > maxfcstwidth: maxfcstwidth = renderedlines[-1].get_width() fcstlines += 1 else: renderedlines.append( fonts.fonts.Font(35, "").render("No Forecast Available", 0, wc(self.CharColor))) if hw.screenwidth > 350: h = h + renderedlines[-1].get_height() * 5 fcstlines = 2 + (fcstlines + 1) / 2 usewidth = hw.screenwidth / 2 else: h = h + renderedlines[-1].get_height() * 5 fcstlines = 5 usewidth = hw.screenwidth s = (self.useablevertspace - h) / (fcstlines + 1) startvert = vert_off horiz_off = (usewidth - maxfcstwidth) / 2 for dy, fcst in enumerate(renderedlines): hw.screen.blit(fcst, (horiz_off, vert_off)) vert_off = vert_off + s + fcst.get_height() if (dy == 4) and (hw.screenwidth > 350): horiz_off = horiz_off + usewidth vert_off = startvert pygame.display.update()
def PaintBase(self): hw.screen.fill(wc(self.BackgroundColor)) if config.sysStore.ErrorNotice != -1: pygame.draw.circle(hw.screen, tint(self.BackgroundColor, tint_factor=.5), (self.markradius, self.markradius), self.markradius, 0)
def repaintClock(self): usefulheight = config.screenheight - config.topborder - config.botborder h = 0 renderedforecast = [] sizeindex = 0 renderedtime = [] renderedtimelabel = [] self.store.BlockRefresh() tw = 0 for i in range(len(self.TimeFormat)): renderedtime.append(config.fonts.Font(self.ClockSize, self.Font).render( time.strftime(self.TimeFormat[i]), 0, wc(self.CharColor))) h = h + renderedtime[-1].get_height() if renderedtime[-1].get_width() > tw: tw = renderedtime[-1].get_width() sizeindex += 1 renderedtimelabel.append(pygame.Surface((tw, h))) renderedtimelabel[-1].set_colorkey(wc('black')) v = 0 for l in renderedtime: renderedtimelabel[0].blit(l, (((tw - l.get_width()) / 2), v)) v = v + l.get_height() spaces = 1 if self.LocationSize != 0: renderedtimelabel.append( config.fonts.Font(self.LocationSize, self.Font).render( self.fmt.format("{d}", d=self.scrlabel), 0, wc(self.CharColor))) h = h + renderedtimelabel[-1].get_height() spaces += 1 sizeindex += 1 if self.store.failedfetch: errmsg1 = config.fonts.Font(self.LocationSize, self.Font).render('Weather', 0, wc(self.CharColor)) errmsg2 = config.fonts.Font(self.LocationSize, self.Font).render('unavailable', 0, wc(self.CharColor)) errmsg3 = config.fonts.Font(self.LocationSize, self.Font).render('or error', 0, wc(self.CharColor)) self.PaintBase() vert_off = config.topborder for tmlbl in renderedtimelabel: horiz_off = (config.screenwidth - tmlbl.get_width()) / 2 config.screen.blit(tmlbl, (horiz_off, vert_off)) vert_off = vert_off + 20 + tmlbl.get_height() config.screen.blit(errmsg1, ((config.screenwidth - errmsg1.get_width()) / 2, vert_off)) config.screen.blit(errmsg2, ((config.screenwidth - errmsg2.get_width()) / 2, vert_off + errmsg1.get_height())) config.screen.blit(errmsg3, ((config.screenwidth - errmsg3.get_width()) / 2, vert_off + 2 * errmsg1.get_height())) else: cb = CreateWeathBlock(self.ConditionFormat, self.DecodedCondFields, self.Font, self.CondSize, self.CharColor, self.condicon, self.FcstLayout == 'LineCentered') h = h + cb.get_height() maxfcstwidth = 0 forecastlines = 0 spaces += 1 for dy in range(self.ForecastDays): fb = CreateWeathBlock(self.ForecastFormat, self.DecodedFcstFields, self.Font, self.FcstSize, self.CharColor, self.fcsticon, self.FcstLayout == 'LineCentered', day=dy + self.SkipDays) renderedforecast.append(fb) if fb.get_width() > maxfcstwidth: maxfcstwidth = fb.get_width() forecastlines += 1 forecastitemheight = renderedforecast[-1].get_height() if self.FcstLayout in ('2ColVert', '2ColHoriz'): h = h + forecastitemheight * ((self.ForecastDays + 1) // 2) forecastlines = (forecastlines + 1) // 2 usewidth = config.screenwidth // 2 else: h = h + forecastitemheight * self.ForecastDays usewidth = config.screenwidth s = (usefulheight - h) / (spaces + forecastlines - 1) extraspace = (usefulheight - h - s * (spaces + forecastlines - 1)) / spaces self.PaintBase() vert_off = config.topborder for tmlbl in renderedtimelabel: horiz_off = (config.screenwidth - tmlbl.get_width()) // 2 config.screen.blit(tmlbl, (horiz_off, vert_off)) vert_off = vert_off + s + tmlbl.get_height() + extraspace config.screen.blit(cb, ((config.screenwidth - cb.get_width()) // 2, vert_off)) vert_off = vert_off + s + cb.get_height() + extraspace startvert = vert_off maxvert = startvert fcstvert = renderedforecast[0].get_height() horiz_off = (usewidth - maxfcstwidth) // 2 for dy, fcst in enumerate(renderedforecast): h_off = horiz_off v_off = vert_off if self.FcstLayout == '2ColHoriz': h_off = horiz_off + (dy % 2) * usewidth vert_off = vert_off + (dy % 2) * (s + fcstvert) elif self.FcstLayout == '2ColVert': vert_off = vert_off + s + fcstvert if dy == (self.ForecastDays + 1) // 2 - 1: horiz_off = horiz_off + usewidth vert_off = startvert elif self.FcstLayout in ('BlockCentered', 'LineCentered'): vert_off = vert_off + s + fcstvert h_off = (usewidth - fcst.get_width()) // 2 else: vert_off = vert_off + s + fcstvert if v_off > maxvert: maxvert = v_off config.screen.blit(fcst, (h_off, v_off)) if self.FcstLayout == '2ColVert': pygame.draw.line(config.screen, wc('white'), (usewidth, startvert + fcstvert // 3), (usewidth, maxvert + 2 * fcstvert / 3)) pygame.display.update() config.DS.Tasks.AddTask(self.ClockRepaintEvent, 1)
def __init__(self, BackgroundColor, Outline, CharColor, label, initvalue, changevals, setvalueproc, returnscreen): screen.ScreenDesc.__init__(self, {}, label + ' -ValChange') self.BackgroundColor = BackgroundColor self.Outline = Outline self.CharColor = CharColor self.label = label self.initvalue = initvalue self.changevals = changevals self.setvalueproc = setvalueproc self.returnscreen = returnscreen self.name = "VALUECHANGESCREEN" self.Value = initvalue self.Keys = {} vertzonepct = .8 vertzonesize = int( .25 * hw.screenheight) # todo switch to use useable vert hgt screencenter = (hw.screenwidth / 2, hw.screenheight / 2 ) # todo switch to use useable vert hgt self.font = fonts.fonts.Font(40) self.arrowht = int(vertzonesize * vertzonepct) self.arrowwd = min(.8 * (hw.screenwidth / len(changevals)), self.arrowht) self.uparrowcenter = [] self.dnarrowcenter = [] self.uparrowverts = [] self.dnarrowverts = [] self.uparrow = [[0, self.arrowht / 2], [self.arrowwd / 2, -self.arrowht / 2], [-self.arrowwd / 2, -self.arrowht / 2]] # verticies ref 0,0 center self.dnarrow = [[0, -self.arrowht / 2], [self.arrowwd / 2, self.arrowht / 2], [-self.arrowwd / 2, self.arrowht / 2]] self.chgval = [] for i in range(len(changevals)): self.uparrowcenter.append( ((i + .5) * hw.screenwidth / (len(changevals)), screencenter[1] + vertzonesize)) self.Keys['up' + str(i)] = TouchPoint( 'up' + str(i), self.uparrowcenter[-1], self.arrowwd, functools.partial(self.ValChange, changevals[i])) self.uparrowverts.append([ functools.partial(self.offsetpoint, self.uparrowcenter[-1])(self.uparrow[k]) for k in range(3) ]) self.dnarrowcenter.append( ((i + .5) * hw.screenwidth / (len(changevals)), screencenter[1] - vertzonesize)) self.Keys['dn' + str(i)] = TouchPoint( 'up' + str(i), self.dnarrowcenter[-1], self.arrowwd, functools.partial(self.ValChange, -changevals[i])) self.dnarrowverts.append([ functools.partial(self.offsetpoint, self.dnarrowcenter[-1])(self.dnarrow[k]) for k in range(3) ]) fs = self.font.size(str(changevals[i])) self.chgval.append(((-fs[0] / 2, fs[1]), self.font.render(str(changevals[i]), True, wc(CharColor)))) self.titlecenter = (screencenter[0] - int(1.75 * vertzonesize), screencenter[1]) valuebuttoncenter = screencenter valuebuttonsize = (hw.screenwidth / 2, int(vertzonesize * vertzonepct)) labelcenter = (screencenter[0], screencenter[1] - int(1.75 * vertzonesize)) self.labelrend = self.font.render(label, True, wc(CharColor)) labelsz = self.font.size(label) self.labelloc = (labelcenter[0] - labelsz[0] / 2, labelcenter[1] - labelsz[1] / 2) cancelcenter = (screencenter[0], screencenter[1] + int(1.75 * vertzonesize)) cancelsize = (hw.screenwidth / 2, int(vertzonepct * hw.screenheight * .125) ) # todo switch to use useable vert hgt self.Keys['cancel'] = ManualKeyDesc(self, 'cancel', [ 'Cancel', ], BackgroundColor, CharColor, CharColor, cancelcenter, cancelsize, proc=self.CancelChange) self.Keys['accept'] = ManualKeyDesc(self, 'accept', ["Accept", "#"], BackgroundColor, CharColor, CharColor, valuebuttoncenter, valuebuttonsize, proc=self.AcceptChange) # need to insert current value (actually in PaintKey probably pass
def ShowScreen(self): rtxt = self.isy.try_ISY_comm( 'nodes/' + self.ISYObj.address ) # todo fix for lost connect when move to common screen # noinspection PyBroadException try: tstatdict = xmltodict.parse(rtxt) except: logsupport.Logs.Log("Thermostat node sent garbage: ", rtxt, severity=ConsoleWarning) return props = tstatdict["nodeInfo"]["properties"]["property"] self.oldinfo = dict(self.info) self.info = {} dbgStr = '' for item in props: dbgStr = dbgStr + item["@id"] + ':' + item[ "@formatted"] + "(" + item["@value"] + ") " # debug.debugPrint('Main', item["@id"]+":("+item["@value"]+"):"+item["@formatted"]) # noinspection PyBroadException try: self.info[item["@id"]] = (int(item['@value']), item['@formatted']) except: self.info[item["@id"]] = (0, item['@formatted']) debug.debugPrint('Main', dbgStr) if self.oldinfo == {}: self.oldinfo = dict(self.info) # handle initial case updtneeded = True else: updtneeded = False for i, val in self.info.items(): if self.oldinfo[i] != val: updtneeded = True debug.debugPrint('Main', 'Tstat reading change: ', i + ':', self.oldinfo[i], '->', self.info[i]) if not updtneeded: return self.ReInitDisplay() r = fonts.fonts.Font(self.fsize[3], bold=True).render( u"{:4.1f}".format(self.info["ST"][0] // 2), 0, wc(self.CharColor)) hw.screen.blit(r, ((hw.screenwidth - r.get_width()) // 2, self.TempPos)) if isinstance(self.info["CLIHCS"][0], int): r = fonts.fonts.Font(self.fsize[0]).render( ("Idle", "Heating", "Cooling")[self.info["CLIHCS"][0]], 0, wc(self.CharColor)) else: r = fonts.fonts.Font(self.fsize[0]).render("n/a", 0, wc(self.CharColor)) hw.screen.blit(r, ((hw.screenwidth - r.get_width()) // 2, self.StatePos)) # r = config.fonts.Font(self.fsize[2]).render( # "{:2d} {:2d}".format(self.info["CLISPH"][0]//2, self.info["CLISPC"][0]//2), 0, # wc(self.CharColor)) rL = fonts.fonts.Font(self.fsize[2]).render( "{:2d}".format(self.info["CLISPH"][0] // 2), 0, wc(self.CharColor)) rH = fonts.fonts.Font(self.fsize[2]).render( "{:2d}".format(self.info["CLISPC"][0] // 2), 0, wc(self.CharColor)) hw.screen.blit(rL, (self.SPHPosL - rL.get_width() // 2, self.SPPos)) hw.screen.blit(rH, (self.SPHPosR - rH.get_width() // 2, self.SPPos)) hw.screen.blit(self.AdjButSurf, (0, self.AdjButTops)) # noinspection PyBroadException try: r1 = fonts.fonts.Font(self.fsize[1]).render( ('Off', 'Heat', 'Cool', 'Auto', 'Fan', 'Prog Auto', 'Prog Heat', 'Prog Cool')[self.info["CLIMD"][0]], 0, wc(self.CharColor)) except: r1 = fonts.fonts.Font(self.fsize[1]).render( '---', 0, wc(self.CharColor)) # noinspection PyBroadException try: r2 = fonts.fonts.Font(self.fsize[1]).render( ('On', 'Auto')[self.info["CLIFS"][0] - 7], 0, wc(self.CharColor)) except: r2 = fonts.fonts.Font(self.fsize[1]).render( '---', 0, wc(self.CharColor)) hw.screen.blit( r1, (self.Keys['Mode'].Center[0] - r1.get_width() // 2, self.ModesPos)) hw.screen.blit( r2, (self.Keys['Fan'].Center[0] - r2.get_width() // 2, self.ModesPos)) pygame.display.update()