def ApplyAttributes(self, attributes):
     Container.ApplyAttributes(self, attributes)
     sm.RegisterNotify(self)
     self.jobData = attributes.jobData
     self.materialGroups = []
     self.lines = []
     self.fromLine = None
     self.bigConnectorCircle = None
     self.animateTextThread = None
     noItemsLabelCont = Container(
         parent=self,
         align=uiconst.TOPLEFT_PROP,
         pos=(0.0, 0.5, 0.5, 500),
         padRight=industryUIConst.RADIUS_CENTERCIRCLE_OUTER)
     self.noItemsRequiredLabel = EveCaptionMedium(
         name='noItemsRequiredLabel',
         parent=noItemsLabelCont,
         align=uiconst.CENTER,
         opacity=0.0)
     self.bg = StretchSpriteHorizontal(name='groupBackground',
                                       parent=self,
                                       align=uiconst.TOLEFT_PROP,
                                       state=uiconst.UI_DISABLED,
                                       width=0.5,
                                       height=402,
                                       leftEdgeSize=10,
                                       rightEdgeSize=400)
     groupsData = self.GetMaterialGroups()
     self.ConstructGroups(groupsData)
     self.ConstructLines(groupsData)
     self.UpdateState()
     self.AnimEntry()
 def ApplyAttributes(self, attributes):
     ContainerAutoSize.ApplyAttributes(self, attributes)
     sm.RegisterNotify(self)
     self.node = attributes.node
     self.factionID = self.node.factionID
     self.shipGroupID = self.node.shipGroupID
     self.iconsPerRow = self.node.GetIconsPerRow()
     self.typeIDs = sm.GetService('shipTree').GetShipTypeIDs(self.factionID, self.shipGroupID)
     self.zoomLevel = sm.GetService('shipTreeUI').GetZoomLevel()
     self.iconSize = self.node.GetIconSize()
     nodeNum = attributes.nodeNum
     self.groupNameLabel = EveHeaderMedium(name='groupNameLabel', parent=self, align=uiconst.TOPLEFT, text=GetByMessageID(cfg.fsdInfoBubbleGroups[self.shipGroupID].nameID), left=43, top=0)
     self.iconAndBar = ShipGroupIconAndSkillBar(parent=self, top=20, node=self.node)
     self.shipContainer = ContainerAutoSize(name='shipContainer', parent=self, align=uiconst.TOPLEFT, height=self.iconSize, left=46, top=24)
     self.LoadShips()
     self.lineTop = StretchSpriteHorizontal(name='lineTop', parent=self, align=uiconst.TOTOP, texturePath='res:/UI/Texture/Classes/ShipTree/Groups/frameUpper.png', leftEdgeSize=4, rightEdgeSize=4, height=3, padTop=16)
     width = len(self.typeIDs) % self.iconsPerRow or self.iconsPerRow
     width = self.iconSize * width + 4
     self.lineBottom = StretchSpriteHorizontal(name='lineBottom', parent=self, align=uiconst.BOTTOMLEFT, texturePath='res:/UI/Texture/Classes/ShipTree/Groups/frameLower.png', leftEdgeSize=4, rightEdgeSize=4, height=1, width=width, left=43, top=-7)
     self.UpdateState(nodeNum, animate=False)
     zoomLevel = sm.GetService('shipTreeUI').GetZoomLevel()
     if zoomLevel == ZOOMED_OUT:
         self.groupNameLabel.opacity = 0.0
         self.lineTop.opacity = 0.0
         self.lineBottom.opacity = 0.0
 def Startup(self, tabgroup, data):
     from carbonui.primitives.stretchspritehorizontal import StretchSpriteHorizontal
     self.blinkDrop = StretchSpriteHorizontal(
         parent=self,
         align=uiconst.TOTOP_NOPUSH,
         color=(0.5, 0.5, 0.5, 0.0),
         name='blinkDrop',
         height=11,
         leftEdgeSize=6,
         rightEdgeSize=6,
         offset=-2,
         blendMode=trinity.TR2_SBM_ADD,
         texturePath='res:/UI/Texture/Lines/BLUR4.png')
     self.sr.args = data.get('args', None)
     self.sr.grab = [0, 0]
     self.sr.tabgroup = tabgroup
     self._selected = False
     self.sr.panel = data.get('panel', None)
     self.sr.panelparent = data.get('panelparent', None)
     self.sr.code = data.get('code', None)
     self.sr.LoadTabCallback = data.get('LoadTabCallback', None)
     self.SetLabel(data.get('label', None))
     self.SetIcon(data.get('icon', None))
     self.Deselect(False)
     self.hint = data.get('hint', None)
     if hasattr(self.sr.code, 'GetTabMenu'):
         self.GetMenu = lambda: self.sr.code.GetTabMenu(self)
     if hasattr(self.sr.panel, 'sr'):
         self.sr.panel.sr.tab = self
     self.name = data.name or data.label
