<s> '''<STR_LIT>''' <EOL> import datetime <EOL> from tkinter import Menu , constants , BooleanVar <EOL> from arelle import ViewWinGrid , ModelObject , XbrlConst <EOL> from arelle . UiUtil import ( gridBorder , gridSpacer , gridHdr , gridCell , gridCombobox , <EOL> label , checkbox , <EOL> TOPBORDER , LEFTBORDER , RIGHTBORDER , BOTTOMBORDER , CENTERCELL ) <EOL> from collections import defaultdict <EOL> def viewFactsGrid ( modelXbrl , tabWin , header = "<STR_LIT>" , arcrole = XbrlConst . parentChild , linkrole = None , linkqname = None , arcqname = None , lang = None ) : <EOL> modelXbrl . modelManager . showStatus ( _ ( "<STR_LIT>" ) ) <EOL> view = ViewFactsGrid ( modelXbrl , tabWin , header , arcrole , linkrole , linkqname , arcqname , lang ) <EOL> if view . tableSetup ( ) : <EOL> view . ignoreDims = BooleanVar ( value = False ) <EOL> view . showDimDefaults = BooleanVar ( value = False ) <EOL> menu = view . contextMenu ( ) <EOL> optionsMenu = Menu ( view . viewFrame , tearoff = <NUM_LIT:0> ) <EOL> view . ignoreDims . trace ( "<STR_LIT:w>" , view . view ) <EOL> optionsMenu . add_checkbutton ( label = _ ( "<STR_LIT>" ) , underline = <NUM_LIT:0> , variable = view . ignoreDims , onvalue = True , offvalue = False ) <EOL> view . showDimDefaults . trace ( "<STR_LIT:w>" , view . view ) <EOL> optionsMenu . add_checkbutton ( label = _ ( "<STR_LIT>" ) , underline = <NUM_LIT:0> , variable = view . showDimDefaults , onvalue = True , offvalue = False ) <EOL> menu . add_cascade ( label = _ ( "<STR_LIT>" ) , menu = optionsMenu , underline = <NUM_LIT:0> ) <EOL> menu . add_cascade ( label = _ ( "<STR_LIT>" ) , underline = <NUM_LIT:0> , command = view . close ) <EOL> view . menuAddLangs ( ) <EOL> view . view ( ) <EOL> view . blockSelectEvent = <NUM_LIT:1> <EOL> view . blockViewModelObject = <NUM_LIT:0> <EOL> view . viewFrame . bind ( "<STR_LIT>" , view . cellEnter , '<STR_LIT:+>' ) <EOL> view . viewFrame . bind ( "<STR_LIT>" , view . cellLeave , '<STR_LIT:+>' ) <EOL> class ViewFactsGrid ( ViewWinGrid . ViewGrid ) : <EOL> def __init__ ( self , modelXbrl , tabWin , header , arcrole , linkrole = None , linkqname = None , arcqname = None , lang = None ) : <EOL> super ( ViewFactsGrid , self ) . __init__ ( modelXbrl , tabWin , header , True , lang ) <EOL> self . arcrole = arcrole <EOL> self . linkrole = linkrole <EOL> self . linkqname = linkqname <EOL> self . arcqname = arcqname <EOL> def tableSetup ( self ) : <EOL> self . blockSelectEvent = <NUM_LIT:1> <EOL> self . blockViewModelObject = <NUM_LIT:0> <EOL> self . tag_has = defaultdict ( list ) <EOL> relationshipSet = self . modelXbrl . relationshipSet ( self . arcrole , self . linkrole , self . linkqname , self . arcqname ) <EOL> if not relationshipSet : <EOL> self . modelXbrl . modelManager . addToLog ( _ ( "<STR_LIT>" ) . format ( self . arcrole ) ) <EOL> return False <EOL> factConcepts = set ( fact . concept for fact in self . modelXbrl . factsInInstance ) . append ( fact ) <EOL> definedLinkroles = [ ] <EOL> for linkrole in set ( rel . linkrole <EOL> for rel in relationshipSet . modelRelationships <EOL> if rel . fromModelObject in factConcepts or rel . toModelObject in factConcepts ) : <EOL> modelRoleTypes = self . modelXbrl . roleTypes . get ( linkrole ) <EOL> if modelRoleTypes : <EOL> roledefinition = modelRoleTypes [ <NUM_LIT:0> ] . definition <EOL> if not roledefinition : <EOL> roledefinition = linkrole <EOL> else : <EOL> roledefinition = linkrole <EOL> definedLinkroles . append ( ( roledefinition , linkrole ) ) <EOL> definedLinkroles . sort ( ) <EOL> if not definedLinkroles : <EOL> return False <EOL> self . linkrole = definedLinkroles [ <NUM_LIT:0> ] [ <NUM_LIT:1> ] <EOL> self . linkroleSetup ( ) <EOL> return True <EOL> def linkroleSetup ( self ) : <EOL> relationshipSet = self . modelXbrl . relationshipSet ( self . arcrole , self . linkrole , self . linkqname , self . arcqname ) <EOL> conceptsInLinkrole = set ( ) <EOL> for rel in relationshipSet : <EOL> conceptsInLinkrole . add ( rel . fromModelObject ) <EOL> conceptsInLinkrole . add ( rel . toModelObject ) <EOL> self . conceptFacts = defaultdict ( list ) <EOL> self . periodContexts = defaultdict ( set ) <EOL> contextStartDatetimes = { } <EOL> for fact in self . modelXbrl . facts : <EOL> if fact . concept in conceptsInLinkrole : <EOL> self . conceptFacts [ fact . qname ] . append ( fact ) <EOL> context = fact . context <EOL> if context . isForeverPeriod : <EOL> contextkey = datetime . datetime ( datetime . MINYEAR , <NUM_LIT:1> , <NUM_LIT:1> ) <EOL> else : <EOL> contextkey = context . endDatetime <EOL> objectId = context . objectId ( ) <EOL> self . periodContexts [ contextkey ] . add ( objectId ) <EOL> if context . isStartEndPeriod : <EOL> contextStartDatetimes [ objectId ] = context . startDatetime <EOL> self . periodKeys = list ( self . periodContexts . keys ( ) ) <EOL> self . periodKeys . sort ( ) <EOL> columnIds = [ ] <EOL> columnIdHeadings = [ ] <EOL> self . contextColId = { } <EOL> self . startdatetimeColId = { } <EOL> self . numCols = <NUM_LIT:1> <EOL> for periodKey in self . periodKeys : <EOL> colId = "<STR_LIT>" . format ( self . numCols ) <EOL> columnIds . append ( colId ) <EOL> columnIdHeadings . append ( ( colId , periodKey ) ) <EOL> for contextId in self . periodContexts [ periodKey ] : <EOL> self . contextColId [ contextId ] = colId <EOL> if contextId in contextStartDatetimes : <EOL> self . startdatetimeColId [ contextStartDatetimes [ contextId ] ] = colId <EOL> self . numCols += <NUM_LIT:1> <EOL> self . treeView [ "<STR_LIT>" ] = columnIds <EOL> for colId , colHeading in columnIdHeadings : <EOL> self . treeView . column ( colId , width = <NUM_LIT> , anchor = "<STR_LIT:w>" ) <EOL> if colHeading . year == datetime . MINYEAR : <EOL> date = "<STR_LIT>" <EOL> else : <EOL> date = ( colHeading - datetime . timedelta ( days = <NUM_LIT:1> ) ) . strftime ( "<STR_LIT>" ) <EOL> self . treeView . heading ( colId , text = date ) <EOL> return True <EOL> def view ( self ) : <EOL> self . viewFrame . clearGrid ( ) <EOL> self . zAxisRows = <NUM_LIT:1> <EOL> self . dataCols = <NUM_LIT:0> <EOL> self . dataRows = <NUM_LIT:0> <EOL> self . colHdrRows = <NUM_LIT:0> <EOL> self . dataRows = <NUM_LIT:0> <EOL> xFilters = [ ] <EOL> self . analyzeColHdrs ( self . parentFacts , <NUM_LIT:1> ) <EOL> self . colHdrTopRow = self . zAxisRows + ( <NUM_LIT:2> if self . zAxisRows else <NUM_LIT:1> ) <EOL> self . dataFirstRow = self . colHdrTopRow + self . colHdrRows <EOL> self . dataFirstCol = <NUM_LIT:2> <EOL> gridHdr ( self . gridTblHdr , <NUM_LIT:0> , <NUM_LIT:0> , <EOL> self . tupleFact . concept . label ( lang = self . lang ) , <EOL> anchor = "<STR_LIT>" , <EOL> rowspan = ( self . dataFirstRow ) , <EOL> wraplength = <NUM_LIT:200> ) <EOL> self . zAxis ( ) <EOL> self . xAxis ( self . dataFirstCol , self . colHdrTopRow , self . colHdrTopRow + self . colHdrRows - <NUM_LIT:1> , <EOL> self . tupleFact . modelTupleFacts , xFilters , True , True , True ) <EOL> self . bodyCells ( self . dataFirstRow , <NUM_LIT:0> , self . parentFacts , xFilters , True ) <EOL> def analyzeColHdrs ( self , tupleFacts , depth ) : <EOL> for xAxisChildObj in tupleFacts : <EOL> isItem = xAxisChildObj . isItem <EOL> if isItem : <EOL> self . dataCols += <NUM_LIT:1> <EOL> if depth > self . colHdrRows : self . colHdrRows = depth <EOL> self . analyzeColHdrs ( xAxisChildObj . modelTupleFacts , depth + <NUM_LIT:1> ) <EOL> def zAxis ( self , row ) : <EOL> if row is not None : <EOL> gridBorder ( self . gridColHdr , self . dataFirstCol , row , TOPBORDER , columnspan = <NUM_LIT:2> ) <EOL> gridBorder ( self . gridColHdr , self . dataFirstCol , row , LEFTBORDER ) <EOL> gridBorder ( self . gridColHdr , self . dataFirstCol , row , RIGHTBORDER , columnspan = <NUM_LIT:2> ) <EOL> gridHdr ( self . gridColHdr , self . dataFirstCol , row , <EOL> "<STR_LIT>" , <EOL> anchor = "<STR_LIT:w>" , columnspan = <NUM_LIT:2> , <EOL> wraplength = <NUM_LIT:200> , <EOL> objectId = "<STR_LIT>" , <EOL> onClick = self . onClick ) <EOL> self . combobox = gridCombobox ( <EOL> self . gridColHdr , self . dataFirstCol + <NUM_LIT:2> , row , <EOL> values = [ definition for definition , linkrole in self . definedLinkroles ] , <EOL> selectindex = self . zFilterIndex , <EOL> comboboxselected = self . comboBoxSelected ) <EOL> gridBorder ( self . gridColHdr , self . dataFirstCol + <NUM_LIT:2> , row , RIGHTBORDER ) <EOL> row += <NUM_LIT:1> <EOL> def comboBoxSelected ( self , * args ) : <EOL> self . linkrole = self . definedLinkroles [ self . combobox . valueIndex ] [ <NUM_LIT:1> ] <EOL> self . view ( ) <EOL> def xAxis ( self , leftCol , topRow , rowBelow , tupleFacts , xFilters , childrenFirst , renderNow , atTop ) : <EOL> parentRow = rowBelow <EOL> noDescendants = True <EOL> rightCol = leftCol <EOL> widthToSpanParent = <NUM_LIT:0> <EOL> sideBorder = not xFilters <EOL> if atTop and sideBorder and childrenFirst : <EOL> gridBorder ( self . gridColHdr , self . dataFirstCol , <NUM_LIT:1> , LEFTBORDER , rowspan = self . dataFirstRow ) <EOL> for xAxisChildObj in tupleFacts : <EOL> isItem = xAxisChildObj . isItem <EOL> noDescendants = False <EOL> rightCol , row , width , leafNode = self . xAxis ( leftCol , topRow + <NUM_LIT:1> , rowBelow , xAxisChildObj . modelTupleFacts , xFilters , <EOL> childrenFirst , childrenFirst , False ) <EOL> if row - <NUM_LIT:1> < parentRow : <EOL> parentRow = row - <NUM_LIT:1> <EOL> widthToSpanParent += width <EOL> label = xAxisChildObj . concept . label ( lang = self . lang ) <EOL> if childrenFirst : <EOL> thisCol = rightCol <EOL> sideBorder = RIGHTBORDER <EOL> else : <EOL> thisCol = leftCol <EOL> sideBorder = LEFTBORDER <EOL> if renderNow : <EOL> columnspan = ( rightCol - leftCol + ( <NUM_LIT:1> if isItem else <NUM_LIT:0> ) ) <EOL> gridBorder ( self . gridColHdr , leftCol , topRow , TOPBORDER , columnspan = columnspan ) <EOL> gridBorder ( self . gridColHdr , leftCol , topRow , <EOL> sideBorder , columnspan = columnspan , <EOL> rowspan = ( rowBelow - topRow + <NUM_LIT:1> ) ) <EOL> gridHdr ( self . gridColHdr , leftCol , topRow , <EOL> label if label else "<STR_LIT:U+0020>" , <EOL> anchor = "<STR_LIT>" , <EOL> columnspan = ( rightCol - leftCol + ( <NUM_LIT:1> if isItem else <NUM_LIT:0> ) ) , <EOL> rowspan = ( row - topRow + <NUM_LIT:1> ) if leafNode else <NUM_LIT:1> , <EOL> wraplength = width , <EOL> objectId = xAxisChildObj . objectId ( ) , <EOL> onClick = self . onClick ) <EOL> if isItem : <EOL> gridBorder ( self . gridColHdr , thisCol , self . dataFirstRow - <NUM_LIT:1> , BOTTOMBORDER ) <EOL> xFilters . append ( xAxisChildObj . concept , <EOL> ) <EOL> if isItem : <EOL> rightCol += <NUM_LIT:1> <EOL> if renderNow and not childrenFirst : <EOL> self . xAxis ( leftCol + ( <NUM_LIT:1> if isItem else <NUM_LIT:0> ) , topRow + <NUM_LIT:1> , rowBelow , xAxisChildObj . modelTupleFacts , xFilters , childrenFirst , True , False ) <EOL> leftCol = rightCol <EOL> if atTop and sideBorder and not childrenFirst : <EOL> gridBorder ( self . gridColHdr , rightCol - <NUM_LIT:1> , <NUM_LIT:1> , RIGHTBORDER , rowspan = self . dataFirstRow ) <EOL> return ( rightCol , parentRow , widthToSpanParent , noDescendants ) <EOL> def tupleDescendant ( self , tupleParent , descendantConcept ) : <EOL> for tupleChild in tupleParent . modelTupleFacts : <EOL> if tupleChild . concept == descendantConcept : <EOL> return tupleChild <EOL> tupleDescendant = self . tupleDescendant ( tupleChild , descendantConcept ) <EOL> if tupleDescendant : <EOL> return tupleDescendant <EOL> return None <EOL> def bodyCells ( self , row , indent , tupleFacts , xFilters , zFilters ) : <EOL> for modelTupleFact in tupleFacts : <EOL> if modelTupleFact . concept == self . tupleConcept : <EOL> for i , xColConcept in enumerate ( xFilters ) : <EOL> fact = self . tupleDescendant ( modelTupleFact , xColConcept ) <EOL> if fact : <EOL> value = fact . effectiveValue <EOL> objectId = fact . objectId ( ) <EOL> justify = "<STR_LIT:right>" if fact . isNumeric else "<STR_LIT:left>" <EOL> else : <EOL> value = None <EOL> objectId = None <EOL> if value is not None : <EOL> gridCell ( self . gridBody , self . dataFirstCol + i , row , value , justify = justify , width = <NUM_LIT:12> , <EOL> objectId = objectId , onClick = self . onClick ) <EOL> else : <EOL> gridSpacer ( self . gridBody , self . dataFirstCol + i , row , CENTERCELL ) <EOL> gridSpacer ( self . gridBody , self . dataFirstCol + i , row , RIGHTBORDER ) <EOL> gridSpacer ( self . gridBody , self . dataFirstCol + i , row , BOTTOMBORDER ) <EOL> row += <NUM_LIT:1> <EOL> return row <EOL> def onClick ( self , event ) : <EOL> self . modelXbrl . viewModelObject ( event . widget . objectId ) <EOL> def cellEnter ( self , * args ) : <EOL> self . blockSelectEvent = <NUM_LIT:0> <EOL> def cellLeave ( self , * args ) : <EOL> self . blockSelectEvent = <NUM_LIT:1> <EOL> def cellSelect ( self , * args ) : <EOL> if self . blockSelectEvent == <NUM_LIT:0> and self . blockViewModelObject == <NUM_LIT:0> : <EOL> self . blockViewModelObject += <NUM_LIT:1> <EOL> self . blockViewModelObject -= <NUM_LIT:1> <EOL> def viewModelObject ( self , modelObject ) : <EOL> if self . blockViewModelObject == <NUM_LIT:0> : <EOL> self . blockViewModelObject += <NUM_LIT:1> <EOL> '''<STR_LIT>''' <EOL> self . blockViewModelObject -= <NUM_LIT:1> </s>
