from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.uix.togglebutton import ToggleButton

Builder.load_string('''

#:kivy 1.11.1

<NumberInput@TextInput>:

    pos_hint: {'center_x': .5, 'center_y': .5}
    padding: [6, 0.9*(self.height-self.line_height)/2]
    input_filter: 'int'
    multiline: False
    text: '10'

<GridButton@ToggleButton>:
    id: self.id
    state: 'down'
    text: self.id.replace('b','')
    size_hint: None, None
    size: 30, 30

<MainScreen>:

    grid_size_x: grid_size_x
    grid_size_y: grid_size_y

    BoxLayout:
        orientation: 'vertical'
        
        GridLayout:
            cols:2
            
            Label:
                text: 'Grid size (X)'
                
            NumberInput:
                id: grid_size_x
                
            Label:
                text: 'Grid size (Y)'
                
            NumberInput:
                id: grid_size_y
                
        Button:
            text: 'Make grid'
            on_release: root.open_popup()

<PopupScreen>:

    orientation: 'vertical'
    size: root.size
    pos: root.pos
    
    Label:
        text: 'This is a grid'
        size_hint_y: None
        height:30
    
    Button:
        text: 'Print'
        on_release: root.print_output()
        size_hint_y: None
        height:30
    
    Button:
        text: 'Cancel'
        on_release: root.cancel()
        size_hint_y: None
        height:30
        
''')

class GridButton(ToggleButton):
    
    id = StringProperty('') # <- likely cause
    pass

class PopupScreen(BoxLayout):

    print_output = ObjectProperty(None)
    cancel = ObjectProperty(None)

class MainScreen(FloatLayout):

    grid_size_x = ObjectProperty(None)
    grid_size_y = ObjectProperty(None)
    
    def dismiss_popup(self):
    
        self._popup.dismiss()
        
        # return window to adjusted size
        Window.size = self.current_size

    def get_values(self):

        # print grid size

        print(f"x size: {self.grid_size_x.text}" + '\n' +
              f"y size: {self.grid_size_y.text}")
        
        ###########################################
        ### get states of grid buttons          ###
        ### for example,                        ###
        ### print(state of button with id: b1)  ###
        ### or get list of 'up' buttons         ###
        ###########################################
        
        print(self._popup.ids.b1.state) # <- doesn't work...

    def open_popup(self):
    
        # get grid sizes
        x_grid = int(self.grid_size_x.text)
        y_grid = int(self.grid_size_y.text)

        # remember main screen window size
        self.current_size = Window.size
        
        # set popup window size
        Window.size = 100+x_grid*30, 200+y_grid*30
        
        # set content of popup
        content = PopupScreen(print_output=self.get_values,
                              cancel=self.dismiss_popup)
        
        # create grid
        grid = GridLayout(cols=x_grid,
                          size_hint=(None,None),
                          size=(x_grid*30, y_grid*30))
        
        # add buttons to grid
        for i in range(x_grid * y_grid):
            grid.add_widget(GridButton(id='b'+str(i+1))) # <- likely cause

        # center grid with AnchorLayout
        grid_wid = AnchorLayout(anchor_x='center',
                                anchor_y='center')
        grid_wid.add_widget(grid)

        # add grid to popup
        content.add_widget(grid_wid, 2)

        # open popup
        self._popup = Popup(title="Popup", content=content)
        self._popup.open()

# define Base Class of Kivy App
class TestApp(App):

    def build(self):    
        Window.size = 200, 150
        return MainScreen()

# run program
if __name__ == '__main__': 
    TestApp().run()