Example #4
0
 def ApplyAttributes(self, attributes):
     Container.ApplyAttributes(self, attributes)
     Sprite(
         parent=self,
         align=uiconst.TOLEFT,
         width=126,
         texturePath='res:/UI/Texture/classes/shipTree/frame/topLeft.png')
     cont = ContainerAutoSize(
         parent=self,
         align=uiconst.TOLEFT,
         alignMode=uiconst.TOPLEFT,
         bgTexturePath='res:/UI/Texture/classes/shipTree/frame/topMiddle.png'
     )
     Label(parent=cont,
           text=GetByLabel('UI/ShipTree/InterbusShipIdentificationSystem'),
           color=COLOR_BG,
           top=3,
           fontsize=12,
           uppercase=True,
           bold=True,
           padRight=4)
     StretchSpriteHorizontal(
         parent=Container(parent=self),
         align=uiconst.TOTOP,
         texturePath='res:/UI/Texture/classes/ShipTree/frame/topRight.png',
         leftEdgeSize=40,
         rightEdgeSize=5,
         height=26)
 def ApplyAttributes(self, attributes):
     Container.ApplyAttributes(self, attributes)
     self.value = 0.0
     iconPath = attributes.iconPath
     iconSize = attributes.iconSize
     minValue = attributes.minValue
     maxValue = attributes.maxValue
     showBG = attributes.get('showBG', True)
     isCompact = attributes.get('isCompact', False)
     self.jobData = attributes.jobData
     self.gauge = Gauge(parent=self, align=uiconst.TOBOTTOM, state=uiconst.UI_DISABLED, height=6, gaugeHeight=6, padTop=1, backgroundColor=(1.0, 1.0, 1.0, 0.05))
     if isCompact:
         self.icon = None
         self.valueLabel = None
         return
     mainCont = Container(name='mainCont', parent=self)
     if showBG:
         self.bg = StretchSpriteHorizontal(bgParent=mainCont, texturePath='res:/UI/Texture/Classes/Industry/Center/bgMETE.png')
         FillThemeColored(bgParent=self, opacity=0.5)
     else:
         self.bg = None
     left = 8 if showBG else 2
     self.icon = Sprite(name='icon', parent=mainCont, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, pos=(left,
      3,
      self.ICONSIZE,
      self.ICONSIZE), texturePath=self.ICONPATH, opacity=0.6)
     self.valueLabel = EveLabelMediumBold(parent=mainCont, align=uiconst.TOPRIGHT, top=4, left=left)
     self.removeIcon = Sprite(parent=mainCont, align=uiconst.CENTERRIGHT, state=uiconst.UI_HIDDEN, texturePath='res:/ui/texture/icons/73_16_45.png', pos=(0, 0, 12, 12), color=Color.RED, hint=localization.GetByLabel('UI/Industry/PreviewModeHint'))
     self.removeIcon.OnClick = self.OnRemoveIconClick
     self.previewEdit = SinglelineEdit(name='previewEdit', parent=mainCont, align=uiconst.CENTERRIGHT, state=uiconst.UI_HIDDEN, ints=(0, self.MAXVAL), OnChange=self.OnPreviewEdit, pos=(12, 0, 34, 20))
     self.errorFrame = ErrorFrame(bgParent=self, padding=(1, 1, 1, 8))
Example #6
0
 def ApplyAttributes(self, attributes):
     Container.ApplyAttributes(self, attributes)
     self.jobData = attributes.jobData
     self.ConstructTop()
     self.ConstructBottom()
     self.ConstructCenter()
     self.ConstructCostAndTimeLabels()
     self.bg = StretchSpriteHorizontal(parent=self, state=uiconst.UI_DISABLED, align=uiconst.TORIGHT_PROP, width=0.5, height=402, leftEdgeSize=400, rightEdgeSize=10, texturePath='res:/UI/Texture/Classes/Industry/Input/bg1Groups.png', rotation=pi)
     self.UpdateState()
     self.AnimEntry()
Example #7
0
 def ApplyAttributes(self, attributes):
     Container.ApplyAttributes(self, attributes)
     Sprite(
         parent=self,
         align=uiconst.TOLEFT,
         width=259,
         texturePath='res:/UI/Texture/classes/shipTree/frame/bottomLeft.png'
     )
     cont = ContainerAutoSize(parent=self, align=uiconst.TOLEFT, padLeft=4)
     Label(parent=cont,
           align=uiconst.TOPLEFT,
           text=GetByLabel('UI/ShipTree/Showing'),
           uppercase=True,
           top=38,
           fontsize=9,
           color=COLOR_FONT)
     Label(parent=self,
           text='V1.%s.%s' % (len(cfg.shiptypes), macho.version),
           uppercase=True,
           top=43,
           left=82,
           fontsize=10,
           color=COLOR_FONT)
     Label(parent=cont,
           align=uiconst.TOPLEFT,
           text=GetByLabel('UI/ShipTree/MilitaryAndIndustrialVessels'),
           uppercase=True,
           top=49,
           fontsize=9,
           color=COLOR_FONT)
     self.AddSeperator(uiconst.TOLEFT)
     self.AddSeperator(uiconst.TORIGHT)
     Label(parent=ContainerAutoSize(align=uiconst.TORIGHT,
                                    parent=self,
                                    padLeft=4),
           align=uiconst.TOPLEFT,
           text=GetByLabel('UI/ShipTree/CourtesyLabel'),
           uppercase=True,
           top=49,
           fontsize=9,
           color=COLOR_FONT)
     self.AddSeperator(uiconst.TORIGHT)
     StretchSpriteHorizontal(
         parent=Container(parent=self, padding=(4, 0, 4, 0)),
         align=uiconst.TOBOTTOM,
         texturePath='res:/UI/Texture/classes/ShipTree/frame/bottomLine.png',
         leftEdgeSize=20,
         rightEdgeSize=20,
         height=2)
Example #8
0
 def ApplyAttributes(self, attributes):
     super(InfoBubbleRace, self).ApplyAttributes(attributes)
     sm.RegisterNotify(self)
     self.factionID = attributes.factionID
     self.mainCont = Container(name='mainCont', parent=self)
     self.content = ContainerAutoSize(name='mainCont',
                                      parent=self.mainCont,
                                      align=uiconst.TOTOP,
                                      callback=self.OnMainContResize)
     self.bgFrame = Container(name='bgFrame',
                              parent=self,
                              state=uiconst.UI_DISABLED)
     self.frameTop = StretchSpriteHorizontal(
         name='frameTop',
         parent=self.bgFrame,
         align=uiconst.TOTOP,
         texturePath=
         'res:/UI/Texture/classes/ShipTree/InfoBubble/frameUpper.png',
         height=36)
     self.frameBottom = StretchSpriteHorizontal(
         name='frameBottom',
         parent=self.bgFrame,
         align=uiconst.TOBOTTOM,
         texturePath=
         'res:/UI/Texture/classes/ShipTree/InfoBubble/frameLower.png',
         height=36)
     self.bgFill = Container(name='bgFill',
                             parent=self,
                             state=uiconst.UI_DISABLED)
     StretchSpriteHorizontal(
         parent=self.bgFill,
         align=uiconst.TOTOP,
         texturePath=
         'res:/UI/Texture/classes/ShipTree/InfoBubble/backTopExtender.png',
         height=1)
     StretchSpriteHorizontal(
         parent=self.bgFill,
         align=uiconst.TOBOTTOM,
         texturePath=
         'res:/UI/Texture/classes/ShipTree/InfoBubble/backBottom.png',
         height=6)
     Sprite(parent=self.bgFill,
            align=uiconst.TOALL,
            texturePath=
            'res:/UI/Texture/classes/ShipTree/InfoBubble/backMiddle.png')
     topCont = ContainerAutoSize(name='topContainer',
                                 parent=self.content,
                                 align=uiconst.TOTOP,
                                 padding=(10, 10, 10, 0),
                                 height=50)
     topRightCont = ContainerAutoSize(parent=topCont,
                                      align=uiconst.TOPLEFT,
                                      left=64,
                                      width=190)
     self.icon = Sprite(name='icon',
                        parent=topCont,
                        pos=(0, 0, 64, 64),
                        align=uiconst.TOPLEFT)
     self.caption = EveCaptionSmall(parent=topRightCont,
                                    align=uiconst.TOTOP)
     self.attributeCont = ContainerAutoSize(name='attributeCont',
                                            parent=topRightCont,
                                            align=uiconst.TOTOP,
                                            height=30,
                                            padTop=5)
     self.descriptionLabel = Label(name='descriptionLabel',
                                   parent=self.content,
                                   align=uiconst.TOTOP,
                                   padding=(10, 6, 10, 10))
     self.ShowFaction(self.factionID)
Example #9
0
 def ApplyAttributes(self, attributes):
     StretchSpriteHorizontal.ApplyAttributes(self, attributes)
     ColorThemeMixin.ApplyAttributes(self, attributes)
Example #10
0
 def ApplyAttributes(self, attributes):
     Container.ApplyAttributes(self, attributes)
     self.parentObj = attributes.parentObj
     self.topOffset = attributes.Get('topOffset', self.default_topOffset)
     self.__isClosing = False
     self.mainCont = Container(name='mainCont', parent=self, padding=10)
     self.bgFrame = Container(name='bgFrame',
                              parent=self,
                              state=uiconst.UI_DISABLED)
     self.frameTop = StretchSpriteHorizontal(
         parent=self.bgFrame,
         align=uiconst.TOTOP,
         texturePath=
         'res:/UI/Texture/classes/ShipTree/InfoBubble/frameUpper.png',
         height=36,
         opacity=0.0)
     self.frameBottom = StretchSpriteHorizontal(
         parent=self.bgFrame,
         align=uiconst.TOBOTTOM,
         texturePath=
         'res:/UI/Texture/classes/ShipTree/InfoBubble/frameLower.png',
         height=36,
         opacity=0.0)
     self.bgFill = Container(name='bgFill',
                             parent=self,
                             state=uiconst.UI_DISABLED,
                             opacity=0.0)
     StretchSpriteHorizontal(
         parent=self.bgFill,
         align=uiconst.TOTOP,
         texturePath=
         'res:/UI/Texture/classes/ShipTree/InfoBubble/backTopExtender.png',
         height=1)
     StretchSpriteHorizontal(
         parent=self.bgFill,
         align=uiconst.TOBOTTOM,
         texturePath=
         'res:/UI/Texture/classes/ShipTree/InfoBubble/backBottom.png',
         height=6)
     Sprite(parent=self.bgFill,
            align=uiconst.TOALL,
            texturePath=
            'res:/UI/Texture/classes/ShipTree/InfoBubble/backMiddle.png')
     self.topContainer = ContainerAutoSize(
         name='topContainer',
         parent=self.mainCont,
         align=uiconst.TOTOP,
         callback=self.OnMainContentSizeChanged)
     self.iconCont = Container(name='iconCont',
                               parent=self.topContainer,
                               align=uiconst.TOPLEFT,
                               width=80,
                               height=80,
                               left=0,
                               top=0)
     self.topRightCont = ContainerAutoSize(name='topRightCont',
                                           align=uiconst.TOPLEFT,
                                           left=90,
                                           width=self.width - 115,
                                           parent=self.topContainer)
     self.caption = EveCaptionMedium(parent=self.topRightCont,
                                     align=uiconst.TOTOP)
     self.attributeCont = ContainerAutoSize(name='attributeCont',
                                            parent=self.topRightCont,
                                            align=uiconst.TOTOP,
                                            padTop=5)
     self.mainContent = ContainerAutoSize(
         name='mainContent',
         parent=self.mainCont,
         align=uiconst.TOTOP,
         callback=self.OnMainContentSizeChanged,
         padTop=5)
class MaterialGroups(Container):
    default_name = 'MaterialGroups'
    __notifyevents__ = ['OnMultipleItemChange', 'OnUIScalingChange']

    def ApplyAttributes(self, attributes):
        Container.ApplyAttributes(self, attributes)
        sm.RegisterNotify(self)
        self.jobData = attributes.jobData
        self.materialGroups = []
        self.lines = []
        self.fromLine = None
        self.bigConnectorCircle = None
        self.animateTextThread = None
        noItemsLabelCont = Container(
            parent=self,
            align=uiconst.TOPLEFT_PROP,
            pos=(0.0, 0.5, 0.5, 500),
            padRight=industryUIConst.RADIUS_CENTERCIRCLE_OUTER)
        self.noItemsRequiredLabel = EveCaptionMedium(
            name='noItemsRequiredLabel',
            parent=noItemsLabelCont,
            align=uiconst.CENTER,
            opacity=0.0)
        self.bg = StretchSpriteHorizontal(name='groupBackground',
                                          parent=self,
                                          align=uiconst.TOLEFT_PROP,
                                          state=uiconst.UI_DISABLED,
                                          width=0.5,
                                          height=402,
                                          leftEdgeSize=10,
                                          rightEdgeSize=400)
        groupsData = self.GetMaterialGroups()
        self.ConstructGroups(groupsData)
        self.ConstructLines(groupsData)
        self.UpdateState()
        self.AnimEntry()

    def DrawBigConnectorCircle(self, groupsData):
        x, y = self.GetPointBigCircleLeft()
        if not self.bigConnectorCircle:
            self.bigConnectorCircle = MaterialGroupDashedCircle(
                name='bigConnectorCircle',
                parent=self,
                radius=industryUIConst.RADIUS_CONNECTOR_LARGE,
                color=industryUIConst.COLOR_READY,
                numSegments=len(groupsData),
                lineWidth=3.0,
                materialsByGroupID=groupsData,
                jobData=self.jobData)
            self.bigConnectorCircle.UpdateState(1)
        self.bigConnectorCircle.left = x
        self.bigConnectorCircle.top = y - industryUIConst.RADIUS_CONNECTOR_LARGE

    def ConstructLines(self, groupsData):
        for line in self.lines:
            line.Close()

        if self.fromLine:
            self.fromLine.Close()
        self.lines = []
        if self.materialGroups:
            self.DrawBigConnectorCircle(groupsData)
            self.DrawLines()
        if self.jobData:
            self.DrawLineFromCenter()

    def GetStatusText(self):
        if self.jobData:
            status = self.jobData.status
            if status == industry.STATUS_UNSUBMITTED:
                text = GetByLabel('UI/Industry/NoInputItemsRequired')
            elif status == industry.STATUS_INSTALLED:
                text = GetByLabel('UI/Industry/JobActive')
            elif status == industry.STATUS_READY:
                text = GetByLabel('UI/Industry/JobReadyForDelivery')
            else:
                text = self.jobData.GetJobStateLabel()
        else:
            text = GetByLabel('UI/Industry/NoBlueprintSelectedCaption')
        return text

    def ConstructGroups(self, groupsData):
        for group in self.materialGroups:
            group.Close()

        self.materialGroups = []
        numGroups = max(len(groupsData) - 1, 0)
        numRowsByGroupIdx = GROUP_NUMROWS[numGroups]
        if groupsData:
            top = 1
            for i, (industryGroupID, materialsData) in enumerate(groupsData):
                numRows = numRowsByGroupIdx[i]
                height = 60 * numRows + 8 * max(0, numRows - 1)
                materialGroup = MaterialGroup(parent=self,
                                              industryGroupID=industryGroupID,
                                              jobData=self.jobData,
                                              materialsData=materialsData,
                                              pos=(0, top, 400, height),
                                              numRows=numRows,
                                              opacity=0.0)
                top += height + 8
                self.materialGroups.append(materialGroup)

            statusText = ''
        else:
            statusText = self.GetStatusText()
        self.AnimateStateText(statusText)
        self.bg.SetTexturePath(GROUP_BACKGROUNDS[numGroups])

    def AnimateStateText(self, text):
        if self.animateTextThread:
            self.animateTextThread.kill()
        self.animateTextThread = uthread.new(self._AnimateStateText, text)

    def _AnimateStateText(self, text):
        if self.noItemsRequiredLabel.text:
            uicore.animations.FadeOut(self.noItemsRequiredLabel,
                                      duration=0.3,
                                      sleep=True)
        self.noItemsRequiredLabel.text = text
        uicore.animations.FadeTo(self.noItemsRequiredLabel,
                                 0.0,
                                 0.9,
                                 duration=0.6)
        self.animateTextThread = None

    def GetInnerCircleIntersectPoint(self, y):
        """
        Returns inner circle intersection point and angle (in radians)
        of line coming from a group, given y-coordinate of that line
        """
        pCenter = self.GetPointCenter()
        y = pCenter[1] - y
        th = asin(y / industryUIConst.RADIUS_CENTERCIRCLE_OUTER) + pi
        r = industryUIConst.RADIUS_CENTERCIRCLE_INNER
        p = (r * cos(th), r * sin(th))
        p = geo2.Vec2Add(p, pCenter)
        return (p, th)

    def GetOuterCirclePoint(self, p, p1):
        """
        Offset point by radius of connector circle
        """
        l = industryUIConst.RADIUS_CENTERCIRCLE_OUTER - industryUIConst.RADIUS_CENTERCIRCLE_INNER
        t = 1.0 - (l - industryUIConst.RADIUS_CONNECTOR_SMALL) / l
        return geo2.Vec2Lerp(p, p1, t)

    def DrawLine(self, points):
        line = IndustryLineTrace(parent=self, opacity=0.0)
        line.AddPoints(points)
        self.lines.append(line)

    def DrawLineFromCenter(self):
        self.fromLine = IndustryLineTrace(name='fromLine',
                                          parent=self,
                                          opacity=0.0)
        self.fromLine.AddPoints(
            (self.GetPointCenter(), self.GetPointCenterRight()))

    def DrawLineToCenter(self, p):
        self.DrawLine((p, self.GetPointBigCircleLeft()))
        self.DrawLine((self.GetPointBigCircleRight(), self.GetPointCenter()))

    def GetPointCenter(self):
        width, height = self.GetAbsoluteSize()
        return (width / 2, height / 2 + 1)

    def GetPointBigCircleLeft(self):
        x, y = self.GetPointCenter()
        return (x - BIGCIRCLE_OFFSET - industryUIConst.RADIUS_CONNECTOR_LARGE,
                y)

    def GetPointBigCircleRight(self):
        x, y = self.GetPointCenter()
        return (x - BIGCIRCLE_OFFSET + industryUIConst.RADIUS_CONNECTOR_LARGE,
                y)

    def GetPointCenterLeft(self):
        x, y = self.GetPointCenter()
        return (x - industryUIConst.RADIUS_CENTERCIRCLE_INNER, y)

    def GetPointCenterRight(self):
        w, h = self.GetCurrentAbsoluteSize()
        return (w - 334, h / 2.0)

    def DrawLines(self):
        """
        Draw lines connecting materialGroups to center circle
        """
        x1, y1 = self.GetAbsolutePosition()
        linePoints = []
        thetas = []
        for materialGroup in self.materialGroups:
            x0, y0 = materialGroup.GetEndPoint()
            p = (x0, materialGroup.top + materialGroup.height / 2.0)
            p1, theta = self.GetInnerCircleIntersectPoint(p[1])
            thetas.append(theta)
            p0 = self.GetOuterCirclePoint(p, p1)
            linePoints.append((p0, p1))

        if len(linePoints) == 1:
            p = linePoints[0][0]
            self.DrawLineToCenter(p)
            return
        thetaFirst = thetas[0]
        thetaLast = thetas[-1]
        numPoints = int(fabs((thetaFirst - thetaLast) * 8))
        stepSize = (thetaLast - thetaFirst) / numPoints
        lineStart = linePoints.pop(0)
        arcPoints = [lineStart[0]]
        r = industryUIConst.RADIUS_CENTERCIRCLE_INNER
        for i in xrange(numPoints):
            th = thetaFirst + float(i) * stepSize
            p = (r * cos(th), r * sin(th))
            p = geo2.Vec2Add(self.GetPointCenter(), p)
            arcPoints.append(p)

        lineEnd = linePoints.pop()
        arcPoints.extend([lineEnd[1], lineEnd[0]])
        self.DrawLine(arcPoints)
        for p0, p1 in linePoints:
            self.DrawLine((p0, p1))

        self.DrawLineToCenter(self.GetPointCenterLeft())

    def AnimEntry(self, animate=True):
        k = 0.05
        for i, materialGroup in enumerate(self.materialGroups):
            if animate:
                uicore.animations.FadeTo(materialGroup,
                                         0.0,
                                         1.0,
                                         duration=0.3,
                                         timeOffset=k * i)
            else:
                materialGroup.opacity = 1.0
            materialGroup.AnimEntry(k * i, animate=animate)

        i = 0
        for i, line in enumerate(self.lines):
            line.AnimEntry(0.2, i, animate=animate)

        if self.fromLine:
            self.fromLine.AnimEntry(0.8, i + 1, animate=animate)
        if self.jobData and animate:
            uicore.animations.FadeTo(self.bg, 0.0, 1.0, duration=0.6)

    def GetMaterialGroups(self):
        if not self.jobData:
            return []
        else:
            return self.jobData.GetMaterialsByGroups()

    def OnMultipleItemChange(self, items, change):
        self.OnRunsChanged()

    def OnRunsChanged(self):
        for materialGroup in self.materialGroups:
            materialGroup.OnRunsChanged()

        self.UpdateState()

    def OnNewJobData(self, jobData):
        self.jobData = jobData
        groupsData = self.GetMaterialGroups()
        if self.bigConnectorCircle:
            self.bigConnectorCircle.Close()
            self.bigConnectorCircle = None
        self.ConstructGroups(groupsData)
        self.ConstructLines(groupsData)
        self.UpdateState(animate=False)
        self.AnimEntry()

    def UpdateState(self, animate=True):
        isReady = self.IsAllGroupsReady()
        for i, line in enumerate(self.lines):
            line.UpdateColor(isReady, animate=animate)

        if self.fromLine:
            self.fromLine.UpdateColor(isReady, animate=animate)
        if self.bigConnectorCircle:
            self.bigConnectorCircle.UpdateState(self.GetNumGroupsReady(),
                                                self.IsAllGroupsReady())

    def IsAllGroupsReady(self):
        for group in self.materialGroups:
            if not group.IsReady():
                return False

        return True

    def GetNumGroupsReady(self):
        return sum(
            [materialGroup.IsReady() for materialGroup in self.materialGroups])

    def OnUIScalingChange(self, *args):
        self.OnNewJobData(self.jobData)

    def _OnResize(self, *args):
        if not self.jobData:
            return
        for group in self.materialGroups:
            group.ConstructLines()

        self.ConstructLines(self.GetMaterialGroups())
        self.UpdateState(animate=False)
        self.AnimEntry(animate=False)